收藏
回答

微信支付V3回调解密错误(测试正常,上线失败)

引入的SDK版本

<dependency>
    <groupId>com.github.wechatpay-apiv3</groupId>
    <artifactId>wechatpay-java</artifactId>
    <version>0.2.12</version>
</dependency>


加密config(pem文件在resources下)

private Config getConfig() {
    if(config == null){
        PrivateKey privateKey = getPrivateKey("wechatpay/apiclient_key.pem");
        config = new RSAAutoCertificateConfig.Builder()
                        .merchantId(properties.getMch().getMchId())
                        .privateKey(privateKey)
                        .merchantSerialNumber(properties.getMch().getMchSn())
                        .apiV3Key(properties.getMch().getApiV3Key())
                        .build();
    }
    return config;
}


解密config(pem文件在resources下)

public NotificationConfig getNotificationConfig() {
    if(notificationConfig == null){
        PrivateKey privateKey = getPrivateKey("wechatpay/apiclient_key.pem");
        notificationConfig = new RSAAutoCertificateConfig.Builder()
                .merchantId(properties.getMch().getMchId())
                .privateKey(privateKey)
                .merchantSerialNumber(properties.getMch().getMchSn())
                .apiV3Key(properties.getMch().getApiV3Key())
                .build();
    }
    return notificationConfig;
}


***问题:

测试环境:用natapp内网穿透映射的回调地址,回调解密正常

生产环境:用nginx代理的回调地址,回调解密失败

错误信息(****是我打的码):

com.wechat.pay.java.core.exception.ValidationException: Processing WechatPay notification,signature verification failed,signType[WECHATPAY2-SHA256-RSA2048]     serial[7D816CEC414164CF1C9899187865763F3******]        message[1725464137
1kfL1LvqkBsHt715Tvr54Iz******
{"id":"2954fad7-e7d0-51e9-baf9-6ca*******","create_time":"2024-09-04T23:35:37+08:00","resource_type":"encrypt-resource","event_type":"TRANSACTION.SUCCESS","summary":"鏀粯鎴愬姛","resource":{"original_type":"transaction","algorithm":"AEAD_AES_256_GCM","ciphertext":"6zJ+yFafNx+Rr3Z3qn2W1Na4gvhHSMdKl5NlDO1Up5BI1JP7hW0uiJd2EMkq/7Xem3y9b2jteJXxuhDN/aeoss2lXB1WlXHedOVq3W0ZOMbWZp5oqnF/S1fPFgbrPCRe8k2011xUAmTaHZEzjZd9mDm0iuDQTjx4W2Am9hfH8vCNlE9TJPF2yyFji7A6ue0Xf3sWAQJi2Wla1AxtoOOZVRvnH4Ook3cj1lkKOnhDqHQJNyeoDiRvGsHW/I3axTkSGAJUT3UEmhArfqvD5IeubQLCXPVUD2dATmnWtb0HMVdO+ZTlgT62RTMJ0EAmN4xvTQMxqAJW9/YJ/44siBWpT84Wa6P4g427r5KnRtrGK0Lr+Ny6kuV+mEG4RE76jsHbized6YiB1CgKogBG52psX7RTBGg9IdRufQ791yhGXx1frc28k6uCyJUG***********xhyB
iI+96+QQ9AXHqKJq0UY+04qfo1Xs7yzXZVPnCiqpv+LN1PY3*******","associated_data":"transaction","nonce":"6uiyqNHQ****"}}
]       sign[C1JY8Jf+VeYmbALKx9qcUSBF8Vsj430YK8o+TonodqkNRegv7X**********3RAOd1Gu+K+DCJLg+D847v2pcoF7cv6tm0f+ES2a+86acT3XDELVYFIGV8ZbODg4vKoahLC2BfvKzPPayo+KUh2845nz0N1vhY4SHRUqV3hXbukuLljaaniDljRl24iXtrZkSn1FKH0aq8T1/hIILU6zNxkDjQGcBl8rMktARCRx0JUmAJwkwCZOcGiJ+NyrIO9R++YJGbET9uAm1iOuOJUwLOneeLUh+nDVpL9IvyUlBAtHF1LNtH5sAOWpbTFtLHYD/5+gYPY8IAmDw==]
回答关注问题邀请回答
收藏

1 个回答

  • Memory (私信不回复)
    Memory (私信不回复)
    09-05

    summary字段乱码了导致的,编码问题导致

    09-05
    有用 1
    回复 10
    • ziho
      ziho
      09-05
      同一套代码,那为什么测试环境没有编码问题,生产环境就有呢,是因为nginx吗?
      09-05
      回复
    • Memory (私信不回复)
      Memory (私信不回复)
      09-05回复ziho
      那得问你代码咋写的啊,和nginx没关系
      09-05
      回复
    • ziho
      ziho
      09-05
      /**
           * 【微信支付】回调地址
           * <p>
           * request 请求体
           * response 响应体
           */
          @RequestMapping(value = "callback")
          public ResponseEntity.BodyBuilder callBack(HttpServletRequest request) throws IOException {
              //读取请求体的信息
              ServletInputStream inputStream = request.getInputStream();
              StringBuffer stringBuffer = new StringBuffer();
              BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
              String s;
              //读取回调请求体
              while ((s = bufferedReader.readLine()) != null) {
                  stringBuffer.append(s);
              }
              String requestBody = stringBuffer.toString();
              String timestamp = request.getHeader(WECHAT_PAY_TIMESTAMP);
              String nonce = request.getHeader(WECHAT_PAY_NONCE);
              String serialNo = request.getHeader(WECHAT_PAY_SERIAL);
              String signature = request.getHeader(WECHAT_PAY_SIGNATURE);
              //请求参数
              RequestParam requestParam = new RequestParam.Builder()
                      .signType("WECHATPAY2-SHA256-RSA2048")
                      .serialNumber(serialNo)
                      .nonce(nonce)
                      .signature(signature)
                      .timestamp(timestamp)
                      .body(requestBody)
                      .build();
              // 初始化 NotificationParser
              NotificationParser parser = new NotificationParser(wechatPayService.getNotificationConfig());
              try {
                  // 以支付通知回调为例,验签、解密并转换成 Transaction
                  Transaction transaction = parser.parse(requestParam, Transaction.class);
                  StaticLog.info("【微信支付回调】回调信息:"+transaction);
                  if(transaction != null){
                      WechatPayCallbackPO callbackPO = new WechatPayCallbackPO();
                      BeanUtil.copyProperties(transaction, callbackPO);
                      callbackPO.setCreateTime(new Date());
                      wechatPayCallbackService.save(callbackPO);
                  }
                  WechatPayOrderPO order = wechatPayOrderService.findById(transaction.getOutTradeNo());
                  if(order == null){
                      StaticLog.error("【微信支付回调】异常:订单不存在");
                      return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR);
                  }
                  switch (transaction.getTradeState()){
                      case SUCCESS:
                          order.setWechatOrderId(transaction.getTransactionId());
                          order.setPayTime(DateUtil.parseUTC(transaction.getSuccessTime()));
                          order.setPayStatus(WechatPayOrderStatusEnum.支付成功);
                          StaticLog.info("【微信支付回调】订单:{}=支付成功",order.getWechatOrderId());
                          if(order.getBusiness() != null){
                              switch (order.getBusiness()){
                                  case 订货订单:
                                      OrderDetailPO orderDetail = orderDetailService.findById(order.getBusinessId());
                                      if(orderDetail == null){
                                          StaticLog.error("【微信支付回调】异常:订货订单不存在");
                                          return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR);
                                      }
                                      orderDetail.setOrderPayAmount(order.getPayAmount());
                                      orderDetail.setAmountReceivable(order.getPayAmount());
                                      orderDetail.setConfirmStatus(OrderStatusEnum.审核通过);
                                      orderDetailService.save(orderDetail);
                                      StaticLog.info("【微信支付回调】订货订单:{}=更新成功",orderDetail.getOrderCode());
                                      break;
                                  default:
                                      break;
                              }
                          }
                          break;
                      case NOTPAY:
                          order.setPayStatus(WechatPayOrderStatusEnum.未支付);
                          StaticLog.info("【微信支付回调】订单:{}=未支付",order.getWechatOrderId());
                          break;
                      case CLOSED:
                          order.setPayStatus(WechatPayOrderStatusEnum.已关闭);
                          StaticLog.info("【微信支付回调】订单:{}=已关闭",order.getWechatOrderId());
                          break;
                      case PAYERROR:
                          order.setPayStatus(WechatPayOrderStatusEnum.支付失败);
                          StaticLog.info("【微信支付回调】订单:{}=支付失败",order.getWechatOrderId());
                          break;
                  }
                  wechatPayOrderService.save(order);
              } catch (ValidationException e) {
                  // 签名验证失败,返回 401 UNAUTHORIZED 状态码
                  e.printStackTrace();
                  return ResponseEntity.status(HttpStatus.UNAUTHORIZED);
              }
              // 处理成功,返回 200 OK 状态码
              return ResponseEntity.status(HttpStatus.OK);
          }
      09-05
      回复
    • Memory (私信不回复)
      Memory (私信不回复)
      09-05回复ziho
      还需要检查一下你是不是参数压缩了,导致编码没生效
      09-05
      回复
    • ziho
      ziho
      09-05
      可是在idea上运行没问题,回调过来也正常验签解密(内网穿透)
      09-05
      回复
    查看更多(5)
登录 后发表内容