Learn how to store a card on file with SCA (Strong Customer Authentication) to your application.
The steps in this topic add code to the application you created (with a card payment) from the Quickstart project sample, as documented in Take a Card Payment with the Web Payments SDK. If you haven't created an application using the Quickstart, you need to do so before completing the following steps.
You can see a complete code example in the Web Payments Quickstart on GitHub.
- In the body tag, update the payment form input field for the customer ID.
- Add "Store Card" to the button tag, so the form can extract the customer ID into a variable.
The form input takes the customer ID of the customer associated with the card on file.
<body>
<form id="payment-form">
<input
id="customer-input"
type="text"
aria-required="true"
aria-label="Customer ID"
required="required"
placeholder="Customer ID"
name="customerId"
/>
<div id="card-container" style="margin-top: 0"></div>
<button id="card-button" type="button">Store Card</button>
</form>
<div id="payment-status-container" class="store-card-message"></div>
</body>
Inside the <script>
tag, update the cardButton.addEventListener
callback method with the following code.
The card button event listener validates the text from the input form field and then stores the customer ID in a variable. The handleStoreCardMethodSubmission
method is called with the customer ID.
const cardButton = document.getElementById(`card-button`);
cardButton.addEventListener('click', async function (event) {
const textInput = document.getElementById('customer-input');
if (!textInput.reportValidity()) {
return;
}
const customerId = textInput.value;
// Add the `handleStoreCardMethodSubmission` method.
handleStoreCardMethodSubmission(event, card, customerId);
}
Add the following code after the initializeCard
function.
The storeCard
function replaces the createPayment
function in your code and creates the card on file associated with the customer ID.
async function storeCard(token, customerId) {
const bodyParameters = {
locationId,
sourceId: token,
customerId,
};
const body = JSON.stringify(bodyParameters);
const paymentResponse = await fetch('/card', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body,
});
if (paymentResponse.ok) {
return paymentResponse.json();
}
const errorBody = await paymentResponse.text();
throw new Error(errorBody);
}
Inside the
<script>
tag, rename thehandlePaymentMethodSubmission
function tohandleStoreCardMethodSubmission
after thelet card
object declaration and add the customer ID parameter.The
handleStoreCardMethodSubmission
method receives information about the card on file payment event with the customer ID.In the
try
statement, replace thepaymentResults
object with thestoreCardResults
method.The
storeCardResults
method takes the card's token and customer ID. The updated event handler code looks like the following example in thedocument.addEventListener
object:async function handleStoreCardMethodSubmission( event, paymentMethod, // Add the customer ID. customerId, ) { event.preventDefault(); try { // Disable the submit button as we await tokenization and make a payment request. cardButton.disabled = true; const token = await tokenize(paymentMethod); const storeCardResults = await storeCard( token, customerId, ); displayResults('SUCCESS'); console.debug('Store Card Success', storeCardResults); } catch (e) { displayResults('FAILURE'); console.error('Store Card Failure', e); } }
Navigate to http://localhost:3000/ in your browser. The browser loads the form with the customer ID input field, credit card input field, and the Store Card button.
In another browser tab, log in to your Square developer account and access API Explorer in your Sandbox environment.
Get the customer ID from a customer profile. If you don't have a customer profile for testing, use the CreateCustomer endpoint of the Customers API to create a new test customer profile in API Explorer.
On the form, enter the customer ID, any card number from the following table (any CVV or postal code works), and choose Store Card.
Brand Number CVV Visa 4111 1111 1111 1111 111 Mastercard 5105 1051 0510 5100 111 Discover 6011 0000 0000 0004 111 Diners Club 3000 000000 0004 111 JCB 3569 9900 1009 5841 111 American Express 3400 000000 00009 1111 China UnionPay 6222 9888 1234 0000 123 Verify that the application successfully stored the customer ID and credit card on file. In the Developer Dashboard, open the application, and choose API Logs in the left pane.
Important
Your application should always attempt to create a payment with a verification token when a token is returned. It should also be prepared to respond to a payment failure in a small number of cases where a payment is rejected despite receiving a buyer verification token.
Update the
storeCard
function to take theverificationToken
parameter.// verificationToken can be undefined, as it doesn't apply to all payment // methods. async function storeCard(token, verificationToken) { const bodyParameters = { locationId, sourceId: token, verificationToken }; const body = JSON.stringify(bodyParameters); // Same as in the cards example. const paymentResponse = await fetch('/payment', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body, }); if (paymentResponse.ok) { return paymentResponse.json(); } const errorBody = await paymentResponse.text(); throw new Error(errorBody); }Define the
verifyBuyer
function with billing contact details after thedisplayResults
function.Your production application should collect the billing address of the buyer. Although providing an empty
billingContact
is acceptable, by providing as much billing contact information as possible, you increase the chances of a successful authentication. This example uses an object that is declared with a hard-coded billing address. Your application might collect a billing address at payment time or, if the buyer is a customer on the seller Square account, from the buyer's customer record.Note
The Web Payments SDK produces a payment token that can be used to make a payment with the presented card or to store the card on file. These operations are represented by two intents:
CHARGE
to make a payment andSTORE
to store the card.The code in the following steps adds the billing contact values needed by SCA (with the payments.verifyBuyer function) to verify the authenticity of the card holder.
async function verifyBuyer(payments, token) { const verificationDetails = { billingContact: { addressLines: ['123 Main Street', 'Apartment 1'], familyName: 'Doe', givenName: 'John', email: '[email protected]', country: 'GB', phone: '3214563987', region: 'LND', city: 'London', }, intent: 'STORE', }; const verificationResults = await payments.verifyBuyer( token, verificationDetails ); return verificationResults.token; }The
verifyBuyer
function creates a StoreVerifyBuyerDetails object that verifies a card to be stored on file and provides the buyer and purchase details needed by 3DS.Add the
verifyBuyer
function to thehandleStoreCardMethodSubmission
function and update thestoreCard
method call to includeverificationToken
.async function handleStoreCardMethodSubmission( event, paymentMethod, customerId ) { event.preventDefault(); try { // disable the submit button as we await tokenization and make a payment request. cardButton.disabled = true; const token = await tokenize(paymentMethod); // Add verifyBuyer. let verificationToken = await verifyBuyer(payments, token); // Add verificationToken. const storeCardResults = await storeCard( token, customerId, verificationToken ); displayResults('SUCCESS'); console.debug('Store Card Success', storeCardResults); } catch (e) { cardButton.disabled = false; displayResults('FAILURE'); console.error('Store Card Failure', e); } }Test the application.
Navigate to
http://localhost:3000/
in your browser.Use one of the test cards in the following table with a challenge type of “Modal with Verification Code":
Brand Number CVV Challenge type Verification code Visa 4800 0000 0000 0004 111 No Challenge N/A Mastercard 5222 2200 0000 0005 111 No Challenge N/A Discover EU 6011 0000 0020 1016 111 No Challenge 123456 Visa EU 4310 0000 0020 1019 111 Modal with
Verification Code123456 Mastercard 5248 4800 0021 0026 111 Modal with
Verification Code123456 Mastercard EU 5500 0000 0020 1016 111 Modal with
Verification Code123456 American Express EU 3700 000002 01014 1111 Modal with
Verification Code123456 Visa 4811 1100 0000 0008 111 No Challenge with
Failed VerificationN/A
After you submit, you see the following window where you enter the verification code:
Verify that the application passed in the verification token with a successful response. Check the application's API log again in your developer account.