ZYMIX 接口文档 管理后台 · 接口文档 · 开发者文档 · Markdown 源文件

ZYMIX 小游戏通用后台接口文档

服务入口

当前局域网服务 http://192.168.1.200:18080

路径 内容
/admin 管理后台,账号密码登录
/docs 本接口文档网页
/docs/api.md Markdown 源文件
/docs/developer 原钉钉开发者文档整理网页
/docs/developer.md 钉钉文档 Markdown
/health 存活探针,包含 revision
/ready MySQL 和 Redis 就绪检查,失败 503

API 使用 JSON,成功包含 ok: true,错误包含 ok: false, code, message。业务写请求在 MySQL 事务提交后响应。请求体最大 1 MiB,必须为 JSON 对象。时间为 ISO 8601 UTC。客户端收到 429/503 应退避重试;一次性登录 code 不得重复兑换。

管理端登录

管理 API 前缀 /api/admin,浏览器同源使用 Cookie,不支持手工 ADMIN_TOKEN。所有非 GET 操作均需 X-Requested-With: ZymixAdmin。浏览器跨站 Origin 被拒绝。

await fetch('/api/admin/auth/login', {
  method: 'POST', credentials: 'same-origin',
  headers: {'Content-Type':'application/json', 'X-Requested-With':'ZymixAdmin'},
  body: JSON.stringify({username:'zymix', password:'管理员密码'})
});
方法和路径 请求 成功响应
POST /api/admin/auth/login username、password username、expiresAt、renewAfterSeconds,Set-Cookie
GET /api/admin/auth/me Cookie username、expiresAt、renewAfterSeconds
POST /api/admin/auth/refresh Cookie、防跨站请求头 会话信息,到轮换时间时 Set-Cookie
POST /api/admin/auth/logout Cookie、防跨站请求头 ok,删除服务端会话并清除 Cookie

Cookie 为 HttpOnly、SameSite=Strict;HTTPS 使用 Secure。局域网 HTTP 显式 COOKIE_SECURE=false。默认空闲 1 小时、最长 12 小时、每 10 分钟轮换;旧令牌兼容 30 秒以支持并发标签页。页面自动续期,401 时要求重新登录。Redis 故障不放行鉴权。

项目配置

方法和路径 说明
GET /api/admin/projects 返回 projects,最多 1000 个,按创建时间降序
POST /api/admin/projects 创建,成功 201,返回 project,version=1
GET /api/admin/projects/:id 获取完整脱敏配置
PATCH /api/admin/projects/:id 修改,必须携带读取时的 version,成功 version+1
DELETE /api/admin/projects/:id 删除项目及其会话、存档、事件、领奖、防重记录
GET /api/admin/projects/:id/stats 统计,支持 from/to ISO 日期

AppID 必填且唯一,1~128 个字母、数字、下划线、连字符,创建后不可变更。name 必填,最长 200 字符。AppSecret 加密保存,管理回显 [redacted];未配置时为空。空值、缺省、[redacted] 保留已有密钥,clearAppSecret:true 显式清除。

TCMPP 最小创建示例:

{
  "name": "示例小游戏",
  "appId": "your-game-appid",
  "appSecret": "从控制台取得的密钥",
  "enabled": true,
  "environment": "production",
  "auth": {
    "protocol": "tcmpp",
    "jscode2sessionUrl": "https://实际OpenServer域名/openserver/sns/jscode2session",
    "requestTimeoutMs": 5000,
    "providers": {}
  }
}
配置 说明
auth.protocol 默认 tcmpp;明确选择时支持 wechat-mini-game / qq-mini-game
auth.jscode2sessionUrl TCMPP 控制台完整 URL,保留路径,不使用微信默认地址
auth.requestTimeoutMs 200~10000 毫秒
auth.providers 按 platform 映射独立 appId、appSecret、protocol、jscode2sessionUrl、requestTimeoutMs
domains request/upload/download/socket/business 数组,openServer 展示配置;真正兑换使用 auth 的 URL
share enabled、shareKeys、idRange、channels
ads.rewardedVideo 广告配置数组,placement、adUnitId、adUnitIds、platforms、enabled、reward、最低宿主版本
reward type 为 1~40 位字母数字下划线连字符,amount 为 0~1000000 整数
platforms wx/tt/ks/my/bl 的分享模板、订阅模板 ID、feed 内容 ID 配置
gray enabled、rules,按 priority 降序匹配白名单或百分比
minHostVersion android / ios 最低版本配置
privacyPolicyUrl 隐私协议地址
publicMetadata 公开扩展配置,禁止放入任何敏感数据
internalMetadata 只在后台返回的内部扩展配置

共享根凭据和独立 provider 的空白密钥保存规则一致。删除 provider 配置时提交更新后的 providers 全量对象。OpenServer 主机必须由服务器运维命令 sh deploy/ops.sh allow-host 域名 加入 MySQL 安全配置允许列表,网页和 HTTP API 不提供该列表的修改接口,只允许公网 HTTPS,不跟随重定向。

统计返回:stats.totalEventsstats.uniqueUsersstats.byType、最近 30 条 stats.recentEvents。GET 配置不写事件;需要统计曝光时客户端显式上报事件。

小游戏登录

POST /api/projects/:appId/login,无需业务 token。

{"code":"wx.login 返回的新 code", "platform":"wx", "userInfo":{"nickname":"玩家"}}

platform 默认为 wx。wx/tcmpp 默认使用根凭据,其他标识必须在 auth.providers 显式配置。本接口只支持已实现的 TCMPP、微信、QQ 换码协议;配置 tt/ks 等标识不意味着实现了其原生专有登录协议。

后台 GET 控制台提供的完整 URL,参数为 appidsecretjs_codegrant_type=authorization_code。TCMPP 详细文档路径包含 /openserver/sns/jscode2session;教程示例不同,因此以控制台为准。不能用 console.tcmpp.com 登录页面代替。

{
  "ok": true,
  "token": "业务签名token",
  "expiresAt": "2026-09-17T00:00:00.000Z",
  "user": {"userId":"usr_项目隔离标识", "userInfo":{"nickname":"玩家"}}
}

不返回 AppSecret、openid、session_key。客户端提交 userId 不改变身份。userInfo 是客户端资料,不能当作平台认证的权限或身份声明。

后续业务接口携带 Authorization: Bearer <token>。默认有效期 7 天,由 SESSION_TTL_SECONDS 配置;到期或 Redis 会话丢失后重新 wx.login。管理员 Cookie 续期与小游戏 token、腾讯 getAccessToken 是不同机制。

GET /api/session/me 返回 session 的 id、appId、userId、userInfo、createdAt、expiresAt。

公开配置和灰度

方法和路径 请求 响应
GET /api/projects/:appId/config config,安全白名单字段
GET /api/projects/:appId/share-options ?id=101&shareKey=zymixFriends share、validation;不合法 400
GET /api/projects/:appId/ads/rewarded ?placement=default,all 返回所有 ads,已启用广告
POST /api/projects/:appId/gray/evaluate userId/deviceId/guid gray.matched、rule、version

灰度匹配是客户端发布选择提示,不能用作访问敏感资源的权限控制。公开配置不包含内部元数据、认证 provider 或密钥。

存档

客户端请优先阅读 小游戏云存档接入标准,包含完整请求响应、version 管理、428/409 处理和 wx.request 示例;Markdown 源文件

GET /api/projects/:appId/data/:key 要求业务 token,按项目和用户隔离。

{"ok":true,"key":"save","exists":false,"value":null,"version":0,"updatedAt":null}

PUT /api/projects/:appId/data/:key

{"version":0,"value":{"level":1,"coins":0}}

创建时 version=0;更新时传最近读到的 version。成功返回 key、value、新 version。并发修改只有一个版本成功,其余 409,客户端应重新读取并合并业务状态,不能无条件覆盖。缺版本 428。key 最长 128 字符。存档属于客户端数据,不能作为可信积分余额。

事件和分享回调

POST /api/projects/:appId/events 要求业务 token:

{"type":"level_complete","payload":{"level":1}}

持久化后返回 202。type 为字母开头、最长 80 位的字母数字下划线点连字符;禁止伪造 login/reward_granted/project_created/project_updated 系统事件。payload 敏感键会脱敏。

POST /api/projects/:appId/share/callback 要求业务 token,提交 id、shareKey 及业务信息;写入分享校验事件,合法 200,不合法 400。

激励奖励确认

钉钉文档要求前端仅在广告 onClose 且完整观看时发放本地奖励。客户端 isEnded 不能证明服务端奖励可信。本后台持久化奖励增加可信业务服务 HMAC 确认,未配置确认服务时返回 503,不能仅凭 isEnded=true 入账。

POST /api/projects/:appId/ads/reward/complete 要求业务 token:

{
  "traceId":"可信服务签发的一次性业务追踪号",
  "adUnitId":"已配置广告位",
  "isEnded":true,
  "expires":1789023000,
  "proof":"可信服务签名"
}

可信服务在核验平台回调或业务依据后计算 HMAC-SHA256,使用独立 REWARD_PROOF_SECRET,对 JSON.stringify([projectId,userId,adUnitId,traceId,expires]) 签名,输出 base64url。expires 为未来最多 600 秒的 Unix 秒。签名密钥只能在可信服务器,不能放入小游戏、管理页面或公开配置。代码参考 src/reward-proof.js。本服务不声称验证了腾讯广告平台回调;没有可信确认链路时只使用前端本地奖励或暂停服务端发奖。

成功返回 duplicate 与 reward(traceId、userId、adUnitId、reward、grantedAt)。同项目同 traceId 持久化一次,并发不会重复记账。签名错误 403;traceId 已归属另一用户 409。这是发奖记录,不是资金账户或积分钱包。

错误码和客户端处理

HTTP 常见 code 处理
400 invalid_project_identity / invalid_provider_url / invalid_event_type / invalid_reward 修正参数
400 code_required / invalid_platform / data_key_invalid / data_value_required 补齐或修正参数
401 admin_login_required / invalid_credentials / session_expired / invalid_login_code 重新登录;小游戏重新获取 code
403 csrf_rejected / invalid_reward_proof / reward_proof_expired 核对同源请求头或可信确认签名
404 project_not_found / ad_not_found / not_found 检查项目、广告和路径
409 conflict / project_version_conflict / data_version_conflict 唯一键或版本竞争;重新读取
409 code_consumed / reward_owner_mismatch 获取新 code;拒绝跨用户奖励重用
413 request_error 请求体过大
428 project_version_required / data_version_required 带上读取时版本
429 rate_limited / login_busy 退避,避免立即无限重试
502 code_exchange_failed / code_exchange_http_error / code_exchange_network_error / code_exchange_invalid_response 检查平台服务、凭据和配置;原始响应不会透出
503 database_unavailable / service_unavailable 存储不可用,退避重试
503 app_secret_not_configured / code_exchange_not_configured / reward_confirmation_not_configured 管理员补全服务端配置
504 code_exchange_timeout 获取新 code 后重试

平台 code 兑换失败可能附带数字 details.providerCode,不回显上游 errmsg 或 URL 查询参数。客户端网络超时可能发生在数据库已提交之后:存档需读取最新版本,奖励用相同追踪号检查,不能生成新编号重复发奖。