feat: 新增退单操作接口及相关逻辑
主要修改: 1. 在LinkController中新增退单操作接口,支持用户对指定链接进行退单。 2. 在LinkStatusService中实现退单逻辑,确保用户只能退单自己的链接,并更新链接状态。 3. 在ScriptClient中新增调用退单接口的方法,处理与外部系统的交互。 技术细节: - 通过新增的退单功能,提升了用户对链接的管理能力,确保操作的安全性和有效性。
This commit is contained in:
293
docs/退单接口使用说明.md
Normal file
293
docs/退单接口使用说明.md
Normal file
@@ -0,0 +1,293 @@
|
||||
# 退单接口使用说明
|
||||
|
||||
## 📋 功能概述
|
||||
|
||||
退单接口允许代理用户对自己创建的链接进行退单操作。执行退单时,系统会:
|
||||
|
||||
1. 调用外部脚本退单接口:`http://36.138.184.60:1234/yijianwan_netfile/saveMsg?文件名=判断退单&cc2={machineId}`
|
||||
2. 将链接状态更新为 `REFUNDED`
|
||||
3. 记录退单时间
|
||||
|
||||
## 🔧 接口详情
|
||||
|
||||
### 基本信息
|
||||
- **请求方式**: `POST`
|
||||
- **请求路径**: `/api/link/{codeNo}/refund`
|
||||
- **认证方式**: JWT Bearer Token
|
||||
- **返回类型**: `application/json`
|
||||
|
||||
### 请求参数
|
||||
|
||||
#### 路径参数
|
||||
| 参数名 | 类型 | 必填 | 说明 |
|
||||
|--------|------|------|------|
|
||||
| codeNo | String | 是 | 链接编号 |
|
||||
|
||||
#### 请求头
|
||||
| 参数名 | 类型 | 必填 | 说明 |
|
||||
|--------|------|------|------|
|
||||
| Authorization | String | 是 | JWT认证令牌,格式:`Bearer {token}` |
|
||||
|
||||
### 响应格式
|
||||
|
||||
#### 成功响应 (HTTP 200)
|
||||
```json
|
||||
{
|
||||
"data": true,
|
||||
"success": true,
|
||||
"message": "操作成功"
|
||||
}
|
||||
```
|
||||
|
||||
#### 错误响应
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"message": "错误详情",
|
||||
"code": "错误代码"
|
||||
}
|
||||
```
|
||||
|
||||
## 📝 使用示例
|
||||
|
||||
### 1. 基本退单操作
|
||||
|
||||
```bash
|
||||
curl -X POST 'http://localhost:8080/api/link/ABC12345/refund' \
|
||||
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...' \
|
||||
-H 'Content-Type: application/json'
|
||||
```
|
||||
|
||||
**成功响应:**
|
||||
```json
|
||||
{
|
||||
"data": true,
|
||||
"success": true,
|
||||
"message": "退单操作成功"
|
||||
}
|
||||
```
|
||||
|
||||
### 2. JavaScript 示例
|
||||
|
||||
```javascript
|
||||
async function refundOrder(codeNo, jwt_token) {
|
||||
try {
|
||||
const response = await fetch(`http://localhost:8080/api/link/${codeNo}/refund`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${jwt_token}`,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
console.log('退单成功');
|
||||
return true;
|
||||
} else {
|
||||
console.error('退单失败:', result.message);
|
||||
return false;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('退单请求失败:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 使用示例
|
||||
refundOrder('ABC12345', 'your_jwt_token');
|
||||
```
|
||||
|
||||
### 3. Python 示例
|
||||
|
||||
```python
|
||||
import requests
|
||||
|
||||
def refund_order(code_no, jwt_token):
|
||||
"""执行退单操作"""
|
||||
url = f'http://localhost:8080/api/link/{code_no}/refund'
|
||||
headers = {
|
||||
'Authorization': f'Bearer {jwt_token}',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
|
||||
try:
|
||||
response = requests.post(url, headers=headers)
|
||||
response.raise_for_status()
|
||||
|
||||
result = response.json()
|
||||
|
||||
if result.get('success'):
|
||||
print('退单成功')
|
||||
return True
|
||||
else:
|
||||
print(f'退单失败: {result.get("message")}')
|
||||
return False
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'退单请求失败: {e}')
|
||||
return False
|
||||
|
||||
# 使用示例
|
||||
refund_order('ABC12345', 'your_jwt_token')
|
||||
```
|
||||
|
||||
## 🚫 错误处理
|
||||
|
||||
### 常见错误类型
|
||||
|
||||
| 错误码 | HTTP状态 | 错误信息 | 说明 |
|
||||
|-------|---------|---------|------|
|
||||
| AUTH_001 | 401 | 用户未认证 | JWT令牌无效或过期 |
|
||||
| LINK_001 | 400 | 链接不存在 | 指定的链接编号不存在 |
|
||||
| LINK_002 | 400 | 权限不足 | 用户无权操作此链接 |
|
||||
| LINK_003 | 400 | 链接已经退过单 | 不能重复退单 |
|
||||
| LINK_004 | 400 | 过期链接不允许退单 | 链接已过期 |
|
||||
| LINK_005 | 400 | 已完成链接不允许退单 | 游戏已完成的链接 |
|
||||
|
||||
### 错误处理示例
|
||||
|
||||
```javascript
|
||||
async function handleRefund(codeNo, token) {
|
||||
try {
|
||||
const response = await fetch(`/api/link/${codeNo}/refund`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (!result.success) {
|
||||
switch (result.code) {
|
||||
case 'LINK_003':
|
||||
alert('此链接已经退过单了');
|
||||
break;
|
||||
case 'LINK_004':
|
||||
alert('过期链接无法退单');
|
||||
break;
|
||||
case 'LINK_005':
|
||||
alert('已完成的游戏无法退单');
|
||||
break;
|
||||
default:
|
||||
alert('退单失败: ' + result.message);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
alert('退单成功');
|
||||
return true;
|
||||
|
||||
} catch (error) {
|
||||
console.error('退单请求失败:', error);
|
||||
alert('网络错误,请稍后重试');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🔄 状态流转
|
||||
|
||||
### 允许退单的状态
|
||||
- `NEW` (新建)
|
||||
- `USING` (使用中)
|
||||
- `LOGGED_IN` (已登录)
|
||||
|
||||
### 不允许退单的状态
|
||||
- `REFUNDED` (已退款) - 已经退过单
|
||||
- `EXPIRED` (已过期) - 链接已过期
|
||||
- `COMPLETED` (已完成) - 游戏已完成
|
||||
|
||||
### 状态流转图
|
||||
```
|
||||
NEW/USING/LOGGED_IN → [退单操作] → REFUNDED (最终状态)
|
||||
```
|
||||
|
||||
## 📊 业务逻辑
|
||||
|
||||
### 退单流程
|
||||
|
||||
1. **身份验证**
|
||||
- 验证JWT令牌有效性
|
||||
- 确认用户有权限操作该链接
|
||||
|
||||
2. **状态检查**
|
||||
- 检查链接是否存在
|
||||
- 检查链接当前状态是否允许退单
|
||||
|
||||
3. **外部接口调用**
|
||||
- 如果链接有关联设备,调用脚本端退单接口
|
||||
- URL格式:`http://36.138.184.60:1234/yijianwan_netfile/saveMsg?文件名=判断退单&cc2={真实设备ID}`
|
||||
- 即使外部接口调用失败,仍会更新数据库状态
|
||||
|
||||
4. **数据库更新**
|
||||
- 更新链接状态为 `REFUNDED`
|
||||
- 记录退单时间 `refund_at`
|
||||
- 更新修改时间 `updated_at`
|
||||
|
||||
### 注意事项
|
||||
|
||||
1. **权限控制**: 用户只能退单自己创建的链接
|
||||
2. **状态限制**: 只有特定状态的链接才能退单
|
||||
3. **重复操作**: 已退单的链接不能再次退单
|
||||
4. **外部接口**: 即使外部接口调用失败,也会更新本地状态,避免用户重复操作
|
||||
5. **事务性**: 整个退单操作在事务中执行,确保数据一致性
|
||||
|
||||
## 🧪 测试示例
|
||||
|
||||
### 完整测试流程
|
||||
|
||||
```bash
|
||||
# 1. 登录获取JWT令牌
|
||||
curl -X POST 'http://localhost:8080/api/auth/login' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"username":"test_user","password":"password"}'
|
||||
|
||||
# 2. 生成测试链接
|
||||
curl -X POST 'http://localhost:8080/api/link/generate' \
|
||||
-H 'Authorization: Bearer YOUR_JWT_TOKEN' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"times":1,"linkCount":1}'
|
||||
|
||||
# 3. 查看链接状态 (退单前)
|
||||
curl -X GET 'http://localhost:8080/api/link/YOUR_CODE_NO/status'
|
||||
|
||||
# 4. 执行退单操作
|
||||
curl -X POST 'http://localhost:8080/api/link/YOUR_CODE_NO/refund' \
|
||||
-H 'Authorization: Bearer YOUR_JWT_TOKEN'
|
||||
|
||||
# 5. 查看链接状态 (退单后,应该是REFUNDED状态)
|
||||
curl -X GET 'http://localhost:8080/api/link/YOUR_CODE_NO/status'
|
||||
```
|
||||
|
||||
## 🔍 日志示例
|
||||
|
||||
### 成功退单日志
|
||||
```
|
||||
2024-01-15 14:30:00.123 INFO LinkStatusService - === 开始处理退单操作 ===
|
||||
2024-01-15 14:30:00.124 INFO LinkStatusService - 链接编号: ABC12345, 代理ID: 1001
|
||||
2024-01-15 14:30:00.125 INFO LinkStatusService - 链接关联设备: f1, 调用脚本端退单接口
|
||||
2024-01-15 14:30:00.234 INFO ScriptClient - 调用退单接口: 设备=f1, url=http://36.138.184.60:1234/yijianwan_netfile/saveMsg?文件名=判断退单&cc2=f1
|
||||
2024-01-15 14:30:00.567 INFO ScriptClient - 退单接口调用成功: 设备=f1, 结果=SUCCESS
|
||||
2024-01-15 14:30:00.580 INFO LinkStatusService - 退单操作成功: codeNo=ABC12345, 设备=f1, 状态更新为REFUNDED
|
||||
2024-01-15 14:30:00.581 INFO LinkStatusService - === 退单操作完成 ===
|
||||
```
|
||||
|
||||
### 失败退单日志
|
||||
```
|
||||
2024-01-15 14:30:00.123 INFO LinkStatusService - === 开始处理退单操作 ===
|
||||
2024-01-15 14:30:00.124 INFO LinkStatusService - 链接编号: ABC12345, 代理ID: 1001
|
||||
2024-01-15 14:30:00.125 WARN LinkStatusService - 链接已经退过单: codeNo=ABC12345, status=REFUNDED
|
||||
2024-01-15 14:30:00.126 ERROR LinkStatusService - === 退单操作失败 ===
|
||||
2024-01-15 14:30:00.127 ERROR LinkStatusService - codeNo=ABC12345, agentId=1001, 错误详情: 链接已经退过单
|
||||
```
|
||||
|
||||
## 🔗 相关接口
|
||||
|
||||
- [链接生成接口](./API文档.md#链接生成)
|
||||
- [链接状态查询接口](./链接状态接口测试.md)
|
||||
- [链接列表接口](./链接列表接口测试.md)
|
||||
- [JWT认证说明](./JWT认证使用说明.md)
|
||||
Reference in New Issue
Block a user