最近对接这个批量转账到零钱的文档,其他的接口都对接好了卡在了这个 下载电子回单接口
问题描述:
我对接的这些接口都是通过一样的签名方式,但是就是这个接口一直返回 "code":"INVALID REQUEST","message":"错误的签名,导致验签失败"
我仔细看了这个接口的签名方式是正确的 文档描述这个接口的GET请求的URL是通过 查询转账电子回单 查询过来的down_url后面有带token参数 我签名的时候也是把这个参数都加上了的 就是过不了签名 请问有人之前碰到过一样的问题吗!!!
如果你用的 php,并且是 laravel 框架,可以尝试一下下边的代码:
public function test_receipt_query() { $res = $this->getApi()->receiptQuery('xxx4d0fb9fd745de8d1dff937755x xx', 'xxxf925a72b740e5ba943e7f40efdxxx'); if ($res->isSuccess()) { // 商户号 $merchantId = 'xxx27xxxxx'; // 商户序列号 $serialNo = 'xxxxxBA3B465F51D1F5B4CF825580F1409xxxxxx'; $nonceStr = unsigned_uuid(); $time = time(); // 下载地址拆分,取路径和参数去签名 $url_parts = parse_url($res->getDownloadUrl()); $canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : "")); $sign = $this->sign($canonical_url, $nonceStr, $time); $res = Http::withHeaders([ 'Authorization' => 'WECHATPAY2-SHA256-RSA2048 mchid="' . $merchantId . '",serial_no="' . $serialNo . '",nonce_str="' . $nonceStr . '",timestamp="' . $time . '",signature="' . $sign . '"' ])->get($res->getDownloadUrl()); if (!is_dir(storage_path('app/public/test'))) { Storage::makeDirectory('public/test'); } file_put_contents(storage_path('app/public/test/' . $time . '.pdf'), $res->body()); } } public function sign($url, $nonceStr, $time) { $str = "GET" . "\n" . $url . "\n" . $time . "\n" . $nonceStr . "\n"; if (!openssl_sign($str, $signature, $this->merchantPrivateKeyInstance, OPENSSL_ALGO_SHA256)) { throw new \Exception('Signing the input $message failed, please checking your $privateKey whether or nor correct.'); } }
写的时候折腾了半天,不想吐槽了,👋
package com.util; 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 zkinghao * @Date 2021/12/18 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()); } }
这是我写的工具源码,downloadUrl是你获取到的下载地址,你用我的这个工具,就可以获取到流了,这个流你要存本地还是存oss都是可以的。
官方文档写的根本就没有代码,只有一个postman的脚本,还是我自己看脚本,然后看规则,然后自己抓包来看那个Authorization在来自己写一个没有脚本的postman调试出来的,问技术基本也是没有回过声的,
真的,没有文档的东西,开发起来,真的是让人疲惫,耗时间,希望后面的人可以不要踩坑了。也希望微信能好好更新文档,弄的更通俗易懂,V3版本的demo真的是少的可怜,开发起来都要从头到尾看一遍。看的是都以为自己是腾讯人员的开发人员一样,要从头到尾的来读你的源码。
您好,请按照以下几点排查: 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编码 上面是客服的回复 1.我接的是V3,然后用下载了签名验证工具,验证了自己代码中生成的签名跟明文进行过比对了是一致的 2. 参数我也看过了是token那个参数在请求的url里面跟签名的参数是一直的 3. 没有encode
这个业务,在你的对接群问