Reusing Card Information
PaymentsOS allows you to save a customer’s card information, so that customers do not need to re-enter their payment details each time they want to initiate a transaction on your site.
This functionality requires API version 1.2.0 or higher.
Requesting User Consent
If you want to enable users to save their card information, you will need to update your payment flow to include a step in which you ask users to save their cards for future use. Where you do this, depends entirely on your payment logic. For instance, if you are running an eCommerce store you would typically prompt users to save their card information while they are making a purchase on your site. Alternatively, you could also allow users to save theirs cards without requiring them to make a purchase (like when users sign-up for a free trial and only pay after the trial period ends).
Validating the Card
You may want to ensure that a card is valid before saving it. The only way to do this, is to invoke an authorization request and see that it goes through. If you prompt users to save their card while they are making a purchase, you can rest assured that the card is valid (since your payment flow will always include an authorization or charge request). If you want to validate the card without requiring users to make a purchase first, simply invoke an authorization request for a small amount and then void the authorization to cancel the payment.
Saving the Token
Once users gave their consent to store their card information and you validated their card, you can proceed to save it. A user’s card information is always represented as a token. PaymentsOS creates a token representation of that user’s card when you collect a user’s card information.
You can use a token only once in an authorization or charge request. If you want to reuse the token for subsequent transactions, you will need to save it in a customer
object first.
Beware that the CVV code is not part of the token and is thus not saved. If you require a CVV code in your checkout form, you must pass it separately into the authorization or charge request.
Token Validity
After creating the token, you have a 24-hour window in which you can save it. Unless saved, the token is deleted after 24 hours.
If you imported our Postman Collection, you can follow-along with the examples in this topic by invoking the requests in the Reusing Card Information folder.
Step 1: Create the Customer Object
Invoke the Create Customer API to create a customer
object. Notice that the request body requires a customer_reference
. This is a string that you must provide to uniquely identify the customer.
var request = new XMLHttpRequest();
request.open('POST', 'https://api.paymentsos.com/customers');
request.setRequestHeader('Content-Type', 'application/json');
request.setRequestHeader('api-version', '1.3.0');
request.setRequestHeader('x-payments-os-env', 'test');
request.setRequestHeader('app-id', 'com.zooz.docapp');
request.setRequestHeader('private-key', 'bede7ee5-eaad-4c8a-bc1f-617ba28257ae');
request.setRequestHeader('idempotency-key', 'cust-34532-trans-001356-p');
var body = {
"customer_reference": "johntravolta18021954",
"email": "john@travolta.com"}
request.send(JSON.stringify(body));
curl --compressed -X POST \
https://api.paymentsos.com/customers \
-H 'Content-Type: application/json' \
-H 'api-version: 1.3.0' \
-H 'x-payments-os-env: test' \
-H 'app-id: com.zooz.docapp' \
-H 'private-key: bede7ee5-eaad-4c8a-bc1f-617ba28257ae' \
-H 'idempotency-key: cust-34532-trans-001356-p' \
-d '{
"customer_reference": "johntravolta18021954",
"email": "john@travolta.com"
}'
Important Note when Using Network Tokens
If you want to use
network tokens, then you
must pass the customer’s email address when creating the customer object. Without having the email address on file, the PaymentsOS token will be used rather than the token provisioned by the card networks.
Step 2: Store the Token in the Customer Object
From the response body of the Create Customer API, grab the customer id
. Now invoke the Create Payment Method API request to store the token in the customer object. In the request URL, pass the customer id
(the first parameter), together with the card’s token
(the second parameter).
var request = new XMLHttpRequest();
request.open('POST', 'https://api.paymentsos.com/customers/{customer_id}/payment-methods/{token}');
request.setRequestHeader('Content-Type', 'application/json');
request.setRequestHeader('api-version', '1.3.0');
request.setRequestHeader('x-payments-os-env', 'test');
request.setRequestHeader('app-id', 'com.zooz.docapp');
request.setRequestHeader('private-key', 'bede7ee5-eaad-4c8a-bc1f-617ba28257ae');
request.setRequestHeader('idempotency-key', 'cust-34532-trans-001356-p');
request.send();
curl --compressed -X POST \
https://api.paymentsos.com/customers/{customer_id}/payment-methods/{token} \
-H 'Content-Type: application/json' \
-H 'api-version: 1.3.0' \
-H 'x-payments-os-env: test' \
-H 'app-id: com.zooz.docapp' \
-H 'private-key: bede7ee5-eaad-4c8a-bc1f-617ba28257ae' \
-H 'idempotency-key: cust-34532-trans-001356-p' \
Maximum Number of Tokens
You can store a maximum of 100 tokens per customer.
Step 3: Use the Saved Token to Accept a Payment
The next time you want to create an authorization or charge, you’ll now need to fetch the token from the customer object. We’ll illustrate this using the Retrieve Customer API, which requires that you pass in the customer ID.
Notes
-
Since we require the customer ID, you may want to store it in your backend database and fetch it when the customer logs into your site. Alternatively, you can also use the Retrieve Customer by Reference API, to which you pass the customer reference rather than the customer ID.
-
In addition to storing the token in a customer object, you can also choose to keep a copy in your own database as well. You can then use the token from your database to accept a payment, rather than fetching the token from the customer object.
Let’s create the request:
var request = new XMLHttpRequest();
request.open('GET', 'https://api.paymentsos.com/customers/{customer_id}');
request.setRequestHeader('Content-Type', 'application/json');
request.setRequestHeader('api-version', '1.3.0');
request.setRequestHeader('x-payments-os-env', 'test');
request.setRequestHeader('app-id', 'com.zooz.docapp');
request.setRequestHeader('private-key', 'bede7ee5-eaad-4c8a-bc1f-617ba28257ae');
request.setRequestHeader('idempotency-key', 'cust-34532-trans-001356-p');
request.send();
curl --compressed -X GET \
https://api.paymentsos.com/customers/{customer_id}/ \
-H 'Content-Type: application/json' \
-H 'api-version: 1.3.0' \
-H 'x-payments-os-env: test' \
-H 'app-id: com.zooz.docapp' \
-H 'private-key: bede7ee5-eaad-4c8a-bc1f-617ba28257ae' \
-H 'idempotency-key: cust-34532-trans-001356-p' \
Now you can grab the token from the response body. Notice that the token is stored as an attribute in the payment_methods
array of the response body. If you added multiple payment methods, they will be listed in the response as well (so customers can select their payment method of choice).
Here’s an example response (truncated for brevity):
{
...
"payment_methods": [
{
"token": "f504fb05-474b-48c0-a2d0-ea080f2b2535",
"type": "tokenized",
"token_type": "credit_card",
"fingerprint": "df0b5dda-1377-4dcd-87d4-b858c0eed43d",
"holder_name": "John Mark",
"expiration_date": "10/2029",
"last_4_digits": "1111",
...
}
]
}
Showing Card Information in a Checkout Page
You can use the response of the Retrieve Customer API request to list a customer’s payment options and show their card information in your checkout page. For security reasons, only part of a user’s card details can be shown.
Collecting the CVV Code
While you can reuse a customer’s saved card information, you may still be required to pass a customer’s CVV code in an authorization or charge request. Since the CVV code is not part of the saved token, you will thus need to collect the CVV code from your customers before you can proceed with the payment flow.
PaymentsOS allows you to securely collect a customer’s CVV code using either a Secure Code Form that you embed in your web page or the Javascript API. For help in creating the form and collecting the CVV code, see Collecting the CVV Code.
Passing a Card on File Indicator
When storing customers' card information for use in authorization, charge or credit requests, or when using this information in subsequent transactions, the major card brands now require that you indicate this in the transaction request. In PaymentsOS, you do this by explicitly informing PaymentsOS that you used a customer’s card on file (COF) to process the transaction.
Note
This feature may not be supported with all providers. To see whether passing a card-on-file indicator is supported with a specific provider, use the
Bodybuilder to generate a sample request (make sure to include optional fields when generating the example).
Step 1: Create a Consent Transaction
In the first request, you must indicate that the customer gave consent for using her saved card information. You do this by passing a card_entry_mode
indicator with a value of either consent_transaction
or recurring_consent_transaction
. Here’s an example request body for a Create Authorization request:
...
"cof_transaction_indicators": {
"card_entry_mode": "consent_transaction",
},
"payment_method": {
"credit_card_cvv": "123",
"token": "f78cbf5b-0e23-44e0-be11-2081791d9501",
"type": "tokenized"
}
Depending on the provider processing the transaction, the provider_data
object returned in the response of the consent transaction may include an ID that you must pass in all subsequent authorization, charge or credit requests. This ID identifies the initial consent transaction.
Note
If you configured
routing rules for directing payments to multiple providers, make sure that all providers specified in your rules expect the same value for the consent transaction ID. Unless this is the case, do not pass a consent transaction ID since this may lower your acceptance rates.
Here’s a sample provider_data
object, in which the ID is returned in the network_transaction_id
field. Bear in mind that depending on the provider, this ID may be returned in another field (to see which field returns the ID, refer to the notes in the field overview table of the sample request generated by the Bodybuilder).
{
"provider_data": {
...
"external_id": "string",
"documents": [],
"additional_information": {},
"network_transaction_id": "1a2bcd3"
},
}
Note
If the first transaction is declined when attempting to store card information, the card information should not be stored. As such, you must not use the card information for any subsequent transactions.
Step 2: Create all Subsequent Transactions
In all subsequent authorization, charge or credit requests, pass one of the following card_entry_mode
values:
cof_cardholder_initiated_transaction
: The card holder initiated the transaction.
cof_merchant_initiated_transaction
: You, as the merchant, initiated the transaction.
recurring_subsequent_transaction
: The transaction is a recurring one.
If the initial consent transaction request returned an ID that identifies the request, then pass this identifier in the cof_consent_transaction_id
field.
In the example body below, we pass a card_entry_mode
with a value of cof_cardholder_initiated_transaction
, to indicate that the transaction was initiated by the card holder:
{
"cof_transaction_indicators": {
"card_entry_mode": "cof_cardholder_initiated_transaction", // The card holder initiated the transaction
"cof_consent_transaction_id": "1a2bcd3" // Pass if returned by the consent transaction request
},
"payment_method": {
"credit_card_cvv": "123",
"token": "f78cbf5b-0e23-44e0-be11-2081791d9501",
"type": "tokenized"
}
}
To update a customer’s card information, you need to delete the existing token from the customer
object and then add the new token again. To delete the token, invoke the Delete Payment Method API. In the request URL, pass the customer id
(the first parameter) and the card’s token
(the second parameter).
var request = new XMLHttpRequest();
request.open('DELETE', 'https://api.paymentsos.com/customers/{customer_id}/payment-methods/{token}');
request.setRequestHeader('Content-Type', 'application/json');
request.setRequestHeader('api-version', '1.3.0');
request.setRequestHeader('x-payments-os-env', 'test');
request.setRequestHeader('app-id', 'com.zooz.docapp');
request.setRequestHeader('private-key', 'bede7ee5-eaad-4c8a-bc1f-617ba28257ae');
request.setRequestHeader('idempotency-key', 'cust-34532-trans-001356-p');
request.send();
curl -X DELETE \
https://api.paymentsos.com/customers/{customer_id}/payment-methods/{token} \
-H 'Content-Type: application/json' \
-H 'x-payments-os-env: test'
-H 'api-version: 1.3.0' \
-H 'app-id: com.zooz.docapp' \
-H 'idempotency-key: cust-34532-trans-001356-p' \
-H 'private-key: e1a5dacb-1484-4ee2-adcb-98c96c8c5fdb' \
To delete a customer’s card information, simply delete the token from the customer object by invoking the Delete Payment Method API. In the request URL, pass in the token to delete as the second parameter:
DELETE https://api.paymentsos.com/customers/{customer_id}/payment-methods/{token}
Note
If you did not save the token in a customer object, it will automatically be deleted after 24 hours.
Checking for Identical Card Numbers
There are scenarios in which you may want to check whether a customer’s card number already exists when storing the card’s token. For instance, a customer may need to update her account with new card information if her old card expired, in which case you can prompt your customer to remove the expired card details from her account rather than keeping both cards on file. You can also check for potentially fraudulent behavior when a customer adds her card details, by identifying whether another customer account already has an identical card number registered.
To check whether two cards are identical, you can use that card’s fingerprint
. The fingerprint
is a value that uniquely identifies a particular card number. Here’s an example of a fingerprint
returned in the response data of the Create Payment Method API:
{
"type": "tokenized",
"token": "b7094f8f-03cf-4bb7-86e6-08b6aa5030e7",
"token_type": "credit_card",
"fingerprint": "df0b5dda-1377-4dcd-87d4-b858c0eed43d",
...
}
After storing a customer’s card information, you can always fetch a card’s fingerprint
by retrieving a customer’s information using either the Retrieve Customer API or the Retrieve Customer by Reference API. Retrieving a customer’s payment methods using the Retrieve all Payment Methods API or the Retrieve a Payment Method API, will return the fingerprint
as well.
Topics in this Section
While you can reuse a customer’s saved card information, you may still be required to pass a customer’s CVV code in an authorization or charge request. Since the CVV code is not part of the saved token, you will thus need to collect the CVV code from your customers before you can proceed with the payment flow.servers.
Last modified May 30, 2022