vending-machine/贩卖机硬件API对接文档.md
2026-04-08 20:45:41 +08:00

259 lines
6.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 贩卖机硬件 API 对接文档
## 基本信息
- 基础地址:`https://your-domain.com/api/vending`
- 数据格式JSON
- 字符编码UTF-8
- 所有请求需在 Header 中携带 `X-Machine-Id`(贩卖机唯一标识)
## 通用响应格式
```json
{
"success": true,
"data": {},
"message": ""
}
```
| 字段 | 类型 | 说明 |
|------|------|------|
| success | boolean | 请求是否成功 |
| data | object/null | 响应数据,失败时可能为 null |
| message | string | 提示信息,失败时为错误原因 |
---
## 对接流程
```
用户打开 APP 展示会员二维码(含 token5 分钟有效)
贩卖机扫描二维码,提取 token
调用【接口1】获取用户信息
├── 返回 isLocked: true → 提示"该用户已在其他机器操作中"
├── 返回 isMember: false → 提示"非会员用户"(正常情况不会出现)
└── 返回正常用户信息 + 优惠券列表
用户选择商品,贩卖机根据优惠券信息判断是否使用优惠券
(每次只能使用一张,优先使用快到期、抵扣金额最大的)
用户完成支付(或取消/失败)
调用【接口2】上报支付结果无论成功或失败都必须调用
```
---
## 接口1获取用户信息
贩卖机扫描用户二维码后,通过此接口获取用户会员信息和可用优惠券列表。
调用成功后,系统会自动锁定该用户(防止同时在多台机器操作),并使二维码失效(防止截图盗刷)。
### 请求
```
POST /api/vending/user-info
```
**Headers**
| 名称 | 必填 | 说明 |
|------|------|------|
| Content-Type | 是 | application/json |
| X-Machine-Id | 是 | 贩卖机唯一标识 |
**Body**
```json
{
"qrcodeToken": "用户二维码中包含的 token 字符串"
}
```
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| qrcodeToken | string | 是 | 从用户二维码中解析出的 token |
### 响应
**成功(正常用户):**
```json
{
"success": true,
"data": {
"userId": "user_abc123",
"isMember": true,
"isLocked": false,
"coupons": [
{
"couponId": "coupon_001",
"type": "thresholddiscount",
"thresholdAmount": 100.00,
"discountAmount": 5.00,
"expireAt": "2026-04-30T23:59:59Z"
},
{
"couponId": "coupon_002",
"type": "directdiscount",
"thresholdAmount": null,
"discountAmount": 3.00,
"expireAt": "2026-05-15T23:59:59Z"
}
]
},
"message": ""
}
```
**成功(用户已被其他机器锁定):**
```json
{
"success": true,
"data": {
"userId": "user_abc123",
"isMember": true,
"isLocked": true,
"coupons": []
},
"message": ""
}
```
### 响应字段说明
| 字段 | 类型 | 说明 |
|------|------|------|
| userId | string | 用户唯一标识 |
| isMember | boolean | 是否为会员 |
| isLocked | boolean | 是否已被其他贩卖机锁定。为 true 时应提示用户"已在其他机器操作中" |
| coupons | array | 用户可用优惠券列表(已按规则排序) |
**优惠券字段说明:**
| 字段 | 类型 | 说明 |
|------|------|------|
| couponId | string | 优惠券 ID支付回调时需回传 |
| type | string | 优惠券类型:`thresholddiscount`(满减券)、`directdiscount`(抵扣券) |
| thresholdAmount | decimal/null | 满减门槛金额。满减券时有值,抵扣券时为 null |
| discountAmount | decimal | 抵扣金额 |
| expireAt | string | 到期时间UTCISO 8601 格式) |
**优惠券排序规则(已由服务端排好序):**
1. 到期时间升序(快到期的排前面)
2. 到期时间相同时,抵扣金额降序(金额大的排前面)
**优惠券使用规则:**
- 每次交易只能使用一张优惠券
- 满减券:用户消费金额 ≥ thresholdAmount 时可使用
- 抵扣券:无门槛,直接抵扣
- 建议优先使用列表中排在前面的优惠券(已按最优顺序排列)
### 错误响应
| 场景 | success | message |
|------|---------|---------|
| 二维码无效或已过期 | false | 二维码无效或已过期 |
| 用户不存在 | false | 用户不存在 |
---
## 接口2支付结果回调
用户在贩卖机完成支付后(无论成功、失败或取消),贩卖机必须调用此接口上报支付结果。
系统会根据支付结果:
- 支付成功:发放积分、核销优惠券、解除用户锁定
- 支付失败/取消:仅解除用户锁定
**重要无论支付结果如何都必须调用此接口否则用户将保持锁定状态10 分钟后自动超时解锁)。**
### 请求
```
POST /api/vending/payment-callback
```
**Headers**
| 名称 | 必填 | 说明 |
|------|------|------|
| Content-Type | 是 | application/json |
| X-Machine-Id | 是 | 贩卖机唯一标识 |
**Body**
```json
{
"userId": "user_abc123",
"machineId": "machine_001",
"paymentAmount": 50.00,
"usedCouponId": "coupon_001",
"paymentStatus": "success",
"transactionId": "txn_20260408_001"
}
```
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| userId | string | 是 | 用户 ID从接口1获取 |
| machineId | string | 是 | 贩卖机 ID |
| paymentAmount | decimal | 是 | 用户实际支付金额(优惠券抵扣后的金额) |
| usedCouponId | string | 否 | 使用的优惠券 ID未使用时传 null 或不传 |
| paymentStatus | string | 是 | 支付状态:`success`(成功)、`failed`(失败)、`cancelled`(取消) |
| transactionId | string | 是 | 贩卖机端的交易流水号(用于对账) |
### 响应
**成功:**
```json
{
"success": true,
"data": null,
"message": "支付回调处理成功"
}
```
### 错误响应
| 场景 | success | message |
|------|---------|---------|
| 用户不存在 | false | 用户不存在 |
| 处理异常 | false | 支付回调处理失败 |
---
## 附录
### 用户锁定机制
- 调用接口1成功获取用户信息后系统自动锁定该用户
- 锁定期间其他贩卖机扫同一用户的二维码接口1会返回 `isLocked: true`
- 调用接口2后系统自动解除锁定
- 安全兜底:锁定 10 分钟后自动超时解锁防止贩卖机异常未调用接口2
### 二维码说明
- 二维码由用户 APP 端生成,有效期 5 分钟
- 二维码内容为一个 token 字符串,贩卖机扫码后提取该 token 调用接口1
- 每个二维码只能使用一次,扫码成功后立即失效
- 用户可重新生成新的二维码
### 积分发放规则
- 仅会员用户支付成功时发放积分
- 积分 = 支付金额 × 转换比(后台可配置,默认 1 元 = 1 积分)
- 积分发放由系统在接口2处理时自动完成无需贩卖机额外操作