# Collect payment details without an initial payment session
To support advanced payment scenarios, you can render Flow components and collect payment details without an initial payment session. For example, if you need to create the session later after additional validations or user actions have taken place.
You can integrate this payment flow with the following payment methods:
- AlipayCN
- AlipayHK
- Alma
- Bancontact
- Benefit Payment Gateway
- Dana
- Electronic Payment Standard (EPS)
- GCash
- iDEAL
- KakaoPay
- Klarna
- KNET
- MB WAY
- Multibanco
- Octopus
- Przelewy24
- QPay
- SEPA
- Swish
- Touch 'n Go
- TrueMoney
---
## Payment process
1. The customer lands on the checkout page.
1. You initialize and mount the individual Flow components for each payment method you want to display.
1. Flow displays the payment methods to the customer. If the customer's chosen payment method requires additional customer data, Flow captures this from them.
1. Optionally, you capture additional order details from the customer during checkout.
1. When the customer clicks the _Pay_ option, you submit their chosen payment method.
1. You perform a server-side request to complete the checkout and include the payment details you received from Flow.
1. After you create the order on your server, you request a payment session.
1. You return the payment session response to the client side and use it to handle the submission callback. Flow handles any additional actions required – For example, a third-party payment page redirect.
1. If the customer selected the option to save their card for faster checkout, we create a [Remember Me](https://www.checkout.com/docs/payments/accept-payments/accept-a-payment-on-your-website/extend-your-flow-integration/enable-remember-me.md) profile for them and save their card to it. The customer can reuse their saved cards in future transactions.
1. The customer is redirected to the success or failure URL you specified in the payment session and you receive a webhook notifying you of the payment status.
---
## Before you start
Make sure you have a [test account](https://www.checkout.com/get-test-account) with Checkout.com.
Create a [public key and a secret key](https://www.checkout.com/docs/resources/api-authentication/api-keys.md) from the [Dashboard](https://dashboard.checkout.com), with the following key scopes:
- Public key – `payment-sessions:pay` and `vault-tokenization`
- Secret key – `payment-sessions`
To receive webhooks for the [payment events](https://www.checkout.com/docs/developer-resources/event-notifications/event-types.md#Gateway), [configure your webhook server](https://www.checkout.com/docs/developer-resources/event-notifications/receive-webhooks/configure-your-webhook-server.md).
---
## Initialize and mount Flow `Client side`
You can install the `@checkout.com/checkout-web-components` package via npm:
```bash
npm install @checkout.com/checkout-web-components --save
```
Alternatively, you can load the package directly via a script:
```html
```
To remain PCI compliant, you should only ever load the script directly from `https://checkout-web-components.checkout.com`. Do not download or host the script yourself, or include it in a bundle.
The client side initializes an instance of `CheckoutWebComponents` with configuration information.
> **Information**
>
> For Klarna integrations, you must provide additional fields in `componentOptions` when you initialize `CheckoutWebComponents`.
**Klarna**
```javascript
// Insert your public key here
const publicKey = '{YOUR_PUBLIC_KEY}';
// Handle payment submission with your server integration
const handleSubmit = async (component, submitData) => {
const submitResponse = await performPaymentSubmission(submitData);
return submitResponse;
};
const checkout = await CheckoutWebComponents({
publicKey,
environment: 'sandbox',
handleSubmit,
componentOptions: {
amount: 900,
currency: "GBP",
processingChannelId: "{YOUR_PROCESSING_CHANNEL_ID}",
data: {
billingCountry: "GB",
},
items: [
{
name: "Test item",
quantity: 1
unitPrice: 900,
totalAmount: 900
}
]
},
});
```
**Other payment methods**
```javascript
// Insert your public key here
const publicKey = '{YOUR_PUBLIC_KEY}';
// Handle payment submission with your server integration
const handleSubmit = async (component, submitData) => {
const submitResponse = await performPaymentSubmission(submitData);
return submitResponse;
};
const checkout = await CheckoutWebComponents({
publicKey,
environment: 'sandbox',
handleSubmit,
});
```
### Configuration options
You can use the following configuration options to instantiate an instance of `CheckoutWebComponents`:
| JavaScript key | Description |
| --- | --- |
| `appearance` | Allows you to customize the visual appearance of the `CheckoutWebComponents` elements. To see the customization options, refer to the [Appearance options](https://www.checkout.com/docs/payments/accept-payments/accept-a-payment-on-your-website/customize-your-flow-integration.md#Appearance_options) documentation. |
| `componentOptions` | Allows you to customize the options for the individual Flow components. For example, you can change the position of the cardholder field in the `card` component. To see the customization options, refer to the [component options](https://www.checkout.com/docs/payments/accept-payments/accept-a-payment-on-your-website/flow-library-reference/checkoutwebcomponents.md#Initialization) documentation. |
| `environment` | Sets the environment that the library should point, and send requests to. This can be one of:
- `production`
- `sandbox` |
| `handleSubmit(component, submitData)` | Raised when you or the customer submit a component element.
This enables you to receive payment details provided by the customer, which you can use to submit a server-side payment session request.
You must provide this callback in the `CheckoutWebComponents` initialization. |
| `locale` | Sets the customer's locale. Explicitly setting this value overrides the `locale` returned by the `PaymentSession`. To see a list of supported languages, refer to the [localization](https://www.checkout.com/docs/payments/accept-payments/accept-a-payment-on-your-website/add-localization-to-your-flow-integration.md) documentation. |
| `onChange(component)` | An event fired when a component changes after a customer interaction. |
| `onError(component, error)` | An event fired when an error occurs. |
| `onPaymentCompleted(component, paymentResponse)` | An event fired when the payment has been completed synchronously. |
| `onReady(component)` | An event fired when a component is initialized and ready for the customer to interact. |
| `onSubmit(component)` | An event fired when you or the customer trigger a component submission. |
| `publicKey` | Your public API key. Your key is prefixed with `pk_`.
This field is required. |
| `translations` | Allows you to provide custom text translations for natively supported languages, or add custom text for locales and languages not natively supported by Flow. To learn how to add translations, refer to the [Add localization to your Flow integration](https://www.checkout.com/docs/payments/accept-payments/accept-a-payment-on-your-website/add-localization-to-your-flow-integration.md) documentation. |
---
## Initialize and mount the payment components `Client side`
Use `CheckoutWebComponents` to create an object for each payment method you want to display. For example:
```javascript
const alipayCnComponent = checkout.create('alipay_cn');
const idealComponent = checkout.create('ideal');
```
For integrations without an initial payment session, you can create any of the following payment method components:
- `alipay_cn`
- `alipay_hk`
- `alma`
- `bancontact`
- `benefit`
- `dana`
- `eps`
- `gcash`
- `ideal`
- `kakaopay`
- `klarna`
- `knet`
- `mbway`
- `multibanco`
- `p24`
- `qpay`
- `sepa`
- `tng`
- `truemoney`
Mount the payment components to the website using the `mount()` method. The method takes an [Element selector](https://developer.mozilla.org/en-US/docs/Web/API/Element) or an [Element](https://developer.mozilla.org/en-US/docs/Web/API/Document_object_model/Locating_DOM_elements_using_selectors) as an argument. For example:
**Mount the payment components to a Selector**
```javascript
if (await alipayCnComponent.isAvailable()) {
alipayCnComponent.mount('#alma-container');
}
if (await idealComponent.isAvailable()) {
idealComponent.mount('#alma-container');
}
```
**Mount the payment components to an Element**
```javascript
const alipayCnElement = document.getElementById('alipaycn-container');
const idealElement = document.getElementById('ideal-container');
if (await alipayCnComponent.isAvailable()) {
alipayCnComponent.mount(alipayCnElement);
}
if (await idealComponent.isAvailable()) {
idealComponent.mount(idealElement);
}
```
> **Note**
>
> Embedding Flow within an iframe or onto a Shadow DOM is not supported.
---
## Handle the payment submission `Client side`
When the customer finishes entering their order details and is ready to pay, call the `submit()` method using the payment method component that the customer selected.
The `handleSubmit` callback provides the captured payment details, which you can use in your server-side integration to submit the payment session request.
```javascript
// Handle payment submission
submitButton.addEventListener('click', () => {
// Get the payment method selected by customer
const selectedPaymentMethod = getSelectedPaymentMethod();
// Trigger payment submission using the selected payment method component
switch (selectedPaymentMethod) {
case 'alipay_cn':
alipayCnComponent.submit();
break;
case 'ideal':
idealComponent.submit();
break;
}
});
```
---
## Submit the payment session request `Server side`
The data you receive from the `handleSubmit` callback contains a `session_data` property which you can use to send a server-side request to securely create a payment session.
> **Information**
>
> Some payment methods have specific field requirements. For more information, see each [payment method's](https://www.checkout.com/docs/payments/add-payment-methods.md) Flow documentation.
Call the [Create and submit payment session](https://api-reference.checkout.com/tag/Flow/#operation/CreateAndSubmitPaymentSession) endpoint:
> **Information**
>
> Your base URL's `{prefix}` value is unique to your account and environment. To learn how to retrieve your base URLs for the sandbox and production environments, see [API endpoints](https://www.checkout.com/docs/developer-resources/api/api-endpoints.md).
**Production**
`POST` `https://{prefix}.api.checkout.com/payment-sessions/complete`
**Sandbox**
`POST` `https://{prefix}.api.sandbox.checkout.com/payment-sessions/complete`
### Request example
```json
{
"session_data": "eyJ0eXBlIjoiYWxpcGF5X2NuIiwic2Vzc2lvbl9tZXRhZGF0YSI6eyJpbnRlcm5hbF9wbGF0Zm9ybSI6eyJuYW1lIjoiQ2hlY2tvdXRXZWJDb21wb25lbnRzIiwidmVyc2lvbiI6IjEuMTM4LjAifSwiZmVhdHVyZV9mbGFncyI6WyJhbmFseXRpY3Nfb2JzZXJ2YWJpbGl0eV9lbmFibGVkIiwiY2FyZF9maWVsZHNfZW5hYmxlZCIsImdldF93aXRoX3B1YmxpY19rZXlfZW5hYmxlZCIsImxvZ3Nfb2JzZXJ2YWJpbGl0eV9lbmFibGVkIiwicmlza19qc19lbmFibGVkIiwidXNlX25vbl9iaWNfaWRlYWxfaW50ZWdyYXRpb24iXSwiZXhwZXJpbWVudHMiOnt9fX0=",
"amount": 1000,
"currency": "HKD",
"billing": {
"address": {
"address_line1": "Customer Home",
"city": "Shanghai",
"country": "CN"
}
},
"success_url": "https://example.com/payments/success",
"failure_url": "https://example.com/payments/failure",
"reference": "ORD-123A"
}
```
### Response example
```json
{
"id": "pay_mbabizu24mvu3mela5njyhpit4",
"status": "Action Required",
"type": "alipay_cn",
"action": {
"type": "redirect",
"url": "https://third-party-provider.com/ui"
},
"payment_session_id": "ps_2Un6I6lRpIAiIEwQIyxWVnV9CqQ",
"payment_session_secret": "pss_9823241e-2cec-4c98-b23d-7b29ow4e2e34"
}
```
---
## Handle the payment response `Client side`
When you receive the payment response, you must return it to the client side integration and use it when you return the `handleSubmit` callback.
You can use Flow to handle payment methods that require a redirect (asynchronous payments) and those that do not (synchronous payments).
### Asynchronous payments
Depending on the payment outcome, some payment methods and 3D Secure authentication flows redirect the customer to a success or failure URL on your website.
We send a webhook to your server notifying you of changes to the payment's status. Wait for the webhook callback before you start your order fulfillment process.
For payments submitted with Flow, the `PaymentSession` ID is returned in the webhook payload's `data.metadata.cko_payment_session_id` field.
Optionally, you can retrieve the payment result from your server. Call the [Get payment details](https://api-reference.checkout.com/tag/Payments/#operation/getPaymentDetails) endpoint and provide the `cko-payment-id` from the URL as the request's `{id}` path parameter. For example:
```
https://example.com/success?cko-payment-id=pay_mbabizu24mvu3mela5njyhpasd
```
### Synchronous payments
Payment methods that do not require a redirect trigger an `onPaymentCompleted` event when the payment is successfully completed. You can use this to notify the customer of the payment status.
```javascript
const checkout = await CheckoutWebComponents({
publicKey,
environment: 'sandbox',
onPaymentCompleted: async (_self, paymentResponse) => {
// Handle synchronous payments
await handlePayment(paymentResponse.id);
},
});
```
The event returns the payment ID in the `paymentResponse.id` field. To retrieve the payment result from your server, call the [Get payment details](https://api-reference.checkout.com/tag/Payments/#operation/getPaymentDetails) endpoint and provide the payment ID as the `{id}` path parameter.
---
## Test the integration
For each [payment method](https://www.checkout.com/docs/payments/add-payment-methods.md) you intend to support, follow the testing steps and simulate different payment flows to ensure your integration is set up correctly and behaving as expected.
> **Information**
>
> Ensure that you test each payment method that you plan to offer to your customers.
You can check the status of a payment from the _Payments_ > _Processing_ > _All payments_ screen in the [Dashboard](https://dashboard.checkout.com).
---
## Content Security Policy
If you have a Content Security Policy (CSP) on your website, Checkout.com requires the following directives:
```
connect-src, https://*.checkout.com
frame-src, https://*.checkout.com
script-src, https://*.checkout.com
img-src, https://*.checkout.com
```
---
## Next steps
**[Customize your Flow integration](https://www.checkout.com/docs/payments/accept-payments/accept-a-payment-on-your-website/customize-your-flow-integration.md)**
Learn how to customize your Flow integration.
**[Flow library reference](https://www.checkout.com/docs/payments/accept-payments/accept-a-payment-on-your-website/flow-library-reference.md)**
See the configuration options and error handling steps for Flow.
**[Configure your webhook server](https://www.checkout.com/docs/developer-resources/event-notifications/receive-webhooks/configure-your-webhook-server.md)**
Configure a webhooks workflow to choose which events to subscribe to, and when you want them to occur.