package com.tourguide.modules.finance.service; import com.alibaba.fastjson.JSONObject; import com.tourguide.common.huifu.biz.DouGongWithdrawBiz; import com.tourguide.common.huifu.biz.FenZhangUtil; import com.tourguide.modules.finance.dto.WithdrawalResponse; import com.tourguide.modules.finance.entity.GuideWithdrawal; import com.tourguide.modules.finance.entity.GuideWithdrawalAccount; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import java.util.Arrays; import java.util.Map; /** 编排主账户划账、导游账户取现及异常后的原流水查询。 */ @Service public class GuideWithdrawalPayoutService { private static final Logger log = LoggerFactory.getLogger(GuideWithdrawalPayoutService.class); private static final String UNKNOWN_ERROR_CODE = "9999"; private final GuideWithdrawalStateService stateService; private final GuideSettlementService settlementService; private final FenZhangUtil fenZhangUtil; private final DouGongWithdrawBiz withdrawBiz; public GuideWithdrawalPayoutService(GuideWithdrawalStateService stateService, GuideSettlementService settlementService, FenZhangUtil fenZhangUtil, DouGongWithdrawBiz withdrawBiz) { this.stateService = stateService; this.settlementService = settlementService; this.fenZhangUtil = fenZhangUtil; this.withdrawBiz = withdrawBiz; } public WithdrawalResponse approve(Long id, String remark, String processor) { GuideWithdrawal withdrawal = stateService.prepareTransfer(id, remark, processor); submitTransfer(withdrawal); return new WithdrawalResponse(stateService.find(id)); } public void advance(Long id) { GuideWithdrawal withdrawal = stateService.find(id); if (GuideWithdrawalStateService.TRANSFERRING.equals(withdrawal.getStatus())) { resolveTransfer(withdrawal); } else if (GuideWithdrawalStateService.TRANSFERRED.equals(withdrawal.getStatus())) { if (StringUtils.hasText(withdrawal.getCashReqSeqId()) && StringUtils.hasText(withdrawal.getCashReqDate())) { GuideWithdrawal processing = stateService.resumeCashQuery(withdrawal.getId()); if (processing != null) resolveCash(processing); } else { submitCash(withdrawal.getId()); } } else if (GuideWithdrawalStateService.PROCESSING.equals(withdrawal.getStatus())) { resolveCash(withdrawal); } } private void submitTransfer(GuideWithdrawal withdrawal) { try { GuideWithdrawalAccount account = settlementService.requireApprovedCard( withdrawal.getGuideId(), withdrawal.getBankCardId()); Map response = fenZhangUtil.fenzhang( withdrawal.getTransferReqSeqId(), withdrawal.getTransferReqDate(), withdrawal.getAmount().toString(), account.getHuifuId()); handleTransferResponse(withdrawal, response); } catch (Exception exception) { log.error("主账户划账调用异常,withdrawalId={},reqSeqId={}", withdrawal.getId(), withdrawal.getTransferReqSeqId(), exception); stateService.markTransferPending(withdrawal.getId(), null, "主账户划账结果待查询:" + exception.getMessage()); } } private void handleTransferResponse(GuideWithdrawal withdrawal, Map response) { if (transactionSucceeded(response)) { stateService.markTransferred(withdrawal.getId(), value(response, "hf_seq_id", "trans_seq_id")); submitCash(withdrawal.getId()); return; } if (transactionFailed(response) || businessRejected(response)) { stateService.markTransferFailed(withdrawal.getId(), "主账户划账失败:" + message(response)); return; } stateService.markTransferPending(withdrawal.getId(), value(response, "hf_seq_id"), "主账户划账处理中:" + message(response)); } private void resolveTransfer(GuideWithdrawal withdrawal) { try { Map response = fenZhangUtil.queryFenzhang( withdrawal.getTransferReqSeqId(), withdrawal.getTransferReqDate()); if (transactionSucceeded(response)) { stateService.markTransferred(withdrawal.getId(), value(response, "hf_seq_id", "trans_seq_id")); submitCash(withdrawal.getId()); } else if (transactionFailed(response)) { stateService.markTransferFailed(withdrawal.getId(), "主账户划账失败:" + message(response)); } else { stateService.markTransferPending(withdrawal.getId(), value(response, "hf_seq_id"), (businessRejected(response) ? "主账户划账查询失败:" : "主账户划账结果待确认:") + message(response)); } } catch (Exception exception) { log.warn("查询主账户划账状态失败,withdrawalId={},原因={}", withdrawal.getId(), exception.getMessage()); stateService.markTransferPending(withdrawal.getId(), null, "主账户划账结果待查询:" + exception.getMessage()); } } private void submitCash(Long withdrawalId) { GuideWithdrawal withdrawal = stateService.prepareCash(withdrawalId); if (withdrawal == null) return; GuideWithdrawalAccount account = settlementService.requireApprovedCard( withdrawal.getGuideId(), withdrawal.getBankCardId()); JSONObject response = withdrawBiz.encashment(withdrawal.getAmount(), account.getHuifuId(), account.getTokenNo(), withdrawal.getCashReqSeqId(), withdrawal.getCashReqDate()); if (businessRejected(response) || transactionFailed(response)) { stateService.markCashRetry(withdrawal.getId(), "导游账户取现失败:" + message(response)); return; } stateService.markCashPending(withdrawal.getId(), value(response, "hf_seq_id", "trans_seq_id", "cash_hf_seq_id"), "导游账户取现已受理:" + message(response)); } private void resolveCash(GuideWithdrawal withdrawal) { GuideWithdrawalAccount account = settlementService.requireApprovedCard( withdrawal.getGuideId(), withdrawal.getBankCardId()); JSONObject response = StringUtils.hasText(withdrawal.getCashHfSeqId()) ? withdrawBiz.query(account.getHuifuId(), withdrawal.getCashReqDate(), withdrawal.getCashReqSeqId(), withdrawal.getCashHfSeqId()) : withdrawBiz.query(account.getHuifuId(), withdrawal.getCashReqDate(), withdrawal.getCashReqSeqId()); if (transactionSucceeded(response)) { stateService.markApproved(withdrawal.getId(), value(response, "hf_seq_id", "trans_seq_id", "cash_hf_seq_id")); } else if (transactionFailed(response)) { stateService.markCashRetry(withdrawal.getId(), "导游账户取现失败:" + message(response)); } else { stateService.markCashPending(withdrawal.getId(), value(response, "hf_seq_id", "trans_seq_id", "cash_hf_seq_id"), (businessRejected(response) ? "导游账户取现查询失败:" : "导游账户取现结果待确认:") + message(response)); } } private boolean transactionSucceeded(Map response) { String status = value(response, "trans_stat", "cash_stat", "cash_status", "trans_status", "status"); return "S".equalsIgnoreCase(status) || "SUCCESS".equalsIgnoreCase(status) || "SUCCEEDED".equalsIgnoreCase(status); } private boolean transactionFailed(Map response) { String status = value(response, "trans_stat", "cash_stat", "cash_status", "trans_status", "status"); return "F".equalsIgnoreCase(status) || "FAIL".equalsIgnoreCase(status) || "FAILED".equalsIgnoreCase(status); } private boolean businessRejected(Map response) { String code = value(response, "resp_code", "code"); return StringUtils.hasText(code) && !UNKNOWN_ERROR_CODE.equals(code) && !Arrays.asList("00000000", "00000100").contains(code); } private String message(Map response) { if (response == null) return "斗拱服务无响应"; String message = value(response, "resp_desc", "msg", "message"); return StringUtils.hasText(message) ? message : "等待斗拱返回最终状态"; } @SuppressWarnings("unchecked") private String value(Map response, String... keys) { if (response == null) return null; for (String key : keys) { Object value = response.get(key); if (value != null && StringUtils.hasText(value.toString())) return value.toString(); } Object data = response.get("data"); if (data instanceof Map) return value((Map) data, keys); if (data instanceof String && StringUtils.hasText((String) data)) { try { JSONObject nested = JSONObject.parseObject((String) data); return value(nested, keys); } catch (RuntimeException ignored) { // 非 JSON 包装直接按字段缺失处理。 } } return null; } }