# 更新记录

更新日期 | 说明
---|---
2026-11-03 | 【[捞回活动](420_promotion_win_back.md)】移除独立配置模版的定时、手动圈人发箱，未完成任务不再续发；保留召回批次触达组发箱。已发宝箱查询、领取、充值加倍及旧回归只读接口不变，客户端无需修改接口。
2026-10-31 | 【[每日签到](404_promotion_daily_checkin.md#detail)】修复正时区（如 UTC+8 / UTC+9）商户连续签到次日被误判为"今天已签"、周期天数卡在第 0 天的问题，现按最近一次领取的真实日期（商户时区）判断连续，周期中途的会员不会被重置；接口字段与奖励规则不变。
2026-10-31 | 【[通行证](402_promotion_battle_pass.md)】【[大亨](405_promotion_magnate.md)】性能优化，接口字段与规则不变：通行证红点 / 可领项数使用的节点进度最多滞后约 30 秒（打开通行证页面时实时刷新），领取仍按实时进度判定；大亨详情中的下级人数 / 充值 / 投注统计最多滞后约 30 秒，自动发奖前仍实时复核，转盘等写操作不受影响。
2026-10-31 | 【[救济金](409_promotion_rescue_bonus.md)】【[周救济金](411_promotion_weekly_rescue_bonus.md)】性能优化，接口字段与规则不变：详情及红点中的净损改为短时缓存读取（今日 / 本周实时部分最多滞后约 10 秒；统计期刚结束的头 2 小时最多滞后约 3 分钟），领取接口始终按实时净损计算入账金额。
2026-10-31 | 【[全站洗码](407_promotion_rakeback.md)】【[每日签到](404_promotion_daily_checkin.md#detail)】性能优化，接口字段与规则不变：洗码自然日结算今日预览改读注单明细（几秒内可见）；昨天的待领在日界线后 10 秒起、会员首次访问时就地生成并立即可见，更早仍在领取期内的漏结算日子同次补齐，无后台批量任务；签到详情及红点的近 7 日投注最多滞后约 15 分钟（今日部分约 10 秒），领取仍按实时投注判定。
2026-10-30 | 【[活动列表](400_promotion.md#list)】新增活动投放设置：登录会员不在活动开放范围（推广商 / 渠道）或落在对照组时，该活动对其表现与未开启一致（列表、`enabled_kinds`、红点 / 可领项数、详情、领取、购买均不可用，领取 / 购买报「活动未启用」）。VIP、代理返佣、全站洗码、捞回活动不受影响。接口与字段不变。
2026-10-29 | 【[捞回活动](420_promotion_win_back.md)】修正尾段阈值语义：赠送金额继续递增，达到或超过关闭金额时，仅关闭该尾段宝箱的充值随机翻倍（`boost_enabled=false`）；不截断免费赠送金额，不影响普通档位，已发宝箱不重算。
2026-10-28 | 【[捞回活动](420_promotion_win_back.md)】宝箱详情及领取结果新增 `boost_enabled`；关闭时只可免费领取，状态为终态 `claimed_free`，不再展示充值翻倍入口或提供存款参与资格，建单也强校验开关。已发宝箱保持原快照；尾段递增免费赠送金额加入封顶。
2026-10-27 | 【[WagerTask 对象](201_wager_tasks.md#task)】`source_kind` 新增 `adjust`（后台新增打码要求，无入账、不出现在奖金列表），对应 `source=admin_wager_adjust`，该类任务 `amount` / `multiple` 均为 `0`，只按 `target_amount` 展示；**客户端需补充 `admin_wager_adjust` 的来源名称映射**。`terminal_reason` 新增 `admin_force_complete`（后台一键完成，奖金整体转入现金）。耗尽清理规则措辞同步：`recharge` / `adjust` 任务仅在现金与奖金都小于 `0.1` 时失效。接口路径与其它字段不变。
2026-10-26 | 【[投注排行榜](421_promotion_bet_rank.md)】截止日期改为**按榜**配置：Board 新增 `end_date`（该榜实际截止日，已按自然周期对齐到周日 / 月末，含当日）与 `ended`（当前自然周期已越过截止日、不再开新期）；头卡「截止于」请改用各榜 `end_date`。`detail.end_date` 保留为各启用榜中最晚的截止日（任一榜不限则为空）
2026-10-22 | 【[创建充值订单](200_finance.md#recharge_create)】巴西新增通道 `egpayglobal`，`product_code = PIX`，`pay_info` 为收银台支付页 URL（与 `pay4z` / `egpaybr` 同形态）。该通道仅接受**整数金额**，非整数下单返回业务错误。无新增字段。
2026-10-20 | 【[账号任务奖励](420_promotion_account_tasks.md#client)】IP／设备领取限额提示统一为「通知奖励已达上限」，不向玩家区分限制维度；限额及领取规则不变。
2026-10-20 | 【[账号任务奖励](420_promotion_account_tasks.md#client)】非 PWA 环境领取时提示并直接进入现有安装流程；失败后冷却 3 秒再重试，保留失败提示，领取结果不确定时仍先查询再重试。接口和资金规则不变。
2026-10-20 | 【[获取充值配置](200_finance.md#recharge_config)】【[创建充值订单](200_finance.md#recharge_create)】墨西哥新增通道 `egpaymx`，`product_code` 新增 `CASHIER`（`MXN`）：`pay_info` 为收银台支付页 URL，按链接跳转 / 内嵌打开。该通道按**实付金额**入账：玩家重复转账会生成新的充值订单（【[我的充值订单](200_finance.md#recharge_my)】可见），实付与下单金额不一致时订单 `amount` 以实付为准。无新增字段。
2026-10-19 | 【[投注排行榜](421_promotion_bet_rank.md)】已登录会员自己的积分改为**实时读取**：高于榜单快照时服务端把自己投影到应在名次（`me.projected=true`，`list` / `top` / `last` 同步体现），投注结算后刷新即见，不必等约 1 分钟的快照周期
2026-10-19 | 【[投注排行榜](421_promotion_bet_rank.md)】「我的」行新增 `qualified`（当前名次奖励是否已锁定）与 `entry_bet`（锁定奖励还需追加的有效投注）；新进榜真人有一段随期末收敛的宽限，期间 `qualified=false`、之后可能被超越，前端请据此显示 🔒 并引导追加投注
2026-10-19 | 【[投注排行榜](421_promotion_bet_rank.md)】积分口径改为 **有效投注 × 投注系数 + 充值到账 × 充值系数**（商户后台可调，默认 ×1 / ×3），`detail` 新增 `score_rule`（`bet_weight` / `recharge_weight`）；`display_pool` / `score` / `gap` 均为积分而非金额，规则区文案与「再投 Y」换算请按 `score_rule`
2026-10-19 | 【[捞回活动](420_promotion_win_back.md)】发箱配置接入自定义会员与单次指定日期执行；自定义账号保存时校验商户归属并固定会员 ID，仍沿用彩金落档、批次优先级、进度恢复及宝箱互斥规则。玩家查询、领取和充值翻倍接口不变。
2026-10-19 | 【[捞回活动](420_promotion_win_back.md)】加倍奖金基数修正为本箱赠送奖金，乘实际倍数后向下取两位；充值金额仅判断门槛。存款档位改为固定奖金下界投影，结算结果新增 `boost_basis` 区分新旧口径；历史已结算记录不自动调账。
2026-10-19 | 【[捞回活动](420_promotion_win_back.md)】改为按商户时区排期、定时分页分批发箱；资格按实际筛选时的当前状态与账户指标判断，持久化结果供重试复用。登录及回到前台只查询已有宝箱；旧 `POST /promotion/win_back/reentry` 保留为只读兼容，固定返回 `query_only`，不再发箱；【[登录](100_auth.md#login)】移除 `win_back_reentry_id`。领取及绑定充值订单翻倍规则不变。
2026-10-17 | 【[账号任务奖励](420_promotion_account_tasks.md)】首次领取新增必填 `device_id`；同商户 PWA 通知任务按 IP／设备号终身限制成功领取账号数，默认各 1 个、商户可调。非 PWA 环境点击领取仅提示安装并从桌面打开，结果查询不受影响；移除共用活动说明 `description`，按任务展示对应规则。旧活动及资金规则不变。
2026-10-17 | 【[捞回活动](420_promotion_win_back.md)】发箱触发改为登录前及已登录玩家 PWA 冷启动 / 回到前台时进行单会员回归评估，新增 `POST /promotion/win_back/reentry` 与回归事件幂等 ID；【[登录](100_auth.md#login)】成功响应新增 `win_back_reentry_id`；天数门槛统一按连续滚动时长（1 天 = 24 小时）计算；取消星期 / 小时配置和批量扫描 / 过期扫描，保留回归前活跃快照及失败重试；不再由定时任务批量筛选发放
2026-10-16 | 新增【[账号任务奖励](420_promotion_account_tasks.md)】：本期仅通知任务，游客和存量账号可参加，每账号每项终身一次；订阅与领取分离。领取结果新增可选 `new_reward_granted`，仅明确布尔 `false` 跳过领奖风控钩子，旧活动缺省行为不变。
2026-10-15 | 【[创建充值订单](200_finance.md#recharge_create)】**文档勘误**：巴西 `product_code = PIX` 的 `pay_info` 一直是收银台支付页 URL（此前误写为复制粘贴码），应跳转 / 内嵌打开；新接入通道 `egpaybr` 同形态。接口行为无变化，无新增字段。
2026-10-15 | 【[站点配置](500_site_content.md#config)】`data` 新增 `vip_service_link`（VIP 贵宾客服链接）、`vip_channel_link`（VIP 频道链接）、`message_community_link`（站内信社区链接），均为字符串，未配置为空，由后台「站点内容配置」维护。
2026-10-14 | 【[损失救援明细](418_promotion_loss_rescue.md#loss_detail)】`window_id` 固定归属窗口，`date` 筛选窗口内当天数据，两者同时生效；日期与窗口无交集返回 `data: null`。明细金额为当天数据，整笔窗口结算、冻结金额与领取规则不变；无新增字段。
2026-10-13 | 新增活动【[投注排行榜](421_promotion_bet_rank.md)】`kind=bet_rank`：按商户时区日 / 周 / 月榜统计全站有效投注实时排名，期末按名次占比分配「展示奖池 × 派发系数」；`detail` 返回各榜头卡 + 领奖台 / 第 4~6 名 / 末名 + 「我的」行（名次 / 差距）与待领奖金，`POST /promotion/bet_rank/claim` 手动领取（`prize_id` 可选）；新增 `GET /promotion_bet_rank/board` 全部榜单、`GET /promotion_bet_rank/history` 上一期榜单、`GET /promotion_bet_rank/prizes` 我的奖金记录。进榜 / 名次上升推 `type=msg` toast，结算后有奖者推 `promotion_trigger` / `data.kind=bet_rank`
2026-10-12 | 【[游戏列表](300_game.md)】【[游戏标签详情](310_game_tag.md)】游戏项新增 `rtp`（标称 RTP，两位小数字符串，未配置时不返回）。
2026-10-12 | 新增【[上报 PWA 安装态](110_pwa.md#activate)】`POST /pwa/activate`（需登录，幂等）：启动 URL 带 `pa` 或 `display-mode: standalone` 时调一次，标记会员为 PWA 用户。此前「是否 PWA」只看注册时的 `source=pwa`，浏览器注册后再安装 PWA 的会员会被漏计；现改为独立状态，注册 `source=pwa` / 本接口 / 【[上报推送 token](111_pwa_push.md#subscribe)】任一触发即标记
2026-10-10 | 【[每日签到](404_promotion_daily_checkin.md#detail)】修复同日已签到后升档可补领但 `has_unclaimed` 不提示的问题；入口以最新 `can_be_collected` 展示红点。补充当日已领等级与补领差额说明。
2026-10-10 | 【[红包雨](408_promotion_red_packet_rain.md)】活动列表新增精确 `can_claim`、当前窗口时间段和服务端时间，供免费奖金列表展示限时领取卡及倒计时；详情新增 `claimed`，包含零金额领取记录。共用待领角标口径不变。
2026-10-10 | 【[注册](100_auth.md#register)】/【[游客注册](100_auth.md#guest_register)】`link_queries` 补充约定：APK / IPA WebView 场景 URL 上的 `app_id` / `appsflyer_id` / `adid` / `advertising_id` / `device_id` 须随 `link_queries` 原样透传，服务端据此向 AppsFlyer / Adjust 上报注册与首充事件；接口字段不变
2026-10-10 | 1. 【[幸运补偿](419_promotion_lucky_compensation.md#detail)】`detail` 新增 `first_deposit_valid_hours`（首充有效期，小时）：大于 0 时仅玩家首次充值成功后 N 小时内的存款会开观察窗口，超过后不再触发；`0` 不限。仅规则展示用，其它接口无变化
2026-10-09 | 【[活动列表](400_promotion.md#list)】新增顶层 `enabled_kinds`，返回商户已开启且平台已上架的活动类型，不受「在活动列表展示」开关影响，供客户端按实际活动开关控制入口显隐
2026-10-09 | 1. 新增活动【[幸运补偿](419_promotion_lucky_compensation.md)】`kind=lucky_compensation`（与「每日幸运补偿」`daily_bankrupt_pack` 是两个独立活动）：支付通道存款到账后观察窗口内净亏损达线即命中，生成**待开箱**补偿并推【[实时提示](510_message.md#realtime-promotion-trigger)】`promotion_trigger` / `data.kind=lucky_compensation`；`POST /promotion/lucky_compensation/claim` 开宝箱领补偿本金（开箱前 `compensation_amount` / `multiplier` / `boost_amount` 恒为 0），开箱后进入**待加赠**；加赠有效期内【[创建充值订单](200_finance.md#recharge_create)】新增 `source=lucky_compensation`，新存款 ≥ `boost_min_deposit` 到账时同事务全额发 `补偿 × 幸运倍数`。`detail` 待加赠态下发存款页候选统一契约 `amount_tiers`（`bonus_type=fixed`）；`popups` / `triggered[]` 各增一类 `kind=lucky_compensation`；加赠过期后存款推 `type=msg` toast「幸运加赠已过期，本次存款未加赠」
2026-10-08 | 【[神秘彩金](406_promotion_mystery_bonus.md#detail)】新增 `next_claim_at`（下一资格日开始时间）；【[宝箱奖励](401_promotion_treasure_box.md#detail)】新增 `next_tier`（下一档有效邀请门槛及金额）。两项均同步下发到 `/promotion/list` 的 `data[].payload`，供免费奖金卡片展示。
2026-09-28 | 1. 【[获取充值配置](200_finance.md#recharge_config)】`data` **新增 `fixed_amount`**（bool，商户后台「充值套餐」维护）：`true` 时玩家仅可从 `packages[].amount` 选择面额，充值页**不得展示自定义金额输入框**（conapay 美国代收上游只接受固定面额）；未配置为 `false`，行为不变
2026-09-23 | 1. 【[站点配置](500_site_content.md#config)】`data` **新增 `bonus_banners`**（奖金页轮播图资源列表，元素结构与 `main_banners` 一致），由后台「站点内容/配置」维护；未配置时为 `[]`
2026-09-22 | 1. 【[免费注册奖金 · 规则](418_promotion_free_register_bonus.md#rules)】触顶 toast 由「首次只推一次」改为**每次**试玩派彩使 `free_money` 从上限以下跨到 `free_money_cap` 都推【[实时提示](510_message.md#realtime)】`type=msg`（文案不变），跌落后再回触重复推；达标 toast 仍只推首次，同一局同时触顶仍只推触顶那条。接口契约无变化
 | 2. 【[游戏列表](300_game.md#list)】`Game` 对象（含【[收藏列表](300_game.md#favorite_list)】/【[最近游玩列表](300_game.md#recent_list)】）、【[标签详情](310_game_tag.md#tag_detail)】`games[]`、【[跑马灯](300_game.md#marquee)】`items[]` **新增 `landscape_cover_url`**（横版封面图 URL）：平台游戏库维护，商户可在后台单独覆盖；未配置时为空串，客户端需回退 `cover_url`
 | 3. 新增【[我的奖金列表](201_wager_tasks.md#rewards)】`GET /finance/rewards`（需登录）：面向「奖金详情」页，每条记录对应一次奖励入账（活动奖励 / 套餐赠送 / 后台赠送，**不含充值本金**），内联打码任务摘要 `task`（`status` / `multiple` / `target_amount` / `progress_amount` / `remaining_amount` / `terminal_*`），**列表即详情，点击弹窗无需再请求**；无打码要求的奖励 `task.status="none"`、金额字段均为 `"0"`。支持 Query `kind`（来源，同 `WagerTask.source`）/ `start_time` / `end_time`（商户时区，纯日期 `end_time` 含整日）；响应另带 `summary.total_amount`（同筛选条件下全部奖励金额之和，不受分页影响），页头「锁定奖金」沿用【[账户余额](200_finance.md#account_balance)】的 `bonus_money`。`config_snapshot` 结构因 `kind` 而异，已约定键见文档表格；本次同步为 `rakeback` 补写 `rate_percent` / `bet_basis` / `period_start`、为 `loss_rescue` 补写 `rate` / `window_start_at` / `window_end_at` / `user_type`（此前已发放的记录无这些键，客户端需兑底）
2026-09-21 | 1. 新增【[最近游玩列表](300_game.md#recent_list)】`GET /game/recent/list?limit=`：返回玩家最近游玩的完整游戏卡片（`Game` 结构，按最近一次游玩倒序去重，默认 `20` 条、最大 `50`），供个人中心「常玩的游戏」页面直接渲染；游客返回空数组
 | 2. ⚠️ 【[收藏列表](300_game.md#favorite_list)】`items` **由收藏记录（`id`/`user_id`/`provider_game_code`/`created_at`）改为完整 `Game` 卡片**（含 `game_name` / `cover_url` / `provider_id` 等，`provider_game_code` 字段保留），排序与【[游戏列表](300_game.md#list)】顶部「我的收藏」类别一致（最近玩过的收藏排前并带 `last=true`）；已下架 / 不在模板范围内的收藏不再下发。取消收藏仍按 `provider_game_code` 调用
 | 3. 【[游戏列表](300_game.md#list)】文档修正：登录态是在**最顶部插入「我的收藏」类别**（`id="favorite"`、`type=3`），`last=true` 只在该类别内出现，不是「每类前插最近游玩」（接口行为未变，仅纠正描述）
 | 4. 【[免费注册奖金 · 规则](418_promotion_free_register_bonus.md#rules)】新增**达标 toast**：试玩中派彩使 `free_money` **首次** ≥ `target_amount` 时推【[实时提示](510_message.md#realtime)】`type=msg`（`icon=bonus`，文案 `<p>免费奖金任务已达标。</p>`），跌落后再达标不重复推；同一局同时触顶时只推既有的「已达最大值」toast。触顶 toast 行为不变
 | 5. 【[免费注册奖金 · 作废](418_promotion_free_register_bonus.md#rules)】新增**到期 toast**：试玩中 / 已锁定倒计时归零作废时（惰性结算 / 定时兑底 / 游戏内下注回调任一触发）推【[实时提示](510_message.md#realtime)】`type=msg`（`icon=bonus`，文案 `<p>免费奖金活动已到期，免费余额已失效，请充值后继续游戏。</p>`），每人一次；作废时 `free_money` 确有清零则同时推【[余额变动](510_message.md#realtime-balance-changed)】`balance_changed` **新标识 `void`**（含关闭救援时的输光作废），玩家端回源刷一次【[账户余额](200_finance.md#account_balance)】。同时**免费模式下注回调遇到期改为先作废再拒绝**（上游仍收到 `免费奖金已到期` 错误，不再等定时任务清零），接口契约无变化
 | 6. 新增【[可选头像列表](500_site_content.md#avatars)】`GET /site_content/avatars`（免登录）：返回商户在后台「站点内容/头像配置」维护的启用中预设头像（`name` / `image_url` / `sort_order` / `is_active`，按后台摆放顺序）；新增【[选择头像](500_site_content.md#avatar_select)】`POST /site_content/avatar/select {image_url}`（需登录），服务端校验所选图片在启用列表内后写入 `head_portrait`，否则返回 `头像不存在或已停用`
 | 7. 【[注册](100_auth.md)】行为变化：商户配置了至少一张启用中的预设头像时，注册（含游客注册）会**随机分配一张**写入 `head_portrait`，不再为空串；未配置时行为不变，客户端仍需保留默认头像兑底
 | 8. 新增【[投注统计](300_game.md#bet_stats)】`GET /game/bet/stats`（需登录）：返回当前玩家**终身**的 `bet_count`（总投注场数）/ `win_count`（总胜场数）/ `bet_amount`（总投注额），口径与商户后台报表一致，结果缓存 30s，供个人中心展示
 | 9. 新增【[可领奖励项数](400_promotion.md#unclaimed_count)】`GET /promotion/unclaimed_count`（免登录，游客恒 `0`）：返回当前玩家在商户**全部已开启活动**中的可领奖励项数 `count`（不下发金额），供首页角标 / 个人中心入口展示；一“项”= 一次独立领取动作能领到的单元（宝箱逐个、救援金逐笔、累充逐阶梯、战令逐节点、VIP 升级礼金 / 周俸 / 月俸各 1 项，其余单项类与 `has_unclaimed` 一致，完整口径表见文档）。【[活动列表](400_promotion.md#list)】新增可选 Query `with_unclaimed=1`：传了才下发顶层 `unclaimed_count`（覆盖全部已开启 kind，含未开启列表展示的）与 `data[]` 行级 `unclaimed_count`；不传则响应与服务端开销**完全不变**。`has_unclaimed` 红点字段的判定逻辑与缓存未动，老客户端不受影响；注意部分 kind 的红点语义是「可参与」而非「有奖待领」（存款加赠类、拼多多），可能出现 `has_unclaimed=true` 而 `unclaimed_count=0`，新客户端做角标请以 `unclaimed_count` 为准
2026-09-20 | 1. 【[我的充值订单](200_finance.md#recharge_my)】新增 Query `start_time` / `end_time`（此前传入被忽略）：按订单创建时间筛选，`YYYY-MM-DD` 或 `YYYY-MM-DD HH:mm:ss`，按商户时区解析；`end_time` 传纯日期时包含当天整日
 | 2. 【[批量活动详情](400_promotion.md#detail_batch)】**新增 `GET /promotion/detail_batch?kinds=k1,k2,...`**：一次请求合并返回多个 kind 的 `detail`，与逐个调用 `GET /promotion/{kind}/detail` 完全等价，**不受 [活动列表](400_promotion.md#list) 的 `show_in_list` 过滤影响**（该开关只影响 `/list` 的 `data[]`，不影响单个 kind 的 `detail`），供充值页等只是借用几个活动费率、自身不是活动列表的页面合并请求、减少并行数
 | 3. 【[活动列表](400_promotion.md#list)】`data[]` / `triggered[]` **新增 `sort_order`**（展示排序，商户自定义优先、未配置回退平台默认），供客户端统一按该字段排序两个数组的卡片，不再各自维护固定顺序；`data[]` 新增可选 `payload`：`daily_deposit_bonus` / `deposit_first_n_bonus` 下发与各自 `detail.data` 同结构的摘要（含 `can_join`），**客户端应据此判断卡片是否可参与展示，不要再用 `is_active`**（`is_active` 只代表后台开关，未考虑今日已参与 / 次数用完）。`detail` 仍保留、结构不变，仅建议改为**点开详情 / 规则弹层时才请求**，不再作为列表显隐的判定来源
 | 4. 【[损失救援](418_promotion_loss_rescue.md#detail)】**未登录也下发 `user_type`（恒 `new`）/ `max_rate`/ `window_hours` / `claim_expire_hours` / `tiers`**（按新用户档位），用于常驻营销卡展示最高返奖比例与完整费率表招徕游客；其余字段（`windows`/`in_progress`/`pending`）仍只在登录后返回
 | 5. 【[活动列表](400_promotion.md#list)】`data[]` 的 `payload` 新增 `loss_rescue`：与 [活动详情](418_promotion_loss_rescue.md#detail) 的 `data` 完全同结构，客户端可直接用它渲染常驻卡/领取卡，不必再单独请求 `GET /promotion/loss_rescue/detail`（该接口仍保留，供懒加载详情/游戏列表弹层使用）
 | 6. ⚠️ 【[免费注册奖金 · 锁定](418_promotion_free_register_bonus.md#rules)】**首笔充值到账即把 `free_money` 全额转入 `record.total_amount` 并清零**（此前是冻结留在账户、拆笔时才清零）：`stage=locked` 起 `detail.free_money` / `triggered[].payload.free_money` 与【[账户余额](200_finance.md#account_balance)】`free_money` 均为 `"0.00"`；`reached_target` 在 `locked` 起**恒为 `true`**（锁定时未达标如 `30/50` 同样锁定，后续按 `30` 拆笔）。客户端：`stage=locked` 时进度条**直接画满格（100%），不再展示分子 / 分母数字**；`playing` 阶段渲染规则不变
2026-09-19 | 1. ⚠️ 【[打码任务](201_wager_tasks.md#task)】`WagerTask.status` 新增 **`not_started`（未开始）**：创建时默认该状态，**首次写入进度**时转 `pending`（进行中）。原「待完成」语义现由 `not_started` + `pending` 两个值共同承担，均占用打码额度、阻止提现并参与 FIFO / 整体放弃 / 低余额失效；【[我的打码任务](201_wager_tasks.md#list)】`status` 可分别传 `not_started` / `pending` 精确筛选，待完成页传新增虚拟值 **`status=active`** 一次取回两种状态（原 `status=pending` 的调用上线后会漏掉未开始任务，需改为 `active`）。存量数据已回刷：进度为 `0` 的 `pending` 任务改为 `not_started`
 | 2. 【[我的打码任务](201_wager_tasks.md#list)】列表排序改为 `created_at DESC, id DESC`（最新在前）；任务消耗顺序不变仍按 `sequence` FIFO
 | 3. 【[损失救援](418_promotion_loss_rescue.md)】开窗规则放宽：不再把「存在未过期待领取（`pending`）救援金」计入活跃窗口，**只有存在未结算的进行中窗口（`open`）才阻挡新窗口开启**；命中阶梯待领取但尚未 `claim` 的旧窗口，不影响下一笔达标存款开新窗，`in_progress` 与 `pending` 可同时下发
 | 4. ⚠️ 【[损失救援](418_promotion_loss_rescue.md)】修复新/老用户身份判定漏洞：上一条放宽后，若第一个新用户窗口已结算命中（`pending`，尚未领取）时又开了第二个窗口，此前只在**实际点击领取**后才转老用户，会导致两个窗口都按新用户档位计算、变相领两次新用户奖励。现在**命中即锁定资格**——存在一条 `user_type=new` 且已结算命中的窗口（`pending`，含已过期未领取）即视为老用户，无需等真正领取；未命中（`miss`）不占用资格，仍可按新用户重试
 | 5. ⚠️ 【[损失救援](418_promotion_loss_rescue.md#detail)】修复并发窗口下身份显示串号问题：`in_progress[]`/`pending[]` 每项新增 `user_type`/`max_rate`/`tiers`（该窗口自己开窗时身份的快照），客户端渲染常驻卡/领取卡时必须用这两个字段自己的值，**不能再用顶层 `max_rate`/`tiers`**（顶层仅表示玩家当前最新身份，并发窗口下与具体窗口身份可能不一致）；同时把 `isVeteran` 等派生字段的计算改到 `settleDue` 结算之后，避免本次请求刚结算命中却还返回结算前的旧身份
 | 6. 【[免费注册奖金 · 作废](418_promotion_free_register_bonus.md#rules)】修复到期后免费余额残留：此前到期作废只在 `detail` / `launch_free` / 充值到账时惰性结算，玩家到期后不再进详情时 `/promotion/list` 已不返回入口、但【[账户余额](200_finance.md#account_balance)】`free_money` 仍显示旧值。现新增服务端定时兜底（每分钟扫描 `playing / locked` 且已到期的记录作废并清零 `free_money`），接口契约无变化
 | 7. 【[免费注册奖金 · 活动详情](418_promotion_free_register_bonus.md#detail)】修复拆笔后仍下发倒计时：`detail` 顶层与 `triggered[].payload` 的 `expire_at` / `remaining_seconds` 此前在 `unlocking` 阶段仍透传领取时的快照值，导致卡片误渲染倒计时。现仅 `stage ∈ {playing, locked}` 下发，其余阶段固定 `null` / `0`（与「进入状态 3 后不再有时限」口径一致）；客户端仍应以 `remaining_seconds > 0` 作为是否渲染倒计时的判据
 | 8. 【[实时提示 · 余额变动清单](510_message.md#realtime-balance-changed)】新增 `balance_changed` 标识 `rescue`：【[幸运救援](418_promotion_free_register_bonus.md#rescue)】补发到 `free_money` 后，与 `promotion_trigger`（弹窗）同时下发，玩家端据此回源刷一次【[账户余额](200_finance.md#account_balance)】（站点顶栏 / 进度卡；游戏内钱包已由游戏回调更新）。按既定约定 `reason` 为开放集，老客户端遇未知值照常刷新即可
2026-09-18 | 1. ⚠️ 【[免费注册奖金](418_promotion_free_register_bonus.md)】**状态机重做（按 PRD 09-18 版）**：锁定时机由「绑定转正」改为**任一笔充值到账**（余额冻结留在 `free_money`、不再可投注、在途派彩没收，`stage=locked`，`record.status=2`），拆笔时机改为**累计充值（实收）≥ `min_total_deposit` 的那笔到账**（`stage=unlocking`），**与是否绑定账号无关**——游客充满门槛同样拆笔，`gate=guest` 仅作提款前置。到期规则改为**试玩中 / 已锁定倒计时归零一律作废**（不再有「达标保留等转正」，移除 `stage=expired_locked`），试玩中某局结算后 `free_money < 0.1` 视为输光作废。首笔一律需打码（取消「转正时已达标首笔免打码」），打码口径改为与【[打码任务](201_wager_tasks.md)】同源的**有效投注**（同一笔投注双计），从拆笔时刻起算、超额不结转
 | 2. 【[领取](418_promotion_free_register_bonus.md#rules)】领取只发生在【[游客注册](100_auth.md#guest_register)】，`launch_free` 不再惰性补发；领取时把达标金额 / 上限 / 充值门槛 / 到期时刻快照到账户，改配置或关活动对已领取用户不生效，拆分序列与倍数在拆笔时快照。新增后端防刷：每 IP 领取次数上限（`0` 不限）+ IP 白名单（IP / CIDR），超限时游客注册返回新错误 `当前网络领取免费奖金的次数已达上限`。新增 **`GET /free_register_bonus/eligibility`**（免登录）：`{claimable, reason(inactive/logged_in/ip_limit), bonus_amount}`，弹首访弹窗前调用；设备维度「登录过不再弹」由客户端本地控制
 | 3. 【[活动详情](418_promotion_free_register_bonus.md#detail)】`stage` 枚举改为 `none / playing / locked / unlocking / finished / void`；顶层新增 `target_amount` / `min_total_deposit`（领取时快照，未领取为当前配置）；`free_money` 在 `locked` 为冻结值；`record` **自领取起即下发**（`status` 新增 `4` 试玩中 / `2` 已锁定 / `3` 已作废，新增 `locked_at` / `converted_at`，拆笔前 `chunks=[]`）。`gate` 语义：`progress` 仅 `stage=playing` 时出现；`guest` 任何阶段仍是游客即命中；`deposit_short` 前端改为「提示并直接跳转存款页」
 | 4. ⚠️ 【[直接提款当前笔](418_promotion_free_register_bonus.md#withdraw)】`POST /free_register_bonus/withdraw` **改为与统一提款完全同一套校验**（最低额、一人一在途单、账户打码任务均生效，且占用普通提款在途名额）；金额低于渠道最低额时客户端应提示切换方式或走 `claim`「转入您的余额」（`claim` 不限金额）。提款单失败 / 取消时款项按普通流程退回真实余额，该笔份额**仍算已提取、不回滚**
 | 5. 【[免费账户启动游戏](300_game.md#launch_free)】**不再要求 `is_guest=true`**，锁定前游客与已绑定会员均可进；业务错误改为 `尚未领取免费奖金` / `已完成充值，免费账户不再可用` / `免费奖金已到期` / `免费账户余额不足`（余额 < `0.1`），移除 `仅游客账号可使用免费账户启动游戏` / `活动未开启`。【[绑定账号](100_auth.md#bind_account)】不再触碰免费账户。【[活动列表](400_promotion.md#list)】`triggered[]` 的 `free_register_bonus` 行现覆盖 `playing / locked / unlocking`，payload 含 `stage / gate / free_money / target_amount / reached_target / expire_at / remaining_seconds / has_deposit / total_deposit / min_total_deposit`（`locked`/`unlocking` 另带 `record` 摘要字段）
 | 6. 【[免费注册奖金 · 幸运救援奖金](418_promotion_free_register_bonus.md#rescue)】**新增试玩阶段兜底**：`stage=playing` 且未到期，免费模式一局派彩结算后 `free_money < rescue_threshold`（默认 `0.5`）即在同事务内补发 `rescue_amount`（默认 `10`，受 `free_money_cap` 约束）到免费账户，**次数不限、无需领取**，游戏回调返回的余额已含补发；倒计时不重置。入账后推【[实时提示](510_message.md#realtime-promotion-trigger)】`type=promotion_trigger` **新标识 `free_register_bonus_rescue`**，玩家端据此在游戏页上层弹「幸运救援奖金」弹窗（金额用 `detail.rescue_amount`，「Claim」/「✕」仅关闭，不调接口）。→ **作废口径变化**：开启救援时试玩中**只有倒计时归零一条作废路径**，「`free_money < 0.1` 输光作废」仅在商户将 `rescue_threshold` 配为 `0` 关闭救援时保留。【[活动详情](418_promotion_free_register_bonus.md#detail)】顶层新增 `rescue_threshold` / `rescue_amount`（领取时快照；未领取为当前配置），`config` 新增同名字段，`record` 新增 `rescue_count` / `rescue_total_amount`；`triggered[]` payload 同步带 `rescue_threshold` / `rescue_amount`
 | 7. 【[免费注册奖金 · 前端展示约定](418_promotion_free_register_bonus.md#rules)】首页 / 赌场常驻卡显示条件从「`stage ∈ {playing, locked}` 且 `reached_target=false`」改为 **`stage ∈ {playing, locked}` 期间一直显示**（达标后不消失，继续提醒充值），`reached_target` 只决定卡片两态样式；进入 `unlocking` 后常驻卡才消失。接口无变化
2026-09-17 | 1. ⚠️ 【[损失救援](418_promotion_loss_rescue.md)】**领取模型回退为两阶段（撤销 09-15 的“窗口期即领取期”修订）**：充值开窗后窗口期内**不可提前领取**，仅老虎机净损累计；窗口到期（`window_hours`）冻结净损结算，命中阶梯生成待领取救援金（金额固定），进入独立的领取有效期（`claim_expire_hours`，配置项重新参与新窗口生命周期）；超期作废。`pending[]` 只含已结算记录，不再随进行中窗口净损实时变化
 | 2. 【[领取](418_promotion_loss_rescue.md#claim)】移除业务错误 `亏损金额未达到最低档位`（进行中窗口不再支持提前领取，该错误场景已不存在）
 | 3. 【[活动详情](418_promotion_loss_rescue.md#detail)】`data` 新增 `in_progress[]`：进行中窗口命中最低档位时的实时预估（`loss_amount`/`tier_index`/`amount`/`bet_multiple`/`window_end_at`），**仅供展示「待结算」金额，不可据此发起 `claim`**；未命中最低档时不下发。客户端用于「已充值待结算」卡片态，与营销卡（未充值）为同一卡片切换文案，不叠加展示；与 `pending[]`（已结算待领取）分属不同展示态，二者不会同时出现
2026-09-16 | 1. 【[提款配置](200_finance.md#withdraw_config)】`GET /finance/withdraw/config` 的 `method_list[].channels[]` **新增字段** `fee_rate`（string，手续费费率小数，如 `0.02`）与 `fee_fixed`（string，每笔固定手续费）。服务端手续费口径 `fee = round(amount × fee_rate + fee_fixed, 2)`（负数按 `0`、超过金额按金额夹紧）；客户端可用 `min_amount + (min_amount × fee_rate + fee_fixed)` 估算该渠道的提现门槛，在可用金额不足时给出提示。**完全向后兼容**，老客户端按「忽略未知字段」处理即可
 | 2. ⚠️ 【[提款配置](200_finance.md#withdraw_config)】**`method_list` / `methods` 只包含至少有 1 个可用 `channels` 的提款方式**：商户后台未配置 / 未启用代付项的方式不再以空 `channels` 下发。客户端**不应再假定** USD 商户必然返回 3 条、BRL 商户必然返回 `pix`，一律以响应为准；`method_list` 为空表示当前无可用提款方式
 | 3. ⚠️ 【[提款配置](200_finance.md#withdraw_config)】**方式顺序变化**：`method_list` 改为按商户后台代付项配置的排序（`sort_order`）下发，不再是固定的注册表顺序，**首项即默认选中的提款方式**；`methods` 与 `method_list` 顺序一致。请求 / 响应结构无其他变化
 | 4. 【[提款配置](200_finance.md#withdraw_config)】商户后台代付项现按提款方式拆条配置（如 conapay USD 的 `card` / `cashapp` / `paypal` 各一条），因此**同一 `channel` 在不同 `method` 下的 `name` / `min_amount` / `max_amount` / `fee_rate` / `fee_fixed` 都可能不同**，客户端必须按 `method + channel` 组合取值，不要按 `channel` 缓存全局值；「`min_amount` / `max_amount` 为商户通道限额与提款方式限额的交集」仍然成立。「商户币种 → 下发的 methods」表改为「最多可能下发」口径。无新增 / 删除接口，无新增错误文案
2026-09-15 | 1. ⚠️ 【[损失救援](418_promotion_loss_rescue.md)】**领取模型修订：窗口期即领取期**——充值开窗后，窗口期内老虎机净损实时累计，**一旦命中最低档位即可随时领取**（`detail` 的 `pending[]` 实时下发进行中窗口的当前可领金额，`claim_expires_at` = 窗口结束时间）；领取时按「窗口开始 → 领取时刻」实时结算入账，窗口随即关闭；**窗口到期未领取即作废**（不再有「到期结算 → 领取有效期」两阶段），配置项「领取有效期」不再参与新窗口生命周期
 | 2. 【[领取](418_promotion_loss_rescue.md#claim)】新增业务错误 `亏损金额未达到最低档位`（窗口内净损未命中最低档时领取）；`pending[]` 金额随亏损增长，前端刷新 `detail` 即可拿到最新可领金额
 | 3. 【[损失救援](418_promotion_loss_rescue.md)】开窗规则修订：同一时间**最多一个活跃窗口**（存在进行中窗口时，新的达标存款不开新窗；领取成功或超期作废回退后需新的单笔达标存款重新触发）
 | 4. 【[活动详情](418_promotion_loss_rescue.md#detail)】`pending[]` 新增 `window_start_at`（窗口开始时间，供卡片「{日期} 损失救援」标题前缀）；「货币」框取值属充值/钱包域，由前端自行获取，活动接口不下发币种
 | 5. 新增【[损失金额明细](418_promotion_loss_rescue.md#loss_detail)】（`GET /loss_rescue/loss_detail`，需登录）：按商户时区自然日返回每游戏老虎机净输明细 `items`、`total_loss`、当日已领奖励合计 `reward_amount` 与 `loss_amount`（= 游戏损失 − 所获奖金）；`date` 缺省或非法回退今天。日期导航仅为按天查历史，与滚动窗口结算无关
2026-09-15 | 1. 新增活动【[免费注册奖金](418_promotion_free_register_bonus.md)】（`kind=free_register_bonus`）：游客注册即发 `bonus_amount`（默认 30）到免费账户 `free_money`，`window_hours`（默认 48h，自 `granted_at` 起）窗口内免费游玩；进度 = `free_money`，目标 `target_amount`（默认 50），余额上限 `free_money_cap`（默认 100，派彩超出截断，**首次触顶推一条 `type=msg` toast** `<p>免费奖金已达最大值 <strong>%s</strong>。</p>`）。到期余额 < 目标 → 作废（`stage=void`）；≥ 目标 → 保留等转正（`expired_locked`）
 | 2. 【[免费注册奖金 · 转正与解锁](418_promotion_free_register_bonus.md#rules)】：【[绑定账号](100_auth.md#bind_account)】转正时 `free_money` 快照转入活动记录并清零；拆笔按 `chunk_amounts` 序列（默认 `[20, 10]`，用完按末值继续）、末笔余数，每笔打码 = 笔金额 × `chunk_bet_multiple`（15），转正瞬间已达目标则首笔免打码。按 `current_index` 顺序解锁，当前笔进度 = 累计有效投注 − 上笔领取快照（与打码任务并行双计），达标且 `gate=ok` 才能 `claim`；领取直接入现金 `user_money`，**不新增打码任务**
 | 3. `GET /promotion/free_register_bonus/detail`（**免登录**，匿名也返回 `config` 供首访弹窗）字段：`kind` / `is_active` / `description` / `config{bonus_amount,target_amount,free_money_cap,window_hours,min_total_deposit,chunk_amounts,chunk_bet_multiple}` / `stage`（`none` / `playing` / `expired_locked` / `void` / `unlocking` / `finished`）/ `free_money` / `reached_target` / `cap_reached` / `granted_at` / `expire_at` / `remaining_seconds` / `gate` / `is_guest` / `has_deposit` / `total_deposit` / `record{total_amount,claimed_amount,claimed_count,current_index,status,chunks[{index,amount,bet_required,bet_progress,status}]}`。四层门禁 `gate` 按序：`progress`（游客未达标）/ `guest`（达标未转正）/ `no_deposit`（零充值，档位表复用【[首充奖励 detail](413_promotion_first_recharge_bonus.md#detail)】）/ `deposit_short`（累计充值 < `min_total_deposit` 49）/ `ok`
 | 4. `POST /promotion/free_register_bonus/claim`（需登录，无 body）领取当前笔到现金余额，输出 `amount` / `chunk_index` / `claimed_amount` / `total_amount` / `finished`；业务错误 `免费奖金进度未达标` / `请先绑定账号完成注册` / `请先完成充值后再解锁奖金` / `累计充值需达到 %s 才能解锁奖金` / `暂无可解锁的奖金` / `奖金已全部领取` / `当前奖金打码量未达标` / `领取冲突，请重试`。新增 `POST /free_register_bonus/withdraw`（需登录，`method` + `channel`）：解锁当前笔并**同事务**建提款单，**不受**最低提现额 / 一人一在途单 / 账户打码限制（且不占用普通提款的在途名额），单笔上限 / 每日限额 / 审核分流同普通提款，订单带后台审核标注「免费注册奖金提款」。常驻卡按商户「列表展示」开关出现在 `/promotion/list` 的 `data`，进行中另出现在 `triggered`（见第 5 条），红点 = 当前笔可领
 | 5. 【[活动列表](400_promotion.md#list)】`GET /promotion/list` 响应顶层**新增 `triggered[]`**（会员名下已激活的限时 / 阶段性入口，每条记录一行，按 `expire_at` 升序、不限时在后，匿名为 `[]`），单项 `{kind, entry_id, banner_url, icon_url, expire_at, server_now, payload}`；**同一 kind 可同时出现在 `data` 与 `triggered`**（常驻卡 + 限时卡）。首批：`daily_bankrupt_pack`（当前有效 offer）、`free_register_bonus`（免费游玩中 / 到期保留 / 转正解锁中）。`data` 的内容、排序与字段**完全不变**，老客户端只读 `data` 即行为不变；新客户端把 `triggered` 渲染在 `data` 之前
 | 6. 【[免费账户启动游戏](300_game.md#launch_free)】新增业务错误 `活动未开启` / `免费奖金已到期`；「免费账户语义」修订：额度 / 上限 / 目标 / 窗口由本活动配置决定，转正时余额**不再一律作废**，改为按上文规则转入拆笔记录（到期未达目标的仍作废）
 | 7. 新增【[免费账户启动游戏](300_game.md#launch_free)】（`POST /game/launch_free`，需登录，**仅游客 `is_guest=true` 可调**）：以游客的**免费账户余额（体验金）**启动游戏。输入与【[启动游戏](300_game.md#launch)】完全相同（`internal_code` 必填，`device_type` / `currency` / `return_url` / `lang` 可选）；输出在 `url` / `launch_url` / `session_id` / `session_token` 基础上**新增 `free_balance`**（string，启动时的免费账户余额）。由客户端判定「是游客且选择体验」后调用，真钱游戏仍调 `/game/launch`。首次调用若尚未发放且商户配置额度 > 0 会先发放再启动；余额为 `0` 仍可启动（游戏内下注失败提示），客户端应据 `free_balance` 提前引导绑定账号。目前**仅支持 365 平台游戏**。新增业务错误 `仅游客账号可使用免费账户启动游戏` / `该游戏不支持游客试玩`（非 365 平台或商户未配置免费试玩凭据，在发放额度前校验），其余同 `/game/launch`
 | 8. 【[账户余额](200_finance.md#account_balance)】新增字段 `free_money`（string，免费账户余额；与 `user_money` / `bonus_money` **完全隔离**，不可提现、不可转入真实余额、不计打码量，**不计入 `total`**；游客转正后清零为 `0`）与 `free_granted_at`（string，免费额度发放时间，未发放为 `null`）。**完全向后兼容**，老客户端按「忽略未知字段」处理即可
 | 9. 免费账户语义：商户后台配置初始额度，游客注册时一次性发放（存量游客首次调 `/game/launch_free` 时补发），**用完不补**；免费投注不触发任何活动 / 奖励 / 返水 / VIP 经验，投注记录也**不进入**【[投注汇总](300_game.md#bet_summary)】等投注记录相关接口
 | 10. 【[游客注册](100_auth.md#guest_register)】「游客账号特性」补充：拥有免费账户（体验金）；通过【[绑定账号](100_auth.md#bind_account)】转正时免费余额清零（去向见第 2 条），之后只能走真实账户与 `/game/launch`
2026-09-14 | 1. 新增活动【[损失救援](418_promotion_loss_rescue.md)】（`kind=loss_rescue`，走通用活动接口，无新增路由）：单笔存款达到开窗门槛后开启滚动结算窗口（新用户默认 24h / 老用户默认 120h，以 `detail` 下发的 `window_hours` 为准），窗口到期结算窗口期内老虎机净损，命中阶梯生成待领取救援金，须在领取有效期内领取（带打码倍数），超期作废；领取过一次新用户救援金后转为老用户；每笔达标存款各开一窗、可多窗口并存、逐笔领取
 | 2. 【[活动详情](418_promotion_loss_rescue.md#detail)】`GET /promotion/loss_rescue/detail` 免登录，**未登录仅返回 `is_active` / `description` / `deposit_threshold`**；登录后按当前活动内身份下发 `user_type` / `max_rate` / `window_hours` / `claim_expire_hours` / `tiers`（新老配置独立，前端**按下发值动态渲染、不要写死默认值**），以及进行中窗口 `windows` 与待领取列表 `pending`（**只含未过期记录**）
 | 3. 【[领取](418_promotion_loss_rescue.md#claim)】`POST /promotion/loss_rescue/claim` 传 `{"id": "<pending[].id>"}` 逐笔领取，返回 `{"amount": ...}`；业务错误 `活动未启用` / `救援金不存在或已领取` / `救援金已领取超时`（详见专章）。前端卡片状态建议按 `pending > open > idle` 优先级展示
 | 4. 【[活动接口](400_promotion.md)】已注册 kind 清单新增 `loss_rescue`
2026-09-14 | 1. ⚠️ **破坏性变更：`POST /auth/guest_login` 已下线**，`device_id` 不再是登录凭证（服务端已删除该字段），调用将不再可用，请迁移到下方新契约
 | 2. 新增【[游客注册](100_auth.md#guest_register)】（`POST /auth/guest_register`，免登录）：**客户端自行随机生成** `username`（8-64，必须匹配 `^g[A-Za-z0-9]{7,63}$`）与 `password`（8-64）提交，服务端据此开游客号并返回 `token` / `user_id`；`promoter_code` / `channel_id` / `source` / `link_queries` 可选，语义同注册。⚠️ 客户端必须在调用前把这副账号密码持久化到本机（与伪设备号同存同退），服务端不会在任何接口返回密码；玩家不经手也不可见，不要展示。新增业务错误 `游客账号格式不正确`；撞名返回 `账号已存在`，重新生成再试。仍需商户后台开启「允许游客登录」（默认关闭），频控同 IP 1 分钟 >10 次
 | 3. 【[登录](100_auth.md#login)】`login_type` 枚举新增 `guest`：按 `username` 精确匹配，供客户端用本机保存的游客账号密码**自动登录**（用回原账号，余额 / 奖金 / 记录都在）。客户端流程：本机有游客凭证 → 调 `/auth/login`（`login_type=guest`）；没有 → 本地随机生成并保存一副凭证后调 `/auth/guest_register` 开号。**不要每次启动都调游客注册**，否则会不断造新号
 | 4. 【[绑定账号](100_auth.md#bind_account)】游客转正语义变更：传入的 `password` **覆盖**游客密码，本机那副游客凭证随即失效（再用它 `login_type=guest` 登录返回 `账号或密码错误`），**不再**保留任何免密登回会员账号的后门。客户端应在转正成功时立即清除本机游客凭证并隐藏「游客登录」入口
 | 5. 【[Member 对象](100_auth.md#member)】`username` 说明去掉 `device_id` 相关描述；游客现在**有密码**（客户端生成），此前「`/auth/login` 用游客 `username` 恒返回 `账号或密码错误`」「修改密码不可用」两条特性作废。业务错误 `设备ID格式不正确` 移除
2026-09-12 | 1. ⚠️ **破坏性变更：`GET /game/tag_list` 已下线**（原按 `placement` 一次返回全部标签 + 游戏的聚合接口），调用将不再可用，请迁移到下方新接口
 | 2. 新增【[标签详情（含游戏）](310_game_tag.md#tag_detail)】（`GET /game/tag_detail`，免登录）：Query 必填 `tag_ids`（逗号分隔，单次最多 50 个），`items` 按传入顺序返回各标签的 `id` / `name` / `sort_order` / `count` / `games`（元素含 `id` / `provider_game_code` / `game_name` / `cover_url` / `game_type` / `provider_id`，为该标签全部在架游戏，按标签内排序下发，`count` = `games` 长度）。不存在 / 已删除 / 已停用的标签**静默跳过不占位**。结果按商户 + 单标签缓存约 5 分钟，不做主动失效，标签 / 关系 / 上下架变更**最长 5 分钟后生效**
 | 3. ⚠️ **破坏性变更：【[站点配置](500_site_content.md#config)】标签字段改为 ID 数组**——原 `game_tags` / `lobby_game_tags`（对象数组，含 `name` / `icon_url` / `color` / `sort_order`）**删除**，改为 `game_tag_ids`（首页）/ `lobby_game_tag_ids`（游戏大厅），均为**已按摆放顺序排列的标签 ID 字符串数组**。前端把整个数组一次传入【[标签详情（含游戏）](310_game_tag.md#tag_detail)】渲染区块，查不到的 ID 服务端自动跳过
 | 4. 标签不再有 `icon_url` / `color` / `description` 属性，相关渲染逻辑（图标 / 色块）请移除
2026-09-10 | 1. ⚠️ 【[站点配置](500_site_content.md#config)】`game_tags` 与【[标签列表（含游戏）](310_game_tag.md)】`items` 的**标签下发顺序调整**：改为按商户后台标签区块的**摆放顺序**下发（此前按 `sort_order` 升序）。`sort_order` 字段仍照常下发但仅为商户侧排序值，**客户端请按数组顺序渲染，勿按 `sort_order` 重排**。请求 / 响应结构无任何变化，未自行重排的客户端无需改动
 | 2. 【[站点配置](500_site_content.md#config)】`data` 新增字段 `lobby_game_tags`（list&lt;object&gt;，**游戏大厅**标签区块，元素结构与 `game_tags` 完全一致）；`game_tags` 语义明确为**首页**标签区块。两组由商户在后台「站点内容配置 - 标签区块」各自独立挑选与排序，同一标签可同时出现在两组。**完全向后兼容**：老客户端按「忽略未知字段」处理即可
 | 3. 【[标签列表（含游戏）](310_game_tag.md)】新增**可选** Query 参数 `placement`：`home`=首页（默认）/ `lobby`=游戏大厅，返回对应区块的标签及嵌套游戏。**完全向后兼容**：不传时行为与此前一致（首页区块），老客户端无需改动；缓存改为按商户 + 区块约 5 分钟
2026-09-09（文档更新，版本待发布） | 1. 按当前已落盘实现更新双钱包与打码任务契约。**当前 schema 尚未正式部署，版本发布前需完成配套数据库迁移；此日期不是上线日期**。不承诺房间混合钱包及通用异常冲正已支持
 | 2. 【[账户余额](200_finance.md#account_balance)】`GET /finance/account/balance`：现金、奖金标准字段为 `user_money`、`bonus_money`，`total = user_money + bonus_money`；移除响应字段 `cash`、`bonus`、`legacy_wager_remaining`，账户类型枚举不变。补充任务进度与提现、整体放弃资格；`bet_amount` 表示旧剩余打码量，不包含 `task_wager_remaining`，总剩余按 `bet_amount + task_wager_remaining` 计算，不另设重复字段。不能单凭 `bet_amount` 为 `0` 判断可提现，余额也不等于可提现金额；阻断原因 `legacy_wager` 保留
 | 3. 新增【[打码任务](201_wager_tasks.md)】专章并由 MkDocs 自动导航收录：`GET /finance/wager_tasks`（状态过滤、分页、完整任务字段）与 `POST /finance/wager_tasks/abandon_all`（必填 `request_id`）。整体放弃须商户允许（默认关闭）、存在 `pending` 且全部 `pending`（含排队任务）可放弃；玩家只使用综合 `can_abandon_all`，不新增开关参数或重复响应字段。关闭时新请求拒绝，开启不能覆盖不可放弃充值任务；成功后清空全部奖金，现金与旧 `bet_amount` 不变，不支持单任务放弃。已成功标识在随后关闭开关后重试仍成功且不重复扣款，新标识受当前策略约束。切换影响已有任务资格但不改快照、提现或系统耗尽清理；直接读配置无本地缓存，不撤销已通过校验的在途事务，不保证跨库瞬时原子生效
 | 4. 明确充值本金进现金但仍建不可放弃任务，奖励有码进奖金、无码进现金；各活动倍数及放弃权限在发奖时固化。新任务于首次派彩固定有效投注，先消耗旧码再 FIFO 推进；结算先解锁，再按严格 `< 0.1` 处理尾数与任务失效。统一及旧 PIX 提现均须全部待完成任务与旧码清零
 | 5. 更新【[活动通用规则](400_promotion.md#wager_rules)】及【[代理返佣](412_promotion_agent_rebate.md)】【[兑换码](416_promotion_redeem_code.md)】【[每日幸运补偿](417_promotion_daily_bankrupt_pack.md)】冲突文案：不能用单笔奖励完成推导提现；返佣按各结算日分别生成任务；幸运补偿符合条件的加赠与充值本金同事务入账，总余额用于礼包余额条件
2026-09-07 | 1. 新增【游客登录】（⚠️ 2026-09-14 已被【[游客注册](100_auth.md#guest_register)】替代，`device_id` 契约作废）（`POST /auth/guest_login`，免登录）：按客户端生成并持久化的 `device_id`（长度 16-128，字符集 `A-Z a-z 0-9 . _ : -`）快捷注册/登录。设备已有账号 → 直接登录；没有 → 自动注册（`username` 服务端随机生成，**不包含** `device_id`；`register_type` = `guest`；无密码）后登录。响应比【[登录](100_auth.md#login)】多一个 `is_new`（bool，`true` 表示本次自动创建了账号）。**需商户后台开启「允许游客登录」（默认关闭）**，未开启返回 `当前商户未开放游客登录`。可选参数 `promoter_code` / `channel_id` / `source` / `link_queries` 语义同注册，**仅首次自动注册时生效**
 | 2. ⚠️ **`device_id` 本身就是登录凭证**：丢失即无法再登录该账号、泄露即他人可登录，客户端须妥善持久化、不要暴露；服务端**不会**在任何接口（含 Member 对象）返回它
 | 3. 游客账号特性：无密码，`/auth/login` 用游客 `username` 恒返回 `账号或密码错误`；【[修改密码](100_auth.md#change_password)】不可用；**不可提现**——【[创建提现订单（统一）](200_finance.md#withdraw_create)】与【[创建 PIX 提现](200_finance.md#withdraw_pix_create)】新增业务错误 `游客账号不支持提现，请先绑定正式账号`（通过下方第 5 条的【绑定账号】转正后解除）
 | 4. 【[Member 对象](100_auth.md#member)】新增 `is_guest`（bool，是否游客；游客登录首登为 `true`，绑定账号并设密码转正后变为 `false`），客户端应据此展示「绑定账号 / 设置密码」引导；`register_type` 枚举新增 `guest`；`username` 说明补充游客为随机生成、不含 `device_id`，且用户名一经创建不可修改。⚠️ `register_type` 是**注册来源**，绑定转正后不变，判断当前是否游客请用 `is_guest`
 | 5. 新增【[绑定账号](100_auth.md#bind_account)】（`POST /auth/bind_account`，需登录）：`account_type`（`phone` / `email`）+ `account`（手机号不含区号 / 邮箱，2-64）+ `password`（4-64）+ 可选 `area_code`（仅 phone，语义同注册）。**游客必传 `password`**：绑定手机或邮箱并同时设密码 → 转正，之后可用【[登录](100_auth.md#login)】密码登录，也仍可用原 `device_id` 走游客登录，提现限制解除；**非游客必须留空 `password`**，仅补绑另一种账号。校验与注册一致（商户配了区号才校手机格式与区号；邮箱归一化小写；同商户内手机 / 邮箱唯一，邮箱与 PIX 收款邮箱共用唯一空间）；已有 `phone` / `email` 的槽位不可重复绑定。输出无。新增业务错误 `游客绑定账号需同时设置密码` / `当前账号已设置密码，请勿重复提交` / `已绑定手机号，不可重复绑定` / `已绑定邮箱，不可重复绑定`，其余复用注册的 `手机区号与商户配置不一致` / `手机号格式不正确` / `邮箱格式不正确` / `该手机号已被注册` / `该邮箱已被注册`
 | 6. ⚠️ 认证接口新增**频控**，超限统一返回业务错误 `操作过于频繁，请稍后再试`：【[登录](100_auth.md#login)】只记**失败**（同账号 10 分钟 ≥10 次 / 同 IP 10 分钟 ≥50 次即拒绝，成功不计）；【[注册](100_auth.md#register)】同 IP 1 分钟 >10 次；【游客登录（现为[游客注册](100_auth.md#guest_register)）】同 IP 1 分钟 >10 次；【[绑定账号](100_auth.md#bind_account)】同会员 10 分钟 >10 次。客户端不要在每次请求前重复调登录 / 游客登录，应缓存 token
2026-09-03 | 1. 【[创建充值订单](200_finance.md#recharge_create)】新增**可选**参数 `product_code`（代收产品编码，取值来自【[获取充值配置](200_finance.md#recharge_config)】中同通道 `channel[]` 数组各项的 `product_code`）。**完全向后兼容**：不传时行为与此前完全一致（取该通道下 `sort_order` 最小的第一条启用支付项），**老客户端无需任何改动**。传了则精确选中对应产品的支付项；传了但在该通道下找不到匹配的启用支付项时返回业务错误 `支付方式不可用`（不会静默回退到第一条）
 | 2. 【[获取充值配置](200_finance.md#recharge_config)】明确并修正：`data.channel[].channel` 是**数组，同一通道下可能有多条支付项**，区别只在 `product_code`（同分组内 `code` 全部相同，不能用它区分）。玩家端必须遍历渲染全部选项，**不要只取第一条**；⚠️ **一个通道下有多条支付项时，下单必须回传 `product_code`**，否则玩家点哪个图标都会走第一条
 | 3. 【[获取充值配置](200_finance.md#recharge_config)】`product_code` 枚举新增美区三项：`USDApplePay`（Apple Pay）/ `USDGooglePay`（Google Pay）/ `USDCashApp`（Cash App），`currency` 新增 `USD`。`product_code` 是**开放集**，遇到未知值照常展示（名称取 `name`），不得当错误过滤
 | 4. 【[创建充值订单](200_finance.md#recharge_create)】`pay_info` 渲染分支新增第三种：`product_code` 为 `USDApplePay` / `USDGooglePay` / `USDCashApp` 时，`pay_info` 是**收银台支付页 URL**，应跳转 / 内嵌打开，**不可当文本或二维码渲染**；是否到账一律以服务端回调为准，不要依赖返回页判定
 | 5. 【[提款配置](200_finance.md#withdraw_config)】`data.currency` 新增 `USD`；USD 商户的 `methods` 下发 3 种新提款方式：`card`（Card）/ `cashapp`（Cash App）/ `paypal`（PayPal），`method_list` 同步下发各自的 `account_types`（`CARD` / `CASHTAG` / `PAYPAL`）与 `extra_fields`。⚠️ **BRL（PIX）/ MXN（CLABE）商户零变化**，新方式只下发给 USD 商户
 | 6. 【[保存收款资料](200_finance.md#withdraw_account_save)】新增三种方式的字段与校验规则（详见【[字段校验规则](200_finance.md#withdraw_account_rules)】）：`card` = `account_name` + `account_no`（纯数字 12–19 位）+ `card_expire_year`（4 位、不早于当前年）+ `card_expire_month`（`01`–`12`，需补零），年月组合不得早于当月；`cashapp` = `account_no` 为 Cashtag（`^\$[A-Za-z][A-Za-z0-9_]{0,19}$`，**未带 `$` 前缀时服务端自动补上**，故回读值一定带 `$`）；`paypal` = `account_no` 为邮箱或手机号且长度 ≤ 64。新增对应业务错误文案。另明确既有行为：`fields` 会按 `extra_fields` 做 **key 白名单裁剪**，多传的 key 静默丢弃
 | 7. 【[创建提现订单](200_finance.md#withdraw_create)】`method` 合法值增加 `card` / `cashapp` / `paypal`，币种匹配校验扩展为三者 ↔ `USD`；补充下单前的收款资料完整性校验说明（未保存 → `请先添加收款资料`；缺字段 → `收款账号资料不完整，请重新填写收款方式后再提现`）。【[我的提现订单](200_finance.md#withdraw_my)】`method` 过滤值与 `Withdraw.method` 同步扩展
 | 8. **契约兼容性声明**：【[获取收款资料](200_finance.md#withdraw_account_get)】【[保存收款资料](200_finance.md#withdraw_account_save)】【[删除收款资料](200_finance.md#withdraw_account_remove)】三个端点的请求与响应结构**逐字段不变**，`fields` 仍是与 `extra_fields` 对称的 kv 或 `null`。已按 `extra_fields` 动态渲染表单的客户端**无需任何改动**即可支持新方式；只有写死 `pix` / `bank_clabe` 分支的客户端需要改为按 `method_list` 驱动
 | 9. 【[金额与币种](200_finance.md#amount_currency)】币种取值新增 `USD`（美元）；【[通用枚举](200_finance.md#enums)】新增「提款方式 `method`」对照表（method / 名称 / 币种 / `account_types`），仅供对照，**实际可用方式一律以 `/finance/withdraw/config` 下发为准**
2026-09-02 | 1. 【[注册](100_auth.md#register)】新增可选参数 `account_type`（`phone` 手机号 / `email` 邮箱），【[登录](100_auth.md#login)】新增可选参数 `login_type`（同枚举）。**没有新增接口，完全向后兼容**：两个参数留空时一律按 `phone` 处理，**旧客户端无需任何改动**，行为与之前完全一致
 | 2. 【[注册](100_auth.md#register)】【[登录](100_auth.md#login)】账号字段仍复用原有的 `username`：`phone` 时传手机号（纯号码，不含区号），`email` 时传邮箱。邮箱会被**归一化**（去首尾空格 + 转小写）后存储与匹配，`A@B.com` 与 `a@b.com` 视为同一账号；同一商户内**邮箱唯一、手机号唯一**
 | 3. 【[注册](100_auth.md#register)】新增业务错误 `邮箱格式不正确` / `该邮箱已被注册` / `该手机号已被注册`，并补充既有的 `账号已存在` / `注册失败，请重试`。手机号注册的区号一致性与号码格式校验口径不变——**仅在商户配置了区号时才校验**
 | 4. 【[登录](100_auth.md#login)】明确：`login_type` 为 `phone`（或留空）时先按 `phone` 匹配、未命中自动降级按 `username` 匹配，存量会员照常登录；⚠️ **账号不存在与密码错误返回同一文案 `账号或密码错误`**（防账号枚举），客户端**不得**据此判断账号是否已注册
 | 5. 【[Member 对象](100_auth.md#member)】新增字段 `phone`（登录手机号，不含区号）、`register_type`（注册方式 `phone` / `email`）、`phone_verified`、`email_verified`。⚠️ **`phone_verified` / `email_verified` 当前恒为 `false`**：注册流程不做任何真实性验证（不发短信 / 邮件），它们是预留给提款等敏感操作的风控门槛，**与能否登录无关**，前端不要用它们拦截登录或提示"请先验证"
 | 6. 【[Member 对象](100_auth.md#member)】`email` 字段语义扩展：此前仅为 PIX 收款邮箱，现同时作为**登录标识**；邮箱注册会员的登录邮箱与手机号注册会员的 PIX 收款邮箱**共用同一字段与同一唯一空间**
2026-09-01 | 1. 【[消息列表](510_message.md#list)】修复：**全员广播消息的已读态改为按会员独立记录**。此前广播消息的已读状态是全局共享的一行，任一玩家标记已读会导致所有玩家该条消息都变成已读。现在 `status` 一律是**当前会员自己的**已读态，互不影响。**请求 / 响应结构无任何变化**，客户端无需改动，仅行为修正
 | 2. 【[全部已读](510_message.md#read-all)】⚠️ **移除 120s 结果缓存**：此前 120s 内重复调用直接返回首次调用的缓存条数，导致缓存期内新到达的消息不会被真正标记为已读、`count` 也不反映真实结果。现在每次调用都实际执行，`count` 为**本次真实标记为已读的条数**，重复调用幂等（已无未读时返回 `0`）。另说明：单次调用最多为 **1000 条**全员广播消息补齐已读标记，超出部分由下次调用继续（正常运营量级不会触发）
 | 3. 【[标记单条已读](510_message.md#read)】参数 `message_type` **已废弃**（由「必填」改为「可选，服务端忽略」，保留仅为向后兼容）：服务端现按**消息 ID 自行判定**走主表还是会员绑定表，客户端不再需要传类型，传错也不会导致标记失败。补充错误说明：消息 ID 不存在或不属于当前会员可见范围时返回业务错误 `消息不存在`
 | 4. 【[标记单条已读](510_message.md#read)】【[全部已读](510_message.md#read-all)】明确未登录（匿名会话）调用返回业务错误 `会员不存在`，与【[消息列表](510_message.md#list)】【[未读数](510_message.md#unread)】口径一致
 | 5. 【[消息列表](510_message.md#list)】修正文档与实现不符之处：服务端结果缓存为 **3s**（文档此前误写 120s）
2026-08-25 | 1. 【[事件格式](510_message.md#realtime-events)】`type` 枚举新增第 3 种：**`balance_changed`**（`data` = `{reason}`），表示玩家钱包余额已发生非下注类变动。**这是一条给程序看的刷新信号，不要弹 toast**（同一笔到账已有 `type=msg` 负责提示，重复弹会双弹窗）。老客户端不受影响：按既有的「未知 `type` 静默丢弃」规则处理即可
 | 2. 【[余额变动清单](510_message.md#realtime-balance-changed)】当前 `reason` 只有 `recharge_credit`（充值到账）。**一笔充值只推一条**：充值赠送与本金同事务入账，刷到的余额已含赠送。下注、活动领奖、后台赠送、提现等变动**当前不推**。**`reason` 是开放集，遇到未知值也要照常刷新**，不得用它做白名单过滤
 | 3. 【[余额变动清单](510_message.md#realtime-balance-changed)】接入要求：收到后回源刷一次余额（含游戏内钱包），建议**去抖 300~500ms**。载荷**不带金额与余额快照**，余额一律以业务接口返回为准；SSE 可丢失，**原有的定时 / 页面回前台刷新必须保留**，本事件只是把到账后的刷新提前
2026-08-22 | 1. 【[游戏列表](300_game.md#list)】响应新增顶层字段 `version`（string，不透明版本号），返回形如 `{"items": [...], "version": "..."}`；客户端拉取列表时应保存该值
 | 2. 新增【[游戏列表版本号](300_game.md#list_version)】（`GET /api/game/game/list/version`，免登录、无参数）：轻量返回 `{"version": "..."}`。PWA 长驻不刷新场景下，**启动游戏失败时**调用本接口与本地保存的 `version` 比对，不一致说明游戏列表已更新（如商户切换游戏模板、游戏上下架），应重拉【[游戏列表](300_game.md#list)】并刷新界面。版本号是不透明字符串，**只做相等比较、不保证单调**；版本键 30 天 TTL 过期会自然轮换一次（多一次无害重拉），不要长期缓存比对结果
2026-08-13 | 1. 新增【[实时提示推送（SSE）](510_message.md#realtime)】：`POST /api/game/notify/ticket`（需登录，返回一次性建连凭证 `ticket`，**TTL 30s**，响应为 `{"data":{"ticket":"...","expire_in":30}}`）+ `GET /api/game/notify/stream?ticket=xxx`（SSE 长连接，无需 `Authorization` 头）。**这是一条纯瞬时、可丢失、不落库的 toast 通道，不是消息系统**：服务端不补偿、不重放、不回源，玩家错过即错过；需要回溯的内容一律走既有【[站内信](510_message.md#list)】接口，两条链路互不依赖，前端**不得**把 toast 当作业务状态的唯一来源
 | 2. 【[事件格式](510_message.md#realtime-events)】`event: toast` 的报文体含 `type` + `data` 两字段，`data` 结构随 `type` 变化（枚举与结构以下方第 10、12、13 条为准）。另有 `event: closed`（超连接数上限被踢，携 `retry: 86400000`，**收到必须 `close()` 且不再重连**）、建连时下发的 jitter 化 `retry:` 帧、每 20s 的 `: heartbeat` 注释行
 | 3. 【[文案清单](510_message.md#realtime-i18n-keys)】列出充值 / 提现 / 后台赠送 / 活动领奖已接入的文案及其 `args` 顺序。**文案已改为服务端翻译**（见下方第 12 条），该清单仅供联调对照，前端无需维护词典；**渲染 toast 时应剥标签或转义，不要无脑 `v-html`**
 | 4. 【[文案清单](510_message.md#realtime-i18n-keys)】**活动领奖到账的 toast 文案与站内信统一**：下发 `<p><strong>%s</strong> 奖励已到账：<strong>%s</strong>。</p>`（`args` = `[活动名, 金额]`，活动名同样由服务端翻译）；活动名未登记时退化为 `<p>活动奖励已到账：<strong>%s</strong>。</p>`。站内信侧不受影响，仍照常落 `message_type=2` 记录
 | 5. 【[签票频次限制](510_message.md#realtime-ticket-rate)】`POST /notify/ticket` 新增按会员限流：**固定窗口 1 分钟 / 30 次**，超限返回 `429`「操作过于频繁，请稍后再试」。**前端重连必须带退避**（起步不低于服务端下发的 `retry:` 值），否则网络抖动时会打满配额，把故障放大成「后续合法重连全被挡住」
 | 6. 【[建立推送连接](510_message.md#realtime-stream)】补充两种「**刚连上就断**」的正常情形：① **服务端连接已满**（单实例硬上限 10000 条）；② **服务端正在停机**（滚动发布）。两者 HTTP 均已返回 `200`，服务端下发一次 `retry:` 帧后立即关闭，**不发 `event: closed`**，前端处理方式与网络故障一致（退避 → 重新签票 → 新建 `EventSource`），不要当异常上报。`event: closed` 的 `reason` **当前仍只有 `conn_limit` 一个取值**
 | 7. 【[建立推送连接](510_message.md#realtime-stream)】明确死链回收时延：关标签页 / 刷新 / `close()` 会被立即感知，但切网、飞行模式这类**不发 FIN** 的断开靠 TCP keepalive（空闲 30s + 3×10s 探测）**约 60 秒**才释放旧连接。前端行为不变（照常重新签票建连），仅需知晓这 60 秒内该会员在服务端可能多占一个连接名额（单实例 3 条软上限）
 | 8. 【[客户端接入规则](510_message.md#realtime-client-rules)】强制契约：登录后才建连；收到 toast 直接渲染**不发任何回源请求**；未知 `type` / 未知 key / 未知活动标识**静默丢弃**（不展示原始值、不弹错）；**不做降级轮询**；**重连必须带退避与次数上限**；容忍「刚连上就断」；`visibilitychange` 转 hidden 超 5min 主动 `close()`、转 visible 重建且**不补拉**断连期间的 toast；展示时长与叠加策略由前端自定；单会员单实例最多 3 条连接（超出踢最旧）。⚠️ **ticket 一次性**（服务端 `GETDEL` 消费），浏览器原生重连会复用已消费的 ticket 而必然 `401`，故恢复连接须走「**重新签发 ticket → 新建 `EventSource`**」
 | 9. 【[常见坑](510_message.md#realtime-pitfalls)】本地开发经 Vite 代理走 HTTP/1.1，同域名 6 连接上限，多开标签页会耗尽连接导致其它请求挂起（生产经 CF 走 HTTP/2 无此问题）；ticket 不可复用、不可放进任何可重放的缓存；无退避重连会被 `429` 锁在门外
 | 10. 【[事件格式](510_message.md#realtime-events)】**`type` 枚举最终定为 2 种**：`msg`（成品文案，直接展示）与 `promotion_trigger`（活动触发信号，需回源）。⚠️ **破坏性变更：活动奖励到账不再单独立类型**——它本就会落一条站内信，现与其它财务文案一样走 `msg` 下发同一份成品文案（活动名也已翻译），因此 `promotion` 类型**已取消**、原【活动标识清单】章节已删除，前端**无需再维护 `<活动>_claim` 到文案的映射**。新增的 `promotion_trigger`（见【[活动触发清单](510_message.md#realtime-promotion-trigger)】）表示玩家刚满足某活动触发条件，`content` 为**不带 `_claim` 后缀**的活动标识、**`args` 恒为 `[]`**，⚠️ **不得再假定 `args[0]` 一定存在**
 | 11. 【[每日幸运补偿](417_promotion_daily_bankrupt_pack.md#lifecycle)】触发时机从「仅在 `GET /site_content/config` 时惰性判定」扩展为兼容两种：**余额下降后约 3 秒无新变动即主动判定**，命中则即时生成礼包并推一条 `type=promotion_trigger` / `data.kind=daily_bankrupt_pack` 的 toast；原 `config` 惰性判定**保留为兵底**。**接口与字段无任何变化**，不接 SSE 的客户端行为完全不变；接了则玩家**无需刷新首页**即可看到弹窗。同一份礼包只推一次，但**必须按 `offer_id` 去重**（toast 与 config 响应可能几乎同时送达同一礼包）
 | 12. 【[事件格式](510_message.md#realtime-events)】⚠️ **破坏性变更：`type=msg` 的文案改由服务端翻译**。`content` 不再是 i18n key，而是**已按语言翻译并完成 `%s` 插值的成品文案**（口径与【[消息列表](510_message.md#list)】完全一致），前端**不要再查词典、不要再插值**，剥标签 / 转义后直接展示即可；`args` 仍原样下发，仅供做样式或埋点。仍按 key 渲染的客户端会展示出未翻译原文。语言取自【[签票请求](510_message.md#realtime-ticket)】的 `Accept-Language`，在建连时**固化到该条连接**上，因此 ① **签票请求必须带 `Accept-Language`**；② **玩家切换界面语言后必须 `close()` 并重新签票建连**，否则会继续收到旧语言文案。`promotion_trigger` 的 `content` 仍是**永不翻译**的英文活动标识，不受影响
 | 13. 【[事件格式](510_message.md#realtime-events)】⚠️ **破坏性变更：toast 报文体重构为 `{type, data}`**，`content` / `args` 顶层字段**已移除**（本条覆盖第 10、12 条中的字段描述）。`data` 结构随 `type` 变化：`msg` → `{icon, content, show_time}`（`icon` 为展示分类 `recharge` / `withdraw` / `activity` / `bonus`，未知值按默认样式；`content` 仍是服务端翻好插好的成品文案；`show_time` 建议展示秒数，当前恒为 `0` = 前端自定）；`promotion_trigger` → `{kind}`（原 `content` 里的活动标识改放 `data.kind`）。`args` 不再下发（插值已在服务端完成，样式分流改用 `icon`）
2026-08-12 | 1. 【[首充奖励详情](413_promotion_first_recharge_bonus.md#detail)】新增 `bonus_type`（`fixed` 固定金额 / `percent` 按充值金额比例），`Tier` 新增 `bonus_percent`（加赠比例 %）。**前端须按 `bonus_type` 决定展示 `bonus` 还是 `bonus_percent`**；`percent` 模式下实际加赠 = 充值金额 × 比例（向下取整到分）。旧配置未设置 `bonus_type` 时按 `fixed` 处理，行为不变
 | 2. 【[首充奖励详情](413_promotion_first_recharge_bonus.md#detail)】新增 `max_bonus`（加赠上限，`0` 为不限）。**`bonus_type=percent` 时展示预估加赠必须取 `min(充值金额 × 比例, max_bonus)`**，否则大额充值时展示值会高于实发金额
 | 3. 【[每日幸运补偿](417_promotion_daily_bankrupt_pack.md#popup)】弹窗与[详情](417_promotion_daily_bankrupt_pack.md#detail)新增 `bonus_type`（`percent` 按档位门槛比例 / `fixed` 固定金额），商户可为各档配置固定加赠金额。**该字段仅影响文案展示**，各档实际加赠仍一律以 `bonus_amount` / `total_amount` 为准；旧配置未设置时按 `percent` 处理，行为不变
 | 4. 【[每日幸运补偿](417_promotion_daily_bankrupt_pack.md#group)】支持按玩家**历史累计充值**分层：不同累充区间的玩家看到各自独立的礼包档位与上限。弹窗与详情新增 `group_index` / `group_min_recharge` / `group_max_recharge` / `total_deposit`。**`tiers`、`single_charge_max_bonus`、`recommended_tier_index` 仍是命中层的扁平值，前端无需改动**，也不要自行按累充金额选层；分层在礼包生成时即锁定，倒计时内充值升层不影响本笔发奖。历史累计充值未达最低层门槛的玩家不再生成礼包
2026-08-11 | 1. 活动更名（仅显示文案变更，接口路径与 `kind` 标识不变）：「每日破产礼包」→「[每日幸运补偿](417_promotion_daily_bankrupt_pack.md)」（`daily_bankrupt_pack`），`claim` 接口错误文案同步改为「幸运补偿由充值订单自动发放」
 | 2. 【[首充奖励详情](413_promotion_first_recharge_bonus.md#detail)】新增 `is_active`（活动是否开启）与 `can_join`（当前玩家是否可参加）两个字段。**充值页只需读 `can_join`** 即可决定是否展示「参加首充活动」选项；详情接口本身免登录且不会因活动停用而报错
 | 3. 【[首充奖励](413_promotion_first_recharge_bonus.md)】修复：商户将活动**停用**后，【[站点配置](500_site_content.md#config)】的 `popups` 仍会下发 `first_recharge_bonus` 的问题（现在停用即不再下发）。注意：这只约束**活动自动注入**的弹窗项（仅含 `kind` 字段）；商户在站点配置里**手工配的弹窗**（含 `title` / `image_url` / `url` 等字段）不受活动开关控制，仍按其自身 `is_active` 下发
2026-08-10 | 1. 新增【[每日破产礼包](417_promotion_daily_bankrupt_pack.md)】活动（`kind=daily_bankrupt_pack`）：余额跌破破产线且当日已充值达门槛时，服务端自动生成**限时礼包资格**，通过【[站点配置](500_site_content.md#config)】的 `popups` 下发（含 `offer_id` / `expire_at` / `server_now` / `today_deposit` / `seq` / `daily_max_offers` / `tiers` / `recommended_tier_index` / `single_charge_max_bonus` / `principal_bet_multiple` / `description`）。**无手动领取接口**（`POST /promotion/daily_bankrupt_pack/claim` 直接报错），加赠由充值订单异步自动入账，钱包流水 `action=daily_bankrupt_pack_claim`；倒计时须用 `expire_at` − `server_now` 计算，勿用本地时钟
 | 2. 【[每日破产礼包](417_promotion_daily_bankrupt_pack.md#popup)】档位 `Tier` 下发**服务端算好的生效值**：新增 `bonus_amount`（实际加赠，已按单笔上限封顶）、`bonus_capped`（是否被截断）、`total_amount`（到手总额），`bet_multiple` 为已应用商户全局覆盖后的最终值。**展示金额一律以 `bonus_amount` / `total_amount` 为准**，不要用 `bonus_percent` 自行计算，否则会与实发金额不一致
 | 3. 【[创建充值订单](200_finance.md#recharge_create)】`source` 枚举新增 `daily_bankrupt_pack`（每日破产礼包，需在礼包倒计时内下单）；不传或传错不会触发加赠
 | 4. 【[首充奖励详情](413_promotion_first_recharge_bonus.md#detail)】参赛资格放宽：由「从未充值」改为「**只要未领取过首充奖励就可参加**」，**与历史充值金额无关**；玩家在充值下单时传 `source=first_recharge_bonus` 即表示参加，支付成功后按金额命中的最高档位自动发放。活动列表可见性与首充弹窗下发按同一口径判定，游客（未登录）始终可见
 | 5. 【[首充奖励详情](413_promotion_first_recharge_bonus.md#detail)】`current_recharge` 不再是预留字段，现真实返回玩家累计充值金额（未登录为 `0`），仅供展示，**不再参与参赛资格判定**
 | 6. 【[首充奖励详情](413_promotion_first_recharge_bonus.md#detail)】新增 `recommended_tier_index`（弹窗默认选中档位下标，0-based，服务端已归一化越界值）字段；无新增接口与请求参数
 | 7. 【[创建充值订单](200_finance.md#recharge_create)】补充 `source` 的两条既有行为说明（**非新增限制**）：① 只要 `source` 不是 `normal`，本单就不发放**充值套餐赠送**（活动加赠与套餐赠送互斥）；② 下单时**不校验活动资格**，不具备资格时订单照常创建入账、仅静默不发加赠，接口不报错，需玩家端自行前置判断
2026-08-08 | 1. 活动名称统一（仅显示文案变更，接口路径与 `kind` 标识不变）：「首充加赠」→「[首充奖励](413_promotion_first_recharge_bonus.md)」（`first_recharge_bonus`）、「大亨活动」→「[拼多多](405_promotion_magnate.md)」（`magnate`）、「充值狂欢」→「[充值大酬宾](414_promotion_recharge_bonanza.md)」（`recharge_bonanza`）
2026-07-28 | 1. 增加【[跑马灯](300_game.md#marquee)】（`GET /api/game/marquee/list`）：免登录返回展示用累计派彩金额（每秒 10.00~499.99 自增、触顶 1000 万回落 863126.80）与 50 条高额派彩滚动消息；消息含脱敏手机号、金额与游戏信息（`provider_game_code` 可直接启动游戏），按商户缓存 5 分钟，刷新时把近 20 分钟内派彩超 100 的真实注单随机插入列表
2026-07-25 | 1. 【[获取充值配置](200_finance.md#recharge_config)】**新增 `product_code` 与 `currency` 字段**：此前返回的 `code` 巴西与墨西哥同为通道代码 `pay4z`，玩家端**无法判断该支付项是 PIX 还是 SPEI**；现在每个支付项直接下发 `product_code`（`PIX` / `SPEI`）与 `currency`（`BRL` / `MXN`），与服务端代收下单口径一致
 | 2. 【[创建充值订单](200_finance.md#recharge_create)】补齐三方下单响应字段 `pay_info` / `third_order_sn` / `raw`，并明确 **`pay_info` 需按上述 `product_code` 分支渲染**：`PIX` 为复制粘贴码（渲染二维码），`SPEI` 为收款账号信息文本（不可当二维码渲染）
 | 2. 新增【[金额与币种](200_finance.md#amount_currency)】通用说明：金额均为字符串十进制、单位为货币面额（非分），货币符号应按 `/finance/withdraw/config` 下发的 `currency`（`BRL` / `MXN`）动态渲染，不要写死
 | 3. 修正【[获取账户余额](200_finance.md#account_balance)】响应字段：实际为 `user_money` / `bet_amount` / `total_bet_amount` / `first_deposit_amount`，此前文档误写的 `current_bet_amount` 不存在
 | 4. 修正【[提现订单状态](200_finance.md#enums)】枚举 `7` 的说明：为「没收余额」（订单关闭、扣款不退回），此前误写为「强制失败」
 | 5. 【[PIX 提现通道列表](200_finance.md#withdraw_pix_channels)】补充调用前置约束：**进入提现页必须先调【[提款配置](200_finance.md#withdraw_config)】**，不要直接调 channels 端点
 | 6. **新增统一提现接口组**（见【[统一提现接口——迁移指引](200_finance.md#withdraw_unified)】）：以 `method`（`pix` / `bank_clabe`）为参数的一套通用端点，共 5 个 —— 【[获取收款资料](200_finance.md#withdraw_account_get)】（`GET /api/game/finance/withdraw/account`）、【[保存收款资料](200_finance.md#withdraw_account_save)】（`POST /api/game/finance/withdraw/account`）、【[删除收款资料](200_finance.md#withdraw_account_remove)】（`POST /api/game/finance/withdraw/account/remove`）、【[创建提现订单](200_finance.md#withdraw_create)】（`POST /api/game/finance/withdraw/create`）、【[我的提现订单](200_finance.md#withdraw_my)】（`GET /api/game/finance/withdraw/my`）。表单**自描述**：按 `extra_fields` 动态渲染收款资料表单，与 `/withdraw/account` 的 `fields` 对象 key 完全对称；`channels` 已按提款方式过滤，无需再调 `/withdraw-*/channels`；订单列表统一形状，收款信息收进 `account_extra`，历史记录已折叠。原按方式分裂的 PIX 旧端点（`/finance/pix/*`、`/finance/withdraw-pix/*`，共 7 个）**保留可用、行为不变**，但已标记「已废弃」，不再接收新特性（新接入的提款方式/新国家不会出现在旧端点），**建议玩家端迁移**
 | 7. 【[提款配置](200_finance.md#withdraw_config)】**新增 `data.method_list`**：每种提款方式一项，含 `method` / `name` / `currency` / `account_types` / `extra_fields` / `channels`（通道代码 key 为拼写正确的 `channel`，旧端点为 `channle`）。本接口成为提现页**唯一配置入口**，一次返回渲染整页所需的全部静态配置；原有 `data.currency` / `data.methods` 保留不变
 | 8. 新增「**提现方式必须与商户币种匹配**」校验（`pix` ↔ `BRL`、`bank_clabe` ↔ `MXN`），对新旧提现下单端点**同时生效**；新增业务错误 `提现方式与商户币种不匹配` / `提现方式不可用`
 | 9. **下线 2026-07-24 新增的 7 个银行（CLABE）独立端点**（`/finance/bank/config`、`/finance/bank/index`、`/finance/bank/create`、`/finance/bank/remove`、`/finance/withdraw-bank/channels`、`/finance/withdraw-bank/create`、`/finance/withdraw-bank/my`）：这批端点从未上线使用，现统一由上述统一提现接口组承载，调用时传 `method=bank_clabe` 即可。**巴西 PIX 玩家端不受影响**（PIX 旧端点全部保留）
2026-07-24 | 1. 增加【[提款配置](200_finance.md#withdraw_config)】（`GET /api/game/finance/withdraw/config`）：下发商户币种与可用提款方式代码（`pix` / `bank_clabe`），客户端据此分流 PIX / CLABE（SPEI）提款页面，无需再打包写死
 | 2. 增加墨西哥银行提现（CLABE）接口文档：银行提现通道列表 / 创建银行提现 / 我的银行提现订单 / 获取银行收款资料 / 银行账户类型枚举 / 保存银行收款资料 / 删除银行收款资料（**已于 2026-07-25 下线**，见上方第 9 条）
 | 3. 【[创建 PIX 提现](200_finance.md#withdraw_pix_create)】「无未完成提现单」校验口径说明更新：改为跨提现方式全局判定（此前仅同方式内判定）；接口 URL 与请求/响应结构均无变化
2026-07-16 | 1. 【[注册](100_auth.md#register)】`link_queries` 参数说明更新：应传落地页 URL 的完整 query string（可带 `?` 前缀，最长 1024）；其中 `fbclid` 会被服务端构造为 FB 点击 ID（`fb.1.{注册时刻毫秒}.{fbclid}`）用于 Facebook 广告归因上报（FB CAPI），投放场景务必透传
2026-07-13 | 1. 【[充值配置](200_finance.md#recharge_config)】响应结构调整：顶层新增 `data.bet_multiple`（本金打码倍数，商户级全局配置，原本金打码硬编码 ×1）；`packages[].bet_multiple` 语义仍为“赠送金额打码倍数”保持不变。历史订单不受影响
2026-07-11 | 1. 增加【[通用接口](050_common.md)】：新增玩家端预签名上传接口 `POST /api/game/common/get_upload_url`，客户端两步式直传 S3（先取 `upload_url` 再 `PUT` 二进制），内容哈希幂等判重、命中已上传对象时返回 `exists=true` 直接复用；【[修改用户资料](100_auth.md#update)】的 `head_portrait` 字段补充上传接口跳转链接
2026-07-08 | 1. 增加【[营销线索接口](700_marketing_lead.md)】：新增 `POST /api/game/marketing_lead/allocate`，每玩家每天固定分配 20 个明文手机号，幂等 + 历史去重，`is_registered` 实时刷新
 | 2. 修正【[兑换码兑换](416_promotion_redeem_code.md#redeem)】文档路径为 `POST /api/game/promotion/redeem_code/claim`（走 promotion 框架统一入口 `/promotion/:kind/claim`），原写法 `/api/game/redeem_code/redeem` 未实际注册，会 404
2026-07-07 | 1. 【[邀请人列表](401_promotion_treasure_box.md#invitees)】新增可选参数 `only_valid`，`true` 时仅返回有效用户（`status ≠ 2`）
 | 2. 【[邀请人列表](401_promotion_treasure_box.md#invitees)】读取时顺带实时评估名下未达标邀请（达标即发箱 / 刷新累充累投快照），同一玩家 30 秒冷却
2026-07-02 | 1. 增加【[首充广告上报数据](200_finance.md#recharge_first_report)】（`GET /api/game/finance/recharge/first_report`）：供玩家端判断是否触发首充广告像素（Pixel）上报；命中过滤条件时服务端会自动标记 `is_ad_reported`，避免重复上报
 | 2. 【[注册](100_auth.md#register)】新增可选参数 `area_code`（国家手机区号，纯数字字符串）；商户已配置区号后按对应正则校验 `username`（约定 `username` 即手机号），未配置商户零影响。新增业务错误 `手机区号与商户配置不一致` / `手机号格式不正确`
2026-07-01 | 1. 增加【[代理数据看板](412_promotion_agent_rebate.md#agent_stats)】（`GET /api/game/agent_rebate/agent_stats`）：一次性返回时段维度新下属统计 + 历史累计佣金/有效投注/下线树规模，`range` 支持 today / yesterday / this_week / last_week / this_month / last_month
2026-06-28 | 1. 新增玩家端 VIP 领取记录接口 `GET /api/game/vip_claim/list`，详见【[VIP 领取记录](415_promotion_vip.md#claim_list)】
 | 2. 【[充值配置](200_finance.md#recharge_config)】`packages` 字段调整：移除 `is_active` / `sort_order` / `remark`，套餐改为配置化（列表中出现即为启用，顺序即排序）；`id` 语义变更为数组下标
 | 2. 增加【[兑换码接口](416_promotion_redeem_code.md#redeem)】（`POST /api/game/promotion/redeem_code/claim`）
 | 3. 【[兑换码兑换](416_promotion_redeem_code.md#redeem)】补充业务错误 `兑换码领取人数已达上限`（对应后端 `max_claims` 配额上限）
2026-06-22 | 1. 【[VIP 领取](415_promotion_vip.md#claim)】新增 `kind=all` 一键领取所有可领奖励（升级礼金 / 周俸 / 月俸），不可领的项静默跳过
 | 2. 【[VIP 详情](415_promotion_vip.md#detail)】新增 `pending_amount` 字段，返回当前所有可领奖励金额合计
2026-06-23 | 1. 【[创建充值订单](200_finance.md#recharge_create)】`action_type` 由必填改为可选（不传时自动选用 `sort_order` 最小的启用代收通道）
 | 2. 【[创建充值订单](200_finance.md#recharge_create)】补齐 `source` 字段说明及枚举值 `normal` / `first_recharge_bonus` / `recharge_bonanza`，明确与首充加赠 / 充值大酬宾促销的联动关系
 | 3. 增加【[站内信接口](510_message.md)】（未读数 / 列表 / 单条已读 / 全部已读）
2026-06-18 | 1. 增加【[上报推送 token](111_pwa_push.md#subscribe)】与【[注销推送 token](111_pwa_push.md#unsubscribe)】接口
2026-06-17 | 1. 【[获取登录用户详情](100_auth.md#detail)】新增 `new_token` 字段，支持 JWT 自动续签
2026-06-16 | 1. 【[站点配置](500_site_content.md#config)】新增 `service_links`（客服链接）与 `social_manage`（社媒管理）两个列表字段
2026-06-15 | 1. 增加【[站点配置接口](500_site_content.md#config)】
 | 2. 【[站点配置](500_site_content.md#config)】资源元素补充 `title` 字段；`popups` 支持 `source: "promotion"` 活动弹窗自动注入（带 `kind` / `payload`）
2026-06-13 | 1. 增加【[代理返佣接口](412_promotion_agent_rebate.md)】
 | 2. 增加【[首充加赠接口](413_promotion_first_recharge_bonus.md)】
 | 3. 增加【[充值大酬宾接口](414_promotion_recharge_bonanza.md)】
 | 4. 增加【[VIP 接口](415_promotion_vip.md)】
 | 5. 增加【[PWA manifest](110_pwa.md#manifest)】与【[PWA 免密登录](110_pwa.md#login_pwa)】接口
2026-06-11 | 1. 增加【[修改用户资料](100_auth.md#update)】接口
2026-06-09 | 1. 增加【[访客行为采集接口](600_stats.md)】
2026-06-04 | 1. 增加【[站点内容接口](500_site_content.md)】
2026-06-01 | 1. 完善接口说明
 | 2. 增加【[用户认证接口](100_auth.md)】
 | 3. 增加【[财务接口](200_finance.md)】
 | 4. 增加【[游戏接口](300_game.md)】
 | 5. 增加【[活动接口](400_promotion.md)】
 | 6. 增加【[宝箱活动接口](401_promotion_treasure_box.md)】
 | 7. 增加【[通行证活动接口](402_promotion_battle_pass.md)】
 | 8. 增加【[累计充值活动接口](403_promotion_cumulative_recharge.md)】
 | 9. 增加【[每日签到接口](404_promotion_daily_checkin.md)】
 | 10. 增加【[大亨活动接口](405_promotion_magnate.md)】
 | 11. 增加【[神秘奖金接口](406_promotion_mystery_bonus.md)】
 | 12. 增加【[返水接口](407_promotion_rakeback.md)】
 | 13. 增加【[红包雨接口](408_promotion_red_packet_rain.md)】
 | 14. 增加【[救济金接口](409_promotion_rescue_bonus.md)】
 | 15. 增加【[7日返现接口](410_promotion_weekly_cashback.md)】
 | 16. 增加【[周救济金接口](411_promotion_weekly_rescue_bonus.md)】
2026-05-31 | 初稿