Integrating payments and securely saving card details on your checkout page is straightforward with our "Pay and Save" flow. This allows your customers to store their card information for future transactions during a single end-user journey.
Pay and save flow (with authentication)
Create a payment session
Request - POST /sessions
| Response - POST /sessions
|
---|
Gather the card information
Initiate card_session.js on your page. Collect the card information using
Xendit.payment.collectCardData(reqData, xenditResponseHandler)
. This will collect the card information and send it to Xendit using card_session.js.
Request - to card_session_js
| Response - from card_session_js
|
---|
Important: Store the payment_request_id
. You'll need it to retrieve the transaction's status and it will be included in the webhook for status updates.
Redirect to the authentication page
Redirect customer to the authentication page using the
action_url
from the response object.Customer completes authentication
After successful authentication, your cusotmer is redirected to your
success_return_url
. If authentication fails, they may be redirected to yourfailure_return_url
.Receive the webhook
Xendit sends a payment webhook to your webhook endpoint indicating the final state of the transaction. You can match the payment webhook with the
payment_request_id.
Example payment.capture
webhook:
{
"created": "2024-12-18T05:46:35.109Z",
"business_id": "62440e322008e87fb29c1fd0",
"event": "payment.capture",
"data": {
"type": "PAY",
"status": "SUCCEEDED",
"country": "ID",
"created": "2024-12-18T05:46:08.192Z",
"updated": "2024-12-18T05:46:30.627Z",
"captures": [
{
"capture_id": "cptr-08f17fa3-e80c-4d8e-8c34-17aa3400bc1c",
"capture_amount": 10000,
"capture_timestamp": "2024-12-18T05:46:34.234Z"
}
],
"currency": "IDR",
"payment_id": "py-3f57d678-2448-4c9f-a433-8468d366fb5c",
"business_id": "62440e322008e87fb29c1fd0",
"customer_id": "cust-7de9a9b4-37e8-40ad-b665-d97f42e538c5",
"channel_code": "CARDS",
"reference_id": "97ba0a32-b996-4abf-8a7b-6184a6644676_b8d18f2f-3",
"capture_method": "AUTOMATIC",
"request_amount": 10000,
"payment_details": {
"authorization_data": {
"reconciliation_id": "7345007929096981703954",
"authorization_code": "831000",
"acquirer_merchant_id": "xendit_ctv_agg",
"network_response_code": "00",
"network_transaction_id": "016153570198200",
"cvn_verification_result": "M",
"retrieval_reference_number": "435205253972",
"address_verification_result": "M",
"network_response_code_descriptor": "Approved and completed sucessfully"
},
"authentication_data": {
"flow": "CHALLENGE",
"a_res": {
"eci": "05",
"message_version": "2.1.0",
"authentication_value": "AAIBBYNoEwAAACcKhAJkdQAAAAA=","directory_server_trans_id": "e537f539-d59f-4ebe-8d56-7fdc31a8e9b4"
}
}
},
"payment_request_id": "pr-5593127f-8c7b-4d2f-b487-c785ffc21e2f",
"payment_token_id": "pt-8983127f-98er-76dr-67er-d985gff21z2f"
},
"api_version": "v3"
}
It's recommended to save the payment_id
and payment_details
from the webhook, correlated with the payment_request_id
, as proof of payment.
Pay and Save without authentication
We highly recommend performing authentication when processing card transactions. Authentication does not only provide a liability shift (protecting you from certain fraud disputes), it additionally ensures users are who they say they are.
However, upon request and after a risk-based assessment, Xendit can activate guest checkout without mandating authentication. We’ll perform a risk-based assessment, before allowing you to accept transactions without authentication.
Pay and Save flow without authentication
Create a payment session
Request - POST /sessions
| Response- POST /sessions
|
---|
Gather the card information
Initiate card_session.js on your page. Collect the card information using
Xendit.payment.collectCardData(reqData, xenditResponseHandler)
. This will collect the card information and send it to Xendit using card_session.js.
Request - to card_session_js
| Response - from card_session_js
|
---|
Important: Store the payment_request_id
as it's crucial for retrieving the transaction's status later.
Receive the webhook
Xendit sends a payment webhook to your webhook endpoint indicating the final state of the transaction. You can match the payment webhook with the
payment_request_id.
Example payment.capture
webhook:
{
"created": "2024-12-18T05:46:35.109Z",
"business_id": "62440e322008e87fb29c1fd0",
"event": "payment.capture",
"data": {
"type": "PAY",
"status": "SUCCEEDED",
"country": "ID",
"created": "2024-12-18T05:46:08.192Z",
"updated": "2024-12-18T05:46:30.627Z",
"captures": [
{
"capture_id": "cptr-08f17fa3-e80c-4d8e-8c34-17aa3400bc1c",
"capture_amount": 10000,
"capture_timestamp": "2024-12-18T05:46:34.234Z"
}
],
"currency": "IDR",
"payment_id": "py-3f57d678-2448-4c9f-a433-8468d366fb5c",
"business_id": "62440e322008e87fb29c1fd0",
"customer_id": "cust-7de9a9b4-37e8-40ad-b665-d97f42e538c5",
"channel_code": "CARDS",
"reference_id": "97ba0a32-b996-4abf-8a7b-6184a6644676_b8d18f2f-3",
"capture_method": "AUTOMATIC",
"request_amount": 10000,
"payment_details": {
"authorization_data": {
"reconciliation_id": "7345007929096981703954",
"authorization_code": "831000",
"acquirer_merchant_id": "xendit_ctv_agg",
"network_response_code": "00",
"network_transaction_id": "016153570198200",
"cvn_verification_result": "M",
"retrieval_reference_number": "435205253972",
"address_verification_result": "M",
"network_response_code_descriptor": "Approved and completed sucessfully"
},
"authentication_data": {
"flow": "CHALLENGE",
"a_res": {
"eci": "05",
"message_version": "2.1.0",
"authentication_value": "AAIBBYNoEwAAACcKhAJkdQAAAAA=","directory_server_trans_id": "e537f539-d59f-4ebe-8d56-7fdc31a8e9b4"
}
}
},
"payment_request_id": "pr-5593127f-8c7b-4d2f-b487-c785ffc21e2f",
"payment_token_id": "pt-8983127f-98er-76dr-67er-d985gff21z2f"
},
"api_version": "v3"
}
It's recommended to save the payment_id
and payment_details
from the webhook, correlated with the payment_request_id
, as proof of payment.
Get payment token details
To retrieve details of a saved payment token, such as a masked_card_number
, use the following endpoint:
https://api.xendit.co/v3/payment_token/YOUR_PAYMENT_TOKEN_ID
This will return the details of the payment token.
Response - from payment_token
|
---|
Use payment token for future transactions
Once a payment token is generated, it acts as a secure reference to the end user's stored card details. You can use this token for future transactions, based on your agreement with the end user.
Common Use Cases for Payment Tokens:
Customer-Initiated Transactions (Returning Customers) - Enable returning customers to quickly select a saved card at checkout. To improve the success rate, we recommend prompting users to re-enter their CVN when completing the transaction. See our integration guide
Merchant-Initiated Transactions (Recurring Payments) - Automate recurring billing (subscriptions, etc.) without customer interaction. See our integration guide