Files
jsowell-charger-web/docs/coupon_exchange_api_doc.md
2026-03-11 15:03:21 +08:00

3.5 KiB
Raw Blame History

优惠券兑换 API 文档

本文档提供了用户端兑换优惠券接口的详细说明。当前接口主要用于 App 或小程序中,用户消耗对应的积分来兑换相应的优惠券(如洗车券、折扣券等)。


接口说明

接口路径: /coupon/exchange 请求方法: POST 功能描述: 用户通过指定的积分兑换某一种优惠券。系统将自动扣除该用户的积分并向其发放对应的一张优惠券。该接口具有防重放设计,依赖 requestId 保证请求幂等性。

接口鉴权

建议配合 JWT 认证/统一网关身份校验后使用。(接口本身会读取入参 memberId,在实际部署时可能需要由网关/会话态中解析并传递此参数,防止越权)。


请求参数

参数名称 参数位置 参数类型 是否必填 示例值 描述说明
memberId Query/Form String u_1001 会员用户的全局唯一标识
templateId Query/Form Long 102 需要兑换的优惠券所属的券模板 ID
requestId Query/Form String 9b1deb4d-3b7d-... 客户端生成的防重放幂等键 (UUID),防止网络原因导致的重复提交和重复扣积分

注意事项

  • requestId 务必保证在至少一次完整的业务生命周期内保持唯一,建议客户端每次通过点击或提交生成唯一的 UUID 字符串。
  • templateId 必须处于“上架”状态,并处于允许兑换的时间范围内。

响应数据

返回标准的 AjaxResult (或标准格式的 JSON 对象),其中包含接口处理的状态码、提示信息以及新发放的优惠券明细。

成功响应示例

{
  "code": 200,
  "msg": "操作成功",
  "data": {
    "id": 50012,
    "couponNo": "CP20260311ABCDE",
    "exchangeRequestId": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
    "templateId": 102,
    "memberId": "u_1001",
    "couponType": 1,
    "pointsCost": 500.00,
    "discountRate": null,
    "status": 0,
    "source": 1,
    "exchangeTime": "2026-03-11 10:30:15",
    "expireTime": "2026-04-10 10:30:15",
    "useTime": null,
    "useStoreId": null,
    "useOperator": null
  }
}

失败响应示例

场景 Code Msg 示例
积分不足 500 用户积分不足,仅剩余 100 积分
券库存不足 500 该券已兑完
兑换次数达上限 500 此券单日仅支持兑换 1 次 / 累计兑换次数已达上限
模板不存在或已下架 500 此券无法兑换
不在指定范围内 500 您当前所在站点不支持兑换该券
{
  "code": 500,
  "msg": "用户积分不足,仅剩余 100 积分"
}

业务逻辑说明

本接口在服务端实现了以下前置校验与扣除逻辑:

  1. 幂等性判定:如果之前已有相同的 requestId 被成功处理过,将直接返回上次处理并落库的该张优惠券数据,不对积分和库存进行额外消耗。
  2. 时效与库存判定:若该券已下架、不在兑换时间范围内,或余量已被耗穿,则终止请求并抛出异常。
  3. 频次限制判定:验证该用户对本模板的单日 (dailyLimit)、单月 (monthlyLimit) 及总兑换 (totalLimit) 限流次数表现。
  4. 事务与原子操作:在单次事务中执行“扣减用户积分”与“扣减优惠券剩余库存/新增用户持券记录”的原子操作,确保资产的一致性。