Sfoglia il codice sorgente

fix: openBusinessView 签名改用 APIv2 密钥,末尾拼接 &key

微信支付V2签名规范要求:
1. 使用 APIv2 密钥(非 APIv3 密钥)
2. 签名字符串末尾追加 &key={apiV2Key}
3. HMAC-SHA256 大写十六进制输出

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
skyline 1 settimana fa
parent
commit
b52e00d380

+ 1 - 0
haha-admin/src/main/resources/application.yml

@@ -91,6 +91,7 @@ wechat:
     app-id: wxb1cbe4678e0175f2 # 小程序appid
     mch-id: 1108941936 # 商户号
     v3-api-key: 7P5nbvnQpfj6cXpWrywtYstvJk5frjdK
+    api-v2-key: # TODO: 请填写商户平台-API安全中的APIv2密钥(32位),用于 openBusinessView 签名
     notify-url: https://dev-haha.kuaiyuman.cn/api/payment/callback/wechat
     private-key-path: classpath:cert/apiclient_key.pem
     merchant-serial-number: 58F965A745DF42AA4C8603EE6B2B663E1B100553

+ 1 - 0
haha-miniapp/src/main/resources/application.yml

@@ -67,6 +67,7 @@ wechat:
     app-id: wxb1cbe4678e0175f2 # 小程序appid
     mch-id: 1108941936 # 商户号
     v3-api-key: 7P5nbvnQpfj6cXpWrywtYstvJk5frjdK
+    api-v2-key: # TODO: 请填写商户平台-API安全中的APIv2密钥(32位),用于 openBusinessView 签名
     notify-url: https://dev-haha.kuaiyuman.cn/api/payment/callback/wechat
     private-key-path: classpath:cert/apiclient_key.pem
     merchant-serial-number: 58F965A745DF42AA4C8603EE6B2B663E1B100553

+ 3 - 0
haha-service/src/main/java/com/haha/service/payment/config/WxPayConfig.java

@@ -42,6 +42,9 @@ public class WxPayConfig {
 
     /** API V3 密钥 */
     private String v3ApiKey;
+
+    /** API V2 密钥(32位,用于 openBusinessView 等前端 JSAPI 签名) */
+    private String apiV2Key;
     
     /** 支付结果回调通知地址 */
     private String notifyUrl;

+ 9 - 5
haha-service/src/main/java/com/haha/service/payment/payscore/impl/PayScoreServiceImpl.java

@@ -909,28 +909,32 @@ public class PayScoreServiceImpl implements PayScoreService {
         if (wxPayConfig == null) {
             throw new IllegalStateException("微信支付未配置");
         }
+        String apiV2Key = wxPayConfig.getApiV2Key();
+        if (apiV2Key == null || apiV2Key.isEmpty()) {
+            throw new IllegalStateException("APIv2密钥未配置,请在商户平台-API安全中设置APIv2密钥");
+        }
 
         String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
         String nonceStr = generateNonceStr(32);
         String signType = "HMAC-SHA256";
 
-        // 按 key 字典序拼接: mch_id, nonce_str, out_order_no, service_id, sign_type, timestamp
+        // 按 key 字典序拼接,末尾追加 &key={APIv2密钥}(微信支付V2签名规范)
         String signMessage = "mch_id=" + wxPayConfig.getMchId() + "&"
                 + "nonce_str=" + nonceStr + "&"
                 + "out_order_no=" + outTradeNo + "&"
                 + "service_id=" + wxPayConfig.getServiceId() + "&"
                 + "sign_type=" + signType + "&"
-                + "timestamp=" + timestamp;
+                + "timestamp=" + timestamp
+                + "&key=" + apiV2Key;
 
         String sign;
         try {
             Mac mac = Mac.getInstance("HmacSHA256");
-            byte[] keyBytes = wxPayConfig.getV3ApiKey().getBytes(StandardCharsets.UTF_8);
+            byte[] keyBytes = apiV2Key.getBytes(StandardCharsets.UTF_8);
             SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "HmacSHA256");
             mac.init(secretKey);
             byte[] signBytes = mac.doFinal(signMessage.getBytes(StandardCharsets.UTF_8));
-            // openBusinessView 签名要求大写十六进制,不是 Base64
-            // byte 转无符号防止负值输出 8 位 hex
+            // 输出大写十六进制
             StringBuilder sb = new StringBuilder();
             for (byte b : signBytes) {
                 sb.append(String.format("%02X", b & 0xFF));