使用微信虚拟支付后端请求API总是支付签名校验失败
请求失败报错
{"errcode":268490003,"errmsg":"支付签名(pay_sig)校验失败 rid: 65713307-300240ee-3bfad3fa"}
访问query_order
我的代码:
OrderParam orderParam = new OrderParam();
orderParam.setEnv(env);
orderParam.setOpenid(openid);
orderParam.setOrder_id(outTradeNo);
String orderStr = JSON.toJSONString(orderParam);
String paySign = SignUtils.generateSignature("/xpay/query_order" + "&" + orderStr, appKey);
String signature = SignUtils.generateSignature(orderStr, sessionKey);
String postOrder = "{ \"openid\": \"" + openid + "\", \"env\": " + env + ", \"order_id\": \"" + outTradeNo + "\"}";
String url = "https://api.weixin.qq.com/xpay/query_order?access_token=" + accessToken + "&signature=" + signature + "&pay_sig=" + paySign;
String body = HttpRequest.post(url).body(postOrder).execute().body();
访问notify_provide_goods
我的代码:
GoodsParam goodsParam = new GoodsParam();
goodsParam.setOrder_id(outTradeNo);
goodsParam.setEnv(env);
String goodStr = JSON.toJSONString(goodsParam);
String paySig = SignUtils.generateSignature("/xpay/notify_provide_goods" + "&" + goodStr, appKey);
String signatur = SignUtils.generateSignature(goodStr, sessionKey);
String postGood = "{ \"order_id\": \"" + outTradeNo + "\", \"env\": " + env + "}";
String success = "https://api.weixin.qq.com/xpay/notify_provide_goods?access_token=" + accessToken + "&pay_sig=" + paySig + "&signature=" + signatur;
String bodied = HttpRequest.post(success).body(postGood).execute().body();
获取openid和session_key
// 授权(必填)固定
String grantType = "authorization_code";
// 发送请求
String res = HttpRequest.post("https://api.weixin.qq.com/sns/jscode2session")
.form("appid", appId)
.form("secret", appSecret)
.form("js_code", code)
.form("grant_type", grantType)
.execute().body();
// 解析相应内容(转换成json对象)
JSONObject json = JSONObject.parseObject(res);
String openid = json.getString("openid");
String session_key = json.getString("session_key");
获取access_token
String tokenUrl = "https://api.weixin.qq.com/cgi-bin/stable_token";
String post = "{ \"grant_type\": \"client_credential\", \"appid\": \"" + appId + "\", \"secret\": \"" + appSecret + "\"}";
String str = HttpRequest.post(tokenUrl).body(post).execute().body();
com.alibaba.fastjson2.JSONObject token = JSON.parseObject(str);
String accessToken = token.getString("access_token");
原因排查
- 查看发现数据一模一样,考虑是不是因为手动拼接字符串方式生成JSON时存在格式问题:
手动拼接字符串,可能在拼接的过程中存在格式问题。在这种情况下,确保在拼接字符串时正确转义特殊字符,特别是对于中文字符,可以使用Unicode转义表示。
但是我的数据中没有中文,除了 env 是 int 类型之外其他的全是 String 类型,但在拼接结束后查看到的数据也是没问题的,并且该数据在postman中 curl 后 import 是有效的,但是自己输入或者复制粘贴又是支付签名校验失败。 - 将 post 中的 body (postOrder 和 postGood) 替换为 JSON.parseObject() 对象实体类后的数据(orderStr 和 goodStr),发现可以成功,则逐字对比 str 与 post 数据,发现 post 数据中每一个冒号 : 后面都有一个空格,但是 str 数据后面没有,将 post 拼接中冒号 : 后面的空格删除再试就有用了。
确定原因
拼接JSON字符串时在冒号 : 后面多加了空格,可能导致 JSON 解析器无法正确解析字符串、无法正确理解键和值之间的关系,JSON 规范要求键和值之间是没有空格的。即:
String postOrder = "{ \"openid\": \"" + openid + "\", \"env\": " + env + ", \"order_id\": \"" + outTradeNo + "\"}";
改为:
String postOrder = "{ \"openid\":\"" + openid + "\",\"env\": " + env + ", \"order_id\":\"" + outTradeNo + "\"}";
String postGood = "{ \"order_id\": \"" + outTradeNo + "\", \"env\": " + env + "}";
改为:
String postGood = "{ \"order_id\":\"" + outTradeNo + "\", \"env\":" + env + "}";
或者也可以直接使用 JSON.parseObject(对象实体类) 得到的数据,不用自己拼接更简单,不用向上面拼接一样多此一举。
微信虚拟支付开发文档:虚拟支付