# 支付模块 API 接口文档
## 基础信息
- **服务地址**: `http://your-domain:8080`
- **接口协议**: HTTP/HTTPS
- **数据格式**: JSON
- **字符编码**: UTF-8
---
## 1. 发起微信Native支付
### 接口说明
生成微信支付二维码,用户扫码后完成支付。
### 请求信息
- **请求方式**: `POST`
- **请求路径**: `/api/pay/wechat/native`
- **Content-Type**: `application/json`
### 请求参数
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|--------|------|------|------|------|
| bizOrderId | String | 是 | 业务订单号(唯一标识) | "ORDER20251123001" |
| amount | Integer | 是 | 支付金额(单位:分) | 10000 (表示100元) |
| subject | String | 是 | 订单标题 | "商品订单支付" |
| description | String | 否 | 订单描述 | "购买商品A×1" |
| callbackUrl | String | 是 | 业务回调地址(支付成功后通知) | "https://your-domain.com/notify" |
### 请求示例
```json
{
"bizOrderId": "ORDER20251123001",
"amount": 10000,
"subject": "商品订单支付",
"description": "购买商品A×1",
"callbackUrl": "https://your-domain.com/notify"
}
```
### 响应参数
| 参数名 | 类型 | 说明 |
|--------|------|------|
| code | Integer | 响应码,200表示成功 |
| msg | String | 响应消息 |
| data | Object | 响应数据 |
| data.orderId | Long | 支付订单ID |
| data.transactionId | Long | 交易流水ID |
| data.status | String | 订单状态(PENDING-待支付) |
| data.qrBase64 | String | 二维码图片Base64编码 |
| data.expireAt | String | 过期时间(2小时) |
### 响应示例
```json
{
"code": 200,
"msg": "操作成功",
"data": {
"orderId": 1234567890,
"transactionId": 9876543210,
"status": "PENDING",
"qrBase64": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...",
"expireAt": "2025-11-23 14:00:00"
}
}
```
### 使用说明
1. 调用接口获取 `qrBase64`
2. 前端直接将Base64显示为图片:`
`
3. 用户使用微信扫码支付
4. 支付成功后,系统会调用您提供的 `callbackUrl` 通知结果
---
## 2. 发起支付宝当面付
### 接口说明
生成支付宝支付二维码,用户扫码后完成支付。
### 请求信息
- **请求方式**: `POST`
- **请求路径**: `/api/pay/alipay/precreate`
- **Content-Type**: `application/json`
### 请求参数
与微信支付相同,参考上方表格。
### 请求示例
```json
{
"bizOrderId": "ORDER20251123002",
"amount": 10000,
"subject": "商品订单支付",
"description": "购买商品B×1",
"callbackUrl": "https://your-domain.com/notify"
}
```
### 响应示例
```json
{
"code": 200,
"msg": "操作成功",
"data": {
"orderId": 1234567891,
"transactionId": 9876543211,
"status": "PENDING",
"qrBase64": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...",
"expireAt": "2025-11-23 14:00:00"
}
}
```
---
## 3. 查询订单状态
### 接口说明
查询支付订单的当前状态。
### 请求信息
- **请求方式**: `GET`
- **请求路径**: `/api/pay/orders/{orderId}`
### 路径参数
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| orderId | Long | 是 | 支付订单ID |
### 请求示例
```
GET /api/pay/orders/1234567890
```
### 响应参数
| 参数名 | 类型 | 说明 |
|--------|------|------|
| code | Integer | 响应码 |
| msg | String | 响应消息 |
| data | Object | 订单详情 |
| data.id | Long | 订单ID |
| data.bizOrderId | String | 业务订单号 |
| data.amount | Integer | 金额(分) |
| data.currency | String | 币种(CNY) |
| data.channel | String | 支付渠道(WECHAT/ALIPAY) |
| data.status | String | 订单状态 |
| data.subject | String | 订单标题 |
| data.channelTradeNo | String | 渠道交易号 |
| data.paidAt | String | 支付完成时间 |
| data.expireAt | String | 过期时间 |
| data.createdAt | String | 创建时间 |
### 订单状态说明
| 状态码 | 说明 |
|--------|------|
| INIT | 初始化 |
| PENDING | 待支付 |
| SUCCEEDED | 支付成功 |
| FAILED | 支付失败 |
| CANCELED | 已关闭 |
| EXPIRED | 已过期 |
### 响应示例
```json
{
"code": 200,
"msg": "操作成功",
"data": {
"id": 1234567890,
"bizOrderId": "ORDER20251123001",
"amount": 10000,
"currency": "CNY",
"channel": "WECHAT",
"status": "SUCCEEDED",
"subject": "商品订单支付",
"channelTradeNo": "4200001234567890",
"paidAt": "2025-11-23 12:30:00",
"expireAt": "2025-11-23 14:00:00",
"createdAt": "2025-11-23 12:00:00"
}
}
```
---
## 4. 查询最新交易
### 接口说明
查询订单的最新交易记录(包含二维码)。
### 请求信息
- **请求方式**: `GET`
- **请求路径**: `/api/pay/orders/{orderId}/transactions/latest`
### 请求示例
```
GET /api/pay/orders/1234567890/transactions/latest
```
### 响应示例
```json
{
"code": 200,
"msg": "操作成功",
"data": {
"id": 9876543210,
"orderId": 1234567890,
"channel": "WECHAT",
"clientType": "NATIVE",
"status": "PENDING",
"qrBase64": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...",
"createdAt": "2025-11-23 12:00:00"
}
}
```
---
## 5. 业务回调通知(重要)
### 接口说明
当支付成功后,系统会主动调用您在发起支付时提供的 `callbackUrl`,通知支付结果。
### 回调方式
- **请求方式**: `POST`
- **Content-Type**: `application/json`
- **请求地址**: 您提供的 `callbackUrl`
### 请求头
| 参数名 | 说明 |
|--------|------|
| Content-Type | application/json |
| X-Signature | HMAC-SHA256签名,用于验证请求来源 |
| X-Nonce | 随机字符串 |
| X-Timestamp | 时间戳(毫秒) |
### 回调参数
| 参数名 | 类型 | 说明 |
|--------|------|------|
| tradeId | Long | 交易ID |
| orderId | Long | 订单ID |
| bizOrderId | String | 业务订单号 |
| channel | String | 支付渠道(WECHAT/ALIPAY) |
| amount | Integer | 金额(分) |
| currency | String | 币种(CNY) |
| status | String | 订单状态(SUCCEEDED) |
| channelTradeNo | String | 渠道交易号 |
| paidAt | String | 支付完成时间 |
| subject | String | 订单标题 |
| description | String | 订单描述 |
### 回调示例
```json
{
"tradeId": 9876543210,
"orderId": 1234567890,
"bizOrderId": "ORDER20251123001",
"channel": "WECHAT",
"amount": 10000,
"currency": "CNY",
"status": "SUCCEEDED",
"channelTradeNo": "4200001234567890",
"paidAt": "2025-11-23 12:30:00",
"subject": "商品订单支付",
"description": "购买商品A×1"
}
```
### 签名验证
**签名算法**: HMAC-SHA256
**签名数据**: `payload + nonce + timestamp`
**验证步骤**:
1. 获取请求头中的 `X-Signature`、`X-Nonce`、`X-Timestamp`
2. 获取请求体 JSON 字符串 `payload`
3. 拼接字符串:`signData = payload + nonce + timestamp`
4. 使用配置的 `callbackSignSecret` 计算 HMAC-SHA256
5. 对比计算结果与 `X-Signature` 是否一致
**Java示例代码**:
```java
String payload = "请求体JSON字符串";
String nonce = request.getHeader("X-Nonce");
String timestamp = request.getHeader("X-Timestamp");
String signature = request.getHeader("X-Signature");
String signData = payload + nonce + timestamp;
String calculated = SignUtil.hmacSha256(signData, callbackSignSecret);
if (signature.equals(calculated)) {
// 签名验证通过
}
```
### 响应要求
您的回调接口应返回:
- **成功**: HTTP 状态码 200-299
- **失败**: 其他状态码(系统会自动重试)
### 重试机制
如果回调失败,系统会按以下间隔自动重试(最多10次):
- 立即重试
- 1分钟后
- 5分钟后
- 15分钟后
- 60分钟后
---
## 6. 健康检查
### 接口说明
检查服务是否正常运行。
### 请求信息
- **请求方式**: `GET`
- **请求路径**: `/api/health`
### 响应示例
```json
{
"code": 200,
"msg": "操作成功",
"data": {
"status": "UP",
"service": "dryad-payment",
"time": "2025-11-23 12:00:00",
"message": "支付模块服务运行正常"
}
}
```
---
## 错误码说明
| 错误码 | 说明 |
|--------|------|
| 200 | 成功 |
| 500 | 服务器内部错误 |
| 400 | 请求参数错误 |
| 404 | 资源不存在 |
### 错误响应示例
```json
{
"code": 500,
"msg": "支付创建失败: 微信下单失败",
"data": null
}
```
---
## 集成示例
### cURL示例
**发起微信支付**:
```bash
curl -X POST http://localhost:8080/api/pay/wechat/native \
-H "Content-Type: application/json" \
-d '{
"bizOrderId": "ORDER20251123001",
"amount": 10000,
"subject": "商品订单支付",
"description": "购买商品A×1",
"callbackUrl": "https://your-domain.com/notify"
}'
```
**查询订单**:
```bash
curl http://localhost:8080/api/pay/orders/1234567890
```
### JavaScript示例
```javascript
// 发起支付
async function createPayment() {
const response = await fetch('http://localhost:8080/api/pay/wechat/native', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
bizOrderId: 'ORDER20251123001',
amount: 10000,
subject: '商品订单支付',
description: '购买商品A×1',
callbackUrl: 'https://your-domain.com/notify'
})
});
const result = await response.json();
if (result.code === 200) {
// 显示二维码
document.getElementById('qrcode').src = result.data.qrBase64;
}
}
// 查询订单状态
async function queryOrder(orderId) {
const response = await fetch(`http://localhost:8080/api/pay/orders/${orderId}`);
const result = await response.json();
return result.data.status;
}
```
### Java示例
```java
// 发起支付
RestTemplate restTemplate = new RestTemplate();
String url = "http://localhost:8080/api/pay/wechat/native";
Map request = new HashMap<>();
request.put("bizOrderId", "ORDER20251123001");
request.put("amount", 10000);
request.put("subject", "商品订单支付");
request.put("callbackUrl", "https://your-domain.com/notify");
ResponseEntity