7.14 兑换福利【未授权拦截通过,待登录态联调】

POST /tieup/api/v1/benefit-redemptions

鉴权:需要 Authorization: Bearer <access_token>

请求头:

Idempotency-Key: benefit_10001_20260623143000_x7f9k2

实物福利请求体示例:

{
  "benefit_id": 30001,
  "receiver_name": "张三",
  "receiver_phone": "13800000000",
  "detail_address": "上海市黄浦区详细地址",
  "email_snapshot": "fan@example.com"
}

虚拟福利请求体示例:

{
  "benefit_id": 30002,
  "email_snapshot": "fan@example.com"
}

请求参数:

参数 类型 必填 说明
benefit_id integer 要兑换的福利 ID
address_id integer 收货地址 ID;实物福利可传,虚拟福利不需要
receiver_name string 收货人姓名;实物福利未传 address_id 时必填
receiver_phone string 收货人手机号;实物福利未传 address_id 时必填,必须符合手机号格式
detail_address string 详细地址;实物福利未传 address_id 时必填
email_snapshot string 邮箱快照;need_email=1 的福利必填,必须是单个合法邮箱;与收货地址要求独立

响应字段:

字段 类型 说明
redemption_id integer 福利兑换记录 ID
redemption_no string 福利兑换编号
benefit_id integer 福利 ID
benefit_title string 福利标题
benefit_type integer/null 福利类型:1=实物,2=虚拟
redemption_status integer 福利兑换状态:1=待发放,2=已发放,3=已取消,4=已退款
candy_amount_snapshot string 兑换糖果快照;达标福利固定为 0.00
address_snapshot object/null 兑换时保存的收货地址快照,虚拟福利为空;新直传地址场景包含 receiver_namereceiver_phonedetail_address,使用 address_id 或历史数据时可能包含省市区等扩展字段
address_snapshot.receiver_name string 收货人姓名
address_snapshot.receiver_phone string 收货人手机号
address_snapshot.detail_address string 详细地址
email_snapshot string 兑换时保存的邮箱快照;未填写时为空字符串
condition_type_snapshot string 兑换时福利条件类型快照
condition_value_snapshot integer 兑换时福利条件目标值快照
progress_value_snapshot integer 兑换时粉丝历史累计进度快照
progress_snapshot object 兑换时完整进度快照
progress_snapshot.condition_type string 兑换时福利条件类型
progress_snapshot.current_value integer 兑换时粉丝历史累计进度值
progress_snapshot.target_value integer 兑换时福利条件目标值
progress_snapshot.percent integer 兑换时进度百分比,最大 100
progress_snapshot.remaining_value integer 兑换时距离达标还差的数值
progress_snapshot.remaining_text string/null 兑换时未达标提示文案;已达标时为空
progress_snapshot.is_redeemable integer 兑换时是否可兑换:1=是,2=否
progress_snapshot.is_redeemed integer 兑换时是否已兑换:1=是,2=否
fulfillment_remark string/null 偶像发放备注,待发放时为空

响应示例:

{
  "code": 200,
  "message": "成功",
  "data": {
    "redemption_id": 60001,
    "redemption_no": "BR202606170001",
    "benefit_id": 30001,
    "benefit_title": "亲笔签名照",
    "benefit_type": 1,
    "fan_user_id": 10001,
    "artist_id": 20001,
    "candy_amount_snapshot": "0.00",
    "address_snapshot": {
      "receiver_name": "张三",
      "receiver_phone": "13800000000",
      "detail_address": "上海市黄浦区详细地址"
    },
    "email_snapshot": "fan@example.com",
    "fulfillment_remark": null,
    "condition_type_snapshot": "subscription_months",
    "condition_value_snapshot": 5,
    "progress_value_snapshot": 5,
    "progress_snapshot": {
      "condition_type": "subscription_months",
      "current_value": 5,
      "target_value": 5,
      "percent": 100,
      "remaining_value": 0,
      "remaining_text": null,
      "is_redeemable": 1,
      "is_redeemed": 2
    },
    "status": 1,
    "redemption_status": 1,
    "redeemed_at": "2026-06-23 14:30:00",
    "fulfilled_at": null
  }
}

业务规则:

  • 达标后粉丝可任意时间兑换,兑换本身不扣糖果;candy_spent 只是达标条件之一。
  • 不管福利什么时候创建,达标判断都按粉丝历史上对该偶像的全部有效累计数据计算。例如今天新增“订阅满 5 个月”,粉丝过去已累计订阅 5 个月,则立即可兑换。
  • 订阅按累计有效订阅天数每 30 天折算 1 个月;提问按未退款有效提问数;视频通话按已完成实际分钟;糖果消耗按未取消/未退款的历史有效消耗统计。
  • 实物福利必须提供收货地址,服务端支持 address_id 读取当前用户启用地址,也支持请求体直接传 receiver_namereceiver_phonedetail_address,最终保存兑换时地址快照。
  • address_id 只用于兑换时读取用户地址,查询接口以 address_snapshot 为准;用户后续修改或删除地址簿不会影响历史兑换快照,程序也不会把快照反向恢复成用户地址簿记录。
  • 需要邮箱的福利必须提供 email_snapshot,邮箱要求与收货地址要求独立;实物福利可以同时要求地址和邮箱,虚拟福利也可以要求邮箱。
  • 兑换时锁定 tieup_benefit 行并检查库存;同一 fan_user_id + benefit_id 或同一 fan_user_id + Idempotency-Key 不允许重复创建兑换记录,数据库唯一索引作为并发兜底。
  • 偶像自行兑现福利,程序只记录待发放/已发放状态、地址快照和发放备注。