MatchMaster/docs/starter-pack-v2.md

9.3 KiB
Raw Permalink Blame History

新手礼包逻辑接入

沿用用户搭建的 assets/action_bundle/prefab/newbieGift.prefab,本次代码不创建、删除或重新布局 UI 节点。

NewbieGift 使用 timeContainer/time 显示 HH:MM:SS,使用 btnContainer/btn 处理购买;保留 closeStarter_pack、buyProduct、againGet 按钮绑定。脚本不依赖旧宝箱/气泡 Spine 和 propBg 节点,兼容在编辑器中删除这些旧节点。Loading、ConfirmBox 沿用现有节点,确认框标题为“幸运礼包充值”。到期后显示“已结束”,禁用购买按钮并隐藏首页入口。

当前职责划分

后端管理 48 小时活动期限、旧期限迁移及重新激活间隔,奖励仍由前端发放。后端实现只位于同级独立 ../server 仓库;MatchMaster 内的 server 目录未修改。

前端按 3 元购买,当前统一发放 3000 金币、锤子/冻结/魔法棒各 3 个,以及 30 分钟无限体力。奖励配置位于 assets/Script/module/Config/StarterPack.ts,infinite_health 单位为秒(1800)。正常购买和登录补单共用该配置,不读取订单奖励版本或快照;改版前创建但尚未发放的订单,由新版客户端补发时也采用新版奖励。已经发过的订单不会因此自动补差额。

首页开启门槛不变:通关第 15 关后(内部 level 为 15),满足原支付入口条件。首次触发立即弹出并记入当前账号当天记录,以后每天首次进入首页提醒一次,关闭后保留入口。加载失败不消耗提醒次数。

与原支付接口衔接

  • 购买前读取活动截止时间和购买状态,在前端检查是否仍可购买;不要求活动接口或订单接口返回奖励版本。
  • 直购订单查询返回 pay_state=2 表示已支付待领取,随后调用原 getOrderReward;收到 code=1, data="ok" 即按前端配置发奖。
  • 直购领取确认失败时,本次会话保存已经确认支付的订单号,重试领取确认,避免重新查单被当成已完成。
  • 旧 iOS 客服查单成功时,接口已完成订单;前端直接发奖,不再调用一次领取确认。
  • 直购查询返回已领取,或旧 iOS 接口返回“已经获取到奖励”时,清除过期的待支付界面状态,不再次发奖。
  • 正常购买与补单都显式传递原始订单号,在本地按账号和订单号去重;原领取接口不返回订单元数据。两条路径都通过 setUserPowerTime 发放 1800 秒无限体力,未开启或已过期时从领取时间起算,仍有效时在原截止时间上叠加,并同步后端。领奖窗口显示无限体力,资源埋点沿用该方法,补单标记为 compensate。月卡倍率和普通体力数量不变。

真机支付排查

“获得新手礼包数据”来自 limitedTimeEvent 活动查询,不是发奖日志。微信支付成功回调和回到前台可能各触发一次查询;查单进行中不会再次开启并发查询链。

新手礼包直购每轮查单最长 30 秒,超时显示重新领取确认框,保留原订单,不新建订单、不把微信客户端成功回调当作服务端已支付。晚到的查询响应不会继续触发已经超时的一轮处理。领取确认失败后继续使用已经确认支付的订单重试。

日志前缀为 [新手礼包支付],依次包含微信回调成功、查单目标服务器、每次查单返回、领取确认和前端发奖。日志只输出订单号末 6 位,不输出 token 或微信支付凭证。

体验版和开发版当前连接测试服 sor779u2w8.sealoshzh.site,正式版连接 q6rvwvtnga.sealoshzh.site。直购签名的支付环境仍为 env=0。真机支付成功但查单超时时,需要按同一订单核对微信支付发货回调的实际地址、目标云函数日志和订单库:state=0 尚未记录支付,state=1 已支付待领取,state=2 已确认领取。当前代码无法证明微信后台实际配置了哪个回调地址,不应仅凭前端成功日志手动发奖。

有效期与限制

首次触发从服务器当前时间起计 48 小时。未购买且仍有效的旧 24 小时礼包在读取时增加 24 小时,并标记已迁移。已购买不重新开放;已过期不会因为普通读取或首次触发请求自动续期,符合下述新规则时可重新激活。用户上的 starterPackVersion 仅作为期限迁移标记,客户端发奖不使用它。

重新激活(2026-09-10)

必须同时满足未购买、已触发且已过期、距离最近一次实际展示礼包弹窗严格超过 48 小时,再满足以下任一行为,重新从服务器当前时间开放 48 小时:

  • 金币低于 500:首页检查/到期时,以及金币成功同步到服务器后检查。服务端使用数据库金币数判定,500 不满足。
  • 关卡内点击商城或道具购买入口。
  • 通过任何入口实际打开商城,统一在商城脚本中检查。
  • 连续挑战同一关卡失败 4 次:本地按账号和关卡保存计数,一次挑战内复活后再次失败不重复累计;通关清零。助战关卡不计入本人当前关卡。该计数不跨设备同步,也不由服务器独立结算;后端核对上报关卡与当前关卡一致、次数为至少 4 的整数。

重新激活后,首页恢复入口并弹出礼包;关卡内复用已有预制体显示礼包,关闭时恢复原暂停状态。加载期间如果已购买、过期或进入胜利结算,不再展示。因场景切换或加载失败未能展示时,后续首页检查仍可按原每日提醒规则展示。

实际展示时上报 action=shown,服务器保存 starterPackLastShownAt(毫秒)。首页按钮、自动提醒和重新激活的弹出都会更新该时间;单纯查看活动状态、进入商城或显示首页按钮不会更新。旧记录缺少该字段时,以原截止时间作为保守起点,须从该时间再过 48 小时才允许重新激活。本地保留未成功上报的展示时间,后续检查只能用它延后重开,不能缩短服务端间隔。

保留原有每天首次进首页提醒,不增加每次 login 弹窗;本次不添加商城宣传标签,也不修改 UI 节点。3 元价格和真实支付流程保持现状,当前奖励配置见上文。

部署时先发布独立 server 仓库的完整 limitedTimeEvent.ts,再发布客户端;无需新增云函数或批量清空用户数据。新增 reactivate/shown 动作,原 read/save 兼容旧客户端。未部署后端时,新客户端不能完成重新激活。

本次相关回归:客户端 119 项、后端 31 项通过;后端支付分流测试按现有要求提供测试回调地址环境变量。客户端类型检查无新增诊断,仍有既有诊断。尚未部署或进行真机重新激活验收。

到期前已创建的有效订单可继续走原支付流程。因后端下单接口恢复原逻辑,到期禁购由前端入口和购买前检查控制,不再保证请求到达服务端时仍未过期,也无法阻止旧客户端或直接请求在到期后下单。前端发奖保留原有跨设备去重及中断恢复方面的限制;旧 iOS 查单将订单置为完成后若客户端未收到成功结果,不能仅靠重试保证补发。

本地验证与发布

恢复真实支付(2026-09-09)

前端发奖经体验版验证后,已撤销非正式版跳过支付的临时逻辑。开发版、体验版、正式版均恢复原有下单、支付、查单、领取确认和前端发奖流程。此前的本地测试领取标记不再参与礼包资格判断,已发放的测试资源不会回滚。

独立 server 仓库的订单分流提交 0030b5a 保留,尚未部署。部署环境变量、三个函数和发布顺序见该仓库的 laf-cloud/paymentRouting.README.md;其中描述客户端测试旁路的段落是撤销前状态,以本文为准。生产分流上线前,测试服真实支付仍可能遇到回调落在生产服、测试订单保持 state=0 的问题。

node --test tools/test-starter-pack.cjs tools/test-first-game-entry.cjs tools/test-career-loading.cjs

测试读取实际预制体,覆盖节点绑定、首次/次日提醒、到期按钮、原接口返回格式、旧 iOS 直接发奖、领取确认重试、登录补单、统一奖励和本地去重。客户端测试不再依赖同级 server 仓库。

上次有效期简化验证:客户端 104 项、后端 14 项测试通过。客户端 134 个 TypeScript 文件在补充运行时 cc.fx 声明后与 HEAD 对比,均有 17 条既有类型诊断,没有新增类型诊断;这不等于项目全量编译通过。

本次真机查单问题回归:客户端 108 项测试通过,新增支付回调成功但服务端未确认、30 秒后保留原单重试、超时后晚到响应、异常查询数据和缺失订单号场景。后端未修改。

随后根据云端 function starterPackConfig not found 日志,已将时间规则合并到独立 server 仓库的 limitedTimeEvent.ts。活动接口修复只需替换并发布该完整文件,不再依赖额外的 starterPackConfig 云函数。该错误属于活动接口,不能代替 wx/payCallBack 的调用记录来判断支付是否确认。

后端测试和部署范围见独立仓库的 laf-cloud/starterPack.README.md。若之前已发布带订单版本校验的后端,需要配套恢复原支付函数,否则不带版本的新请求会被旧校验拒绝。未进行真实设备支付验收,也未推送或部署云函数。