Tổng quan SmartOTP
SmartOTP là dịch vụ soft-token của CAKE: một partner app đăng ký một thiết bị, kích hoạt nó bằng khóa bí mật của client (client secret key), rồi tạo mã TOTP ở chế độ offline. Mã có hai cấp độ — OTP cơ bản (basic OTP) được suy ra từ khóa bí mật và thời gian, và OTP nâng cao (advance OTP) còn được gắn thêm với một giao dịch cụ thể thông qua khóa challenge (challenge key).
INFO
Mọi ví dụ trong tài liệu này dùng cùng một danh tính giả định — Nguyễn Văn A, CCCD 001xxxxxxxxx, user_id user_00000001, ref_id ref_00000001. Thông tin xác thực, token và key được ghi dạng <PLACEHOLDER>. Đây không phải dữ liệu thật; hãy thay toàn bộ bằng giá trị của bạn.
Điều kiện tiên quyết
| Thông tin | Mô tả |
|---|---|
| Partner ID | Định danh tổ chức của bạn. Được gửi trong body của mọi request dưới dạng partner_id. Do CAKE cung cấp. |
| Partner Key | Bí mật được ghép cặp với Partner ID của bạn. Được gửi trong body của mọi request dưới dạng partner_key. Do CAKE cung cấp. |
| Base URL | Do CAKE cấp riêng cho từng partner, có dạng https://<HOSTNAME>/api/v1. |
| Mobile SDK | SOTP SDK được nhúng vào ứng dụng của bạn lưu giữ bí mật, kiểm tra PIN, và tạo mã. |
| Firebase push token | Bắt buộc khi kích hoạt để server có thể push khóa challenge đến thiết bị. |
Các ví dụ trong tài liệu này ghi base URL dưới dạng <BASE_URL> — hãy thay bằng giá trị CAKE cấp cho bạn.
WARNING
Mọi request phải dùng https, không bao giờ dùng http — partner_key được truyền trong body của request, nên một request dạng plaintext sẽ để lộ thông tin xác thực partner của bạn.
Xác thực
API này dựa trên JSON và được xác thực bằng partner_id và partner_key gửi trong body của mỗi lệnh gọi, không phải trong header.
POST /api/v1/saas-sotp/get-status HTTP/1.1
Host: <HOSTNAME>
Content-Type: application/json
Accept: application/json
Accept-Charset: utf-8
partner_id={{partner_id}}&partner_key={{partner_key}}&token={{token}}Hầu hết các request cũng yêu cầu token của thiết bị, được tạo bởi Đăng ký. Hai ngoại lệ là chính Đăng ký và Kích hoạt.
WARNING
partner_id và partner_key là thông tin xác thực phía backend và không bao giờ được đưa vào ứng dụng di động của bạn. token gắn với thiết bị chính là thứ ứng dụng được phép giữ. Hãy proxy mọi lệnh gọi SmartOTP qua Partner API của riêng bạn.
Dẫn xuất khóa
| Trường | Kiểu | Mô tả |
|---|---|---|
| Khóa bí mật của client (client secret key) | string | Được băm (hash) từ user_id, device_id và registration_id (unique_id) cùng với private key của server. Được Kích hoạt trả về dưới dạng key. |
| Khóa challenge (challenge key) | string | Được băm (hash) từ user_id, device_id, registration_id, app_id, transaction_id, transaction_amount và unique_id cùng với private key của server. Được Tạo giao dịch trả về. |
Các loại OTP
| Trường | Kiểu | Mô tả |
|---|---|---|
basic | string | Được tạo từ TOTP bằng khóa bí mật của client và thời gian hiện tại. Không gắn với bất kỳ giao dịch nào. |
advance | string | Được tạo từ TOTP bằng khóa bí mật của client, khóa challenge và thời gian hiện tại. Gắn với một giao dịch cụ thể. |
OTP nâng cao chính là thứ khiến mã không thể chuyển nhượng: vì khóa challenge mã hóa số tiền và ID giao dịch, một mã bị lấy được cho một lần chuyển tiền không thể dùng để xác thực cho một giao dịch khác.
Tham số TOTP
Được trả về bởi Kích hoạt và Đồng bộ thời gian:
| Trường | Kiểu | Mô tả |
|---|---|---|
algorithm | string | HmacSHA512. |
period | int | Số giây một mã còn hiệu lực — 15. |
length | int | Số chữ số — 6. |
type | string | totp. |
issuer | string | SOTP. |
Chu kỳ 15 giây ngắn hơn nhiều so với mặc định 30 giây mà hầu hết các ứng dụng authenticator giả định. Độ lệch đồng hồ (clock drift) là điều cần lưu ý — hãy gọi Đồng bộ thời gian khi việc xác minh bắt đầu thất bại.
Cách hoạt động
sequenceDiagram
autonumber
participant User as Người dùng
participant App as Mobile App + SDK
participant PA as Partner API
participant SOTP as Soft-OTP API
Note over App,SOTP: Giai đoạn 1 — Đăng ký và kích hoạt
App->>PA: Bắt đầu thiết lập Smart OTP
PA->>SOTP: POST /register
SOTP-->>PA: registration_id, activation_key, token
PA->>SOTP: POST /activate (+ push_token)
SOTP-->>PA: key, period, algorithm, length
PA-->>App: Cấu hình TOTP + secret
Note over App: SDK lưu secret phía sau PIN của người dùng
Note over User,SOTP: Giai đoạn 2 — OTP nâng cao cho một giao dịch
User->>App: Nhập số tiền, người nhận, mô tả
App->>PA: Tạo giao dịch
PA->>SOTP: POST /create-transaction
SOTP-->>PA: challenge_key
SOTP-->>App: challenge_key được push qua Firebase
PA-->>App: transaction_id, otp_type
User->>App: Nhập PIN
App->>App: isValidPin, sau đó generateSmartOTP(pin, challenge_key)
User->>App: Xác nhận giao dịch
App->>PA: transaction_id + OTP
PA->>SOTP: POST /validate-sotp (otp_type advance)
SOTP-->>PA: code 1 Success
PA-->>App: Đã duyệt
Giai đoạn 1 — Đăng ký và kích hoạt
- Partner API của bạn gọi Đăng ký, trả về
registration_id, mộtactivation_keydùng một lần, vàtokencủa thiết bị. - Sau đó gọi Kích hoạt với
activation_keyvàpush_tokenFirebase của thiết bị. Response mang theokeybí mật của client và cấu hình TOTP. - SDK lưu secret trên thiết bị, được bảo vệ bằng PIN của người dùng.
Giai đoạn 2 — OTP cơ bản
Đối với một lần đăng nhập hoặc một hành động rủi ro thấp, ứng dụng kiểm tra PIN và tạo một mã không gắn với ngữ cảnh giao dịch nào:
SdkSoft.isValidPin(pin = "pin") // false → hiển thị lỗi, yêu cầu nhập lại
val otp = SdkSoft.generateSmartOTP(pin = "PIN")Sau đó, Partner API của bạn gọi Xác minh OTP với otp_type: "basic".
Giai đoạn 3 — OTP nâng cao
- Người dùng nhập chi tiết giao dịch và Partner API của bạn ghi nhận giao dịch.
- Partner API của bạn gọi Tạo giao dịch. Soft-OTP API tạo
challenge_key, trả về nó, và push nó đến thiết bị qua Firebase. - Partner API của bạn trả về
transaction_idvàotp_typecho ứng dụng — cùng với chínhchallenge_keykhi push notification bị tắt. - Ứng dụng kiểm tra PIN và tạo mã đã gắn với giao dịch:
SdkSoft.isValidPin(pin = "pin")
val otp = SdkSoft.generateSmartOTP(pin = "PIN", challenge_key = "fake_challenge_key")- Người dùng xác nhận; ứng dụng gửi
transaction_idvà OTP đến Partner API của bạn. - Partner API của bạn gọi Xác minh OTP với
otp_type: "advance"vàtransaction_id, sau đó chuyển kết quả thành status code riêng của mình cho ứng dụng.
Giai đoạn 4 — Đồng bộ thời gian
TOTP phụ thuộc vào đồng hồ của thiết bị. Khi người dùng mở ứng dụng, SDK có thể gọi Đồng bộ thời gian thông qua Partner API của bạn để đối chiếu period và client_timestamp với server và trả về timestamp của server.
Cấu trúc response dùng chung
{
"success": true,
"code": 1,
"message": "Success",
"data": {}
}| Trường | Kiểu | Mô tả |
|---|---|---|
success | bool | Trạng thái của request. |
code | int | status code. 1 nghĩa là thành công — không phải 0 như trong các API eKYC, NFC và FaceAuthen của CAKE. |
message | string | Thông báo trạng thái hoặc lỗi. |
data | object | Payload riêng của từng endpoint. Một số endpoint trả về field ở cấp cao nhất (top level) thay vì trong data. |
WARNING
Thành công trên API này là code: 1. Nếu bạn đã tích hợp CAKE eKYC, NFC hoặc FaceAuthen, lưu ý rằng các API đó dùng code: 0 cho thành công — dùng chung một response handler cho cả hai sẽ khiến mọi kết quả SmartOTP bị đọc sai.
Status Codes
Các thông báo được trả về bằng tiếng Việt, được sao chép nguyên văn bên dưới.
| Mã | Thông báo |
|---|---|
1 | Success (OTP hợp lệ) |
3 | Parameter invalid |
103 | Thông tin Partner không chính xác. — Partner details are incorrect. |
121 | Yêu cầu vượt giới hạn. Vui lòng thử lại sau ít phút. — Request limit exceeded. |
123 | Yêu cầu vượt giới hạn. Vui lòng thử lại sau ít phút. — Request limit exceeded. |
124 | OTP không hợp lệ. — Invalid OTP. |
125 | OTP hết hạn sử dụng. — OTP expired. |
126 | Có lỗi xảy ra vui lòng thử lại. — An error occurred, please retry. |
129 | Token không hợp lệ. — Invalid token. |
190001 | Thông tin không hợp lệ, device_id đã kích hoạt Soft-OTP. — Device already activated. |
190005 | SmartOTP đang kích hoạt trên một thiết bị khác. — SmartOTP is active on another device. |
190108 | Tài khoản chưa hoạt động. — Account not activated. |
190201 | Không thể tạo transaction hoặc transaction_id đã tồn tại. — Cannot create transaction, or the ID already exists. |
190203 | Không tìm thấy transaction. — Transaction not found. |
190301 | Period không chính xác. — Incorrect period. |
190303 | Client time không chính xác. — Incorrect client time. |
Bước tiếp theo
- Đăng ký — tạo một đăng ký thiết bị và lấy activation key
- Kích hoạt — kích hoạt thiết bị và nhận khóa bí mật của client
- Lấy trạng thái — kiểm tra trạng thái SmartOTP của một thiết bị
- Hủy kích hoạt — hủy kích hoạt SmartOTP của một thiết bị
- Tạo giao dịch — cấp một khóa challenge cho OTP nâng cao
- Lấy giao dịch — đọc một giao dịch và khóa challenge của nó
- Lấy giao dịch mới nhất — đọc giao dịch gần nhất
- Đồng bộ thời gian — đối chiếu đồng hồ thiết bị với server
- Xác minh OTP — xác minh một OTP cơ bản hoặc nâng cao
- Kiểm thử — tạo mã bằng Google Authenticator hoặc một script Python
- Mã lỗi — bảng lỗi đầy đủ của API