Inline Checkout

This guide shows you how to securely accept payments (cards, alternative payments) directly on your website, using our Embedded Components SDK and API SDK.

This guide covers:

  • Integrating the xMoney Client SDK
  • Creating payment intents with the Server API SDK
  • Submitting and confirming payments
  • Mobile integration via WebView

1. Set up the xMoney Client SDK

First, add the xMoney Client SDK to your website.

Installation

Via CDN

    <script
      src="https://secure-stage.xmoney.com/sdk/index.js"
      type="module"
    ></script>

2. Create a Payment Intent (Server Side)

Before submitting a payment, you must create a payment intent on your server using the xMoney API SDK.

Install the API SDK

npm install @xmoney/api-sdk

Initialize the API SDK

import xMoneyApiClient from "@xmoney/api-sdk";

const client = new xMoneyApiClient({
  secretKey: "sk_test_secretkey",
});

Initialize the checkout


async function createPaymentIntent(orderData, customerData) {
  const checkout = client.initializeCheckout({
    publicKey: orderData.publicKey,
    customer: {
      identifier: customerData.id,
      firstName: customerData.firstName,
      lastName: customerData.lastName,
      country: customerData.country,
      city: customerData.city,
      email: customerData.email,
    },
    order: {
      orderId: orderData.id,
      description: orderData.description,
      type: "purchase",
      amount: orderData.amount,
      currency: orderData.currency,
    },
    cardTransactionMode: "authAndCapture",
    backUrl: "https://localhost:3002/transaction-result", // this is the client side URL, where the user will be redirected
  });
  return checkout; // { payload, checksum }
}

You will use the checkout object as an input on the submitPaymet() function on the client SDK

3. Display the Inline Checkout Form

  xMoneyCheckout = new xMoneyCheckout({
      container: "xmoney-inline-checkout",
      elementsOptions: { appearance: checkoutStyles },
      onError: (err) => console.error("❌ Payment error", err),
      onReady: () => setIsLoading(false),
    });
<div
    id="xmoney-inline-checkout"
    class={sdkError() ? "sdk-container error" : "sdk-container"}
  ></div>

This creates a secure, embeddable card input directly into your checkout page.

Init Parameters explained

ParameterTypeRequiredDescriptionAvailability
containerstringyesDOM selector where the card input will be mounted. This will draw all 3 card elements (card number, expiry, cvv) into the DOM.v1.0
publicKeystringyesMerchant’s public key. It has this format: pk_<env>_siteUID. Env can be: test or live.v1.0
cardNumberContainerstringnoDOM selector where the card number will be mounted. It is required only if container is not used.v1.1
cardExpiryContainerstringnoDOM selector where the card expiry input will be mounted.v1.1
cardCVVContainerstringnoDOM selector where the card CVV input will be mounted.v1.1
onReadyfunctionnoCallback fired when the widget is successfully loaded.v1.0
onErrorfunctionnoCallback fired when the payment fails. Receives an error object with details.v1.0
elementOptionsobjectnoOptional customizations (primary text color, font, locale, debug mode)v1.0

4. Customize the Experience

You can easily customize the UI of your checkout form.

Theme Options

var checkoutStyles = { 
  elementOptions?: {
   appearance: {
    variables: {
    containerBorderColor: "#333",
    containerBackgroundColor: "#1e1e1e",
    inputColor: "#fff",
    inputBackground: "#2a2a2a",
    inputBorderRadius: "4px",
    inputFontFamily: "Arial, sans-serif",
    ...
    },
    rules: {
      ".embeded-components-container": {
        display: "grid",
        gap: "12px",
        gridTemplateColumns: "1fr 1fr",
      },
      ".embeded-components-container label": {
        display: "flex",
        flexDirection: "column",
        gap: "4px",
      },
     }
   }
  }
}

Localization

Set the locale manually or auto-detect based on browser settings.

locale: 'ro'

If locale is omitted the SDK will:

  • Try to detect the browser’s language setting
  • Fallback to en if no match is found.

5. Validate the card inputs

Before submitting the payment, you can validate the card fields programmatically, along with your own checkout page validation.

Use the built-in validate(showErrors: bool) method from the xMoneyCheckout instance. Passing true will automatically show the errors bellow the checkout elements. Passing false will just validate and return the errors so you can handle the messages and how they are displayed to your customers.

const { cardNumberError, expDateError, cvvError } = await xMoneyCheckout.validate(true);

if (cardNumberError || expDateError || cvvError) {
  console.error('Validation errors:', { cardNumberError, expDateError, cvvError });
  // Stop the process
} else {
  // Proceed to submit the payment
}

This ensures the card inputs are correctly validated before attempting a payment.

6. Make the payment

To make the payment after validating inputs and creating the payment intent, call your merchant server, then submit the payment using the Client SDK.

try {
  const response = await fetch(
    "http://localhost:3001/checkout-initialization",
    {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        publicKey, // pk_test_xmoneykey1234
        firstName: "",
        lastName: "",
        email: "",
        amount: 1,
        currency: "EUR",
      }),
    }
  );
  const result = await response.json();
  if (!response.ok) {
    throw new Error(result.error || "Failed to create payment intent");
  }
  await checkout.submitPayment(result);
} catch (error) {
  console.error("Error creating payment intent:", error);
} finally {
  setIsSubmitting(false);
}

Make sure your backend endpoint /checkout-initialization returns the required payload and checksum for the checkout to proceed.

7. Handle the payment result

Client

After submitting the payment, handle the encrypted response for the payment received on the redirect using the backUrl. Send the result back to your merchant backend for decryption.

API

On the server side, decrypt the response using the API SDK:

const paymentResponse = this.xMoneyApiClient.decryptOrderResponse(
  body.result,
);

//TODO Your business logic here
if (
  paymentResponse.transactionStatus ===
  xMoneyTransactionStatusEnum.CompleteOk
) {
  console.log('Transaction was successful');
}

return Promise.resolve(paymentResponse);

Display the decrypted transaction status to your users accordingly.

8. Advanced: Saved Cards and One-Click Payments

If you want to offer one-click checkout for returning customers, simply enable card saving:

saveCardOption: true; // show "Save card" checkbox for new cards

On future checkouts, pre-fill saved cards securely without collecting card info again.

9. 3DSv2 Authentication

The SDK automatically detects and sends necessary 3DSv2 parameters, like:

  • Browser IP
  • Browser Language
  • User Agent

You don't need to manually collect these unless you want to override defaults.

10. Mobile Integration via WebView

You can also use xMoney Checkout in a mobile app using a WebView. The API SDK returns a full HTML page that you load directly.

Example

import xMoney from "@xmoney/api-sdk";

const xMoneyCheckout = new xMoney({
  secretKey: "sk_test_secretKey",
});

const orderHtml = xMoneyCheckout.initializeHostedCheckout({
  publicKey: 'pk_test_abc123',
  customer: {
    identifier: "customerIdentifier",
    firstName: "John",
    lastName: "Doe",
    country: "RO",
    city: "Bucharest",
    email: "john.doe@test.com",
  },
  order: {
    orderId: "myUniqueOrderId",
    description: "Order Description",
    type: "purchase",
    amount: 100,
    currency: "EUR",
  },
  cardTransactionMode: "authAndCapture",
  backUrl: "https://127.0.0.1:8080",
});

Render orderHtml inside a mobile WebView. This is ideal for hybrid apps or apps where embedding raw form components is not desirable.

Find more details about Accepting Payments in Your Mobile App

11. Examples