使用微信虚拟支付后端请求API总是支付签名校验失败

请求失败报错

bash 复制代码
{"errcode":268490003,"errmsg":"支付签名(pay_sig)校验失败 rid: 65713307-300240ee-3bfad3fa"}

访问query_order

我的代码:

java 复制代码
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

我的代码:

java 复制代码
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

java 复制代码
	// 授权(必填)固定
	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

java 复制代码
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");

原因排查

  1. 查看发现数据一模一样,考虑是不是因为手动拼接字符串方式生成JSON时存在格式问题:
    手动拼接字符串,可能在拼接的过程中存在格式问题。在这种情况下,确保在拼接字符串时正确转义特殊字符,特别是对于中文字符,可以使用Unicode转义表示。
    但是我的数据中没有中文,除了 env 是 int 类型之外其他的全是 String 类型,但在拼接结束后查看到的数据也是没问题的,并且该数据在postman中 curl 后 import 是有效的,但是自己输入或者复制粘贴又是支付签名校验失败。
  2. 将 post 中的 body (postOrder 和 postGood) 替换为 JSON.parseObject() 对象实体类后的数据(orderStr 和 goodStr),发现可以成功,则逐字对比 str 与 post 数据,发现 post 数据中每一个冒号 : 后面都有一个空格,但是 str 数据后面没有,将 post 拼接中冒号 : 后面的空格删除再试就有用了。

确定原因

拼接JSON字符串时在冒号 : 后面多加了空格,可能导致 JSON 解析器无法正确解析字符串、无法正确理解键和值之间的关系,JSON 规范要求键和值之间是没有空格的。即:

java 复制代码
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(对象实体类) 得到的数据,不用自己拼接更简单,不用向上面拼接一样多此一举。

相关推荐
2401_85763639几秒前
计算机课程管理平台:Spring Boot与工程认证的结合
java·spring boot·后端
1 9 J2 分钟前
Java 上机实践4(类与对象)
java·开发语言·算法
Code apprenticeship3 分钟前
Java面试题(2)
java·开发语言
涔溪1 小时前
HTTP TCP三次握手深入解析
网络·tcp/ip·http
憨子周1 小时前
2M的带宽怎么怎么设置tcp滑动窗口以及连接池
java·网络·网络协议·tcp/ip
霖雨3 小时前
使用Visual Studio Code 快速新建Net项目
java·ide·windows·vscode·编辑器
SRY122404193 小时前
javaSE面试题
java·开发语言·面试
Fiercezm3 小时前
JUC学习
java
无尽的大道3 小时前
Java 泛型详解:参数化类型的强大之处
java·开发语言
ZIM学编程3 小时前
Java基础Day-Sixteen
java·开发语言·windows