shinnosuke
2026-08-06 e5c6b415449d0b7a5e9027dba009e46543004dc0
talent-card-server/src/main/java/com/talentcard/server/business/payment/HuifuPaymentService.java
@@ -47,7 +47,7 @@
        Map<String, Object> response;
        try {
            response = gateway.createMiniProgramPayment(new HuifuMiniProgramPaymentCommand(
                    prepared.paymentNo(), prepared.huifuId(), prepared.openId(), prepared.amountInCent(), prepared.goodsDescription(), prepared.expiresAt()));
                    prepared.paymentNo(), prepared.openId(), prepared.amountInCent(), prepared.goodsDescription(), prepared.expiresAt()));
        } catch (HuifuPaymentGatewayException exception) {
            if (exception.isOutcomeUnknown()) {
                transactions.executeWithoutResult(status -> markCreateUnknown(prepared.paymentNo(), "GATEWAY_UNKNOWN", exception.getMessage()));
@@ -79,14 +79,7 @@
        List<Map<String, Object>> orders = rows("""
                select o.id, o.order_no, o.talent_id, o.merchant_id, o.store_id, o.pay_amount, o.order_status, o.price_version,
                       o.expires_at, coalesce(o.product_name_snapshot, o.order_type, '人才权益服务') goods_description,
                       t.openid,
                       coalesce((select a.provider_huifu_id
                                 from merchant_onboarding_application a
                                 where a.merchant_id = o.merchant_id
                                   and a.status = 'approved'
                                   and a.provider_huifu_id is not null
                                   and trim(a.provider_huifu_id) <> ''
                                 order by a.id desc limit 1), '') provider_huifu_id
                       t.openid
                from benefit_order o
                join talent_user t on t.id = o.talent_id and t.deleted = 0
                where o.deleted = 0 and o.order_no = ? and o.talent_id = ?
@@ -95,7 +88,7 @@
        if (orders.isEmpty()) throw new BusinessException(ErrorCode.NOT_FOUND, "订单不存在或无权支付");
        Map<String, Object> order = orders.get(0);
        long payAmount = number(order.get("payAmount"));
        if (number(order.get("orderStatus")) == 1) return new PreparedPayment("", "", "", 0, "", LocalDateTime.now(), false, true, "", false);
        if (number(order.get("orderStatus")) == 1) return new PreparedPayment("", "", 0, "", LocalDateTime.now(), false, true, "", false);
        if (number(order.get("orderStatus")) != 0) throw new BusinessException(ErrorCode.CONFLICT, "订单当前不可支付");
        if (number(order.get("priceVersion")) != priceVersion) throw new BusinessException(ErrorCode.CONFLICT, "订单金额已更新,请重新确认");
        LocalDateTime expiresAt = localDateTime(order.get("expiresAt"));
@@ -107,12 +100,10 @@
                        verify_status = case when order_type = 'STORE_CONSUME' then 1 else verify_status end
                    where id = ? and order_status = 0
                    """, number(order.get("id")));
            return new PreparedPayment("", "", "", 0, "", LocalDateTime.now(), false, true, "", false);
            return new PreparedPayment("", "", 0, "", LocalDateTime.now(), false, true, "", false);
        }
        String openId = string(order.get("openid"));
        if (openId.isBlank()) throw new BusinessException(ErrorCode.CONFLICT, "当前用户未完成微信支付授权");
        String huifuId = string(order.get("providerHuifuId"));
        if (huifuId.isBlank()) throw new BusinessException(ErrorCode.CONFLICT, "商户汇付商户号未配置或尚未审核通过");
        List<Map<String, Object>> existingRows = rows("""
                select payment_no, order_no, talent_id, status, attempt_no, client_payment_payload
@@ -128,22 +119,22 @@
            }
            String status = string(existing.get("status"));
            String paymentNo = string(existing.get("paymentNo"));
            if ("SUCCEEDED".equals(status)) return new PreparedPayment(paymentNo, "", "", 0, "", LocalDateTime.now(), false, true, "", false);
            if ("SUCCEEDED".equals(status)) return new PreparedPayment(paymentNo, "", 0, "", LocalDateTime.now(), false, true, "", false);
            if ("PREPAY_CREATED".equals(status)) {
                return new PreparedPayment(paymentNo, "", "", 0, "", LocalDateTime.now(), false, false, string(existing.get("clientPaymentPayload")), false);
                return new PreparedPayment(paymentNo, "", 0, "", LocalDateTime.now(), false, false, string(existing.get("clientPaymentPayload")), false);
            }
            if ("CREATED".equals(status) || "CREATE_UNKNOWN".equals(status)) {
                return new PreparedPayment(paymentNo, "", "", 0, "", LocalDateTime.now(), false, false, "", true);
                return new PreparedPayment(paymentNo, "", 0, "", LocalDateTime.now(), false, false, "", true);
            }
            int nextAttempt = (int) number(existing.get("attemptNo")) + 1;
            String retryPaymentNo = BusinessIdGenerator.next("P");
            insertPaymentTransaction(retryPaymentNo, order, orderNo, talentId, payAmount, idempotencyKey, nextAttempt);
            return new PreparedPayment(retryPaymentNo, huifuId, openId, payAmount, string(order.get("goodsDescription")), expiryOrDefault(expiresAt), true, false, "", false);
            return new PreparedPayment(retryPaymentNo, openId, payAmount, string(order.get("goodsDescription")), expiryOrDefault(expiresAt), true, false, "", false);
        }
        String paymentNo = BusinessIdGenerator.next("P");
        insertPaymentTransaction(paymentNo, order, orderNo, talentId, payAmount, idempotencyKey, 1);
        return new PreparedPayment(paymentNo, huifuId, openId, payAmount, string(order.get("goodsDescription")), expiryOrDefault(expiresAt), true, false, "", false);
        return new PreparedPayment(paymentNo, openId, payAmount, string(order.get("goodsDescription")), expiryOrDefault(expiresAt), true, false, "", false);
    }
    private void insertPaymentTransaction(
@@ -336,7 +327,6 @@
    private record PreparedPayment(
            String paymentNo,
            String huifuId,
            String openId,
            long amountInCent,
            String goodsDescription,