接口地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transfer_partner/chapter4_3.shtml
在下载电子回单API 中,接口状态 status code = 200,但是业务请求400是什么原因呢?
排查方式:
1、 V2使用签名检查工具:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=20_1)校验签名算法是否有误
V3请下载文档中的校验工具:https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay6_0.shtml
2、确认秘钥是否有误(服务商模式使用服务商商户号秘钥,秘钥是在商户平台配置,如果同一商户号调用其它接口成功可排除是秘钥问题),商户设置的密钥长度为32个字节
3、确认接口实际的请求参数与生成签名原串的参数一致,不能增加或缺少参数(可通过打印签名原串进行排查)
4、确认参数的大小写,参数名与接口文档一致
5、签名原串的参数值使用原始值,不需要encode
6、接口需要使用UTF-8编码
最终原因:
这个接口的签名方式不一样 因为签名里面写了GET方式时,没有body也有换行符,但是这个接口是不需要换行符的,所以在构建签名的明文的时候 把最后body的换行符去掉就可以了。
用wechatpay-apiv3同样会报错
然后我重新写了一套
import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpResponse; import org.apache.http.client.methods.HttpGet; import java.io.InputStream; import java.security.PrivateKey; import java.security.Signature; import java.util.Base64; import java.util.UUID; /** * 微信电子回单下载 * @Author xiaoqiang * @Date 2022/02/12 17:50 */ public class DownLoadBillUtil { //商户号 private String merchantId; //商户序列号 private String certificateSerialNo; //商户私钥 private PrivateKey privateKey; public DownLoadBillUtil(String merchantId, String certificateSerialNo, PrivateKey privateKey){ this.merchantId = merchantId; this.certificateSerialNo = certificateSerialNo; this.privateKey = privateKey; } public InputStream downloadBill(String downloadUrl) throws Exception{ String timestamp = String.valueOf(System.currentTimeMillis()); String nonceStr = UUID.randomUUID().toString().replace("-", "");; HttpGet httpGet = new HttpGet(downloadUrl); String path = httpGet.getURI().getPath(); String canonicalUrl = httpGet.getURI().getQuery(); if (canonicalUrl != null) { path += "?" + canonicalUrl; } String billSign = this.createBillSign(nonceStr, timestamp, path); StringBuilder sb = new StringBuilder("WECHATPAY2-SHA256-RSA2048 mchid=").append("\"").append(this.merchantId).append("\","); sb.append("serial_no=").append("\"").append(this.certificateSerialNo).append("\","); sb.append("nonce_str=").append("\"").append(nonceStr).append("\","); sb.append("timestamp=").append("\"").append(timestamp).append("\","); sb.append("signature=").append("\"").append(billSign).append("\""); String auth = sb.toString(); HttpResponse execute = HttpRequest.get(downloadUrl).auth(auth).execute(); return execute.bodyStream(); } public String createBillSign(String nonceStr, String timestamp, String download) throws Exception{ String plain_text = "GET" + "\n" + download + "\n" + timestamp + "\n" + nonceStr + "\n"; Signature sign = Signature.getInstance("SHA256withRSA"); sign.initSign(this.privateKey); sign.update(plain_text.getBytes("utf-8")); return Base64.getEncoder().encodeToString(sign.sign()); } }