yeg
2026-09-12 d32e0dee609ab13220908ab28a11390bede07c84
talent-card-server/src/main/java/com/talentcard/server/business/payment/HuifuPaymentCallbackService.java
@@ -9,9 +9,10 @@
import com.alibaba.fastjson.JSON;
import com.talentcard.server.business.DatabaseRows;
import com.talentcard.server.business.order.OrderFundBoundaryService;
import com.talentcard.server.business.payment.HuifuPaymentPayload.TransStatus;
import com.talentcard.server.business.payment.PaymentSettlementService.ProviderPaymentFact;
import com.talentcard.server.business.payment.PaymentSettlementService.SettlementOutcome;
import com.talentcard.server.business.payment.huifu.HuifuPayload;
import com.talentcard.server.business.payment.huifu.HuifuPayload.TransStatus;
import com.talentcard.server.business.payment.huifu.HuifuSignatureService;
import com.talentcard.server.common.BusinessException;
import com.talentcard.server.common.ErrorCode;
@@ -56,8 +57,8 @@
            throw new BusinessException(ErrorCode.FORBIDDEN, "汇付回调验签失败");
        }
        Map<String, Object> envelope = parse(responseData);
        Map<String, Object> data = HuifuPaymentPayload.businessData(envelope);
        String requestNo = HuifuPaymentPayload.firstNonBlank(HuifuPaymentPayload.value(data, "req_seq_id"), HuifuPaymentPayload.value(envelope, "req_seq_id"));
        Map<String, Object> data = HuifuPayload.businessData(envelope);
        String requestNo = HuifuPayload.firstNonBlank(HuifuPayload.value(data, "req_seq_id"), HuifuPayload.value(envelope, "req_seq_id"));
        if (requestNo.isBlank()) throw new BusinessException(ErrorCode.BAD_REQUEST, "汇付回调缺少请求流水号");
        String payloadHash = sha256(responseData);
@@ -69,8 +70,8 @@
            return acknowledgement(requestNo);
        }
        String transStatus = HuifuPaymentPayload.value(data, "trans_stat", "transStat");
        if (HuifuPaymentPayload.status(transStatus) == TransStatus.UNKNOWN) {
        String transStatus = HuifuPayload.value(data, "trans_stat", "transStat");
        if (HuifuPayload.status(transStatus) == TransStatus.UNKNOWN) {
            updateEvent(requestNo, "UNKNOWN_STATUS");
            return acknowledgement(requestNo);
        }
@@ -80,24 +81,24 @@
            return acknowledgement(requestNo);
        }
        if (!HuifuPaymentPayload.paid(transStatus, HuifuPaymentPayload.code(data))) {
        if (!HuifuPayload.paid(transStatus, HuifuPayload.code(data))) {
            // The provider did not confirm money: keep the payment pending for the query path.
            jdbc.update("""
                    update payment_transaction
                    set provider_response_code = ?, provider_response_message = ?
                    where provider = ? and payment_no = ? and status in ('CREATED', 'CREATE_FAILED', 'PREPAY_CREATED', 'CREATE_UNKNOWN')
                    """, HuifuPaymentPayload.code(data), HuifuPaymentPayload.message(data), PROVIDER, requestNo);
                    """, HuifuPayload.code(data), HuifuPayload.message(data), PROVIDER, requestNo);
            updateEvent(requestNo, "PENDING_QUERY");
            return acknowledgement(requestNo);
        }
        SettlementOutcome outcome = settlementService.settle(new ProviderPaymentFact(
                requestNo,
                HuifuPaymentPayload.value(data, "huifu_id", "huifuId"),
                HuifuPaymentPayload.amountInCent(HuifuPaymentPayload.value(data, "trans_amt", "transAmt")),
                HuifuPayload.value(data, "huifu_id", "huifuId"),
                HuifuPayload.amountInCent(HuifuPayload.value(data, "trans_amt", "transAmt")),
                providerTransactionNo(data),
                HuifuPaymentPayload.code(data),
                HuifuPaymentPayload.message(data),
                HuifuPayload.code(data),
                HuifuPayload.message(data),
                "CALLBACK"));
        updateEvent(requestNo, eventStatus(outcome));
        return acknowledgement(requestNo);
@@ -114,15 +115,15 @@
        Map<String, Object> refund = refunds.get(0);
        long orderId = ((Number) refund.get("orderId")).longValue();
        String transStatus = HuifuPaymentPayload.value(data, "trans_stat", "transStat");
        String code = HuifuPaymentPayload.code(data);
        if (HuifuPaymentPayload.paid(transStatus, code)) {
        String transStatus = HuifuPayload.value(data, "trans_stat", "transStat");
        String code = HuifuPayload.code(data);
        if (HuifuPayload.paid(transStatus, code)) {
            jdbc.update("""
                    update order_refund
                    set refund_status = 2, provider = 'HUIFU', provider_refund_no = ?,
                        provider_response_code = ?, provider_response_message = ?, refund_time = coalesce(refund_time, now())
                    where id = ? and refund_status = 1
                    """, providerTransactionNo(data), code, HuifuPaymentPayload.message(data), refund.get("id"));
                    """, providerTransactionNo(data), code, HuifuPayload.message(data), refund.get("id"));
            // 通道确认退款成功是最终事实:订单级退款状态无条件收敛为已退款。
            orderFundBoundary.markRefunded(orderId);
            jdbc.update("""
@@ -132,12 +133,12 @@
                      and o.pay_amount <= (select coalesce(sum(r.refund_amount), 0) from order_refund r where r.order_id = o.id and r.refund_status = 2 and r.deleted = 0)
                    """, refund.get("orderId"));
            updateEvent(refundNo, "PROCESSED");
        } else if (HuifuPaymentPayload.terminalFailure(transStatus, code)) {
        } else if (HuifuPayload.terminalFailure(transStatus, code)) {
            int failed = jdbc.update("""
                    update order_refund
                    set provider_response_code = ?, provider_response_message = ?, refund_status = 3
                    where id = ? and refund_status = 1
                    """, code, HuifuPaymentPayload.message(data), refund.get("id"));
                    """, code, HuifuPayload.message(data), refund.get("id"));
            // 只有本事务真的把退款置为失败,才把订单退回未退款状态;否则会覆盖并发的退款成功。
            if (failed == 1) orderFundBoundary.markRefundFailed(orderId);
            updateEvent(refundNo, "REFUND_FAILED");
@@ -146,7 +147,7 @@
                    update order_refund
                    set provider_response_code = ?, provider_response_message = ?
                    where id = ? and refund_status = 1
                    """, code, HuifuPaymentPayload.message(data), refund.get("id"));
                    """, code, HuifuPayload.message(data), refund.get("id"));
            updateEvent(refundNo, "PENDING_QUERY");
        }
        return true;
@@ -179,8 +180,8 @@
                """, PROVIDER, requestNo);
        if (rows.isEmpty()) return false;
        Map<String, Object> event = rows.get(0);
        return payloadHash.equals(HuifuPaymentPayload.text(event.get("payloadSha256")))
                && TERMINAL_EVENT_STATUSES.contains(HuifuPaymentPayload.text(event.get("processStatus")));
        return payloadHash.equals(HuifuPayload.text(event.get("payloadSha256")))
                && TERMINAL_EVENT_STATUSES.contains(HuifuPayload.text(event.get("processStatus")));
    }
    private void upsertEvent(String requestNo, String payloadHash, String status) {
@@ -199,7 +200,7 @@
    }
    private String providerTransactionNo(Map<String, Object> data) {
        return HuifuPaymentPayload.value(data, "hf_seq_id", "bank_order_no", "hfSeqId");
        return HuifuPayload.value(data, "hf_seq_id", "bank_order_no", "hfSeqId");
    }
    private String acknowledgement(String requestNo) {