# 支付模块 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 response = restTemplate.postForEntity(url, request, Map.class); Map data = (Map) response.getBody().get("data"); String qrBase64 = (String) data.get("qrBase64"); ``` --- ## 注意事项 1. **幂等性**: 同一 `bizOrderId` + `channel` 重复请求会返回同一订单和二维码 2. **过期时间**: 订单创建后2小时内有效,超时自动过期 3. **并发控制**: 同一订单同时只允许一笔进行中的交易 4. **回调签名**: 务必验证回调签名,防止伪造请求 5. **金额单位**: 所有金额单位均为**分**(例如:100元 = 10000分) 6. **环境配置**: 生产环境请使用HTTPS协议 --- ## 技术支持 如有问题,请联系技术支持团队。