yeg
2026-09-16 8fe2249e07ebe15b33e0231cd9dafa7c303486f6
talent-card-server/src/main/java/com/talentcard/server/business/payment/HuifuPaymentService.java
@@ -9,6 +9,8 @@
import com.alibaba.fastjson.JSON;
import com.talentcard.server.business.BusinessIdGenerator;
import com.talentcard.server.business.DatabaseRows;
import com.talentcard.server.business.payment.PaymentReconciliationService.PendingPaymentConfirmation;
import com.talentcard.server.business.payment.PaymentReconciliationService.PendingPaymentState;
import com.talentcard.server.business.payment.huifu.HuifuMiniProgramPaymentCommand;
import com.talentcard.server.business.payment.huifu.HuifuMiniProgramPaymentGateway;
import com.talentcard.server.business.payment.huifu.HuifuPaymentGatewayException;
@@ -29,18 +31,28 @@
    private final JdbcTemplate jdbc;
    private final TransactionTemplate transactions;
    private final HuifuMiniProgramPaymentGateway gateway;
    private final PaymentReconciliationService reconciliationService;
    public HuifuPaymentService(
            JdbcTemplate jdbc,
            TransactionTemplate transactions,
            HuifuMiniProgramPaymentGateway gateway
            HuifuMiniProgramPaymentGateway gateway,
            PaymentReconciliationService reconciliationService
    ) {
        this.jdbc = jdbc;
        this.transactions = transactions;
        this.gateway = gateway;
        this.reconciliationService = reconciliationService;
    }
    public Map<String, Object> beginMiniProgramPayment(String orderNo, Long talentId, int priceVersion, String idempotencyKey) {
        // 上一次支付可能已经被通道收下、回调却没到。那笔钱必须先落成本地已支付:否则这里会再发起一次
        // 支付(同一笔订单付第二次),或者把用户送进「订单已经支付,请勿重复发起支付」的死胡同。
        PendingPaymentConfirmation confirmation = reconciliationService.confirmPendingPayments(orderNo);
        if (confirmation.collected()) return completedResult(confirmation.paymentNo());
        if (confirmation.state() == PendingPaymentState.UNCONFIRMED) {
            throw new BusinessException(ErrorCode.CONFLICT, "支付结果确认中,请稍后再试");
        }
        PreparedPayment prepared = transactions.execute(status -> prepare(orderNo, talentId, priceVersion, idempotencyKey));
        if (prepared == null) throw new BusinessException(ErrorCode.INTERNAL_ERROR, "支付初始化失败");
        if (prepared.completed()) return completedResult(prepared.paymentNo());
@@ -186,6 +198,10 @@
        Map<String, Object> order = orders.get(0);
        if (number(order.get("orderStatus")) == 1) return completedResult(paymentNo == null ? "" : paymentNo);
        // 回调没到、本地还停在待支付时,通道是唯一知道钱有没有收下的地方。问一次就能把状态收敛回来,
        // 人才端也就不会一直停在待支付页。
        PendingPaymentConfirmation confirmation = reconciliationService.confirmPendingPayments(orderNo);
        if (confirmation.collected()) return completedResult(confirmation.paymentNo());
        String filter = paymentNo == null || paymentNo.isBlank() ? "" : " and payment_no = ?";
        Object[] args = paymentNo == null || paymentNo.isBlank()
@@ -258,7 +274,7 @@
    private String statusText(String status) {
        return switch (status) {
            case "SUCCEEDED" -> "PAID";
            case "CLOSED" -> "CANCELLED";
            case "CLOSED", "CANCEL_UNCONFIRMED" -> "CANCELLED";
            case "CREATE_FAILED" -> "PAYMENT_CREATE_FAILED";
            case "CREATED", "PREPAY_CREATED" -> "PAYMENT_PENDING";
            case "CREATE_UNKNOWN" -> "PAYMENT_CONFIRMING";