Quellcode durchsuchen

微信回调验签测试

skyline vor 2 Jahren
Ursprung
Commit
bcae9810aa

+ 18 - 64
service/src/main/java/com/kym/service/wechat/impl/WxPayServiceImpl.java

@@ -161,70 +161,16 @@ public class WxPayServiceImpl implements WxPayService {
         wxHttpClient = (OkHttpClientAdapter) new DefaultHttpClientBuilder().newInstance().config(config).build();
     }
 
-
-    /**
-     * 处理微信回调信息,验签解密
-     *
-     * @param request
-     * @return array[0] RequestParam 请求参数
-     * array[1] NotificationParser 通知解析器
-     * array[2] nonce 随机数
-     */
-    @SneakyThrows
-    Object[] handleWxNotify(HttpServletRequest request) {
-        var no = RandomUtil.randomInt(1000, 9999);
-        var signature = request.getHeader("Wechatpay-Signature");
-        var serial = request.getHeader("Wechatpay-Serial");
-        var nonce = request.getHeader("Wechatpay-Nonce");
-        var timestamp = request.getHeader("Wechatpay-Timestamp");
-        var signatureType = request.getHeader("Wechatpay-Signature-Type");
-
-        LOGGER.info("微信支付回调{}:\n Request参数:\n signature:{},serial:{},nonce:{},timestamp:{},signatureType:{}", no, signature, serial, nonce, timestamp, signatureType);
-
-        // request中获取body
-//        BufferedReader br = request.getReader();
-//        String str;
-//        var requestBody = new StringBuilder();
-//        while ((str = br.readLine()) != null) {
-//            requestBody.append(str);
-//        }
-
-        ServletInputStream inputStream = request.getInputStream();
-        ByteArrayOutputStream result = new ByteArrayOutputStream();
-        byte[] buffer = new byte[1024];
-        for (int lenght; (lenght = inputStream.read(buffer)) != -1; ) {
-            result.write(buffer, 0, lenght);
-        }
-
-
-        LOGGER.info("微信支付回调{}:\nBody数据:\n{}", no, result);
-
-        // 构造 RequestParam
-        RequestParam requestParam = new RequestParam.Builder()
-                .serialNumber(serial)
-                .nonce(nonce) // 随机数
-                .signature(signature)
-                .timestamp(timestamp)
-                .body(result.toString(StandardCharsets.UTF_8))
-                .build();
-        LOGGER.info("微信支付回调{}:构造 RequestParam完毕", no);
-
-        // 如果已经初始化了 RSAAutoCertificateConfig,可直接使用
-        // 初始化 NotificationParser
-        NotificationParser parser = new NotificationParser((NotificationConfig) config);
-        return new Object[]{requestParam, parser, no};
-    }
-
-
     /**
      * 回调签名验证失败排查指引 (body中字段顺序变化造成验签失败是个大坑)
      * https://developers.weixin.qq.com/community/pay/article/doc/0004a879f60928d89340b8b9f64c13
      * https://github.com/wechatpay-apiv3/wechatpay-apache-httpclient/issues/152
+     *
      * @param request
      * @return
      */
     @SneakyThrows
-    Object[] handleWxNotify2(HttpServletRequest request) {
+    Object[] handleWxNotify(HttpServletRequest request) {
         var no = RandomUtil.randomInt(1000, 9999);
         var signature = request.getHeader("Wechatpay-Signature");
         var serial = request.getHeader("Wechatpay-Serial");
@@ -232,6 +178,11 @@ public class WxPayServiceImpl implements WxPayService {
         var timestamp = request.getHeader("Wechatpay-Timestamp");
         var signatureType = request.getHeader("Wechatpay-Signature-Type");
 
+        // 应对探测流量
+        if (signature.contains("SIGNTEST")) {
+            throw new BusinessException("接收到签名探测流量");
+        }
+
         LOGGER.info("微信支付回调{}:\n Request参数:\n signature:{},serial:{},nonce:{},timestamp:{},signatureType:{}", no, signature, serial, nonce, timestamp, signatureType);
 
         ServletInputStream inputStream = request.getInputStream();
@@ -337,9 +288,8 @@ public class WxPayServiceImpl implements WxPayService {
     @Transactional(rollbackFor = Exception.class)
     public ResponseEntity<Object> wxNotify(HttpServletRequest request) {
 
-        var notifyRes = handleWxNotify(request);
-
         try {
+            var notifyRes = handleWxNotify(request);
             // 以支付通知回调为例,验签、解密并转换成 Transaction
             Transaction transaction = ((NotificationParser) notifyRes[1]).parse((RequestParam) notifyRes[0], Transaction.class);
             LOGGER.info("微信支付回调{}:验签解密完毕,数据:\n{}", notifyRes[2], transaction);
@@ -394,16 +344,20 @@ public class WxPayServiceImpl implements WxPayService {
                     activityService.handleRechargeActivity(chargingOrder.getUserId(), transaction.getAmount().getTotal());
                 }
 
-
                 return ResponseEntity.status(HttpStatus.OK).build();
 
             } else {
                 LOGGER.error("微信支付通知处理异常,资金流水为空,回调信息:{}", transaction);
                 return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(Map.of("code", HttpStatus.INTERNAL_SERVER_ERROR, "message", "资金流水为空"));
             }
-        } catch (ValidationException e) {
-            // 签名验证失败,返回 401 UNAUTHORIZED 状态码
-            LOGGER.error("微信支付通知验签失败", e);
+        } catch (Exception e) {
+            if (e instanceof ValidationException) {
+                // 签名验证失败,返回 401 UNAUTHORIZED 状态码
+                LOGGER.error("微信支付通知验签失败", e);
+            }
+            if (e instanceof BusinessException) {
+                LOGGER.error("业务异常", e);
+            }
             return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(Map.of("code", HttpStatus.UNAUTHORIZED, "message", "验签失败"));
         }
     }
@@ -851,7 +805,7 @@ public class WxPayServiceImpl implements WxPayService {
      * 微信开票结果通知
      * event_tyoe为FAPIAO.ISSUED
      *
-     * @param request
+     * @param notifyRes
      * @return
      */
     @Override
@@ -880,7 +834,7 @@ public class WxPayServiceImpl implements WxPayService {
      */
     @Override
     public void invoiceNotify(HttpServletRequest request) {
-        var notifyRes = handleWxNotify2(request);
+        var notifyRes = handleWxNotify(request);
         var requestParam = (RequestParam) notifyRes[0];
         Notification notification = JSONObject.parseObject(requestParam.getBody(), Notification.class);
         switch (notification.getEventType()) {