文档目录
优惠券功能页面

简介

本文件面向 DouPHP 小程序“优惠券”功能页面的开发与维护,覆盖以下目标:

  • 优惠券列表展示、领取、使用的全链路说明
  • 数据模型设计:类型(满减券/折扣券/现金券)、使用条件(最低消费、适用商品范围、有效期)、状态管理(未使用/已使用/已过期)
  • 领取业务逻辑:用户资格校验、库存控制、防重复领取
  • 使用流程:购物车集成与订单结算时的选择与应用
  • 用户体验优化:分类筛选、搜索、到期提醒等
  • 常见问题:冲突处理、退款恢复、异常修复

项目结构

围绕优惠券的小程序端能力由 API 层控制器、前台服务与核心服务共同实现,路由集中在模块声明式路由文件中;订单结算时通过 CheckoutService 完成核销。

graph TB
subgraph "小程序前端"
WX["小程序页面"]
end
subgraph "API 层"
R["路由: coupon.php"]
AC["CouponController (API)"]
UC["UserController (API)"]
end
subgraph "前台服务"
FS["Front CouponService"]
end
subgraph "核心服务"
CS["Core CouponService"]
CE["Core CouponEligibility"]
end
subgraph "数据层"
DB1["表: coupon"]
DB2["表: coupon_log"]
end
subgraph "订单结算"
CO["CheckoutService"]
end
WX --> R
R --> AC
R --> UC
AC --> FS
UC --> FS
FS --> CS
FS --> DB2
CS --> DB1
CS --> DB2
CO --> CE
CO --> DB2

核心组件

  • API 控制器
    • 优惠券主控制器:提供列表占位与领取接口
    • 会员侧控制器:返回分页的优惠券列表数据
  • 前台服务
    • 领取防重与入库
    • 构建会员优惠券列表(含类型、金额、有效期、状态)
  • 核心服务
    • 优惠券列表与详情、折扣计算、状态判定、过期判断、编号生成
    • 使用资格判定:时间窗、首单限制、范围命中、最低消费门槛
  • 订单结算
    • 校验可用后核销并写入使用记录

架构总览

小程序端通过声明式路由访问 API,API 控制器调用前台服务进行领取与列表组装,前台服务再委托核心服务完成复杂逻辑(折扣计算、状态判定、资格校验)。订单结算阶段由 CheckoutService 统一校验并使用优惠券。

sequenceDiagram
participant M as "小程序"
participant R as "路由(coupon.php)"
participant C as "CouponController(API)"
participant S as "Front CouponService"
participant Core as "Core CouponService"
participant DB as "数据库"
M->>R : POST /api/?route=coupon/claim
R->>C : claim(id)
C->>S : claimCouponIfNew(userId, id, ip)
S->>DB : 检查是否已领取
alt 未领取
S->>DB : 插入 coupon_log(user_id, coupon_id, claimed_at, ip)
else 已领取
S-->>C : 直接返回
end
C->>Core : getCouponList(userId)
Core->>DB : 查询 coupon(有效且启用)
Core-->>C : 返回带状态的券列表
C-->>M : 成功响应

详细组件分析

数据模型设计

  • 优惠券主表(coupon)
    • 关键字段:名称、编号、类型(满减/折扣/现金)、面值或折扣率、最低消费门槛、开始/结束时间、简介、排序、状态
    • 参考字段映射与可填充字段定义
  • 领取/使用记录表(coupon_log)
    • 关键字段:用户ID、券ID、领取时间、IP、创建时间、状态、使用时间、关联订单号
  • 类型与状态
    • 类型:百分比折扣、固定金额减免
    • 状态:未使用、已使用、已过期(由服务根据时间与使用记录判定)

优惠券列表展示

  • 小程序列表接口
    • 会员侧接口返回分页的优惠券列表,包含券名、编号、类型、金额/折扣、条件、起止日期、简介与状态
  • 列表数据来源
    • 从 coupon_log 中按用户拉取,并关联 coupon 表补齐信息
    • 使用核心服务的 status 方法计算每条券的状态
flowchart TD
Start(["进入会员优惠券页"]) --> Load["加载分页参数"]
Load --> Query["查询 coupon_log(user_id) 分页"]
Query --> Map["关联 coupon 表补齐信息"]
Map --> Status["调用 status 计算状态"]
Status --> Render["渲染列表(类型/金额/条件/有效期/状态)"]

优惠券领取

  • 入口与路由
    • 小程序通过 POST /api/?route=coupon/claim 提交领取请求
  • 防重复领取
    • 前台服务在插入前检查 coupon_log 是否存在该用户+券的记录
  • 入库字段
    • 用户ID、券ID、领取时间、客户端IP、创建时间
  • 返回结果
    • 成功后返回当前用户的券列表(用于刷新界面)
sequenceDiagram
participant App as "小程序"
participant API as "CouponController(API)"
participant FS as "Front CouponService"
participant DB as "数据库"
App->>API : POST claim(id)
API->>FS : claimCouponIfNew(userId, id, ip)
FS->>DB : 检查是否存在 user_id + coupon_id
alt 不存在
FS->>DB : 插入 coupon_log(...)
else 存在
FS-->>API : 忽略重复
end
API-->>App : 成功(可选携带券列表)

优惠券使用(结算)

  • 资格判定
    • 时间有效性、首单限制、范围命中(全部/模块/分类/商品)、最低消费门槛
  • 折扣计算
    • 百分比折扣:按比例扣减并可设置上限;固定金额:直接减去面值
  • 核销与记录
    • 校验通过后更新 coupon_log 的使用时间与状态,并写入订单明细
flowchart TD
A["选择优惠券"] --> B{"资格判定<br/>时间/首单/范围/门槛"}
B -- 否 --> E["不可用提示"]
B -- 是 --> C["计算折扣金额"]
C --> D{"折扣>0 ?"}
D -- 否 --> E
D -- 是 --> F["更新 coupon_log 使用状态"]
F --> G["写入订单优惠明细"]
G --> H["完成结算"]

用户体验优化建议

  • 分类筛选:基于 scope_type/scope_value 在前端提供“全品类/某分类/指定商品”的快速筛选
  • 搜索:支持按券名、编号模糊检索
  • 到期提醒:对即将过期的券高亮提示,并在列表中标注剩余天数
  • 状态可视化:未使用/已使用/已过期以不同标签与颜色区分
  • 空态引导:无可用券时提供领取入口或活动入口

依赖关系分析

  • 控制器依赖服务:API 控制器依赖前台服务与核心服务
  • 服务依赖数据:前台服务负责领取与列表拼装,核心服务负责折扣与状态
  • 订单结算依赖资格判定:CheckoutService 使用 CouponEligibility 进行可用性判断
graph LR
AC["API CouponController"] --> FS["Front CouponService"]
UC["API UserController"] --> FS
FS --> CS["Core CouponService"]
CS --> DB1["coupon"]
FS --> DB2["coupon_log"]
CO["CheckoutService"] --> CE["CouponEligibility"]
CE --> DB1
CO --> DB2

性能考虑

  • 列表分页:会员券列表采用分页查询,避免一次性加载过多数据
  • 索引建议:对 coupon_log.user_id、coupon_log.coupon_id、coupon.status、coupon.start_at/end_at 建立合适索引以提升查询效率
  • 缓存策略:热门券列表可考虑短期缓存,减少高频读取压力
  • 折扣计算:百分比折扣的上限与精度需统一配置,避免浮点误差

故障排查指南

  • 领取失败或重复领取
    • 检查 coupon_log 是否已有该用户+券的记录;确认领取接口幂等性
  • 券不可用
    • 核对时间窗口、是否首单限制、范围是否命中、是否满足最低消费
  • 结算未生效
    • 确认 CheckoutService 是否正确调用资格判定与核销逻辑
  • 状态异常
    • 检查 coupon_log.used_at 与 coupon.end_at 是否一致;必要时手动修复状态

结论

DouPHP 小程序优惠券功能通过清晰的职责分层实现了“列表—领取—使用”的完整闭环:API 层暴露稳定接口,前台服务保障领取幂等与列表拼装,核心服务负责折扣与状态判定,订单结算阶段统一核销。配合合理的索引与缓存策略,可在保证正确性的同时获得良好性能。后续可按“分类筛选、搜索、到期提醒”等方向持续优化用户体验。

附录

  • 关键接口一览
    • 领取:POST /api/?route=coupon/claim
    • 会员券列表:GET /api/?route=user/coupon
  • 相关视图与样式
    • 后台模板与样式位于 theme 与 admin/view 下,可按需扩展
添加日期:2026-10-05