Chuyển tới nội dung chính

XMDT — Cocos Creator

Một package npm, @alogame/kyc-sdk, cài đặt trọn vẹn luồng XMDT hoàn toàn bằng TypeScript — tự vẽ màn hình bằng chính component UI của Cocos và gọi thẳng 4 endpoint phiên của Ekycx qua HTTPS. Khác với SDK Android, iOS, và Unity, không có code native, không .aar, không .xcframework, không gì phải nhúng vào bản build — toàn bộ package là mã nguồn .ts, project của bạn compile giống hệt cách compile script của chính mình.

Chưa kiểm chứng trên thiết bị thật — đọc trước khi dùng

Package này đã được typecheck với type declaration chính thức của Cocos Creator 3.8, và phần logic nghiệp vụ có 119 test tự động, nhưng chưa từng chạy trong một project Cocos Creator thật, trên thiết bị thật, hay trong Editor. Coi mọi thứ ở trang này là đúng-trên-giấy, chưa được xác nhận. Nếu bạn đang cân nhắc dùng cho tích hợp thật, hãy hỏi trước khi phụ thuộc vào nó.

Các môi trường
Môi trườngBase URL
Devhttps://api-xmdt.dev.alogame.vn
Prodhttps://api-xmdt.alogame.vn

Cả hai đều đang hoạt động. gameId của bạn phải được Alogame Operations bật XMDT trước khi dùng được ở cả hai — xem Tích hợp phía Server.

Đọc phần này trước

Tích hợp Server mô tả lệnh gọi duy nhất phía server của bạn để mint sessionToken. Client của bạn không bao giờ gọi trực tiếp API danh tính của Alogame và không bao giờ thấy secret HMAC của bạn.

Yêu cầu: Cocos Creator 3.8+.

Vì sao có package này bên cạnh SDK Android/iOS/Unity​

Các SDK native (và package Unity bọc chúng) cần thiết bị vật lý mới chạy được — Editor preview và simulator của Cocos không nạp được binary native. Với một game Cocos, điều đó nghĩa là mọi bước tích hợp — thử một layout UI mới, xử lý một Failed reason mới, bất kỳ thứ gì — đều đòi một lần build ra thiết bị đầy đủ. Package này đánh đổi một phần độ mượt UI (xem "Khác gì so với SDK native" bên dưới) để chạy trọn vẹn trong chính Editor preview của Cocos Creator, giống hệt cách phần còn lại của game bạn chạy.

1. Thêm package​

npm install @alogame/kyc-sdk

Cocos Creator resolve nó như mọi dependency npm khác trong project — không cần extension, không cần sửa Project Settings.

2. Khởi tạo​

Gọi một lần, lúc khởi động:

TypeScript
import { init } from "@alogame/kyc-sdk";

init("dev");

3. Set game role​

Sau khi đã có sessionToken từ server của bạn (xem Tích hợp Server):

TypeScript
import { setGameRole } from "@alogame/kyc-sdk";

setGameRole(
"player_account_name", // uid — phải khớp `username` mà server bạn đã mint session cho
sessionToken,
"server_01", // tuỳ chọn
"character_123", // tuỳ chọn
);

uid và sessionToken luôn về cùng một response từ server — không bao giờ gọi với cái này mà thiếu cái kia. Đổi sang uid khác sẽ xoá trạng thái đã xác thực cache của uid cũ.

4. Mở màn hình​

TypeScript
import { show } from "@alogame/kyc-sdk";
import type { AlogameKycListener, AlogameKycResult } from "@alogame/kyc-sdk";

function startXmdt(): void {
show(listener);
}

const listener: AlogameKycListener = {
onResult(result: AlogameKycResult) {
switch (result.kind) {
case "success":
break; // chỉ là tín hiệu UI — đọc cảnh báo bên dưới
case "failed":
console.warn("XMDT failed:", result.reason, result.message);
break;
case "cancelled":
break; // Người chơi đóng form — chỉ xảy ra khi xmdtRequired = false
}
},
onSessionTokenNeeded(uid: string) {
// xem mục "Làm mới token hết hạn" bên dưới
},
};
onResult là tín hiệu UI, không phải bằng chứng

success nghĩa là thiết bị của người chơi báo luồng đã hoàn tất — một client bị chỉnh sửa có thể tạo ra callback này mà không xác thực gì cả. Trước khi cho người chơi qua bất kỳ cổng nào phụ thuộc XMDT, hãy gọi lại POST /xmdt/session từ server của bạn và tin vào field xmdtCompleted trong response đó. Xem Tích hợp Server.

onResult bắn đúng một lần cho mỗi show(), sau khi màn hình đã đóng xong — bạn có thể hiện UI của mình ngay trong đó. onSessionTokenNeeded có thể bắn không lần nào hoặc nhiều lần trước đó.

SDK sở hữu toàn bộ màn hình của nó — họ tên, ngày sinh, nhập số điện thoại, OTP và đồng ý điều khoản đều xử lý bên trong, và không gì người chơi gõ vào lọt ra ngoài game của bạn.

Gọi show() lần nữa khi một luồng đang mở sẽ bị bỏ qua (có ghi log, không crash).

uid đã xác thực rồi thì không mở màn nào

Nếu session cho biết người chơi đã hoàn tất XMDT, show() sẽ trả về success ngay mà không hiện gì. Đó là hành vi đúng — nhưng khi test, nó có nghĩa mỗi uid chỉ chạy được luồng một lần. Hãy dùng uid mới cho mỗi lần thử.

Xử lý failed​

TypeScript
switch (result.reason) {
case "notInitialized":
case "noGameRole":
// Lỗi tích hợp phía bạn — chưa gọi init()/setGameRole() trước.
// Đừng bao giờ hiện cho người chơi; sửa thứ tự gọi.
break;
case "sessionUnavailable":
case "sessionInvalid":
// Không lấy được session token dùng được. Mint token mới rồi thử lại.
break;
case "otpAttemptsExceeded":
case "otpUnavailable":
case "rateLimited":
// Chạm giới hạn chống lạm dụng. Hiện thông báo chung "thử lại sau" —
// đừng lộ ra là chạm giới hạn nào.
break;
case "serviceUnavailable":
// Dịch vụ danh tính lỗi sau khi người chơi đã thử lại ngay trong màn
// hình. Để họ gọi lại sau.
break;
case "unknownError":
// Catch-all cho tương thích về sau. Không bao giờ crash.
break;
}

Các vấn đề còn cứu được — gõ nhầm OTP, lỗi validate, mạng chập chờn — đều được xử lý bên trong màn hình của SDK và không bao giờ tới onResult. Mọi reason ở trên đều là trường hợp luồng không thể tiếp tục, không phải người chơi gõ nhầm.

Làm mới token hết hạn​

Khác với package Unity, một closure JS không có biên nào phải vượt qua, nên tokenProvider được expose trực tiếp:

TypeScript
init("dev", (uid, callback) => {
mintSessionToken(uid).then((token) => callback(token)).catch(() => callback(null));
});

Nếu bạn không truyền tokenProvider, hãy đáp lại onSessionTokenNeeded thay vào đó:

TypeScript
import { provideSessionToken, abortPendingToken } from "@alogame/kyc-sdk";

onSessionTokenNeeded(uid: string) {
mintSessionToken(uid)
.then((token) => (token ? provideSessionToken(token) : abortPendingToken()))
.catch(() => abortPendingToken());
}

Phải đáp lại bằng đúng một trong hai đường. Nếu không làm gì cả, token hết hạn sẽ kết thúc luồng bằng sessionUnavailable thay vì treo.

Khác gì so với SDK native​

Không có gì bị giấu hay ngoài ý muốn — mỗi cái đều là đánh đổi có chủ đích để chạy không cần code native:

  • Không chống chụp màn hình. SDK Android/iOS bật FLAG_SECURE/cơ chế tương đương. Package này thì không: không có yêu cầu pháp lý nào đòi hỏi, và màn hình chỉ hiện dữ liệu người chơi đang tự gõ.
  • Không tự điền OTP từ SMS. Mã OTP phải gõ tay (hoặc dán — xem bên dưới), không bao giờ tự phát hiện từ SMS đến.
  • "Dán mã" chỉ hoạt động trong Editor preview chạy trên browser của Cocos Creator, không hoạt động trên bản build native. Engine của Cocos không có API đọc clipboard nào ngoài browser; trên bản build native, người chơi gõ mã bằng tay.
  • Mã OTP 6 chữ số là một ô nhập duy nhất, không phải sáu ô riêng tự nhảy như SDK native. Component nhập liệu của Cocos chưa xác nhận có cách chuyển focus giữa các ô bằng code.
  • Chỉ tiếng Việt — khớp với SDK native, vốn đã bỏ tiếng Anh theo một quyết định sản phẩm trước đó.

Sample​

Chưa phát hành — package này chưa từng chạy trong một project Cocos Creator thật (xem cảnh báo ở đầu trang).

Tham chiếu​

Thành phầnMục đích
init(env, tokenProvider?)Gọi một lần trước mọi thứ khác
setGameRole(uid, sessionToken, serverId?, roleId?)Luôn truyền uid và sessionToken cùng nhau
setPrefill(fullName)Tuỳ chọn — điền sẵn ô họ tên
isVerified()Cache trong RAM, chỉ dùng cho trạng thái UI — không bao giờ là cổng chặn
show(listener)Mở màn hình
provideSessionToken(token) / abortPendingToken()Đáp lại onSessionTokenNeeded
AlogameKycEnv"dev" | "prod"
AlogameKycResult{kind: "success"} | {kind: "failed", reason, message?} | {kind: "cancelled"}
AlogameKycFailReason9 giá trị đóng — xem ở trên
AlogameKycListeneronResult (bắt buộc), onSessionTokenNeeded (tuỳ chọn)

isVerified() đọc cache trong bộ nhớ từ lần hoàn tất gần nhất — không phải nguồn phân quyền, cùng lưu ý như onResult. Chỉ dùng cho trạng thái UI, không dùng làm cổng chặn.