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

6.9 KiB
Raw Permalink Blame History

贩卖机硬件 API 对接文档

基本信息

  • 基础地址:https://your-domain.com/api/vending
  • 数据格式JSON
  • 字符编码UTF-8
  • 所有请求需在 Header 中携带 X-Machine-Id(贩卖机唯一标识)

通用响应格式

{
  "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

{
  "qrcodeToken": "用户二维码中包含的 token 字符串"
}
字段 类型 必填 说明
qrcodeToken string 从用户二维码中解析出的 token

响应

成功(正常用户):

{
  "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": ""
}

成功(用户已被其他机器锁定):

{
  "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

{
  "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 贩卖机端的交易流水号(用于对账)

响应

成功:

{
  "success": true,
  "data": null,
  "message": "支付回调处理成功"
}

错误响应

场景 success message
用户不存在 false 用户不存在
处理异常 false 支付回调处理失败

附录

用户锁定机制

  • 调用接口1成功获取用户信息后系统自动锁定该用户
  • 锁定期间其他贩卖机扫同一用户的二维码接口1会返回 isLocked: true
  • 调用接口2后系统自动解除锁定
  • 安全兜底:锁定 10 分钟后自动超时解锁防止贩卖机异常未调用接口2

二维码说明

  • 二维码由用户 APP 端生成,有效期 5 分钟
  • 二维码内容为一个 token 字符串,贩卖机扫码后提取该 token 调用接口1
  • 每个二维码只能使用一次,扫码成功后立即失效
  • 用户可重新生成新的二维码

积分发放规则

  • 仅会员用户支付成功时发放积分
  • 积分 = 支付金额 × 转换比(后台可配置,默认 1 元 = 1 积分)
  • 积分发放由系统在接口2处理时自动完成无需贩卖机额外操作