13 KiB
13 KiB
Planting Service API 文档
目录
概述
- Base URL:
http://localhost:3003/api/v1 - 协议: HTTP/HTTPS
- 数据格式: JSON
- 字符编码: UTF-8
Swagger 文档
启动服务后访问: http://localhost:3003/api/docs
认证
所有业务 API(除健康检查外)需要 JWT Bearer Token 认证。
请求头
Authorization: Bearer <jwt_token>
Token 结构
{
"id": "1",
"username": "user@example.com",
"iat": 1699999999,
"exp": 1700003599
}
通用响应格式
成功响应
{
"data": { ... },
"timestamp": "2024-11-30T10:00:00.000Z"
}
错误响应
{
"statusCode": 400,
"message": "错误信息",
"error": "Bad Request",
"timestamp": "2024-11-30T10:00:00.000Z"
}
API 端点
健康检查
GET /health
检查服务健康状态。
请求
GET /api/v1/health
响应
{
"status": "ok",
"timestamp": "2024-11-30T10:00:00.000Z",
"service": "planting-service"
}
GET /health/ready
检查服务就绪状态。
请求
GET /api/v1/health/ready
响应
{
"status": "ready",
"timestamp": "2024-11-30T10:00:00.000Z"
}
订单管理
POST /planting/orders
创建认种订单。
请求
POST /api/v1/planting/orders
Authorization: Bearer <token>
Content-Type: application/json
{
"treeCount": 5
}
参数说明
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| treeCount | number | 是 | 认种数量,1-1000 |
响应
{
"orderNo": "PO202411300001",
"userId": "1",
"treeCount": 5,
"totalAmount": 10995,
"status": "CREATED",
"createdAt": "2024-11-30T10:00:00.000Z"
}
错误码
| 状态码 | 说明 |
|---|---|
| 400 | 参数错误(数量超限) |
| 400 | 超过个人最大认种数量限制(1000棵) |
| 400 | 余额不足 |
| 401 | 未授权 |
GET /planting/orders
查询用户订单列表。
请求
GET /api/v1/planting/orders?page=1&pageSize=10
Authorization: Bearer <token>
参数说明
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| page | number | 否 | 1 | 页码 |
| pageSize | number | 否 | 10 | 每页数量,最大100 |
响应
[
{
"orderNo": "PO202411300001",
"treeCount": 5,
"totalAmount": 10995,
"status": "CREATED",
"selectedProvince": null,
"selectedCity": null,
"createdAt": "2024-11-30T10:00:00.000Z"
},
{
"orderNo": "PO202411300002",
"treeCount": 3,
"totalAmount": 6597,
"status": "MINING_ENABLED",
"selectedProvince": "广东省",
"selectedCity": "广州市",
"createdAt": "2024-11-25T08:00:00.000Z"
}
]
GET /planting/orders/:orderNo
查询订单详情。
请求
GET /api/v1/planting/orders/PO202411300001
Authorization: Bearer <token>
响应
{
"orderNo": "PO202411300001",
"userId": "1",
"treeCount": 5,
"totalAmount": 10995,
"status": "FUND_ALLOCATED",
"selectedProvince": "广东省",
"selectedCity": "广州市",
"provinceCitySelectedAt": "2024-11-30T10:01:00.000Z",
"provinceCityConfirmedAt": "2024-11-30T10:01:05.000Z",
"paidAt": "2024-11-30T10:02:00.000Z",
"fundAllocatedAt": "2024-11-30T10:02:01.000Z",
"allocations": [
{
"targetType": "POOL",
"amount": 9895.5
},
{
"targetType": "OPERATION",
"amount": 549.75
}
],
"createdAt": "2024-11-30T10:00:00.000Z"
}
POST /planting/orders/:orderNo/select-province-city
选择省市(开始5秒倒计时)。
请求
POST /api/v1/planting/orders/PO202411300001/select-province-city
Authorization: Bearer <token>
Content-Type: application/json
{
"provinceCode": "440000",
"provinceName": "广东省",
"cityCode": "440100",
"cityName": "广州市"
}
参数说明
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| provinceCode | string | 是 | 省份代码 |
| provinceName | string | 是 | 省份名称 |
| cityCode | string | 是 | 城市代码 |
| cityName | string | 是 | 城市名称 |
响应
{
"success": true,
"message": "省市选择成功,请在5秒后确认",
"expiresAt": "2024-11-30T10:01:05.000Z"
}
错误码
| 状态码 | 说明 |
|---|---|
| 400 | 订单状态不允许选择省市 |
| 404 | 订单不存在 |
| 403 | 无权操作此订单 |
POST /planting/orders/:orderNo/confirm-province-city
确认省市选择(需在选择5秒后调用)。
请求
POST /api/v1/planting/orders/PO202411300001/confirm-province-city
Authorization: Bearer <token>
响应
{
"success": true,
"message": "省市确认成功"
}
错误码
| 状态码 | 说明 |
|---|---|
| 400 | 还需等待5秒才能确认 |
| 400 | 订单状态不允许确认 |
| 404 | 订单不存在 |
POST /planting/orders/:orderNo/pay
支付订单。
请求
POST /api/v1/planting/orders/PO202411300001/pay
Authorization: Bearer <token>
响应
{
"orderNo": "PO202411300001",
"status": "POOL_SCHEDULED",
"paidAt": "2024-11-30T10:02:00.000Z",
"totalAmount": 10995,
"allocations": [
{
"targetType": "POOL",
"amount": 9895.5,
"description": "资金池"
},
{
"targetType": "OPERATION",
"amount": 549.75,
"description": "运营费用"
},
{
"targetType": "PROVINCE_AUTH",
"amount": 65.97,
"description": "省代奖励"
},
{
"targetType": "CITY_AUTH",
"amount": 32.985,
"description": "市代奖励"
},
{
"targetType": "COMMUNITY",
"amount": 54.975,
"description": "社区长奖励"
},
{
"targetType": "REFERRAL_L1",
"amount": 164.925,
"description": "一级推荐奖励"
},
{
"targetType": "REFERRAL_L2",
"amount": 109.95,
"description": "二级推荐奖励"
},
{
"targetType": "REFERRAL_L3",
"amount": 54.975,
"description": "三级推荐奖励"
},
{
"targetType": "PLATFORM",
"amount": 32.985,
"description": "平台费用"
},
{
"targetType": "RESERVE",
"amount": 32.985,
"description": "储备金"
}
],
"batchInfo": {
"batchNo": "BATCH202411300001",
"scheduledInjectionTime": "2024-12-05T00:00:00.000Z"
}
}
错误码
| 状态码 | 说明 |
|---|---|
| 400 | 余额不足 |
| 400 | 订单状态不允许支付 |
| 400 | 请先确认省市选择 |
| 404 | 订单不存在 |
POST /planting/orders/:orderNo/cancel
取消订单(仅未支付订单可取消)。
请求
POST /api/v1/planting/orders/PO202411300001/cancel
Authorization: Bearer <token>
响应
{
"success": true,
"message": "订单取消成功"
}
错误码
| 状态码 | 说明 |
|---|---|
| 400 | 订单状态不允许取消(已支付) |
| 404 | 订单不存在 |
| 403 | 无权操作此订单 |
持仓查询
GET /planting/position
查询用户持仓信息。
请求
GET /api/v1/planting/position
Authorization: Bearer <token>
响应
{
"totalTreeCount": 15,
"effectiveTreeCount": 12,
"pendingTreeCount": 3,
"firstMiningStartAt": "2024-11-20T00:00:00.000Z",
"distributions": [
{
"provinceCode": "440000",
"provinceName": "广东省",
"cityCode": "440100",
"cityName": "广州市",
"treeCount": 10
},
{
"provinceCode": "310000",
"provinceName": "上海市",
"cityCode": "310100",
"cityName": "上海市",
"treeCount": 5
}
]
}
字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
| totalTreeCount | number | 总认种数量 |
| effectiveTreeCount | number | 有效数量(已开始挖矿) |
| pendingTreeCount | number | 待生效数量 |
| firstMiningStartAt | string | 首次挖矿开始时间 |
| distributions | array | 按省市分布 |
错误码
HTTP 状态码
| 状态码 | 说明 |
|---|---|
| 200 | 成功 |
| 201 | 创建成功 |
| 400 | 请求参数错误 |
| 401 | 未授权 |
| 403 | 禁止访问 |
| 404 | 资源不存在 |
| 500 | 服务器内部错误 |
业务错误码
| 错误信息 | 说明 |
|---|---|
| 超过个人最大认种数量限制 | 单用户最多认种1000棵 |
| 余额不足 | USDT 余额不足以支付 |
| 订单不存在 | 订单号无效或已删除 |
| 无权操作此订单 | 订单不属于当前用户 |
| 订单状态不允许此操作 | 状态机校验失败 |
| 还需等待5秒才能确认 | 省市选择5秒机制 |
数据模型
PlantingOrder
interface PlantingOrder {
orderNo: string; // 订单号,格式:PO + 年月日 + 序号
userId: string; // 用户ID
treeCount: number; // 认种数量
totalAmount: number; // 总金额 (USDT)
status: PlantingOrderStatus;
selectedProvince?: string; // 选择的省份
selectedCity?: string; // 选择的城市
provinceCitySelectedAt?: Date;
provinceCityConfirmedAt?: Date;
paidAt?: Date;
fundAllocatedAt?: Date;
poolInjectionBatchId?: string;
poolInjectionScheduledTime?: Date;
poolInjectionActualTime?: Date;
poolInjectionTxHash?: string;
miningEnabledAt?: Date;
createdAt: Date;
updatedAt: Date;
}
PlantingOrderStatus
enum PlantingOrderStatus {
CREATED = 'CREATED',
PROVINCE_CITY_SELECTED = 'PROVINCE_CITY_SELECTED',
PROVINCE_CITY_CONFIRMED = 'PROVINCE_CITY_CONFIRMED',
PAID = 'PAID',
FUND_ALLOCATED = 'FUND_ALLOCATED',
POOL_SCHEDULED = 'POOL_SCHEDULED',
POOL_INJECTED = 'POOL_INJECTED',
MINING_ENABLED = 'MINING_ENABLED',
CANCELLED = 'CANCELLED'
}
FundAllocationTargetType
enum FundAllocationTargetType {
POOL = 'POOL', // 资金池 90%
OPERATION = 'OPERATION', // 运营 5%
PROVINCE_AUTH = 'PROVINCE_AUTH', // 省代 0.6%
CITY_AUTH = 'CITY_AUTH', // 市代 0.3%
COMMUNITY = 'COMMUNITY', // 社区长 0.5%
REFERRAL_L1 = 'REFERRAL_L1', // 一级推荐 1.5%
REFERRAL_L2 = 'REFERRAL_L2', // 二级推荐 1.0%
REFERRAL_L3 = 'REFERRAL_L3', // 三级推荐 0.5%
PLATFORM = 'PLATFORM', // 平台 0.3%
RESERVE = 'RESERVE' // 储备 0.3%
}
PlantingPosition
interface PlantingPosition {
userId: string;
totalTreeCount: number;
effectiveTreeCount: number;
pendingTreeCount: number;
firstMiningStartAt?: Date;
distributions: PositionDistribution[];
}
interface PositionDistribution {
provinceCode: string;
provinceName: string;
cityCode: string;
cityName: string;
treeCount: number;
}
使用示例
cURL 示例
# 1. 创建订单
curl -X POST http://localhost:3003/api/v1/planting/orders \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"treeCount": 5}'
# 2. 选择省市
curl -X POST http://localhost:3003/api/v1/planting/orders/PO202411300001/select-province-city \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"provinceCode": "440000",
"provinceName": "广东省",
"cityCode": "440100",
"cityName": "广州市"
}'
# 3. 等待5秒后确认省市
sleep 5
curl -X POST http://localhost:3003/api/v1/planting/orders/PO202411300001/confirm-province-city \
-H "Authorization: Bearer $TOKEN"
# 4. 支付订单
curl -X POST http://localhost:3003/api/v1/planting/orders/PO202411300001/pay \
-H "Authorization: Bearer $TOKEN"
# 5. 查询持仓
curl http://localhost:3003/api/v1/planting/position \
-H "Authorization: Bearer $TOKEN"
JavaScript/TypeScript 示例
import axios from 'axios';
const api = axios.create({
baseURL: 'http://localhost:3003/api/v1',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
// 创建订单
const { data: order } = await api.post('/planting/orders', { treeCount: 5 });
// 选择省市
await api.post(`/planting/orders/${order.orderNo}/select-province-city`, {
provinceCode: '440000',
provinceName: '广东省',
cityCode: '440100',
cityName: '广州市'
});
// 等待5秒
await new Promise(resolve => setTimeout(resolve, 5000));
// 确认省市
await api.post(`/planting/orders/${order.orderNo}/confirm-province-city`);
// 支付
const { data: payResult } = await api.post(`/planting/orders/${order.orderNo}/pay`);
console.log('支付成功,资金分配:', payResult.allocations);