Skip to content

Web SDK Overview ​

The Bahn Web SDK is a browser script that collects payment details inside Bahn-hosted iframes and confirms payments against the Bahn API. Card numbers, expiry dates and CVCs are typed into the iframes and never touch your page or your servers.

This page explains how the pieces fit together and which flow to pick. To write code straight away, go to Getting Started.

How It Works ​

An integration has three parts:

PartRuns onWhat it does
Your backendYour serversCreates PaymentIntents with your secret API key, and receives webhooks
Your checkout page + Bahn SDKThe shopper's browserLoads the SDK, mounts the payment fields, and confirms the payment with the client_secret
Bahn iframes + APIbn.cake.vn (production) / bn.cakedigibank.tech (sandbox)Hold the card data, call the Bahn API, and run 3DS challenges
sequenceDiagram
    participant Browser as Checkout page + SDK
    participant Backend as Your backend
    participant Bahn as Bahn API + iframes

    Browser->>Backend: Start checkout
    Backend->>Bahn: Create PaymentIntent (API key)
    Bahn-->>Backend: PaymentIntent + client_secret
    Backend-->>Browser: client_secret
    Browser->>Bahn: confirmPayment({ client_secret }) via card iframe
    Bahn-->>Browser: payment_intent (+ 3DS payload if needed)
    Browser->>Bahn: mount3DS(...) — shopper completes challenge
    Bahn-->>Backend: Webhook with the final status

Keys ​

KeyWhere it's usedCan it be public?
Publishable key (pk)Passed to new Bahn({ pk }) in the browserYes. It only identifies your merchant account.
API keyBn-Api-Key header on server-to-server calls, which are also JWS-signedNo. Never put it in browser code.

Sandbox and production are separate environments. Use the key issued for the environment you pass to new Bahn({ environment }). Keys are issued during Onboarding.

Core Objects ​

ObjectWhat it is
PaymentIntentOne payment attempt for a given amount. Your backend creates it.
client_secretA per-PaymentIntent secret your backend hands to the browser. The SDK uses it to confirm that one PaymentIntent and nothing else.
Confirmation tokenA one-time token wrapping the card the shopper entered. Created in the browser with createConfirmationToken() and sent to your backend, which uses it to create and confirm the payment.
SetupIntentSaves a card for later use without charging it. Confirmed with confirmCardSetup().
3DS sessionA 3D Secure challenge the issuer requires. The SDK shows it with mount3DS() or handleNextAction().

Choose a Flow ​

You want to…UseGuide
Take a card payment for an amount you know up frontDirect confirmation. The backend creates the PaymentIntent, the browser calls confirmPayment().Confirm Payment
Decide the final amount on your server after seeing the card (discounts, surcharges, fraud checks)Token-based flow. The browser calls createConfirmationToken(), the backend creates and confirms, then the browser calls handleNextAction().Token-Based Flow
Save a card without charging itSetupIntent with confirmCardSetup()Save a Card
Let the shopper pay by scanning a bank QR codeNapas QR with mountPaymentQR()QR Payments
Offer a one-tap wallet buttonApple Pay / Google Pay with mountApplePay() / mountGooglePay()Apple Pay, Google Pay

Trust the webhook, not the browser

The browser result tells you what to show the shopper next. Your backend should mark an order as paid only after it receives the webhook for the final status. See Webhooks.

Integration Steps ​

  1. Get your keys during Onboarding.
  2. Load the SDK and mount the card fields. See Getting Started.
  3. Create PaymentIntents on your backend. See Authentication for how to sign requests.
  4. Confirm the payment and handle 3DS in the browser. See Confirm Payment and 3DS Authentication.
  5. Handle webhooks on your backend. See Webhooks.
  6. Test in sandbox with the sandbox test cards.
  7. Go live using the Go-Live Checklist.

Developers