Card on file
The "Card on file" functionality allows users to save credit card information for future use instead of repeatedly entering their credit card information.
Cards can be stored during each of the following flows:
- Charge flow
- From a client card
- During checkout
Saving card during a charge flow
Client consent
For the payment gateway application to determine whether the user chose to save the card, the iFrame should listen to the following postMessage that indicates whether the “Client has consented to save this card on file” checkbox is checked or unchecked.
Code snippet for listening to save card checkbox events
window.addEventListener(
'message',
(event) => {
// Save card checked/unchecked event
if (event.data.type === 'generic' && event.data.func === 'setSaveCard') {
const saveCard = event.data.params.checked.checked; // boolean
return;
}
})
Charge event
Once the user clicks the Charge button, we will start the process of saving the card, and once done, the Charge will continue as described under the Charge section.
At that point, you want to save the payment details along with the credit card information, and make sure you can reference the credit card information based on the "charge token" - the token you provided via the JavaScript postMessage.
Note that this time, the postMessage emitted when the Charge CTA is clicked will indicate that "save_card: true":
{
type: 'generic',
func: 'getToken',
params: {
amount: number,
save_card: true,
pivot_id: string,
client_id: string,
currency: string
}
}
Also, when save_card is true, you'll need to pass a cardholder_name in the postMessage in addition to the token you'd pass in a charge flow.
window.addEventListener(
'message',
(event) => {
if (event.data.type === 'generic' && event.data.func === 'getToken') {
// Do some credit card number validations
const cardValidationErrors = validateCard(); // Can be a function that returns an array of errors
// if card validations checks error
if (cardValidationErrors.length > 0) {
const messageObj = {
type: 'generic',
func: 'validationFailure'
}
window.parent.postMessage(messageObj, '*')
// present the errors in the iFrame
return;
// If the card checks correctly with no issues
} else {
const token = {TOKEN}
const messageObj = {
type: 'generic',
token: {TOKEN}
}
// Add cardholder_name is save_card === true
if (event.data.params.save_card) {
messageObj['cardholder_name'] = this.cardHolderName;
}
window.parent.postMessage(messageObj, '*');
// Store token and payment details in your database for later reference
return;
}
}
}
)
POST /customer
inTandem will send a POST request to {redirect_uri}/customer the first time you're attempting to save a card for a given client. The response should be the client's customer_id.
Following card-on-file attempts for that same client will not trigger another request to /customer.
Request
POST {redirect_uri}/customer
Request body payload
client_id: "jwlubzof7xahdazo"
email: "[email protected]"
name: "first name last name"
Expected response
{customer_id: {CUSTOMER_ID_VALUE}}
customer_id
The customer ID is a unique identifier assigned to a customer by the payment gateway. This identifier is used to represent the customer in the payment gateway's system and is typically used for managing and processing payments, subscriptions, and storing payment information securely.
POST /customer/:token/attach
Next, inTandem will send another POST request to {redirect_uri}/customer/:token/attach.
The "token" param will correspond to the token you initially provided in the Charge event.
POST {redirect_uri}/customer/:token/attach
Request payload:
{
"customer_id": string,
"initiator": "business" | "client"
}
Property | Type | Description |
---|---|---|
initiator | "business" | "client" | Indicates the origin of card-on-file. "business" - when the card-on-file is initiated from the back office by the business. "client" - when the card-on-file is initiated from the client portal by the client. |
Expected response:
{
"card": {
"card_id": "addtkthQ16trAsldSar50v6sLfdmuQ", // card identifier provided by the payment gateway
"card_info": {
"card_brand": "visa",
"last_4": 1217,
"exp_month": 10,
"exp_year": 2030,
"cardholder_name": "John Doe"
}
},
"customer_id": "49v0ud9YhquOoYTczn0PkwdRn9QRb7"
}
That's it. At that point, the card is saved and will appear as an optional payment option for future payments.
Saving card on file from the client card
Saving a card on file from the client card is identical to how you save a card on the Charge flow. On both, inTandem will embed the Payment Processing Page from {redirect_uri}/charge, emit the getToken postMessage when the ADD CTA is clicked (and expecting a following postMessage with a token), followed by a POST request to {redirect_uri}/charge/:token/attach.
For the payment processing page to differentiate between the two flows, when inTandem loads the payment processing page on the client card page, we'll append a query param to the iFrame URL indicating that this is a save-card-only operation and not a charge flow.
{redirect_uri}/charge?save_card=true&pivot_id=BUSINESS_UID
Delete saved cards
Removing saved cards is done by inTandem sending a request to:
POST {api_uri}/customer/:token/detach
Request payload
{
"customer_id": "49v0ud9YhquOoYTczn0PkwdRn9QRb7"
}
Expected response:
{
"customer_id": "49v0ud9YhquOoYTczn0PkwdRn9QRb7"
}
Saving card-on-file on checkout
Get payment information from inTandem (make sure that “allow_save_card” is true). If allow_save_card is false, either the client already has 3 cards saved, or the “checkout_vaulting” feature flag is missing for that account.
Saving cards on checkout is done in two steps:
-
Make sure that the save card feature is available at the account level.
When sending the GET request to /checkout/:url_key as part of the usual checkout flow, make sure that the value of the “allow_save_card” property is true.GET /checkout/:url_key body request:
{
"status": "OK",
"data": {
"amount": "33.0",
"currency": "USD",
"name": "John Doe",
"return_url": "https://clients.meet2know.com/portal/5e3c760d?fromCheckout=true#/loader",
"email": "[email protected]",
"client_id": "zlbsfegs493u9zmo",
"invoice_id": null,
"allow_save_card": true
}
}
-
If “allow_save_card” is true, you can proceed with the checkout flow by appending the customer id and the card information when sending the payment checkout update request.
PUT https://api.vcita.biz/platform/v1/payment/checkout/ body request:
{
"url_key": "ijGghOYFKTFClDWJQZSNzkaZDZNQOiksktubFXpXfWmdovxuSz",
"card":{
"card_id": "15dsanida54",
"card_info": {
"exp_month": "01",
"exp_year": "2025",
"last_4": "6666",
"card_brand": "visa",
"cardholder_name": "John Doe"
}
},
"customer_id": "49v0ud9YhquOoYTczn0PkwdRn9QRb7",
"created": "2020-11-26",
"transaction_id": "12qw34rt56yu",
"type": "checkout.session.completed"
}
Expected response:
{
"status": "OK",
"data": {}
}
Updated about 2 months ago