MatchMaster/server/laf-cloud/coinMadness.README.md

96 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Coin Madness 开发与接入说明
## 本次已实现的规则
- 同一账号每期仅能购买一次;一次支付解锁整期任务,没有付费档位,也没有购买即送金币。
- **付费确认前不计数、不追溯历史通关。** 从服务端确认付款之后开始记录主线新关胜利。
- 阶段独立计数:例如 2、3、5 关,需要分别完成 2、再 3、再 5 关。
- **达标后暂停计数,领取后才进入下一阶段。** 等待领取期间的胜利不会带入下一段。
- 只接入正常主线胜利结算。登录同步、重复结算、无限关不增加进度;一次跳过多个关卡的同步也不追溯。
- 统一使用服务端毫秒时间,`startsAt <= now < endsAt`。截止后不再购买或增加进度。
- 到期仅补发已付费、当前阶段已达标但未领取的金币。未达标部分失效。玩家回到首页或打开活动时执行补发,离线期间保留待处理状态。
## 客户端目录与内存
`assets/coin_madness/` 是独立 Asset Bundle,名称 `coin_madness`。微信、字节跳动构建采用 `subpackage`;当前付费能力只接入微信原生道具直购。
- `CoinMadness.prefab`:活动根预制体,无对其他活动图集、场景或预制体的依赖。
- `CoinMadnessPanel.ts`:橙色活动面板、倒计时、付费入口、滚动任务列表、状态与领取交互。当前使用系统字体和矢量金币,后续美术资源应放在同一个 Bundle 中。
- `assets/Script/CoinMadnessHost.ts`:必要的常驻小桥接层,只负责首页入口、JSON 请求、奖励同步及 Bundle 生命周期;不静态导入活动 UI 类。
- 首次展示前不调用 `loadBundle`。点击入口后依次 `loadBundle('coin_madness')`、`bundle.load('CoinMadness', cc.Prefab)`。
- 关闭时销毁节点;等待 Cocos 延迟销毁完成,再调用 `bundle.releaseAll()` 和 `cc.assetManager.removeBundle(bundle)`。移除定时回调、显示事件监听及 UI 引用,不缓存预制体。
- 对重复点击、场景切换时迟到的加载回调及正在释放时重新打开做了保护。刷新列表先销毁旧节点,避免仅移除父节点造成泄漏。
- 小游戏平台已经执行的 JS 模块和磁盘下载缓存不能保证通过 Cocos API 从进程/设备中卸载。这里释放的是界面实例、图形/文字资源和 Bundle 缓存,不承诺删除平台脚本缓存。
释放方式依据:[Cocos Creator 2.4 Asset Bundle 文档](https://docs.cocos.com/creator/2.4/manual/en/scripting/asset-bundle.html)。
## 原有代码改动范围
| 文件 | 必要接入 |
| --- | --- |
| `assets/Script/JiaZai.ts` | 首页挂载 Host,未改原有场景和活动预制体 |
| `assets/Script/GameManager.ts` | 登录时恢复未确认的金币奖励回执,只处理该活动的金币 |
| `assets/Script/module/Pay/Utils.ts` | 通关上传增加可选的活动胜利标记,其他调用默认不计数 |
| `assets/Script/module/Tool/GameTool.ts` | 正常主线胜利结算时传入标记 |
| `functions/userLevel.ts` | 原有通关保存成功后更新独立活动进度,异常不阻塞原有通关 |
| `functions/userCoin.ts` | 有待确认回执时暂停旧金币快照覆盖;钱包版本比较避免并发旧快照覆盖新奖励 |
| `functions/wx/orderPaySig.ts`、`iosorderPaySig.ts` | 仅对 `coin_madness` 新增期次/资格校验、服务端价格和订单复用 |
| `functions/wx/payCallBack.ts` | 已验签且匹配的活动订单解锁,不直接发金币;重复通知不重复解锁 |
| `functions/wx/getOrderReward.ts` | 禁止通用发奖接口提前消费此活动订单 |
| `functions/wx/KeFuInfo.ts` | 拒绝通过旧客服通道绕过本活动订单校验 |
## 服务端配置
云函数 `coinMadness` 与共享模块 `coinMadnessModel` 都需要同步到 Laf;同时同步表中修改的云函数。没有部署操作包含在本次本地开发中。
环境变量 `COIN_MADNESS_CONFIG` 内容为 `coinMadness.config.example.json` 的完整 JSON。默认关闭,没有默认售价、7 天有效期或正式奖励值。`enabled` 和 `approved` 均为 true 且所有字段校验通过时才开放。
| 字段 | 策划/运营填写 |
| --- | --- |
| `periodId` | 唯一期次编号,1–64 位字母、数字、下划线或横线;**已用期次不得复用** |
| `startsAt` / `endsAt` | 统一起止时间,Unix 毫秒,结束大于开始 |
| `minLevel` | 已完成主线关卡数门槛,非负整数 |
| `priceCents` | 微信人民币分,正整数;注册商品 ID 固定为 `coin_madness` |
| `stages` | 1–50 个 `{ "wins": 正整数, "coins": 正整数 }` |
| `title` | 活动名称,1–40 字符 |
活动首次建立时保存配置快照,避免调整配置影响已产生的任务或订单。修改正式数值应使用新期次;已付费的旧快照即使当前配置关闭,仍可正常领取/到期结算。新期次不继承旧期进度或购买权益,上一期结算/回执处理完成后再创建新期。
本地预览中的价格和任务表仅为测试数据,不写入正式服务端配置。
## 支付与奖励恢复
- Android 和支持 `requestMidasPaymentGameItem` 的 iOS 使用现有微信签名通道,商品金额、数量由服务端决定。
- 用户每期保留同一个待支付订单号;取消、网络失败或切换设备后重试不会生成第二个可付款订单。数据库订单 `_id` 使用该订单号,阻止并发重复插入。
- 旧 iOS 客服付款不支持此新商品;客户端会说明当前平台不支持,服务端也阻止绕过。正式上线前需确认目标客户端支持原生道具直购。
- 服务端确认晚于截止的付款不解锁新期,订单写入 `coinMadnessReviewReason=confirmed_after_deadline`,需要客服核对并退款。**不自动退款**。这一异常流程应在活动上线前落实运营处理人。
- `users.coinMadnessState`:期次快照、购买状态、当前阶段和进度、通关高水位。
- `users.coinMadnessPending`:持久化待确认奖励回执,和阶段状态、金币余额在同一条件更新内保存。
- `users.coinMadnessWalletRevision`:防止领取前发出的旧金币上传在领取后覆盖奖励。
- 客户端将金币与回执号一起落盘,然后确认;响应丢失可以重读/重试。登录有未确认回执时采用其服务端金币余额,避免再次加币。
- 金币上传继续遵循原游戏客户端快照体系,本次未改为全游戏服务端权威钱包。验证范围是本活动重复请求与并发旧快照防护;全游戏其他活动之间的跨设备资源冲突仍需整体经济系统联调。
## 验证命令与结果
需要 Node.js 24 及项目 TypeScript 依赖。
```powershell
node --import ./server/laf-cloud/tests/register-typescript.mjs --test server/laf-cloud/tests/coin-madness.test.mjs
```
16 项新测试通过,覆盖未付费计数、独立阶段、领取前暂停、重复结算、期限、配置与鉴权、服务端定价、订单复用、签名通知、重复/并发领取、回执重试、到期补发、跨期重置和旧金币上传竞争。
本地 Cocos 组件预览(无真实支付、无线上请求):
```powershell
node tools/coin-madness/preview.cjs
# 在另一终端执行;可用 PLAYWRIGHT_MODULE 指定已安装的 Playwright 模块路径
node tools/coin-madness/check-preview.cjs
```
预览使用本机 Cocos Creator 2.4.15 引擎、项目导入缓存、实际 Host 和实际预制体,经真实 Asset Bundle 加载。可通过 `COCOS_CREATOR_PATH` 指定编辑器目录。首次需要用 Creator 导入本项目,生成 `library/imports` 中的内建资源。默认使用 Edge 无头模式,可用 `BROWSER_CHANNEL` 调整。
已验证:文字显示、未购买/可领取/下一阶段状态、双击只领取一次、列表刷新不增加文字节点、连续开关 10 次后 Bundle 不存在且活动节点为 0,资源缓存回到打开前数量;Host 销毁后迟到的预制体加载同样释放资源。
旧支付/丛林活动回归共 38 项,其中 31 项通过、7 项失败;对照修改前 HEAD 后失败项完全一致,未顺带修改旧活动规则。整个仓库 TypeScript 检查受原有 `drawHead.ts` 语法错误阻断;客户端独立检查也有原有声明/类型错误,新增代码未新增诊断。完整 Creator 命令行构建停在资源导入阶段,尚未取得整包构建成功证据。仍需在微信真机和测试支付环境完成最终验收。