URL 比如APP支付文档中为https://api.mch.weixin.qq.com/v3/pay/transactions/app,除去域名部分得到参与签名的URL。如果请求中有查询参数,URL末尾应附加有\'?\'和对应的查询字符串。这里为/v3/pay/transactions/app。
请求时间戳 服务器系统时间戳,保证服务器时间正确并利用System.currentTimeMillis() / 1000获取即可。
请求随机串 找个工具类生成类似593BEC0C930BF1AFEB40B4A08C8FB242的字符串就行了。
请求报文主体 如果是GET请求直接为空字符"" ;当请求方法为POST或PUT时,请使用真实发送的JSON报文。图片上传API,请使用meta对应的JSON报文。
生成签名然后我们使用商户私钥对按照上面格式的待签名串进行SHA256 with RSA签名,并对签名结果进行Base64编码得到签名值。对应的核心Java代码为:
/** * V3 SHA256withRSA 签名. * * @param method 请求方法 GET POST PUT DELETE 等 * @param canonicalUrl 例如 https://api.mch.weixin.qq.com/v3/pay/transactions/app?version=1 ——> /v3/pay/transactions/app?version=1 * @param timestamp 当前时间戳 因为要配置到TOKEN 中所以 签名中的要跟TOKEN 保持一致 * @param nonceStr 随机字符串 要和TOKEN中的保持一致 * @param body 请求体 GET 为 "" POST 为JSON * @param keyPair 商户API 证书解析的密钥对 实际使用的是其中的私钥 * @return the string */ @SneakyThrows String sign(String method, String canonicalUrl, long timestamp, String nonceStr, String body, KeyPair keyPair) { String signatureStr = Stream.of(method, canonicalUrl, String.valueOf(timestamp), nonceStr, body) .collect(Collectors.joining("\n", "", "\n")); Signature sign = Signature.getInstance("SHA256withRSA"); sign.initSign(keyPair.getPrivate()); sign.update(signatureStr.getBytes(StandardCharsets.UTF_8)); return Base64Utils.encodeToString(sign.sign()); } 4. 使用签名签名生成后会同一些参数组成一个Token放置到对应HTTP请求的Authorization请求头中,格式为:
Authorization: WECHATPAY2-SHA256-RSA2048 {Token}Token由以下五部分组成:
发起请求的商户(包括直连商户、服务商或渠道商)的商户号mchid
商户API证书序列号serial_no,用于声明所使用的证书
请求随机串nonce_str
时间戳timestamp
签名值signature
Token生成的核心代码:
/** * 生成Token. * * @param mchId 商户号 * @param nonceStr 随机字符串 * @param timestamp 时间戳 * @param serialNo 证书序列号 * @param signature 签名 * @return the string */ String token(String mchId, String nonceStr, long timestamp, String serialNo, String signature) { final String TOKEN_PATTERN = "mchid=\"%s\",nonce_str=\"%s\",timestamp=\"%d\",serial_no=\"%s\",signature=\"%s\""; // 生成token return String.format(TOKEN_PATTERN, wechatPayProperties.getMchId(), nonceStr, timestamp, serialNo, signature); }将生成的Token按照上述格式放入请求头中即可完成签名的使用。
5. 总结本文我们对微信支付V3版本的难点签名以及签名的使用进行了完整的分析,同时对API证书的解析也进行了讲解,相信能够帮助你在支付开发中解决一些具体的问题。后面有时间我还将对签名的验证进行讲解,关注:码农小胖哥 及时获取系列知识。