Search Overlay

Save Cards

Paysafe Checkout allows consumers to save cards and addresses to their customer profile, enabling faster payments for returning consumers. To reduce your PCI-compliance burden, the Checkout SDK handles storage of the saved information using a secure process involving Customer Tokens.

Saving consumer data requires two levels of consent:

  1. You want to save the cards details.
  2. The consumer must consent to the details being saved.

First transaction

  1. The consumer selects the option to save their card while making a payment in Checkout:


     
    • The customerOperation parameter returned in the resultCallback is set to ADD.
    • If you opted for webhooks, the endpoint receives a webhook with the same information.

      NOTE: Checkout displays the save option to customers by default but, if required, you can make it compulsory for consumers to save their card when making a payment.
  2. As customerOperation is set to ADD, you must include the merchantCustomerId parameter along with the rest of the request payload when you trigger the Payments API.
  3. We create a customer profile and send you a response containing a Paysafe generated customerId and a multiUsePaymentHandleToken which stores the tokenized card information.
    • If you opted for webhooks, the endpoint receives a webhook with the same information.
  4. Store the customerId for future transactions.
    Alternatively, you can use the merchantCustomerId to call the Payments API and retrieve the customer profile as needed - see Get Customer Using Merchant Customer Id.

Checkout SDK with singleUseCustomerToken example

<html>
<head>
<script src="https://hosted.paysafe.com/checkout/v2/paysafe.checkout.min.js"></script>
</head>


<body>
<button onclick="checkout()"> Pay $25 </button>
</body>

<script>
function checkout() {
paysafe.checkout.setup("API Key", {
"currency": "USD",
"amount": 10000,
"locale": "en_US",
...
}
}
</script>
</html>

<html>
<head>
<script src="https://Hosted.paysafe.com/checkout/v2/paysafe.checkout.min.js"></script>
</head>

<body>
<button onclick="checkout()">Deposit</button>
</body>

<script>
function checkout() {
var API_key = "c3V0LTM0ODg2MDpCLXFhMi0wLTVkM2VjYjMwLTEtMzAyYzAyMTQyYTM3NjgxMmE2YzJhYzRlNmQxMjI4NTYwNGMwNDAwNGU2NWI1YzI4MDIxNDU1N2EyNGFiNTcxZTJhOWU2MDVlNWQzMjk3MjZjMmIzZWNjNjJkNWY=";
options = {
currency: "USD",
amount: 540,
merchantRefNum: "162938285366512",
customer: {
firstName: "John",
lastName: "Doe",
email: "DoeJohn.0309@gmail.com",
},
paymentMethodDetails: {
card: { accountId: 1001461040
}
},
};

paysafe.checkout.setup(
API_key,
options,
function resultCallback(instance, error, result) {
if (result && result.paymentHandleToken) {
instance.showSuccessScreen( "Your goods are now purchased. Expect them to be delivered in next 5 business days.");
if (instance.isOpen()) {
instance.close();
}
// make AJAX call to Payments API
} else {
console.error(error); // Handle the error
instance.showFailureScreen( "The payment was declined. Please, try again with the same or another payment method.");
}
},
function(stage, expired) {
if (stage) {
switch (stage) {
case "PAYMENT_HANDLE_NOT_CREATED" :
case "PAYMENT_HANDLE_CREATED" :
case "PAYMENT_HANDLE_REDIRECT" :
case "PAYMENT_HANDLE_PAYABLE" :
default:
}
}
else {
console.log(expired) //Add action in case Checkout is expired
}
}
);
}
</script>
</html>

resultCallback example: Result object

{
"paymentHandleToken": "SCRdJ1peWLUHeGvJ",
"paymentMethod": "CARD",
"customerOperation": "ADD",
"amount": 1000,
"transactionType": "PAYMENT"
}

Payments API request example

{
"merchantRefNum": "1693494165029",
"amount": 1000,
"currencyCode": "USD",
"dupCheck": false,
"settleWithAuth": false,
"paymentHandleToken": "SCRdJ1peWLUHeGvJ",
"merchantCustomerId": "user000",
}

Payments API response example

{
"id": "f19f810e-6111-4258-bebe-57a65c77952e",
"paymentType": "CARD",
"paymentHandleToken": "SCRdJ1peWLUHeGvJ",
"merchantRefNum": "1693494165029",
"currencyCode": "USD",
"settleWithAuth": false,
"txnTime": "2023-08-31T15:02:59Z",
"billingDetails": {
"nickName": "John Dee",
"street": "100",
"street2": "Queen Street",
"city": "Cupertino",
"zip": "14236",
"state": "CA",
"country": "US"
},
"customerIp": "172.0.0.1",
"status": "COMPLETED",
"amount": 100,
"preAuth": false,
"description": "Casino game purchase",
"availableToSettle": 100,
"gatewayResponse": {
"authCode": "187570",
"avsResponse": "MATCH",
"cvvVerification": "MATCH",
"serializable": true
},
"merchantDescriptor": {
"dynamicDescriptor": "Test Description",
"phone": "5555345456"
},
"multiUsePaymentHandleToken": "CtKzQXNTwZ3mxQ8",
"customerId": "8b70d802-02c1-4f20-8dd0-2b0fb52b44c9",
"profile": {
"id": "8b70d802-02c1-4f20-8dd0-2b0fb52b44c9",
"merchantCustomerId": "user000",
"locale": "en",
"firstName": "John",
"lastName": "Doe",
"email": "John.Doe@paysafe.com",
"phone": "84632876432"
},
"card": {
"cardExpiry": {
"month": "12",
"year": "2023"
},
"holderName": "John",
"cardType": "MC",
"cardBin": "541142",
"lastDigits": "0002",
"cardCategory": "CREDIT"
}
}

Subsequent transactions

  1. Before initiating the Checkout SDK, trigger an API call to generate a singleUseCustomerToken using the Customer Tokens API:
    POST: /paymenthub/v1/customers/{customerId}/singleusecustomertokens
  2. We send a response containing the token along with other information.
  3. Pass the token to the Checkout SDK - the tokenized information (saved cards and addresses) is displayed to the consumer in Checkout:

    Saved cards and addresses in Checkout
     
    • After generating the token, there is no need to monitor the consumer's actions (unlike in a first-time transaction). The SDK handles the consumer's save/ delete/ edit actions, and there is no need to pass merchantCustomerId in the Payments API call.
    • The token remains active for 900 seconds and can be used for multiple sessions for the same consumer.

singleUseCustomerToken API response example

{
"id": "ce7cae5d-0581-4888-916d-5233c7a4137c",
"timeToLiveSeconds": 899,
"status": "ACTIVE",
"singleUseCustomerToken": "SPLNnBxb1Tfx6Ef8", //singleUseCustomer Token to be passed in the checkout
"paymentTypes": [
"CARD"
],
"locale": "en",
"firstName": "John",
"lastName": "Doe",
"email": "johndoe@paysafe.com",
"phone": "1234567890",
"addresses": [

{
"id": "58575f51-2ba7-4e93-8a21-84dd7a1b8940",
"nickName": "John Dee",
"street2": "Queen Street",
"city": "Cupertino",
"state": "CA",
"country": "US",
"zip": "14236",
"status": "ACTIVE",
"street": "100"
}
],
"paymentHandles": [


{
"id": "314823c7-8787-4369-981e-f276cf5e58cc",
"status": "INITIATED",
"usage": "SINGLE_USE",
"paymentType": "CARD",
"paymentHandleToken": "SCifYI4OU1tlXSxI",
"card": {
"lastDigits": "0002",
"cardExpiry": {
"month": "12",
"year": "2023"
},
"cardBin": "541142",
"cardType": "MC",
"holderName": "kumar",
"status": "ACTIVE",
"cardCategory": "CREDIT"
},
"billingDetailsId": "58575f51-2ba7-4e93-8a21-84dd7a1b8940",
"multiUsePaymentHandleId": "68c34a34-a98b-494c-9fab-42ed4d3cedb0"
}
],
"customerId": "8b70d802-02c1-4f20-8dd0-2b0fb52b44c9"
}

Checkout SDK with singleUseCustomerToken example

<html>
<head>
<script src="https://Hosted.paysafe.com/checkout/v2/paysafe.checkout.min.js"></script>
</head>

<body>
<button onclick="checkout()">Deposit</button>
</body>

<script>
function checkout() {
var API_key = "c3V0LTM0ODg2MDpCLXFhMi0wLTVkM2VjYjMwLTEtMzAyYzAyMTQyYTM3NjgxMmE2YzJhYzRlNmQxMjI4NTYwNGMwNDAwNGU2NWI1YzI4MDIxNDU1N2EyNGFiNTcxZTJhOWU2MDVlNWQzMjk3MjZjMmIzZWNjNjJkNWY=";
options = {
currency: "USD",
amount: 540,
merchantRefNum: "162938285366512",

singleUseCustomerToken: "SPFAB1cA5iwdu48H", //singleUsecustomerToken containing details of cards, profile and addresses

customer: {
firstName: "John",
lastName: "Doe",
email: "DoeJohn.0309@gmail.com",
},
paymentMethodDetails: {
card: { accountId: 1001461040
}
},
};

paysafe.checkout.setup(
API_key,
options,
function resultCallback(instance, error, result) {
if (result && result.paymentHandleToken) {
instance.showSuccessScreen( "Your goods are now purchased. Expect them to be delivered in next 5 business days.");
if (instance.isOpen()) {
instance.close();
}
// make AJAX call to Payments API
} else {
console.error(error); // Handle the error
instance.showFailureScreen( "The payment was declined. Please, try again with the same or another payment method.");
}
},
function(stage, expired) {
if (stage) {
switch (stage) {
case "PAYMENT_HANDLE_NOT_CREATED" :
case "PAYMENT_HANDLE_CREATED" :
case "PAYMENT_HANDLE_REDIRECT" :
case "PAYMENT_HANDLE_PAYABLE" :
default:
}
}
else {
console.log(expired) //Add action in case Checkout is expired
}
}
);
}
</script>
</html>