shop-back-end/doc/支付网关.md

223 lines
7.2 KiB
Markdown
Raw Normal View History

2025-03-11 08:59:40 +08:00
# 全局公共参数
**全局Header参数**
| 参数名 | 示例值 | 参数类型 | 是否必填 | 参数描述 |
| --- | --- | ---- | ---- | ---- |
| 暂无参数 |
**全局Query参数**
| 参数名 | 示例值 | 参数类型 | 是否必填 | 参数描述 |
| --- | --- | ---- | ---- | ---- |
| 暂无参数 |
**全局Body参数**
| 参数名 | 示例值 | 参数类型 | 是否必填 | 参数描述 |
| --- | --- | ---- | ---- | ---- |
| 暂无参数 |
**全局认证方式**
> 无需认证
# 状态码说明
| 状态码 | 中文描述 |
| --- | ---- |
| 暂无参数 |
# 微信支付
> 创建人: 达民
> 更新人: 达民
> 创建时间: 2025-03-08 08:44:12
> 更新时间: 2025-03-08 08:44:12
```text
暂无描述
```
**目录Header参数**
| 参数名 | 示例值 | 参数类型 | 是否必填 | 参数描述 |
| --- | --- | ---- | ---- | ---- |
| 暂无参数 |
**目录Query参数**
| 参数名 | 示例值 | 参数类型 | 是否必填 | 参数描述 |
| --- | --- | ---- | ---- | ---- |
| 暂无参数 |
**目录Body参数**
| 参数名 | 示例值 | 参数类型 | 是否必填 | 参数描述 |
| --- | --- | ---- | ---- | ---- |
| 暂无参数 |
**目录认证信息**
> 继承父级
**Query**
## JS API支付
> 创建人: 达民
> 更新人: 达民
> 创建时间: 2025-03-08 08:49:16
> 更新时间: 2025-03-08 15:08:38
**在微信内置浏览器里打开目标应用页面(如微信公众号、点击聊天窗口的链接打开页面),根据需要调起微信支付.
1、openid的获取参考https://segmentfault.com/a/1190000013392838 。也可以自己找微信官方文档。
2、如何调起jsapi支付参考文档https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6
3、支付回调。支付网关根据请求支付传递的notify_url将支付结果通知到业务方
回调参数**
| 参数 | 含义 |
| --- | --- |
| client_id | 客户端ID |
| biz_id | 支付网关为业务方分配的ID |
| nonce_str | 参与签名的混淆字段 |
| sign | 签名校验字段值 |
| sign_type | 签名类型一般是MD5 |
| version | 支付网关版本号 |
| timestamp | 回调时的时间戳,毫秒 |
| biz_content | 订单的相关数据以key=value组合并以&拼接在一起的字符串其中value未做urlencode处理 |
| 以上参数按照key=value的形式并对参数值做urlencode& 拼接多个key=value形成一个字符串以POST的方式调用notify_url时将该字符串提交给业务方。 | |
**其中biz_content包含了以下参数**
| 参数 | 含义 |
| --- | --- |
| uid | 应用方为人员分配的记录ID应用方在请求接口时以ucid传递的参数值 |
| trade_id | 支付网关为本次支付分配的记录ID |
| total_amount | 本次支付涉及的金额,单位:分 |
| trade_pay_time | 支付成功的时间格式yyyy-MM-dd HH:mm:ss |
| trade_status | 支付支付状态成功时值为SUCCESS |
| pay_type | 支付方式jsapi接口调起的支付本字段值固定为113 |
| callback_content | 微信回调给支付网关的原始xml数据参考https://pay.weixin.qq.com/doc/v2/partner/4011936644 |
| title | 业务方调接口时传递的title字段值 |
| biz_order_id | 业务方支付订单的订单号 |
**举个例子:
biz_content=%7B%22uid%22%3A%22102579%22%2C%22trade_id%22%3A%221501822040%22%2C%22total_amount%22%3A83601%2C%22trade_pay_time%22%3A%222025-03-08%2008%3A48%3A35%22%2C%22trade_status%22%3A%22SUCCESS%22%2C%22pay_type%22%3A%22113%22%2C%22callback_content%22%3A%22%3Cxml%3E%E7%95%A5%3C%2Fxml%3E%22%2C%22title%22%3A%22%E4%BA%91%E9%98%9F%E9%95%BF%E5%8C%BB%E8%8D%AF%E8%BF%9E%E9%94%81%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9F%22%2C%22biz_order_id%22%3A%2221-364535%22%7D&nonce_str=11961acffe074c7da556a18e8549027f&sign=5ec91e8d3f4feb4b3c273e5512a7d7c3&biz_id=ydrug&sign_type=MD5&version=1.0&client_id=yeshan&timestamp=1741394916159,只有通过了签名校验才应该能被业务方接受并进行业务的下一步处理。业务方应该根据回调数据里的相关参数biz_order_id找回相应的订单以进行下一步的业务处理。注意同一个支付订单的支付结果支付网关可能会多次回调通知业务方所以业务方要做好幂等处理。签名校验算法如下**
```java
/**
* @param appKey 支付网关提供的业务秘钥与biz_id是配对一起提供的
* @param sign 支付网关回调参数里的sign字段值
* @param reqBody 支付网关回调的原始请求body字符串
*/
public static boolean checkOpenSign(String appKey, String sign, String reqBody) {
String[] fields = reqBody.split("&");
Map<String, String> fieldMap = new HashMap<>();
for (String field : fields) {
String[] pair = field.split("=");
if (pair.length != 2) {
continue;
}
// sign字段不参与校验空字段不校验
if (!"sign".equals(pair[0]) && StringUtils.isNotBlank(pair[1])) {
fieldMap.put(pair[0], pair[1]);
}
}
String generateSign = openSign(appKey, fieldMap);
return Objects.equals(generateSign, sign);
}
public static String openSign(String appKey, Map<String, String> params) {
if(MapUtils.isEmpty(params)) {
params = new HashMap<String, String>(1);
}
Map<String, String> sortedParams = new TreeMap<>(params);
List<String> kvPairList = getKVList(sortedParams);
String sourceText = StringUtils.join(kvPairList, "&");
sourceText = sourceText + "&app_key=" + appKey;
LogUtils.NORMAL.info("sourceText:" + sourceText);
try {
return md5(sourceText.getBytes("utf-8"));
} catch (Exception e) {
return null;
}
}
```
**接口状态**
> 开发中
**接口URL**
> http://localhost:7045/open/trade/wx/jsapi/precreate
| 环境 | URL |
| --- | --- |
**请求方式**
> POST
**Content-Type**
> json
**请求Body参数**
```javascript
{
"ucid": "123", //应用方为人员分配的记录ID以方便后续排查问题。选填
"ip": "127.0.0.1", //调用方应用所在服务器的ip。必填
"openid": "o_xsewew131SGS", //微信用户的openid参考【设计】模块的【详细说明】。必填
"biz_order_id": "1234536", //应用方为本次支付订单定义的订单ID务必确保在业务应用内唯一。必填
"pay_amount": 1, //支付金额,单位:分。必填
"title": "测试", //用户在微信支付界面看到订单标题,也就是商品描述。必填
"notify_url": "http://...", //业务方接收支付结果的异步回调地址。必填
"biz_id": "abc", //支付网关为业务方分配的业务应用ID。必填
"extra": "342rewrs" //业务方期望支付网关回调时透传的数据。选填
}
```
**认证方式**
> 继承父级
**响应示例**
* 成功(200)
```javascript
//成功使用以下参数调起jsapi支付。
{
"appId": "",
"timeStamp": "",
"nonceStr": "",
"package": "",
"signType": "",
"paySign": ""
}
```
* 失败(200)
```javascript
{
"timestamp": "2025-03-08T01:55:14.480+0000",
"status": 500,
"error": "Internal Server Error",
"message": "第三方返回失败, errorMsg = 第三方返回失败, errorMsg = 无效的openid",
"path": "/open/trade/wx/jsapi/precreate"
}
```
**Query**