Tài liệu tham chiếu SDK
Tài liệu tham chiếu API đầy đủ cho Bahn Web SDK. Cấu trúc đầy đủ của mọi tham số, kết quả và callback có tại Định nghĩa kiểu — trang này cũng có file bahn.d.ts để tải về cho dự án TypeScript.
Cài đặt
Tải SDK dưới dạng một script đơn giản, đã pin phiên bản — không cần bundler:
<script
src="https://bn.cake.vn/bn-sdk/v2.4.0/index.js"
integrity="sha384-jBbonUZLgKU82F+X/ITqcmeInXYYwZYdmCDoPFX8wkWL9dCkeUHyi0Fs1EUnkeDS"
crossorigin="anonymous"
></script>Cách này expose Bahn như một biến toàn cục (window.Bahn) — không cần import. Đây là cùng một URL script cho cả sandbox và production; chỉ có tùy chọn environment truyền vào new Bahn() là thay đổi domain API/iframe nào được sử dụng. Mỗi bản phát hành nằm tại đường dẫn /bn-sdk/v<version>/index.js riêng cùng với một hash SRI index.js.sha384 tương ứng. Xem Bắt đầu và Môi trường để biết chi tiết.
Class Bahn
Class SDK chính. Một singleton — gọi new Bahn() lần thứ hai sẽ trả về instance hiện có và gộp thêm các tùy chọn mới.
const bahn = new Bahn(options: BahnOptions);BahnOptions
| Tham số | Kiểu | Bắt buộc | Mặc định | Mô tả |
|---|---|---|---|---|
pk | string | Có | — | Publishable key được gửi dưới dạng header X-Bn-Publishable-Key |
environment | "sandbox" | "production" | Có | — | Môi trường API mục tiêu |
appId | string | Không | — | Tenant app ID cho định tuyến 3DS |
teamId | string | Không | — | Tenant team ID cho định tuyến 3DS |
paymentIntentPollAttempts | number | Không | 10 | Số lần thử polling tối đa cho trạng thái payment intent |
Phương thức
bahn.mountCard(containerId, options?): CardComponent
Gắn component nhập thẻ tuân thủ PCI. Xem Thanh toán thẻ để biết chi tiết đầy đủ.
card.unmount(): void
Xóa ô nhập thẻ và dọn dẹp các event listener. Được gọi trên CardComponent trả về từ mountCard().
card.applyConfig(fields, inputStyle?): void
Áp dụng lại cấu hình field cho các iframe đã mount mà không cần mount lại. Được gọi trên CardComponent trả về từ mountCard().
card.applyStyles(stateStyles): void
Áp dụng lại các style theo trạng thái (base/focus/invalid) cho các iframe đã mount mà không cần mount lại. Được gọi trên CardComponent trả về từ mountCard(). Xem Thanh toán thẻ → Tạo kiểu theo trạng thái.
bahn.mountPaymentQR(selector, clientSecret, options?): IQRComponent
Gắn một iframe mã QR Napas và bắt đầu polling. Xem Thanh toán QR để biết chi tiết đầy đủ.
qr.unmount(): void
Xóa iframe QR và dọn dẹp. Được gọi trên IQRComponent trả về từ mountPaymentQR().
bahn.getConfig(): Promise<BahnConfig>
Lấy cấu hình Apple Pay của merchant của bạn — merchant_name, supported_networks, merchant_capabilities. Không bắt buộc phải gọi trước khi gọi mountApplePay(), vì nó tự giải quyết các giá trị này nội bộ. Chỉ gọi getConfig() trực tiếp nếu bạn cần các giá trị này cho mục đích khác ngoài mountApplePay() — ví dụ, giao diện riêng của bạn. Khác với mọi phương thức thanh toán khác, đây là một fetch trực tiếp đơn giản — không cần mount component nào trước.
interface BahnConfig {
apple_pay: {
enabled: boolean;
merchant_name: string;
supported_networks: string[];
merchant_capabilities: string[];
};
}bahn.isApplePayAvailable(): Promise<boolean>
Kiểm tra trước (pre-flight) tùy chọn cho việc trình duyệt/thiết bị của người mua có thể sử dụng Apple Pay hay không. mountApplePay() tự chạy cùng kiểm tra này nội bộ và đơn giản là sẽ không hiển thị nút nếu thất bại, vì vậy gọi hàm này trước không bắt buộc — chỉ dùng nó nếu bạn muốn kiểm soát bố cục riêng của mình (ví dụ ẩn toàn bộ phần "Hoặc thanh toán bằng Apple Pay", không chỉ riêng nút) trước khi gọi mountApplePay(). Đây chỉ là một kiểm tra phía client — nó không xác nhận việc Apple Pay đã được bật ở cấp độ merchant, điều này sẽ được thể hiện qua một sự kiện "error" từ mountApplePay() tại thời điểm người mua nhấn nút. Kết quả true trên Chrome/Firefox/Edge chỉ phản ánh rằng phiên bản trình duyệt hỗ trợ cơ chế fallback cross-browser của Apple, và cần một đăng ký merchant riêng với Apple để thực sự hoạt động — xem Apple Pay → Hỗ trợ trình duyệt.
bahn.mountApplePay(selector, clientSecret, options): IApplePayButtonComponent
Hiển thị một nút Apple Pay tại selector và tự quản lý toàn bộ vòng đời payment sheet — xác thực merchant, ủy quyền, và (nếu kích hoạt) 3D Secure — nội bộ. Thử thách 3D Secure, nếu được kích hoạt trên luồng xác nhận trực tiếp, sẽ được gắn trên trang của riêng bạn thông qua bahn.mount3DS(). Yêu cầu Safari 17 / iOS 17+. Mọi trường trong options ngoài amount/currency/country đều là tùy chọn; merchantName/supportedNetworks/merchantCapabilities sẽ dùng giá trị đã cấu hình của merchant khi bị bỏ qua. Không hiển thị gì nếu Apple Pay không khả dụng — chỉ tự gọi bahn.isApplePayAvailable() trước nếu bạn muốn ẩn hoàn toàn điểm truy cập thay vì phản ứng lại sự kiện "error". Xem Apple Pay để biết chi tiết đầy đủ.
clientSecret chọn luồng: truyền nó cho xác nhận trực tiếp (sự kiện "success"/"error"); bỏ qua nó (undefined) cho luồng dựa trên token (sự kiện "token" kèm một confirmation_token — gửi nó đến backend của riêng bạn, sau đó gọi bahn.handleNextAction() với client_secret kết quả, giống như luồng dựa trên token của thẻ).
options.requestShipping: true thu thập một địa chỉ giao hàng: lắng nghe "shippingcontactselected"/"shippingmethodselected", mỗi sự kiện kích hoạt với { contact | shippingMethod, resolve, reject }; sheet sẽ giữ mở cho đến khi bạn gọi một trong hai hàm đó. Xem Apple Pay → Thu thập địa chỉ giao hàng.
ap.unmount(): void
Xóa nút Apple Pay và dọn dẹp. Được gọi trên IApplePayButtonComponent trả về từ mountApplePay(). bahn.unmountApplePay()/bahn.cleanup() cũng sẽ gỡ nó.
bahn.isGooglePayAvailable(): Promise<boolean>
Kiểm tra trước (pre-flight) tùy chọn cho việc trình duyệt của người mua có thể sử dụng Google Pay hay không. mountGooglePay() tự chạy cùng kiểm tra này nội bộ và đơn giản là sẽ không hiển thị nút nếu thất bại, vì vậy gọi hàm này trước không bắt buộc — chỉ dùng nó nếu bạn muốn kiểm soát bố cục riêng của mình (ví dụ ẩn toàn bộ phần "Hoặc thanh toán bằng Google Pay", không chỉ riêng nút) trước khi gọi mountGooglePay(). Xem Google Pay → Hỗ trợ trình duyệt.
bahn.mountGooglePay(selector, clientSecret, options): IGooglePayButtonComponent
Hiển thị một nút Google Pay tại selector và tự quản lý toàn bộ vòng đời payment sheet — ủy quyền và (nếu kích hoạt) 3D Secure — nội bộ. Thử thách 3D Secure, nếu được kích hoạt trên luồng xác nhận trực tiếp, sẽ được gắn trên trang của riêng bạn thông qua bahn.mount3DS(). Chạy được trên mọi trình duyệt Google Pay hỗ trợ, kể cả Safari và Firefox. Mọi trường trong options ngoài amount/currency/country đều là tùy chọn. Không hiển thị gì nếu Google Pay không khả dụng — chỉ tự gọi bahn.isGooglePayAvailable() trước nếu bạn muốn ẩn hoàn toàn điểm truy cập thay vì phản ứng lại sự kiện "error". Xem Google Pay để biết chi tiết đầy đủ.
clientSecret chọn luồng: truyền nó cho xác nhận trực tiếp (sự kiện "success"/"error"); bỏ qua nó (undefined) cho luồng dựa trên token (sự kiện "token" kèm một confirmation_token — gửi nó đến backend của riêng bạn, sau đó gọi bahn.handleNextAction() với client_secret kết quả, giống như luồng dựa trên token của thẻ).
options.requestShipping: true thu thập một địa chỉ giao hàng: lắng nghe "shippingaddresschanged"/"shippingoptionchanged", mỗi sự kiện kích hoạt với { address | shippingOption, resolve, reject }; sheet sẽ giữ mở cho đến khi bạn gọi một trong hai hàm đó. Xem Google Pay → Thu thập địa chỉ giao hàng.
gp.unmount(): void
Xóa nút Google Pay và dọn dẹp. Được gọi trên IGooglePayButtonComponent trả về từ mountGooglePay(). bahn.unmountGooglePay()/bahn.cleanup() cũng sẽ gỡ nó.
bahn.mount3DS(sessionId, callbacks, options?): IThreeDSecure
Gắn modal thử thách 3DS và trả về component. Modal sẽ tự động gỡ khi thành công/thất bại; gọi unmount() trên component trả về để đóng sớm. Xem Xác thực 3DS để biết chi tiết đầy đủ.
bahn.getChallengeRedirectUrl(sessionId, returnUrl, options?): string
Xây dựng một URL chuyển hướng đầy đủ đến trang thử thách 3DS độc lập cho các luồng chuyển hướng toàn trang (ví dụ từ ứng dụng di động, trang checkout bên ngoài) nơi một overlay iframe không khả thi. Trang thử thách xử lý toàn bộ luồng 3DS và chuyển hướng người dùng trở lại returnUrl khi hoàn tất.
Tham số:
| Tham số | Kiểu | Bắt buộc | Mô tả |
|---|---|---|---|
sessionId | string | Có | ID phiên 3DS từ confirmPayment().three_ds_payload.id |
returnUrl | string | Có | Nơi trang thử thách chuyển hướng trở lại khi hoàn tất |
options.brandName | string | Không | Tên thương hiệu hiển thị khi quay lại ("Returning to {brandName}…"). Mặc định: "Cake" |
Giá trị trả về: Một chuỗi URL đầy đủ, sẵn sàng cho window.location.href.
const url = bahn.getChallengeRedirectUrl(sessionId, "https://merchant.com/callback", {
brandName: "MyStore",
});
window.location.href = url;Xem Trang thử thách độc lập để biết toàn bộ luồng và cấu trúc URL.
bahn.confirmPayment(payload): Promise<{ payment_intent, three_ds_payload? }>
Xác nhận một payment intent thông qua iframe số thẻ. Yêu cầu gọi mountCard() trước. Xem toàn bộ luồng tại Xác nhận thanh toán.
Payload (ConfirmPaymentPayload):
| Trường | Kiểu | Bắt buộc | Mô tả |
|---|---|---|---|
client_secret | string | Có | Client secret của payment intent từ backend của bạn |
payment_method | { billing_details?: ConfirmationTokenBillingDetails } | Không | Thông tin thanh toán tùy chọn (dữ liệu thẻ được iframe ghép vào) |
payment_method_options | Record<string, unknown> | Không | Các tùy chọn riêng của provider |
confirmation_token | string | Không | Token từ createConfirmationToken() |
amount | string | Không | Ghi đè số tiền tùy chọn, theo đơn vị tiền tệ nhỏ nhất |
Giá trị trả về:
| Trường | Kiểu | Mô tả |
|---|---|---|
payment_intent | Record<string, unknown> | Đối tượng PaymentIntent |
three_ds_payload | ThreeDSPayloadDecoded | undefined | Payload 3DS nếu cần |
bahn.confirmCardSetup(payload): Promise<{ setup_intent, three_ds_payload? }>
Xác nhận một setup intent thông qua iframe số thẻ — lưu một thẻ mà không tính phí. Yêu cầu gọi mountCard() trước. Xem Lưu thẻ.
Payload (ConfirmCardSetupPayload):
| Trường | Kiểu | Bắt buộc | Mô tả |
|---|---|---|---|
client_secret | string | Có | Client secret của setup intent từ backend của bạn |
payment_method | { billing_details?: ConfirmationTokenBillingDetails } | Không | Thông tin thanh toán tùy chọn (dữ liệu thẻ được iframe ghép vào) |
payment_method_options | Record<string, unknown> | Không | Các tùy chọn riêng của provider |
Giá trị trả về:
| Trường | Kiểu | Mô tả |
|---|---|---|
setup_intent | Record<string, unknown> | Đối tượng SetupIntent |
three_ds_payload | ThreeDSPayloadDecoded | undefined | Payload 3DS nếu cần |
bahn.createConfirmationToken(payload): Promise<ConfirmationTokenResult>
Tạo một confirmation token dùng một lần. Yêu cầu mountCard() và pk trước. Xem Luồng dựa trên token.
interface ConfirmationTokenResult {
confirmation_token: string;
}bahn.handleNextAction(input, callbacks): Promise<void>
Xử lý hành động tiếp theo cho một payment intent (3DS, polling, hoặc trạng thái cuối). input là một chuỗi client_secret (SDK tự lấy payment intent, yêu cầu mountCard()/mountApplePay(), và poll sau 3DS) hoặc một đối tượng payment_intent mà backend của bạn đã trả về (bỏ qua việc fetch đó, phải bao gồm client_secret, và không bao giờ poll — onSuccess/onFailure được giải quyết ngay từ kết quả 3DS với cùng đối tượng, không cần iframe; một trạng thái không phải cuối, không phải requires_action sẽ gọi onError thay vì âm thầm không làm gì). Xem Luồng dựa trên token → handleNextAction để biết chi tiết đầy đủ.
bahn.pollPaymentIntentStatus(clientSecret, callbacks): void
Bắt đầu polling trạng thái payment intent. Gọi stopPaymentIntentPolling() để hủy. Xem Luồng dựa trên token → pollPaymentIntentStatus để biết chi tiết đầy đủ.
bahn.stopPaymentIntentPolling(): void
Dừng mọi hoạt động polling payment intent đang diễn ra.
bahn.pollSetupIntentStatus(clientSecret, callbacks): void
Bắt đầu polling trạng thái setup intent. Gọi stopSetupIntentPolling() để hủy. Xem Lưu thẻ.
bahn.stopSetupIntentPolling(): void
Dừng mọi hoạt động polling setup intent đang diễn ra.
bahn.cleanup(): void
Dọn dẹp tất cả tài nguyên: gỡ component thẻ, 3DS, QR, và Apple Pay, và dừng polling payment/setup intent.
Hành vi singleton
new Bahn() trả về một singleton. Các lần gọi tiếp theo sẽ gộp các tùy chọn mới vào instance hiện có — các giá trị hiện có khác rỗng được giữ nguyên, các giá trị mới lấp vào chỗ trống. Các xung đột được ghi log dưới dạng cảnh báo.
// Khởi tạo lần đầu
const bahn = new Bahn({ pk: "pk_1", environment: "sandbox" });
// Sau đó — trả về cùng instance, appId được áp dụng vào nó
const same = new Bahn({ pk: "pk_2", appId: "app_123" });
// pk giữ nguyên "pk_1" (giá trị hiện có khác rỗng), appId đặt thành "app_123" (trước đó rỗng)
// Cảnh báo được ghi log: xung đột pk — giữ "pk_1", bỏ qua "pk_2"window.BahnCake
Singleton cũng được đặt trên window.BahnCake:
declare global {
interface Window {
BahnCake?: Bahn;
}
}Bạn có thể truy cập instance trực tiếp:
const bahn = window.BahnCake;
if (bahn) {
bahn.cleanup();
}ThreeDSPayloadDecoded
Cấu trúc của payload 3DS base64 đã giải mã được trả về bởi confirmPayment(). Mọi kiểu khác của SDK có tại Định nghĩa kiểu.
interface ThreeDSPayloadDecoded {
provider: string; // Định danh nhà cung cấp 3DS
app_id: string; // Tenant app ID
team_id: string; // Tenant team ID
id: string; // ID phiên 3DS — truyền vào mount3DS()
}