Sfoglia il codice sorgente

优化代码,添加接口

liuchengsen 1 mese fa
parent
commit
95922ceb7a

+ 7 - 7
zhijiayun-gateway/src/main/resources/application-prod.yml

@@ -115,17 +115,17 @@ payment:
     # 公钥模式(优先):配置了 alipay-public-key 即走公钥模式
     app-private-key: ${ALIPAY_APP_PRIVATE_KEY:}
     alipay-public-key: ${ALIPAY_PUBLIC_KEY:}
-    # 证书模式(备选):未配置 alipay-public-key 时回退到证书模式,从 certs/dev/alipay/ 读取
-    app-private-key-path: ${ALIPAY_APP_PRIVATE_KEY_PATH:certs/dev/alipay/appPrivateKey.txt}
-    app-cert-path: ${ALIPAY_APP_CERT_PATH:certs/dev/alipay/appCertPublicKey_2021005187690877.crt}
-    alipay-cert-path: ${ALIPAY_CERT_PATH:certs/dev/alipay/alipayCertPublicKey_RSA2.crt}
-    alipay-root-cert-path: ${ALIPAY_ROOT_CERT_PATH:certs/dev/alipay/alipayRootCert.crt}
- # 微信支付(开发/测试环境):将测试商户证书文件复制到 certs/dev/wechat/ 目录下
+    # 证书模式(备选):未配置 alipay-public-key 时回退到证书模式,从 certs/prod/alipay/ 读取
+    app-private-key-path: ${ALIPAY_APP_PRIVATE_KEY_PATH:certs/prod/alipay/appPrivateKey.txt}
+    app-cert-path: ${ALIPAY_APP_CERT_PATH:certs/prod/alipay/appCertPublicKey_2021005187690877.crt}
+    alipay-cert-path: ${ALIPAY_CERT_PATH:certs/prod/alipay/alipayCertPublicKey_RSA2.crt}
+    alipay-root-cert-path: ${ALIPAY_ROOT_CERT_PATH:certs/prod/alipay/alipayRootCert.crt}
+ # 微信支付(开发/测试环境):将测试商户证书文件复制到 certs/prod/wechat/ 目录下
   wechat:
     app-id: ${WECHAT_PAY_APP_ID:wxf2f254f9981651dd}
     mch-id: ${WECHAT_PAY_MCH_ID:1612111355}
     api-v3-key: ${WECHAT_PAY_API_V3_KEY:iD1xB1mH6zO7pP2wD1rU4aD2nH7oL2lN}
-    # 三份证书文件(从微信支付商户平台下载,放入 certs/dev/wechat/):
+    # 三份证书文件(从微信支付商户平台下载,放入 certs/prod/wechat/):
     private-key-path: ${WECHAT_PAY_PRIVATE_KEY_PATH:certs/prod/wechat/apiclient_key.pem}         # 证书密钥pem(商户私钥)
     private-cert-path: ${WECHAT_PAY_PRIVATE_CERT_PATH:certs/prod/wechat/apiclient_cert.pem}      # 证书pem格式(商户证书)
     key-path: ${WECHAT_PAY_KEY_PATH:certs/prod/wechat/apiclient_cert.p12}                        # 证书pkcs12格式(密码默认为商户号)

+ 48 - 6
zhijiayun-payment/src/main/java/com/xuekairui/payment/service/PaymentOrderService.java

@@ -291,11 +291,42 @@ public class PaymentOrderService {
     private PrepayResult createPrepay(PaymentChannel channel, String orderNo,
                                       java.math.BigDecimal amount, String subject, String body) {
         return switch (channel) {
-            case WECHAT -> createWechatPrepay(orderNo, amount, subject);
+            case WECHAT -> createWechatPrepay(orderNo, amount, subject, body);
             case ALIPAY -> createAlipayPrepay(orderNo, amount, subject, body);
         };
     }
 
+    /**
+     * 构建微信支付 description,将商品标题与详细描述合并。
+     * 微信 Native 下单的 description 字段上限为 127 字节(UTF-8),超出时自动截断。
+     */
+    private String buildWechatDescription(String subject, String body) {
+        if (body == null || body.isBlank()) {
+            return truncateUtf8(subject, 127);
+        }
+        String combined = subject.trim() + " - " + body.trim();
+        return truncateUtf8(combined, 127);
+    }
+
+    /**
+     * 按 UTF-8 字节长度截断字符串,避免截断到多字节字符中间。
+     */
+    private String truncateUtf8(String value, int maxBytes) {
+        if (value == null) {
+            return "";
+        }
+        byte[] bytes = value.getBytes(java.nio.charset.StandardCharsets.UTF_8);
+        if (bytes.length <= maxBytes) {
+            return value;
+        }
+        int cut = maxBytes;
+        // 避免截断到多字节字符中间:向前回退直到是合法 UTF-8 起始字节
+        while (cut > 0 && (bytes[cut] & 0xC0) == 0x80) {
+            cut--;
+        }
+        return new String(bytes, 0, cut, java.nio.charset.StandardCharsets.UTF_8);
+    }
+
     /**
      * 微信Native支付预下单(API v3)
      *
@@ -303,7 +334,7 @@ public class PaymentOrderService {
      * 返回 codeUrl(二维码链接),前端可直接生成二维码展示。
      * 用户扫码后在微信App中完成付款,微信异步回调 notifyUrl。
      */
-    private PrepayResult createWechatPrepay(String orderNo, java.math.BigDecimal amount, String subject) {
+    private PrepayResult createWechatPrepay(String orderNo, java.math.BigDecimal amount, String subject, String body) {
         PaymentProperties.Wechat wc = paymentProperties.getWechat();
         if (wc.getAppId() == null || wc.getMchId() == null) {
             throw new BusinessException(ErrorCode.PAY_CHANNEL_NOT_CONFIGURED,
@@ -319,7 +350,7 @@ public class PaymentOrderService {
         try {
             WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request();
             request.setOutTradeNo(orderNo);
-            request.setDescription(subject);
+            request.setDescription(buildWechatDescription(subject, body));
             request.setNotifyUrl(wc.getNotifyUrl());
 
             // 金额单位为分
@@ -418,16 +449,27 @@ public class PaymentOrderService {
     }
 
     private OrderResponse toResponse(PaymentOrder order) {
+        PaymentPlan plan = paymentPlanService.getPlanById(order.getPlanId());
         String hint = PaymentStatus.PENDING.name().equals(order.getStatus())
                 ? "请在" + paymentProperties.getOrderExpireMinutes() + "分钟内完成付款,超时订单将自动过期" : null;
+
+        // 待支付订单补充二维码与支付链接,支持重新查询后继续支付
+        String qrCodeBase64 = null;
+        String payUrl = null;
+        if (PaymentStatus.PENDING.name().equals(order.getStatus())
+                && order.getQrCodeUrl() != null && !order.getQrCodeUrl().isBlank()) {
+            qrCodeBase64 = qrCodeService.generateBase64(order.getQrCodeUrl());
+            payUrl = order.getQrCodeUrl();
+        }
+
         return OrderResponse.builder()
                 .orderNo(order.getOrderNo())
-                .planName(null) // 由调用方补充
+                .planName(plan != null ? plan.getPlanName() : null)
                 .amount(order.getAmount())
                 .channel(order.getChannel())
                 .status(order.getStatus())
-                .qrCodeBase64(null)
-                .payUrl(null) // 查询场景不再返回,仅创建时提供
+                .qrCodeBase64(qrCodeBase64)
+                .payUrl(payUrl)
                 .expireTime(order.getExpireTime())
                 .expireHint(hint)
                 .createTime(order.getCreateTime())