使用微信虚拟支付后端请求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(对象实体类) 得到的数据,不用自己拼接更简单,不用向上面拼接一样多此一举。

相关推荐
南极Ou14 分钟前
Mybatis逆向工程详解(附源码文件)动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
xml·java·mybatis
Moshow郑锴21 分钟前
IDEA为何一直无法使用超过4g内存
java·ide·intellij-idea
木头左22 分钟前
Docker容器化镜像分层原理及优化策略
java·eureka
李少兄23 分钟前
IntelliJ IDEA代码提示忽略大小写设置详解
java·ide·intellij-idea
白宇横流学长1 小时前
基于SpringBoot实现的课程答疑系统设计与实现【源码+文档】
java·spring boot·后端
00后程序员张1 小时前
发版前后的调试对照实践:用 WebDebugX 与多工具构建上线验证闭环
websocket·网络协议·tcp/ip·http·网络安全·https·udp
积跬步至千里PRO1 小时前
在 Java 中实现一个标准 Service 接口,并通过配置动态选择具体实现类供 Controller 调用
java·简单工厂模式·解耦
chengchong_cc1 小时前
海康对接摄像头
java·vue.js
菜鸟小九1 小时前
Leetcode20 (有效的括号)
java·数据结构·算法
悟能不能悟2 小时前
讲一件Java虚拟线程
java·开发语言·oracle