前言

优惠券是典型的“看起来简单,生产很复杂”的业务。面试常问:

  • 优惠券怎么防止超发。
  • 下单时怎么锁定优惠券。
  • 支付失败后优惠券怎么返还。
  • 多张券叠加规则怎么设计。
  • 怎么防止批量薅羊毛。

优惠券生命周期

stateDiagram-v2
    [*] --> 待领取
    待领取 --> 已领取: 用户领取
    已领取 --> 已锁定: 下单使用
    已锁定 --> 已核销: 支付成功
    已锁定 --> 已领取: 支付失败/取消
    已领取 --> 已过期: 超过有效期

优惠券状态不能随意跳转,尤其是已核销不能再次使用。

领取怎么设计

领取要解决库存和资格问题。

常见校验:

  • 活动是否开始。
  • 用户是否满足资格。
  • 用户是否超过领取次数。
  • 总库存是否足够。
  • 是否命中风控规则。

并发领取常见方案:

方案 优点 缺点
数据库扣库存 简单 高并发压力大
Redis 预扣库存 性能好 需要补偿
MQ 排队领取 稳定 用户结果延迟

核销怎么设计

优惠券核销通常发生在支付成功后,而不是提交订单时直接最终核销。

下单时:

  • 校验券可用。
  • 锁定优惠券。
  • 记录订单和券关系。

支付成功:

  • 把锁定状态改为已核销。

支付失败或超时:

  • 释放锁定。

这样可以避免用户下单不支付却长期占用优惠券。

叠加规则

营销规则常见维度:

  • 满减券。
  • 折扣券。
  • 品类券。
  • 商品券。
  • 运费券。
  • 平台券和店铺券。

叠加规则可以分为:

  • 不可叠加。
  • 同类型不可叠加,不同类型可叠加。
  • 按优先级叠加。
  • 用户选择最优组合。

复杂营销建议抽象成规则引擎:

flowchart TD
    A[订单金额和商品明细] --> B[筛选可用券]
    B --> C[计算每张券优惠]
    C --> D[应用叠加规则]
    D --> E[返回最优优惠结果]

防薅羊毛

常见风险:

  • 批量注册。
  • 多账号领取。
  • 接码平台。
  • 异常设备。
  • 异常 IP。
  • 领券后批量下单退款。

防护措施:

  • 领取频率限制。
  • 用户实名或手机号校验。
  • 设备指纹。
  • 黑名单。
  • 风控评分。
  • 高风险订单人工审核。

高频面试题

优惠券为什么要有锁定状态?

因为用户下单后不一定支付。锁定状态可以防止同一张券被多个订单同时使用,又能在订单取消后释放。

怎么防止优惠券超发?

用 Redis 原子扣减、数据库唯一约束、领取记录去重和异步补偿共同保证。

优惠券过期怎么处理?

可以通过定时任务扫描,也可以查询时判断有效期。大规模场景通常定时归档加查询实时判断结合。

叠加规则怎么设计?

把规则从代码 if else 中抽象出来,按券类型、适用范围、优先级和互斥关系计算。

总结

优惠券营销的关键是状态机、库存控制、核销幂等、规则计算和风控。企业落地时,优惠券不是简单折扣字段,而是一个带生命周期、库存、资格、风控和财务影响的业务系统。