แนวคิดหลัก
โปรเจกต์ คีย์ เซสชันของผู้เล่น และวิธีที่ SDK ทุกตัวรายงานผลลัพธ์และข้อผิดพลาด
คอมเมนต์ในโค้ดและชื่อ API ยังคงเป็นภาษาอังกฤษเพื่อให้ตรงกับ SDK
โปรเจกต์และคีย์#
แต่ละเกมคือหนึ่ง โปรเจกต์ คีย์ใช้ระบุโปรเจกต์ ไม่ได้ใช้ระบุผู้เล่น
| ข้อมูลรับรอง | ใช้ที่ไหน |
|---|---|
| Base URL | ที่อยู่ของระบบที่ติดตั้งนี้ API อยู่ภายใต้ /v1 |
| Project ID | ทุกคำขอ ในรูปแบบ X-Project-ID เป็นข้อมูลสาธารณะ |
คีย์ไคลเอนต์ pk_live_… | บิลด์เกมและหน้าเว็บ ในรูปแบบ X-Client-Key เป็นข้อมูลสาธารณะ เพราะทำงานแทนได้เฉพาะผู้เล่นที่เข้าสู่ระบบแล้ว |
คีย์ลับ sk_live_… | เซิร์ฟเวอร์ของคุณเองเท่านั้น ในรูปแบบ X-Secret-Key แสดงเพียงครั้งเดียวและจัดเก็บแบบแฮช ใช้ปลดล็อกเอนด์พอยต์สำหรับเซิร์ฟเวอร์เท่านั้น |
sk_live_…) ไว้ในบิลด์เกมหรือหน้าเว็บ ทุกสิ่งที่ส่งถึงผู้เล่นสามารถถูกอ่านได้ผู้เล่นและเซสชัน#
การเรียกในนามผู้เล่นต้องใช้ access token การเข้าสู่ระบบจะได้ access token (ใช้ได้หนึ่งชั่วโมง) พร้อม refresh token (ใช้ได้ 30 วัน)
- SDK จัดเก็บเซสชันไว้บนอุปกรณ์และรีเฟรชก่อนหมดอายุ ผู้เล่นจึงอยู่ในระบบต่อเนื่องแม้ปิดแล้วเปิดเกมใหม่
- Refresh token จะหมุนเวียนทุกครั้งที่ใช้ หากนำ token เก่ากลับมาใช้ซ้ำ เซสชันนั้นจะถูกออกจากระบบในทุกที่ (ตรวจจับการขโมย)
- ผู้เล่นทุกคนเริ่มต้นเป็น เกสต์ และเชื่อมบัญชีอีเมลหรือ Google ภายหลังได้ โดยความคืบหน้าของเกสต์จะย้ายตามไปด้วย ดู ผู้เล่น
ผลลัพธ์แทน exception#
การเรียก SDK จะไม่โยน exception เมื่อเกิดข้อผิดพลาดของเครือข่ายหรือเซิร์ฟเวอร์ แต่จะคืนผลลัพธ์ที่มี ok ค่าที่ได้ และข้อผิดพลาดซึ่งประกอบด้วยรหัสที่คงที่ ข้อความ และรหัสคำขอ
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" }
}
}การลองใหม่และ rate limit#
SDK จะลองส่งคำขอที่ปลอดภัยใหม่เมื่อเกิดข้อผิดพลาดของเครือข่ายหรือได้การตอบกลับ 5xx โดยใช้ exponential backoff และจะรอตาม Retry-After เมื่อได้รับ 429
- แต่ละโปรเจกต์ส่งได้สูงสุด 120 คำขอต่อนาที หากเกินกว่านั้น API จะตอบกลับ
rate_limited - แต่ละบัญชีมี โควตาคำขอรายวัน ตามแพ็กเกจ (ดู ขีดจำกัด) หากเกิน API จะตอบกลับ
quota_exceededจนถึง 00:00 UTC - การตอบกลับมี
X-RateLimit-Limit,X-RateLimit-Remainingและเมื่อใกล้ถึงโควตาจะมีX-RateLimit-Daily-Remaining
รหัสคำขอและล็อก#
ทุกการตอบกลับมีเฮดเดอร์ X-Request-ID และทุกข้อผิดพลาดมี request_id ค้นหารหัสนี้ในหน้า ล็อก ของโปรเจกต์เพื่อดูเอนด์พอยต์ สถานะ เวลาตอบสนอง และผู้เล่น