diff --git a/docs/coupon_exchange_api_doc.md b/docs/coupon_exchange_api_doc.md new file mode 100644 index 000000000..564813b65 --- /dev/null +++ b/docs/coupon_exchange_api_doc.md @@ -0,0 +1,86 @@ +# 优惠券兑换 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 对象),其中包含接口处理的状态码、提示信息以及新发放的优惠券明细。 + +### 成功响应示例 +```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 | `您当前所在站点不支持兑换该券` | + +```json +{ + "code": 500, + "msg": "用户积分不足,仅剩余 100 积分" +} +``` + +--- + +## 业务逻辑说明 + +本接口在服务端实现了以下前置校验与扣除逻辑: +1. **幂等性判定**:如果之前已有相同的 `requestId` 被成功处理过,将直接返回上次处理并落库的该张优惠券数据,不对积分和库存进行额外消耗。 +2. **时效与库存判定**:若该券已下架、不在兑换时间范围内,或余量已被耗穿,则终止请求并抛出异常。 +3. **频次限制判定**:验证该用户对本模板的单日 (`dailyLimit`)、单月 (`monthlyLimit`) 及总兑换 (`totalLimit`) 限流次数表现。 +4. **事务与原子操作**:在单次事务中执行“扣减用户积分”与“扣减优惠券剩余库存/新增用户持券记录”的原子操作,确保资产的一致性。 diff --git a/jsowell-charge-ui b/jsowell-charge-ui new file mode 160000 index 000000000..7881ac11f --- /dev/null +++ b/jsowell-charge-ui @@ -0,0 +1 @@ +Subproject commit 7881ac11ff7c4b2842b866641aa62be64bf7a945