核心概念
项目、密钥、玩家会话,以及各 SDK 如何报告结果和错误。
代码注释和 API 名称保留英文,以便与 SDK 保持一致。
项目和密钥#
每个游戏就是一个项目。项目的密钥用于识别项目,而不是识别玩家。
| 凭据 | 用途 |
|---|---|
| Base URL | 此安装的地址。API 位于 /v1 之下。 |
| Project ID | 每个请求都要以 X-Project-ID 发送。公开。 |
客户端密钥 pk_live_… | 用于游戏构建和网页,以 X-Client-Key 发送。公开:它只能代表已登录的玩家执行操作。 |
私密密钥 sk_live_… | 仅用于你自己的服务器,以 X-Secret-Key 发送。只显示一次,以哈希形式存储;可解锁仅限服务器调用的端点。 |
切勿将私密密钥(
sk_live_…)放入游戏构建或网页中。任何交付给玩家的内容都可能被读取。玩家和会话#
玩家调用需要访问令牌。登录会返回一个访问令牌(有效期一小时),以及一个刷新令牌(有效期 30 天)。
- SDK 会将会话保存在设备上,并在过期前刷新,因此玩家在多次启动之间都能保持登录。
- 刷新令牌每次使用后都会轮换。重复使用旧令牌会让该会话在所有设备上退出登录(盗用检测)。
- 每位玩家都以游客身份开始,之后可以关联邮箱或 Google 账号,游客的进度会随之迁移。参见玩家。
返回结果,而不是抛出异常#
SDK 调用在遇到网络或服务器错误时从不抛出异常,而是返回一个结果:其中包含 ok、一个值,以及一个带有稳定错误码、消息和请求 ID 的错误。
var top = await Majacloud.Leaderboards.GetTopAsync("coins", 10);
if (top.Ok)
{
foreach (var entry in top.Value.Entries)
Debug.Log($"#{entry.Rank} {entry.PlayerName} {entry.Score}");
}
else if (top.Error.IsRetryable)
{
// Network, timeout, 5xx or rate limit: try again later
Debug.Log("Retry in " + top.Error.RetryAfterSeconds + " s");
}
else
{
Debug.LogWarning(top.Error.Code + ": " + top.Error.Message + " (" + top.Error.RequestId + ")");
}var top := await Majacloud.leaderboards.get_top("coins", 10)
if top.ok:
for entry in top.value.entries:
print("#%d %s %d" % [entry.rank, entry.player_name, entry.score])
elif top.is_retryable():
# Network, timeout, 5xx or rate limit: try again later
print("Retry in ", top.retry_after, " s")
else:
push_warning("%s: %s (%s)" % [top.error, top.message, top.request_id])const top = await mc.leaderboards.getTop('coins', { limit: 10 });
if (top.ok) {
for (const entry of top.value.entries) {
console.log(`#${entry.rank} ${entry.player_name} ${entry.score}`);
}
} else if (top.error.retryable) {
// Network, timeout, 5xx or rate limit: try again later
console.log('Retry in', top.error.retryAfter, 's');
} else {
console.warn(`${top.error.code}: ${top.error.message} (${top.error.requestId})`);
}// Success
{ "ok": true, "entries": [ … ], "total": 42 }
// Error (HTTP 4xx/5xx)
{
"ok": false,
"error": {
"code": "rate_limited",
"message": "Project rate limit reached. Try again in a minute.",
"request_id": "6f1c2a9e-…",
"details": { "limit": 120, "window": "minute" }
}
}重试和速率限制#
遇到网络错误和 5xx 响应时,SDK 会以指数退避方式重试安全请求;遇到 429 响应时,会按照 Retry-After 等待。
- 每个项目每分钟最多可发送 120 个请求;超出后 API 会返回
rate_limited。 - 每个账号都有每日请求配额,具体取决于套餐(参见限制);超出后 API 会返回
quota_exceeded,直到 00:00 UTC。 - 响应中包含
X-RateLimit-Limit、X-RateLimit-Remaining,接近配额时还包含X-RateLimit-Daily-Remaining。
请求 ID 和日志#
每个响应都带有 X-Request-ID 头,每个错误都包含 request_id。在项目的日志页面中搜索它,即可查看端点、状态、延迟和玩家。