收藏
回答

微信支付API-V3 怎样获取返回前端的paySign签名

我的操作流程

1.用官方sdk发送请求获取到prepay_id,但是sdk内并没有看到获取paySign签名的方法(返回前端用于拉起微信支付)

// 读取证书私钥
PrivateKey privateKey = PemUtil.loadPrivateKey(new ClassPathResource("apiclient_key.pem").getInputStream());

// 读取平台证书(验签)
X509Certificate certificate = PemUtil.loadCertificate(
    new ClassPathResource("wechatpay_774380E742E4F04BFCFA2804DA234160D8093CE3.pem").getInputStream());
List<X509Certificate> certificates = Arrays.asList(certificate);

// 生成请求签名
WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
    .withMerchant(WxConstants.PAY_MCH_ID, WxConstants.PAY_SERIAL_NO, privateKey).withWechatpay(certificates);

2.生成paySign签名的方法(下段代码)

public static String getSign(String nonceStr, long timestamp, String body, String serialPath) {
    // 请求路径
    HttpUrl url = HttpUrl.parse("https://api.mch.weixin.qq.com/v3/certificates");
    // 组装需要签名的数据
    String message = buildMessage("GET", url, timestamp, nonceStr, body);
    // 使用私钥对数据进行签名(加密),【数据签名之后需要转换为字节数组(采用utf-8)】
    String signature = null;
    try {
        signature = sign(message.getBytes("utf-8"), serialPath);
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    return signature;
}

private static String sign(byte[] message, String serialPath) {
    try {
        // 签名方式(固定SHA256withRSA)
        Signature sign = Signature.getInstance("SHA256withRSA");
        // 使用私钥进行初始化签名(私钥需要从私钥文件【证书】中读取)
        sign.initSign(getPrivateKey(serialPath));
        // 签名更新
        sign.update(message);
        // 对签名结果进行Base64编码
        return Base64.getEncoder().encodeToString(sign.sign());
    } catch (SignatureException | InvalidKeyException | NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    return null;
}

private static String buildMessage(String method, HttpUrl url, long timestamp, String nonceStr, String body) {
    String canonicalUrl = url.encodedPath();
    if (url.encodedQuery() != null) {
        canonicalUrl += "?" + url.encodedQuery();
    }
    return method + "\n" + canonicalUrl + "\n" + timestamp + "\n" + nonceStr + "\n" + body + "\n";
}

3.其中body参数传入空串或返还前端JSONObject的json串都有试过,都是在调起微信支付时弹窗提示支付验证签名失败

// 返回前端数据
JSONObject payMap = new JSONObject();
payMap.put("appId", WxConstants.OFFICIAL_APPID);
long timestamp = System.currentTimeMillis() / 1000;
payMap.put("timeStamp", timestamp + "");
String nonceStr = WXPayUtil.generateNonceStr();
payMap.put("nonceStr", nonceStr);
payMap.put("package", "prepay_id=" + prepay_id);
payMap.put("signType", "RSA");

// 生成请求签名
String jsonStr = new JSONObject(payMap).toJSONString();
String paySign = WxV3Authorization.getSign(nonceStr, timestamp, jsonStr, "apiclient_key.pem");
System.out.println("paySign:" + paySign);
payMap.put("paySign", paySign);

4.生成签名样例

paySign:u/QxdeRo0+nalos8j+phrLLFCiygdXHa7RuushwG0QzgodrG+nfLKFoLDK77ojkNzdtB7yqySHriig90qjcZ8XhSOYAQ6WMRPWBhtJ+XgLJgrSk6kvDVXZ0YaDVa12jfruggYdK2lCaimuY0L6mxMdiwhxqWDIkyZadmh0N/nDPN/k+6Mjj8k2G6Gy6k0Nnlu+zldDclUwxPoKwNLYRUfTxZUho/8CQq/BlTIhDR+aGueZGu/dzfDOpxLHthTc3M00LNQtv4O7iT50Hgunqkug7ltS1Y63IUj+n/zMvDKTq3SONMo8XOilZrreRjXi4JbuLGWYIVR0XADz3+dik4mw==

5.错误截图

第一次发帖排版不好大家见谅,望各位大佬

回答关注问题邀请回答
收藏

3 个回答

  • 微信支付技术助手8
    微信支付技术助手8
    10-27

    参考V3签名文档https://wechatpay-api.gitbook.io/wechatpay-api-v3/


    10-27
    有用
    回复 1
    • 星火
      星火
      10-27
      您好,我就是看文档用的文档的签名生成方法鸭(但是文档是生成整个认证请求头的,我把拼参数部分去了直接返回signature值),是哪里操作的不对吗,传过去的body文档上说要空串,那怎么根据prepay_id及apikeyV3的秘钥生成paySign鸭,看文档生成签名的方法没有地方传这俩参数进去
      10-27
      回复
  • 星火
    星火
    10-28

    已解决,paySign生成签名拼的参数与请求头的不同

    10-28
    有用
    回复
  • 老张
    老张
    10-27

    paySign和统一下单的签名是同一个函数;

    我只有node的:

    function getSign(parts = [], key, str = '') {
      parts.forEach(v => str += v + '\n')
      return crypto.createSign('RSA-SHA256').update(str).sign(key, 'base64')
    }
    
    10-27
    有用
    回复 1
    • 星火
      星火
      10-27
      hhh蟹蟹啦,我想要java后端的
      10-27
      回复
登录 后发表内容
问题标签