报错日志[图片][图片]
V3接口的下载账单API 的签名以及验签问题?问题描述:下载账单API 在调用后一直报错 400,检查是签名问题 需求结果是: 能拿到返回的流或者 response.getEntity().getContent()里的json 串 或者byte[] 2022-08-02 15:38:18 |DEBUG| com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials [68] | authorization token=[mchid="公司服务商的mchid",nonce_str="NzWT1hBVAO3krFhTuh7pGZLR9XWx4ORu",timestamp="1659425898",serial_no="公司服务商的的序列号",signature="LRCxDGacoxLQpYNEQaN/pDbuU1VjysywFHN1ZlZstygrZdFnjlYtrApBRPb+dM0jrohAlB3ix5RiKFrbZ4wXlKRrUTWg45aYsS+QdyGkOKwqcN7AKSfqqALluuGuni28Mnx5CFq9DyIVfBM3NfPf6GObzQC/qeJib6LvBI/XukwLRNpC1P5D+ADYrY26FmqM5piOGfrqDFIJ6SfiEKKeagNhNYNJO5voBzPejdzJdNAx99TDKO0r9y/rly2TSUDrUhpO057hxyBilV0oiIpheHPV2t9hmxGIDPoLoXicqfeCPZQI5ctKSWGe4ySZnoHSRB3OPAuGhP8vsvJsHXU/PA=="] 2022-08-02 15:38:18 |ERROR| com.wechat.pay.contrib.apache.httpclient.SignatureExec [95] | 应答的状态码不为200-299。status code[400] request headers[[Authorization: WECHATPAY2-SHA256-RSA2048 mchid="公司服务商的mchid",timestamp="1659425891",nonce_str="8a44047dabe64cf79cc501faa17032b1",serial_no="公司服务商的的序列号",signature="Mpyw0flcxq4rLAr1rlydR3bwhANJMdK0CUrR8Vn02DxtC+QxBtn8gCg68k4ZweFUvE8GFt/DpInEztO4tVMhAqLVmWRC1WyFtGePvbdKtHT9G6LKo5w6glTixVa5CdNQGrQ8h8ye63o1QWnR9BmDD06rIiTaC9CRRlhclQ6wpIUNj6QbdPG4c7CO+a3e/n01WavapoqE75XxyRo7YMgt791XSw9u+gq01DBf9D2yp2Eme+pWReE1LTnQB21j9Ot6nwxWSwawYJeAdwkUG81VgAwoNw4gVLpmhybwXqXgNwt/fEUf7uZ2kVOYUPLoIR0WGYHb2pPAfLjKEbw0k1bs4g==", Authorization: WECHATPAY2-SHA256-RSA2048 mchid="公司服务商的mchid",nonce_str="NzWT1hBVAO3krFhTuh7pGZLR9XWx4ORu",timestamp="1659425898",serial_no="公司服务商的的序列号",signature="LRCxDGacoxLQpYNEQaN/pDbuU1VjysywFHN1ZlZstygrZdFnjlYtrApBRPb+dM0jrohAlB3ix5RiKFrbZ4wXlKRrUTWg45aYsS+QdyGkOKwqcN7AKSfqqALluuGuni28Mnx5CFq9DyIVfBM3NfPf6GObzQC/qeJib6LvBI/XukwLRNpC1P5D+ADYrY26FmqM5piOGfrqDFIJ6SfiEKKeagNhNYNJO5voBzPejdzJdNAx99TDKO0r9y/rly2TSUDrUhpO057hxyBilV0oiIpheHPV2t9hmxGIDPoLoXicqfeCPZQI5ctKSWGe4ySZnoHSRB3OPAuGhP8vsvJsHXU/PA==", Host: api.mch.weixin.qq.com, Connection: Keep-Alive, User-Agent: WechatPay-Apache-HttpClient/0.4.8 (Windows 10/10.0) Java/1.8.0_121, Accept-Encoding: gzip,deflate]] [图片] 第一个API:调用地址: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter8_1_11.shtml (申请分账账单API ) 调用后返回 结果 如下:(正常返回下载地址) //调用微信API 申请帐单API WXDimensionResponseVo wxDimensionAPI = wxPay.getWXDimensionAPI(wxDimensionVo); [图片] 第二个API:调用地址: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter8_1_12.shtml(下载地址) 调用过程如下:(异常出现) //调用微信API 下载文件API WXBillExcl wXBillExcl = wxPay.getWXDownloadBillingAPI(wxDimensionAPI); /** * 请求方式:GET * param:hash_type 哈希类型 * param:hash_value 哈希值 * param:download_url 下载地址 * author:wzq * 作用:下载账单API * @return API返回数据 * @throws Exception */ public WXBillExcl getWXDownloadBillingAPI(WXDimensionResponseVo wXDimensionResponseVo) throws WXAPIException, IOException { InputStream inputStream = downloadV3(URI.create(wXDimensionResponseVo.getDownloadUrl())); FileOutputStream fos = new FileOutputStream("d:h3.xls"); byte[] b = new byte[1024]; int length; while ((length = inputStream.read(b)) > 0) { fos.write(b, 0, length); } WXBillExcl wxBillExcl = getWXExcl(inputStream); inputStream.close(); fos.close(); System.out.println("执行完成" + inputStream); return wxBillExcl; } /** * param:url * wx v3标准签名 * wzq * */ public InputStream downloadV3(URI url) throws WXAPIException,IOException { HttpGet httpGet = null; try { httpGet = new HttpGet(url); httpGet.addHeader("Authorization",schema+" "+ getToken("GET",HttpUrl.parse(url.toString()),"")); CloseableHttpResponse response = (CloseableHttpResponse) httpClient.execute(httpGet); int statusCode = response.getStatusLine().getStatusCode(); if (HttpStatus.SC_OK == statusCode || HttpStatus.SC_NO_CONTENT == statusCode) { return response.getEntity().getContent(); } } catch (IOException e) { System.out.println("\n【请求地址:" + url + "\n【异常信息】:" + e.getMessage()); } catch (Exception e) { System.out.println("\n【请求地址:" + url + "\n【异常信息】:" + e.getMessage()); throw (e instanceof WXAPIException) ? (WXAPIException) e : new WXAPIException(e.getMessage(), e); } finally { httpGet.releaseConnection(); } return null; } private final static String schema = "WECHATPAY2-SHA256-RSA2048"; public String getToken(String method, HttpUrl url, String body) { Long timestamp = System.currentTimeMillis() / 1000; String nonceStr = UUID.randomUUID().toString().replace("-",""); String message = buildMessage(method, url, timestamp, nonceStr, body); String signature = message; try { signature = sign(message.getBytes("utf-8")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return "mchid=\"" + sp_mchid + "\"," + "timestamp=\"" + timestamp + "\"," + "nonce_str=\"" + nonceStr + "\"," + "serial_no=\"" + sp_mchSerialNo + "\"," + "signature=\"" + signature + "\""; } public String sign(byte[] message) { try { Signature sign = Signature.getInstance("SHA256withRSA"); sign.initSign(PemUtil.loadPrivateKey(new ByteArrayInputStream(sp_privateKey.getBytes("utf-8")))); sign.update(message); return Base64.getEncoder().encodeToString(sign.sign()); } catch (SignatureException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return null; } /** * 签名的方法 * */ public 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"; }
2022-08-02