feat(docs, agents, risk): enhance documentation, API queries, and UI components

Updated the public documentation site with improved layout and accessibility, including new sections for client integration and admin guides. Enhanced API queries by adding 'active_only' and 'group_by' parameters for better data filtering in risk management. Refined UI components for agent management, ensuring consistent styling and improved user experience across the application. Added localization support for new documentation content in English and Nepali.
This commit is contained in:
2026-06-15 17:21:50 +08:00
parent 17335cb47a
commit 641c87ff50
107 changed files with 5114 additions and 943 deletions

View File

@@ -1,13 +1,15 @@
{
"shell": {
"title": "彩票接入文档",
"admin": "管理后台"
"admin": "管理后台",
"adminLogin": "管理后台"
},
"nav": {
"overview": "概览",
"api": "接口",
"ship": "发布",
"home": "总览",
"delivery": "接入交付",
"quickstart": "快速开始",
"fundamentals": "资金模型",
"setup": "接入配置",
@@ -16,7 +18,11 @@
"wallet": "钱包网关",
"transfer": "划转(参考)",
"errors": "错误码",
"golive": "上线清单"
"troubleshooting": "联调排错",
"golive": "上线清单",
"operations": "运营手册",
"adminGuide": "后台管理手册",
"apiReference": "API 对接参考"
},
"headers": {
"component": ["组件", "职责", "实现方"],
@@ -32,271 +38,319 @@
"balance": ["字段", "账户", "说明"],
"call": ["方向", "接口", "鉴权"],
"sequence": ["步骤", "发起方", "说明"],
"envMap": ["项", "后台接入站点", "主站 .env", "说明"],
"envMap": ["项", "后台接入站点", "主站配置项", "说明"],
"account": ["账号", "密码", "site_player_id"],
"contract": ["场景", "HTTP", "响应体"],
"adminField": ["字段", "说明", "示例"]
"adminField": ["字段", "说明", "示例"],
"handoffTable": ["项", "说明", "负责方"],
"env": ["环境", "地址示例", "说明"],
"envelopeTable": ["方向", "消息字段", "说明"],
"faq": ["现象", "排查方向"]
},
"pages": {
"overview": {
"title": "接入总览",
"description": "主站 SSO + 钱包网关。身份用 JWT资金分主站钱包与彩票内余额。",
"roles": "职责",
"flow": "链路",
"description": "面向主站开发/集成工程师。您需实现JWT 签发 + 钱包网关;彩票提供 H5 与 API。",
"roles": "职责划分",
"flow": "业务链路",
"e2eSequence": "端到端时序",
"conventions": "约定",
"readingOrder": "阅读顺序",
"conventions": "通用约定",
"readingOrder": "建议阅读顺序",
"matrix": [
["主站", "签发 JWT实现钱包网关", "客户"],
["彩票 API", "验签、玩法、划转、下注", "我方"],
["彩票前端", "H5 / iframe 承载", "我方"]
["主站(客户)", "用户登录;服务端签发 JWT实现钱包网关", "客户"],
["彩票 API(我方)", "验签 JWT、划转、下注、开奖、结算", "我方"],
["彩票 H5我方", "玩家界面;iframe 或 URL 跳转入场", "我方"]
],
"flowItems": [
"主站登录 → 签发 JWT",
"进入彩票URL 跳转或 iframe",
"转入:主站扣款 + 彩票加款",
"下注 / 派奖(彩票内余额)",
"转出:彩票扣款 + 主站加款"
"用户在主站登录 → 主站服务端签发短效 JWT",
"进入彩票 H5iframe 嵌入或 URL ?token= 跳转",
"玩家在 H5 内「转入」→ 彩票回调主站扣款 彩票加款",
"玩家在 H5 内下注 / 派奖(使用彩票内余额)",
"(可选)玩家在 H5 内「转出」→ 彩票回调主站加款"
],
"e2eRows": [
["1", "主站", "用户登录;服务端签发 JWT"],
["2", "主站", "iframe 嵌入彩票 H5或跳转 ?token="],
["3", "彩票 H5", "收到 token;调用 GET /api/v1/player/me 验签建档"],
["4", "玩家", "在彩票 H5 内点「转入」"],
["1", "主站", "用户登录;服务端签发 JWT(含 site_code、site_player_id"],
["2", "主站", "iframe 嵌入彩票 H5或跳转 lottery_h5_base_url/?token="],
["3", "彩票 H5", "收到 JWT;调用 GET /api/v1/player/me 验签并自动建档"],
["4", "玩家", "在 H5 内点「转入」"],
["5", "彩票 API", "服务端回调主站 POST /wallet/debit-for-lottery"],
["6", "主站钱包", "扣减 main_balance返回 success"],
["7", "彩票 API", "彩票内加"],
["8", "玩家", "在 H5 内下注 / 派奖"],
["9", "玩家", "(可选)在 H5 内转出"],
["6", "主站钱包", "扣减 main_balance返回 success: true"],
["7", "彩票 API", "彩票内余额增加"],
["8", "玩家", "在 H5 内下注 / 等待派奖"],
["9", "玩家", "(可选)在 H5 内点击「转出"],
["10", "彩票 API", "回调主站 POST /wallet/credit-from-lottery"]
],
"conventionRows": [
["金额", "最小货币单位整数minor如 2000 = 20.00"],
["金额", "最小货币单位整数minor如 2000 = 20.00 NPR"],
["编码", "UTF-8 JSON"],
["时间", "JWTUnix 秒iat / exp"],
["鉴权", "玩家 APIBearer JWT钱包网关Bearer wallet_api_key"]
["时间", "JWT 使用 Unix 秒iat / exp,建议 exp - iat ≤ 300 秒"],
["玩家 API 鉴权", "Authorization: Bearer {JWT}(主站签发,彩票验签)"],
["钱包网关鉴权", "Authorization: Bearer {wallet_api_key}(彩票回调时携带)"]
],
"readingItems": ["快速开始 → 接入配置 → 单点登录 → iframe 协议 → 钱包网关 → 错误码 → 上线清单"]
"readingItems": [
"接入交付 — 确认双方交付物与环境地址",
"快速开始 — 按步骤完成首次联调",
"接入配置 — 后台建站与密钥映射",
"单点登录 → iframe 协议 → 钱包网关",
"联调排错 — 常见问题",
"上线清单 — 生产发布检查"
]
},
"delivery": {
"title": "接入交付",
"description": "联调开始前,请与商务/技术支持确认以下交付物。测试与生产环境须完全隔离。",
"handoffScope": "接入范围(您需要做什么)",
"weProvide": "我方提供",
"youProvide": "客户需提供",
"environment": "环境地址",
"process": "典型接入流程",
"note": "密钥sso_jwt_secret、wallet_api_key创建后仅展示一次请立即安全保存。密钥仅保存在主站服务端禁止写入前端或移动端。下列地址为 Tanumo 当前默认环境;客户独立部署时以商务交付为准。",
"handoffRows": [
["JWT 签发", "主站登录后由服务端签发 HS256 JWT无「登录换票」接口", "客户"],
["钱包网关", "实现 balance / debit / credit 三个 HTTPS 接口", "客户"],
["iframe 或 URL 入场", "嵌入彩票 H5 或跳转并携带 JWT", "客户"],
["彩票 H5 + API", "玩法、划转、下注、开奖", "我方"],
["接入站点与密钥", "创建 site_code 并下发密钥", "我方(超管)"]
],
"provideRows": [
["site_code", "站点编码,写入 JWT"],
["sso_jwt_secret", "JWT 签名密钥(主站持有并签发)"],
["wallet_api_key", "彩票回调钱包网关时的 Bearer 密钥"],
["lottery_h5_base_url", "彩票 H5 入口iframe src 或跳转地址);当前默认 https://front.tanumo.com"],
["lottery_api_base_url", "彩票 API 根地址(联调 curl当前默认 https://lotterylaravel.tanumo.com"]
],
"submitRows": [
["wallet_api_url", "客户钱包网关 HTTPS 根地址(公网可达)"],
["iframe_allowed_origins", "主站 origin 白名单iframe 模式必填,每行一个)"],
["测试账号", "若干 site_player_id 及初始 main_balance联调用"],
["出口 IP如需", "若网关有 IP 白名单,请索取彩票服务端出口 IP"]
],
"environmentRows": [
["彩票 API", "https://lotterylaravel.tanumo.com", "联调 curlGET /api/v1/player/me"],
["彩票 H5 入口", "https://front.tanumo.com", "iframe / URL ?token= 跳转;钱包页示例 /wallet"],
["接入文档", "https://lotteryadmin.tanumo.com/docs/integration", "本文档(公开,无需登录)"],
["管理后台", "https://lotteryadmin.tanumo.com/admin", "超管登录;接入站点:配置 → 接入站点"],
["生产环境", "独立域名与密钥", "site_code、密钥、域名均不与联调共用"]
],
"processSteps": [
"商务开通接入 → 我方超管创建「接入站点」并交付密钥与 H5 地址",
"客户实现钱包三接口并部署到公网 HTTPS联调可先内网穿透",
"客户在后台填入 wallet_api_url、iframe_allowed_origins执行连通性测试",
"客户实现 JWT 签发与 iframe postMessage或 URL 跳转)",
"按「快速开始」验收清单完成联调",
"生产环境重新建站、换密钥、全链路复测后上线"
]
},
"quickstart": {
"title": "快速开始",
"description": "本地联调参考。仓库内 main-site/ 为可运行示例,密钥须与后台接入站点或彩票 .env 一致。",
"description": "假设已完成「接入交付」并拿到 site_code、密钥与 H5 地址。按下列步骤完成首次联调。",
"prereq": "前置条件",
"steps": "联调步骤",
"testAccounts": "测试账号main-site",
"reference": "参考实现",
"note": "生产环境须使用 HTTPS、独立 site_code 与密钥。本地未配置 wallet_api_url 时,彩票 API 可能以 stub 模式跳过主站扣款(仅非 production。",
"acceptance": "验收清单",
"note": "JWT 必须在主站服务端签发,禁止在前端硬编码 sso_jwt_secret。生产环境 wallet_api_url 须为公网 HTTPS。",
"prereqItems": [
"彩票 APIlotterLaravel与彩票前端lotteryfront已启动",
"main-site 已启动(默认 http://localhost:5173",
"后台已创建接入站点,或彩票 .env 配置 MAIN_SITE_* 与主站 .env 对齐"
"已收到 site_code、sso_jwt_secret、wallet_api_key、lottery_h5_base_url",
"主站已实现 GET /wallet/balance、POST /wallet/debit-for-lottery、POST /wallet/credit-from-lottery",
"后台接入站点」已填入 wallet_api_url 与 iframe_allowed_origins连通性测试通过",
"已准备至少一个测试 site_player_id 及足够 main_balance"
],
"stepItems": [
"超管在后台创建接入站点(见「接入配置」)并保存密钥",
"密钥写入主站 .env后台填入 wallet_api_url 与 iframe_allowed_origins",
"主站登录测试账号 → iframe 打开彩票 H5/player",
"确认收到 LOTTERY_READY 后下发 MAIN_INIT_TOKEN",
"在彩票 H5 内发起转入 → 观察主站 /wallet/debit-for-lottery 被回调",
"彩票内余额增加后在 H5 内下注",
"可选H5 内转出 → 观察 /wallet/credit-from-lottery",
"按「验收清单」用 curl 自测 JWT 与钱包网关"
"主站服务端实现 JWT 签发见「单点登录」jsonwebtoken 示例)",
"用 curl 自测Bearer JWT 调用 GET https://lotterylaravel.tanumo.com/api/v1/player/me应返回 code=0",
"主站页面嵌入 <iframe src=\"https://front.tanumo.com\">,监听 postMessage",
"收到 LOTTERY_READY 后,发送 MAIN_INIT_TOKENtoken 放在消息顶层,见 iframe 页示例)",
"H5 进入大厅后,在 H5 内发起转入",
"确认主站收到 POST /wallet/debit-for-lottery 且返回 success: true",
"确认 H5 内彩票余额增加,尝试下注",
"可选H5 内转出,确认 POST /wallet/credit-from-lottery 被回调",
"按下方验收清单逐项勾选"
],
"accountRows": [
["alice", "alice123", "10001"],
["bob", "bob123", "10002"],
["demo", "demo123", "10003"]
],
"referenceItems": [
"代码monorepo 内 main-site/Next.js 测试主站壳)",
"主站http://localhost:5173彩票 H5http://localhost:3800",
"主站 README 含环境变量与消息协议说明",
"配置字段对照见「接入配置」页的映射表"
],
"acceptance": "验收清单",
"acceptanceItems": [
"签发 JWT curl GET /api/v1/player/me 返回 code=0",
"自测钱包网关 debit返回 success:truemain_balance 正确",
"相同 idempotent_key 重放响应与首次一致,余额不重复扣",
"iframe子页 LOTTERY_READY 后收到 MAIN_INIT_TOKEN可进入大厅",
"H5 内转入成功主站网关日志有 debit-for-lottery 记录"
"JWT 自测:curl https://lotterylaravel.tanumo.com/api/v1/player/me 返回 code=0data.site_player_id 正确",
"钱包自测curl POST /wallet/debit-for-lottery 返回 success:truemain_balance 正确扣减",
"幂等:相同 idempotent_key 重放响应与首次一致,余额不重复扣",
"iframeLOTTERY_READY MAIN_INIT_TOKEN可进入 H5 大厅",
"转入:H5 内转入成功主站网关日志有 debit-for-lottery 记录",
"续签:等待 JWT 临近过期或触发 LOTTERY_TOKEN_NEEDED 后MAIN_REFRESH_TOKEN 可续签成功"
]
},
"fundamentals": {
"title": "资金模型",
"balances": "两层余额",
"calls": "调用方向",
"note": "金额一律使用 minor 整数。信用盘(代理授信)不在本文档范围。",
"note": "金额一律使用 minor 整数。信用盘(代理授信)不在本文档范围;本文档仅覆盖主站钱包盘。",
"balanceRows": [
["main_balance", "主站钱包", "客户实现网关;彩票回调"],
["lottery balance", "彩票内余额", "转入后用于下注"]
["main_balance", "主站钱包", "客户实现网关;彩票服务端回调扣款/加款"],
["lottery balance", "彩票内余额", "玩家转入后用于下注;由彩票 H5 展示与操作"]
],
"callRows": [
["彩票 → 主站", "balance / debit / credit", "wallet_api_key"],
["彩票 H5 → 彩票 API", "me / 划转 / 下注", "玩家 JWT主站接)"]
["彩票 → 主站", "GET balance / POST debit / POST credit", "Bearer wallet_api_key"],
["彩票 H5 → 彩票 API", "me / 划转 / 下注 / 查余额", "Bearer 玩家 JWT主站无需对接)"]
]
},
"setup": {
"title": "接入配置",
"description": "接入站点创建后一次性下发密钥,请立即保存。",
"weProvide": "我方提供",
"youProvide": "客户需提供",
"defaultPaths": "默认钱包路径",
"envMapping": "配置映射",
"note": "测试与生产环境的 site_code、密钥、域名须隔离。密钥写入主站 .env不会从后台自动同步。本地开发可在彩票 .env 用 MAIN_SITE_* 作兜底。",
"description": "由我方超管在管理后台创建「接入站点」。创建成功后密钥仅展示一次,请立即保存。",
"weProvide": "创建站点后我方提供",
"youProvide": "客户需回填/提供",
"defaultPaths": "钱包网关默认路径",
"envMapping": "配置映射",
"adminSop": "后台建站步骤(我方超管)",
"network": "网络要求",
"note": "测试与生产的 site_code、密钥、域名须完全隔离。密钥写入主站服务端配置不会从后台自动同步到客户系统。",
"receiveRows": [
["site_code", "站点编码"],
["site_code", "站点编码,写入 JWT"],
["sso_jwt_secret", "JWT 签名密钥(主站持有)"],
["wallet_api_key", "钱包回调鉴权(主站校验)"],
["lottery_h5_base_url", "彩票入口地址"]
["lottery_h5_base_url", "彩票 H5 入口地址"]
],
"provideRows": [
["wallet_api_url", "HTTPS 钱包根地址"],
["测试账号", "site_player_id + 初始余额"],
["iframe origin", "嵌入时提供主站 origin"]
["wallet_api_url", "客户钱包网关 HTTPS 根地址(无 path 后缀)"],
["iframe_allowed_origins", "主站 origin 白名单iframe 模式)"],
["测试账号", "site_player_id 列表 + 初始余额"]
],
"pathRows": [
["GET", "/wallet/balance", "余额查询"],
["POST", "/wallet/debit-for-lottery", "扣款"],
["POST", "/wallet/credit-from-lottery", "加款"]
["POST", "/wallet/debit-for-lottery", "扣款(转入时)"],
["POST", "/wallet/credit-from-lottery", "加款(转出时)"]
],
"envMappingRows": [
["site_code", "site_code", "MAIN_SITE_CODE", "JWT 与玩家建档标识;双方须一致"],
["SSO 密钥", "sso_jwt_secret", "MAIN_SITE_SSO_JWT_SECRET", "主站签发;彩票验签"],
["钱包鉴权", "wallet_api_key", "MAIN_SITE_WALLET_API_KEY", "彩票回调主站时 Bearer 携带;主站校验"],
["钱包根地址", "wallet_api_url", "(主站部署路由", "客户 HTTPS 根地址;彩票拼接 /wallet/* 路径"],
["彩票入口", "lottery_h5_base_url", "NEXT_PUBLIC_LOTTERY_IFRAME_URL", "跳转或 iframe 目标"],
["iframe 白名单", "iframe_allowed_origins", "NEXT_PUBLIC_LOTTERY_ORIGIN", "主站 origin彩票允许嵌入"],
["彩票 API", "—", "LOTTERY_API_BASE_URL", "仅参考实现需要"]
["site_code", "code", "MAIN_SITE_CODE", "JWT 与玩家建档标识;双方须一致"],
["SSO 密钥", "sso_jwt_secret", "MAIN_SITE_SSO_JWT_SECRET", "主站签发 JWT;彩票验签"],
["钱包鉴权", "wallet_api_key", "MAIN_SITE_WALLET_API_KEY", "彩票回调主站时 Bearer 携带"],
["钱包根地址", "wallet_api_url", "(主站部署)", "客户 HTTPS 根地址;彩票拼接 /wallet/*"],
["彩票 API", "—", "—", "当前默认 https://lotterylaravel.tanumo.com玩家/钱包业务 API 根地址"],
["彩票 H5", "lottery_h5_base_url", "(主站 iframe src", "当前默认 https://front.tanumo.com"],
["iframe 白名单", "iframe_allowed_origins", "(主站 origin", "须与主站实际 origin 一致"]
],
"adminSop": "后台建站步骤",
"adminSopSteps": [
"超管登录管理后台 → 配置 → 接入站点",
"新建站点填写站点编码site_code、名称、币种",
"填写 wallet_api_urlHTTPS 根地址,无 path、lottery_h5_base_url、iframe_allowed_origins(主站 origin每行一个",
"创建成功后立即保存一次性展示的 sso_jwt_secret、wallet_api_key",
"将密钥写入主站 .env在列表中对站点执行「连通性测试」探测 GET /wallet/balance",
"本地联调可用 main-site/ 参考实现;生产 wallet_api_url 须公网 HTTPS"
"超管登录管理后台 → 左侧「配置」→「接入站点",
"点击新建填写站点编码site_code、名称、默认币种",
"填写 wallet_api_urlHTTPS 根地址、lottery_h5_base_url、iframe_allowed_origins",
"创建成功后立即保存页面展示的 sso_jwt_secret、wallet_api_key",
"将密钥安全交付客户;客户在主站服务端配置",
"在站点列表执行「连通性测试」(探测 GET /wallet/balance"
],
"adminFieldRows": [
["code", "站点编码,写入 JWT site_code", "demo"],
["code", "站点编码,写入 JWT site_code", "partner_demo"],
["wallet_api_url", "客户钱包网关 HTTPS 根地址", "https://wallet.partner.com"],
["lottery_h5_base_url", "彩票 H5 入口", "https://lottery.partner.com"],
["lottery_h5_base_url", "彩票 H5 入口", "https://front.tanumo.com"],
["iframe_allowed_origins", "允许嵌入的主站 origin", "https://www.partner.com"],
["sso_jwt_secret", "创建后一次性下发", "—"],
["wallet_api_key", "创建后一次性下发", "—"]
["sso_jwt_secret", "创建后一次性展示", "—"],
["wallet_api_key", "创建后一次性展示", "—"]
],
"network": "网络要求",
"networkItems": [
"钱包回调由彩票服务端发起非玩家浏览器客户网关须对彩票服务器可达",
"生产环境 wallet_api_url 仅允许 HTTPS 公网地址(拒绝 localhost / 私网 IP",
"路径固定为 /wallet/balance、/wallet/debit-for-lottery、/wallet/credit-from-lottery可后台 path 前缀)",
"建议超时 ≤ 10 秒;超时可能进入待对账状态"
"钱包回调由彩票服务端发起非玩家浏览器客户网关须对彩票服务器网络可达",
"生产环境 wallet_api_url 须为 HTTPS 公网地址(不接受 localhost / 私网 IP",
"默认路径 /wallet/balance、/wallet/debit-for-lottery、/wallet/credit-from-lottery后台配置 path 前缀)",
"建议接口超时 ≤ 10 秒;超时可能导致划转进入待对账状态"
]
},
"sso": {
"title": "单点登录SSO",
"description": "HS256 JWT。主站签发彩票验签。进入方式URL 跳转或 iframe postMessage。",
"description": "HS256 JWT。主站服务端签发,彩票验签。入场URL ?token= 或 iframe postMessage。",
"claims": "JWT 字段",
"sign": "签示例",
"sign": "签示例Node.js",
"entryA": "方式 AURL 跳转",
"entryB": "方式 Biframe 嵌入",
"noExchangeNote": "彩票不提供「登录换票」接口。主站登录后自行签发 JWT玩家 API 统一用 Authorization: Bearer 携带。首次有效 JWT 调用 GET /api/v1/player/me 时自动建档。",
"entryApi": "入场接口(彩票)",
"entryApiNote": "可选:主站登录后服务端代调一次,用于验签与建档(参考 main-site。日常业务由彩票 H5 自行调用玩家 API。",
"entryB": "方式 Biframe postMessage",
"noExchangeNote": "彩票不提供「登录换票」接口。主站登录后自行签发 JWT后续玩家 API 统一用 Authorization: Bearer 携带同一份 JWT。首次有效 JWT 调用 GET /api/v1/player/me 时自动建档,无需先调登录接口。",
"entryApi": "验签与建档",
"entryApiNote": "可选:主站登录后服务端代调一次 GET /api/v1/player/me 做验签预检。日常业务(划转、下注)由彩票 H5 自行携带 JWT 调用,主站无需对接。",
"publicApis": "公开接口(无需 token",
"h5ScopeNote": "划转、下注、彩票内余额查询等玩家业务接口由我方 H5 携带 JWT 调用,不在主站接入范围内。主站只需签发 JWT 实现钱包网关。",
"partnerApis": "主站侧接口(客户实现)",
"refreshNote": "iframe 续签详见「iframe 协议」页。主站收到 LOTTERY_TOKEN_NEEDED 或 LOTTERY_TOKEN_REFRESH_REQUEST 后重新签发 JWT发送 MAIN_REFRESH_TOKEN。",
"authResponse": "鉴权失败响应",
"errors": "错误码",
"iframeNote": "须配置 iframe_allowed_origins。收到 token 后勿重复发送 LOTTERY_READY。",
"h5ScopeNote": "划转、下注、彩票内余额查询等由我方 H5 携带 JWT 调用,不在主站接入范围内。主站只需:① 签发 JWT 实现钱包网关。",
"refreshNote": "iframe 续签:主站收到 LOTTERY_TOKEN_NEEDED 或 LOTTERY_TOKEN_REFRESH_REQUEST 后,重新签发 JWT 并发送 MAIN_REFRESH_TOKEN。详见「iframe 协议」。",
"authResponse": "鉴权失败示例",
"errors": "SSO 错误码",
"iframeNote": "须配置 iframe_allowed_origins。token 通过 postMessage 顶层字段 token 传递,不要放在 payload 内。",
"claimRows": [
["site_code", "string", "是", "接入站点编码"],
["site_code", "string", "是", "接入站点编码,与后台一致"],
["site_player_id", "string", "是", "主站用户 ID稳定唯一"],
["iat", "number", "是", "签发时间(秒)"],
["exp", "number", "是", "过期时间(秒);≤ 300"]
["iat", "number", "是", "签发时间(Unix 秒)"],
["exp", "number", "是", "过期时间(Unix 秒exp - iat ≤ 300"]
],
"messageRows": [
["→ 主站", "LOTTERY_READY", "子页就绪"],
["→ 主站", "LOTTERY_TOKEN_NEEDED", "请求续签"],
["→ 彩票", "MAIN_INIT_TOKEN", "{ token }"],
["→ 彩票", "MAIN_REFRESH_TOKEN", "{ token }"]
["→ 主站", "LOTTERY_READY", "子页就绪,请求 token"],
["→ 主站", "LOTTERY_TOKEN_NEEDED", "token 失效,请求续签"],
["→ 彩票", "MAIN_INIT_TOKEN", "顶层 token 字段"],
["→ 彩票", "MAIN_REFRESH_TOKEN", "顶层 token 字段"]
],
"publicApiRows": [
["GET", "/api/v1/player/ping", "玩家 API 连通性探测"],
["GET", "/api/v1/integration/runtime-origins", "iframe 允许嵌入的 origin 列表"]
],
"partnerApiRows": [
["POST", "/api/auth/refresh", "(参考)续签 JWT返回新 token 供 MAIN_REFRESH_TOKEN"]
],
"errorRows": [
["8001", "缺少 Authorization 头"],
["8002", "JWT 无效或已过期"],
["8003", "玩家未建档"],
["8004", "SSO 密钥未配置"],
["8005", "账号已冻结"]
["8002", "JWT 无效或已过期密钥不一致、exp 超时、签名错误)"],
["8003", "玩家未建档SSO 首次 me 会自动建档;此码多见于内部测试)"],
["8004", "SSO 密钥未配置(站点侧问题,联系我方)"],
["8005", "账号已冻结(站点停用或玩家冻结)"]
]
},
"iframe": {
"title": "iframe 协议",
"description": "主站嵌入彩票 H5 时的 postMessage 约定。URL 跳转模式可跳过本章。",
"description": "主站嵌入彩票 H5 时的 postMessage 约定。若使用 URL ?token= 跳转,可跳过本章。",
"sequence": "推荐时序",
"envelope": "消息结构",
"envelopeSection": "消息格式(注意方向差异)",
"childMessages": "彩票 → 主站",
"parentMessages": "主站 → 彩票",
"targetOrigin": "targetOrigin",
"envelopeNote": "消息为 JSON 对象。彩票发出 type 前缀 LOTTERY_主站发出 MAIN_。建议带 timestamp 与 source。",
"targetOriginNote": "postMessage 第二参数须为具体 origin如 https://www.partner.com禁止使用 *。主站只接受后台 iframe_allowed_origins 中的 origin彩票子页校验 event.origin 在白名单内。",
"timingNote": "收到 MAIN_INIT_TOKEN 后彩票子页勿再发送 LOTTERY_READY避免主站重复下发 token。续签子页发 LOTTERY_TOKEN_NEEDED 或 LOTTERY_TOKEN_REFRESH_REQUEST → 主站回 MAIN_REFRESH_TOKEN。",
"example": "主站集成示例",
"targetOrigin": "targetOrigin 安全",
"envelopeNote": "常见错误:把 token 放在 payload.token。彩票 H5 读取的是消息顶层的 data.token。",
"targetOriginNote": "postMessage 第二参数须为彩票 H5 的 origin当前默认 https://front.tanumo.com禁止使用 *。主站须校验 event.originiframe_allowed_origins 填入主站 origin非彩票域名。",
"timingNote": "收到 MAIN_INIT_TOKEN 后彩票子页不再发送 LOTTERY_READY。续签LOTTERY_TOKEN_NEEDED → 主站回 MAIN_REFRESH_TOKEN顶层 token。",
"sequenceSteps": [
"主站页面嵌入 <iframe src=\"{lottery_h5_base_url}\">",
"彩票 H5 加载白名单后发送 LOTTERY_READY",
"主站监听 message校验 origin 后发送 MAIN_INIT_TOKEN",
"彩票 H5 保存 token调用 /api/v1/player/me 入场",
"Token 将过期:彩票发 LOTTERY_TOKEN_NEEDED → 主站续签后发 MAIN_REFRESH_TOKEN"
"主站嵌入 <iframe src=\"{lottery_h5_base_url}\">",
"彩票 H5 校验白名单后发送 LOTTERY_READY",
"主站监听 message校验 origin 后发送 MAIN_INIT_TOKEN(顶层 token",
"彩票 H5 保存 token调用 GET /api/v1/player/me 入场",
"JWT 将过期:彩票发 LOTTERY_TOKEN_NEEDED → 主站续签后发 MAIN_REFRESH_TOKEN"
],
"envelopeRows": [
["彩票 → 主站", "type + payload + timestamp", "如 LOTTERY_READY业务数据在 payload"],
["主站 → 彩票", "type + token + timestamp", "token 必须在顶层,不要嵌套在 payload"]
],
"childMessageRows": [
["→ 主站", "LOTTERY_READY", "子页就绪,请求下发 token"],
["→ 主站", "LOTTERY_TOKEN_NEEDED", "token 失效,请求续签"],
["→ 主站", "LOTTERY_TOKEN_REFRESH_REQUEST", "主动请求刷新 token"],
["→ 主站", "LOTTERY_HEARTBEAT", "心跳(可忽略)"],
["→ 主站", "LOTTERY_TOKEN_REFRESHED", "续签成功通知"]
["→ 主站", "LOTTERY_TOKEN_REFRESHED", "续签成功通知(子 → 主)"]
],
"parentMessageRows": [
["→ 彩票", "MAIN_INIT_TOKEN", "{ token } 首次下发"],
["→ 彩票", "MAIN_REFRESH_TOKEN", "{ token } 续签"],
["→ 彩票", "MAIN_INIT_TOKEN", "首次下发;顶层 token 字段"],
["→ 彩票", "MAIN_REFRESH_TOKEN", "续签;顶层 token 字段"],
["→ 彩票", "MAIN_REQUEST_STATUS", "请求子页状态"],
["→ 彩票", "MAIN_NAVIGATE", "{ path } 导航"]
["→ 彩票", "MAIN_NAVIGATE", "导航到指定 path"]
]
},
"wallet": {
"title": "钱包网关",
"description": "由客户实现。彩票服务端调用。鉴权:Bearer wallet_api_key。",
"description": "由客户实现。彩票服务端调用非玩家浏览器。鉴权Authorization: Bearer {wallet_api_key}。",
"balance": "查询余额",
"debit": "扣款",
"credit": "加款",
"debit": "扣款(转入)",
"credit": "加款(转出)",
"response": "响应示例",
"httpContract": "HTTP 契约",
"httpErrors": "HTTP 错误",
"creditNote": "请求体与扣款相同;用于转出或失败回滚加款。",
"idempotentNote": "idempotent_key相同键 + 相同操作须返回首次 JSONHTTP 200禁止重复记账同键不同操作/金额 → success: false。",
"idempotentNote": "idempotent_key相同键 + 相同金额须返回首次 JSONHTTP 200禁止重复记账同键不同金额 → success: false。",
"queryRows": [
["site_code", "string", ""],
["site_player_id", "string", ""],
["currency_code", "string", ""]
["site_code", "string", "站点编码"],
["site_player_id", "string", "主站用户 ID"],
["currency_code", "string", "币种代码"]
],
"fieldRows": [
["site_code", "string", ""],
["site_player_id", "string", ""],
["player_id", "number", "彩票玩家 ID"],
["currency_code", "string", ""],
["site_code", "string", "站点编码"],
["site_player_id", "string", "主站用户 ID"],
["player_id", "number", "彩票玩家 ID(参考)"],
["currency_code", "string", "币种代码"],
["amount_minor", "integer", "minor 正整数"],
["idempotent_key", "string", "幂等键"]
["idempotent_key", "string", "幂等键,全局唯一"]
],
"httpErrorRows": [
["401", "unauthorized", "API Key 错误"],
["422", "invalid request", "字段或金额非法"],
["409", "main balance insufficient", "业务拒绝(如余额不足);可含 data.main_balance"]
["401", "unauthorized", "wallet_api_key 错误或缺失"],
["422", "invalid request", "字段缺失或 amount_minor 非法"],
["409", "main balance insufficient", "余额不足等业务拒绝"]
],
"httpContractRows": [
["扣款/加款成功", "200", "success: true含 external_ref_no建议与 data.main_balance"],
@@ -309,24 +363,24 @@
},
"transfer": {
"title": "资金划转(参考)",
"description": "内部说明:由彩票 H5 调用,非主站接入面。",
"outOfScopeNote": "客户无需实现本节 API。转入/转出由我方 H5 携带玩家 JWT 调用;主站只需实现钱包网关 debit/credit。本节仅供理解资金如何在两端移动。",
"description": "本节供理解资金如何在两端移动,非客户接入面。",
"outOfScopeNote": "客户无需实现本节 API。转入/转出由我方 H5 携带玩家 JWT 调用彩票 API;主站只需实现钱包网关 debit/credit。",
"requestFields": "请求字段",
"transferIn": "转入(主站 → 彩票)",
"transferOut": "转出(彩票 → 主站)",
"transferResponse": "成功响应",
"errors": "常见错误码",
"inNote": "流程:彩票调主站 debit-for-lottery → 彩票内加款。",
"outNote": "流程:彩票内扣款 → 彩票调主站 credit-from-lottery。",
"responseNote": "转入与转出结构相同direction 为 in / out。幂等重放返回相同 data。",
"inNote": "流程:玩家 H5 发起转入 → 彩票调主站 debit-for-lottery → 彩票内加款。",
"outNote": "流程:玩家 H5 发起转出 → 彩票内扣款 → 彩票调主站 credit-from-lottery。",
"responseNote": "转入与转出响应结构相同direction 为 in / out。幂等重放返回相同 data。",
"requestFieldRows": [
["amount", "integer", "minor 正整数"],
["currency", "string", "可选;默认玩家 default_currency"],
["idempotent_key", "string", "全局唯一;重复须返回相同结果"]
],
"errorRows": [
["1001", "彩票余额不足(转出)"],
["1009", "主站钱包处理失败"],
["1001", "彩票余额不足(转出"],
["1009", "主站钱包处理失败网关不可达、401、超时等"],
["1010", "幂等键冲突(同键不同金额)"],
["2003", "请先转入后再下注"]
]
@@ -336,11 +390,11 @@
"sso": "SSO 鉴权",
"lotteryWallet": "彩票钱包 / 划转",
"gateway": "客户钱包网关HTTP",
"idempotentNote": "幂等:同一 idempotent_key 须返回相同结果;同键不同金额 → 1010。",
"idempotentNote": "幂等:同一 idempotent_key + 相同金额须返回相同结果;同键不同金额 → 1010 或 success:false。",
"ssoRows": [
["8001", "缺少 Authorization 头"],
["8002", "JWT 无效或已过期"],
["8003", "玩家未建档"],
["8003", "玩家未建档SSO 正常流程会自动建档)"],
["8004", "SSO 密钥未配置"],
["8005", "账号已冻结"]
],
@@ -356,16 +410,58 @@
["409", "—", "业务拒绝(如余额不足)"]
]
},
"troubleshooting": {
"title": "联调排错",
"description": "按现象对照排查。仍无法解决请联系对接技术支持,并提供 site_code、时间戳与请求 ID。",
"faq": "常见问题",
"jwt": "JWT / 入场",
"iframe": "iframe",
"wallet": "钱包网关",
"note": "联调时先用 curl 分别验证 JWT/player/me与钱包网关/wallet/balance再测 iframe 全链路。",
"faqRows": [
["curl /player/me 返回 8002", "检查 sso_jwt_secret 是否与后台站点一致site_code 是否匹配exp 是否已过期≤300 秒)"],
["iframe 白屏 / 不进大厅", "检查 token 是否在 postMessage 顶层;是否收到 LOTTERY_READY 后发送 MAIN_INIT_TOKENiframe_allowed_origins 是否含主站 origin"],
["转入失败 1009", "彩票服务端能否访问 wallet_api_urlwallet_api_key 是否正确debit 是否返回 200 + success:true"],
["连通性测试失败", "wallet_api_url 须公网 HTTPSGET /wallet/balance 可访问且 Bearer wallet_api_key 正确"],
["8005 账号冻结", "后台检查接入站点是否启用;该 site_player_id 是否被冻结"]
],
"jwtRows": [
["8002 Token 无效", "密钥不一致 / exp 过期 / site_code 写错 / 算法非 HS256"],
["8004 SSO 未配置", "联系我方确认站点 sso_jwt_secret 已配置"],
["me 返回 code=0 但 H5 仍失败", "iframe 传的 token 与 curl 测试的不是同一份,或 token 在 payload 内而非顶层"]
],
"iframeRows": [
["收不到 LOTTERY_READY", "iframe src 是否为 lottery_h5_base_urlH5 是否加载完成"],
["postMessage 无响应", "targetOrigin 是否为彩票 H5 的 origin非主站 origin"],
["重复刷 token", "收到 MAIN_INIT_TOKEN 后子页不应再发 LOTTERY_READY"],
["续签失败", "主站是否监听 LOTTERY_TOKEN_NEEDED 并回 MAIN_REFRESH_TOKEN"]
],
"walletRows": [
["401 unauthorized", "wallet_api_key 与后台站点不一致"],
["409 余额不足", "测试账号 main_balance 不足;检查 amount_minor 单位"],
["重复扣款", "idempotent_key 未做幂等;相同 key 须返回首次响应"],
["彩票未回调 debit", "wallet_api_url 不可达或连通性测试未通过"]
]
},
"golive": {
"title": "上线清单",
"checklist": "检查",
"description": "生产发布前,请与客户经理确认联调已通过,并完成下列检查",
"deliveryChecklist": "交付与流程",
"checklist": "技术检查项",
"deliveryItems": [
"生产环境已独立创建接入站点site_code、密钥与联调隔离",
"密钥已安全写入主站生产配置(非前端)",
"wallet_api_url 为生产 HTTPS 公网地址,连通性测试通过",
"iframe_allowed_origins 已配置生产主站 origin",
"全链路联调记录已归档(转入 → 下注 → 派奖 → 转出)"
],
"items": [
"测试与生产site_code、密钥、域名完全分离",
"JWT 仅服务端签发,有效期 ≤ 5 分钟",
"钱包接口 HTTPS超时建议 ≤ 10 秒",
"idempotent_key 幂等处理",
"iframe 模式:配置 iframe_allowed_origins",
"全链路:转入 → 下注 → 派奖 → 转出"
"钱包接口 HTTPS超时 ≤ 10 秒,幂等已实现",
"iframepostMessage token 在顶层origin 校验已启用",
"测试与生产site_code、密钥、域名完全分离",
"监控:钱包网关 4xx/5xx 与 debit/credit 日志告警",
"回滚预案:可临时停用接入站点"
]
}
}