Skip to content

Inline Checkout supports two saved-card flows:

  • Save a card during a card payment with paymentForm() or paymentCard().
  • Charge a previously saved card with the headless savedCardPayment() SDK method.

Saved cards are represented by a cardId. Store that token against your own customer record after you receive it from xMoney, then use it for later payments.

Requirements

To save and reuse cards, your order payload should include:

  1. A stable customer.identifier that maps to the shopper in your system.
  2. saveCard: true when you want xMoney to create a reusable card token.
  3. A backend process that stores the returned cardId only after server-side confirmation.
Confirm tokens server-side

Do not rely only on browser callbacks to store or activate a saved card. Use your webhook or another trusted server-side confirmation path before making the card available for future orders.

Save a card during checkout

Enable saved cards in the card configuration.

const paymentForm = await window.XMoney.paymentForm({
  container: 'xmoney-payment-form',
  publicKey,
  orderPayload,
  orderChecksum,
  card: {
    savedCards: {
      enabled: true,
      optInVisible: true,
    },
  },
  onPaymentComplete(transaction) {
    handlePaymentResult(transaction)
  },
})

savedCards.enabled controls whether returning customers can see available saved cards in the form. savedCards.optInVisible controls whether the shopper can see the save-card choice when entering a new card.

If your business flow requires saving a card, set saveCard: true in the server-generated order payload and make sure the customer consent text is clear in your checkout UI.

{
  "publicKey": "pk_test_your_key",
  "customer": {
    "identifier": "customer-123",
    "email": "customer@example.com"
  },
  "order": {
    "orderId": "order-123",
    "type": "purchase",
    "amount": 4999,
    "currency": "EUR",
    "description": "Online order"
  },
  "cardTransactionMode": "authAndCapture",
  "saveCard": true
}

Read the saved cardId

When tokenization succeeds, the final transaction data can include a cardId.

{
  "externalOrderId": "order-123",
  "transactionId": 987654,
  "transactionStatus": "complete-ok",
  "cardId": 12345,
  "customerId": 67890
}

Store the cardId with the matching shopper only after you validate the final transaction status on your backend.

Pay with a saved card from the form

When card.savedCards.enabled is true and saved cards are available for the customer, the embedded form can render them. The shopper can select a saved card and submit from the same secure component.

await window.XMoney.paymentCard({
  container: 'payment-card',
  publicKey,
  orderPayload,
  orderChecksum,
  card: {
    savedCards: {
      enabled: true,
      optInVisible: false,
    },
  },
  onPaymentComplete(transaction) {
    handlePaymentResult(transaction)
  },
})

Use this when you still want xMoney to own the saved-card selection UI.

Headless saved-card payment

Use XMoney.savedCardPayment() when your application renders its own saved-card list and you only need the SDK to trigger the secure payment. This method does not render a visible UI.

const savedCardPayment = await window.XMoney.savedCardPayment({
  publicKey,
  orderPayload,
  orderChecksum,
  onReady() {
    enableSavedCardButtons()
  },
  onPaymentProcessing(isProcessing) {
    setSavedCardLoading(isProcessing)
  },
  onPaymentComplete(transaction) {
    handlePaymentResult(transaction)
  },
  onError(error) {
    showPaymentError(error?.message || 'Saved card payment failed')
  },
})

document.querySelectorAll('[data-card-id]').forEach((button) => {
  button.addEventListener('click', () => {
    savedCardPayment.pay({
      cardId: Number(button.dataset.cardId),
    })
  })
})

The SDK creates a hidden iframe automatically when no container is provided. Call destroy() when the saved-card checkout UI is no longer active.

savedCardPayment.destroy()

Updating orders

For visible widgets, use updateOrder() when cart totals change.

await paymentForm.updateOrder({
  orderPayload: nextPayload,
  orderChecksum: nextChecksum,
})

For savedCardPayment(), create a new instance for each new order payload before calling pay({ cardId }).

3DS for saved cards

Saved-card payments can still require 3D Secure authentication. The SDK handles the 3DS modal and final callback in the same way as new-card payments. See 3DS and payment results for the complete flow.