【付费游玩】游戏支持买断制泥点付费,购买后才能游玩,后台审核可见价格并无限制试玩 #634
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
背景与问题原因
当前游戏分发只有「已公开即可免费游玩」一条链路,没有任何付费/购买/价格概念:
visibility=published且存在published活动版本」,不校验登录、所有权或付费(server-rs/crates/api-server/src/modules/game_distribution.rs、SpacetimeDBget_public_game_distribution_game_and_return/list_public_game_distribution_games_and_return)。game_distribution_game、版本表game_distribution_version都没有价格字段;server-rs/crates/shared-contracts/src/game_distribution.rs与packages/shared/src/contracts/gameDistribution.ts的游戏 DTO 里也没有 price / purchase。profile_dashboard_state.wallet_balance,流水profile_wallet_ledger(source_type: RuntimeProfileWalletLedgerSourceType),唯一暴露的消费入口是consume_profile_wallet_points_and_return(server-rs/crates/spacetime-module/src/runtime/active/profile.rs)。游戏分发与钱包没有任何关联。apps/admin-web/src/pages/AdminGameDistributionReviewPage.tsx展示资料、包摘要和待审版本预览试玩,但没有价格。docs/【玩法创作】平台入口与玩法链路-2026-05-15.md明确把「交易与创作者收入」列为首版不做,本次需求要先解除该排除并补行为合同。需求:作者上传游戏时可选买断制付费;其他用户需花泥点购买后才能游玩;后台审核时可见该泥点数量,并且审核员可以无限制游玩。
现状事实(已核对)
/games/detail→GameDetailPage「立即玩」→/games/play?id=→GamePlayPage.startGame挂载sandbox="allow-scripts"的 iframe,src =currentVersion.entryUrl(服务端派生的同源/games/<gameId>/),发行网关(serve_release_entry/serve_release_asset)公开、拒绝任意 Cookie、扩展名白名单、Cache-Control: public,max-age=60。/admin/api/game-distribution/reviews待审列表 → 版本详情 →POST /versions/{id}/review(approve/reject,带expectedPublicationRevisionCAS +Idempotency-Key);审核员试玩走POST /admin/api/game-distribution/versions/{id}/preview-session,签发 10 分钟、绑定versionId、仅pending_review/rejected可用的/api/game-distribution/admin-previews/{token}/,资源按 token 前缀解析,不限次数、不扣泥点——这条已满足「审核员无限制游玩」,本次只需保证不破坏它并在详情显示价格。metadata_json冻结作者资料(封面/截图等),审核通过时整体生效到 game 行(cover_object_key/screenshots_json)。价格应沿用同一冻结-生效模式。736a1b6ac)曾给RuntimeProfileWalletLedgerSourceType追加LlmRouterConsume变体,同步 TS 联合类型、前端文案与生成绑定,未改profile_wallet_ledger表结构——game_purchase可沿用同一做法。方案(已与用户确认)
1. 定价与数据模型
game_distribution_game末尾追加price_mud_points: u64(#[default(0)],0= 免费)。价格与封面/截图一样来自版本冻结资料,审核通过时在 approve 事务内写入 game 行。metadata_json增加priceMudPoints;作者创建/更新版本时可提交,api-server 校验范围(例如0..=1_000_000整数)。game_distribution_purchase:purchase_id(PK)、game_id、user_id、price_mud_points(成交价快照)、wallet_ledger_id(泥点流水 ID,便于对账)、created_at;(user_id, game_id)唯一(买断制一人一条),加入migration.rs白名单、表目录与生成绑定。2. 泥点流水
RuntimeProfileWalletLedgerSourceType追加GamePurchase => "game_purchase";同步packages/shared/src/contracts/runtime.ts、shared-contracts、前端platformProfileFundsModel.ts文案(如「购买游戏」)、后台相关映射与生成绑定。metadata_json记{kind:"game_purchase", gameId, priceMudPoints}。INSUFFICIENT_MUD_POINTS),不落 purchase、不改余额。3. 购买接口与并发
POST /api/game-distribution/games/{game_id}/purchase(require_bearer_auth,Idempotency-Key):price > 0、当前版本可服务;免费游戏或已购买时幂等返回既有 purchase(replayed=true),不重复扣费。4. 播放鉴权(真付费保护,已确认选 token 会话)
GameDetailPage显示「N 泥点购买」,不显示可点的「立即玩」。POST /api/game-distribution/games/{game_id}/play-session(付费游戏 require_bearer_auth):校验已购买 / 作者本人 / 管理员,签发绑定gameId + userId + 过期时间的短时 token,返回/api/game-distribution/play-sessions/{token}/。GET /api/game-distribution/play-sessions/{token}[/{*asset}]:沿用现有 admin preview 的实现套路(token 前缀承载相对资源、无登录中间件、拒可解析 Cookie、no-store、token 过期/游戏下架 → 404)。/games/<game_id>/网关:当前活动版本price_mud_points > 0时返回 404,杜绝「猜 gameId 直连绕过」;免费游戏完全不变。record_game_play口径,付费游戏经由播放会话后上报)。5. 后台审核
priceMudPoints(0→ 「免费」/「按当前版本免费」,否则「N 泥点」);待审列表可加价格列。6. 前端
GamePublishPage.tsx新增「付费方式」:免费 / 买断制(正整数泥点,上限与后端一致);更新模式同样可改价(走新版本冻结资料)。PlatformMudPointConfirmDialog(「确认消耗泥点」)二次确认并展示余额,余额不足引导充值;购买成功后刷新usePlatformWalletStore余额。契约、文档与迁移
game_distribution_game追加price_mud_points(表末尾 + 默认值);新增game_distribution_purchase;同步migration.rs、后端架构文档表目录、生成绑定,运行npm run check:spacetime-schema。priceMudPoints、purchased/ownedByViewer、购买请求/响应、播放会话响应。docs/【玩法创作】平台入口与玩法链路-2026-05-15.md,解除「不做交易」排除并新增「买断制付费与播放鉴权」合同章;先按docs/【协作规范】规范驱动开发工作流-2026-09-12.md建主规范/里程碑/实施计划再编码。/api/external/v1,无需更新docs/openapi/genarrative-external-v1.openapi.json。验收判据
/games/<gameId>/返回 404。game_purchase流水、purchase 行唯一。npm run check:spacetime-schema、npm run check:encoding、npm run typecheck、定向 Rust/Vitest、git diff --check通过;真实本地栈 smoke 覆盖发布→审核→购买→游玩闭环。不在本轮范围
退款/撤销购买、作者分成与结算、促销/限时免费、价格运营审核规则、AGC 发布面板(可作第二切片)、评分/评论与付费的耦合、外部 API。
工作区
分支
feat/game-purchase,worktree.worktrees/feat/game-purchase(基于origin/master)。按规范驱动开发工作流先落主规范/里程碑/实施计划,再进入实现。