Applies to: Web Payments SDK | Cards API | Customers API
Learn how to charge and store a card on file with the Web Payments SDK.
The key benefit of using the CHARGE_AND_STORE
intent is to both charge and store a card on file in a single request call, which triggers SCA buyer authentication if needed. You can use the CHARGE_AND_STORE
intent if the buyer wants to store the card on file when the seller charges the card for the payment.
With Web Payments SDK integration, your application can charge and store a card on file in the following two payment flows for a card on file:
- (Beta) A new default payment flow that involves:
- Generating a payment token. During payment tokenization, Square checks the tokenize request to determine whether buyer verification is needed based on the buyer's information.
- Including the payment token in a Payments API request call to process a payment.
- Creating a card on file and storing it with a new customer profile and a card object. When you call
CreateCard
, thesource_id
is thepayment_id
from the Payment API payment response object.
- The existing payment flow that involves:
- Generating a payment token.
- Generating a verification token after verifying the buyer.
- Including both the payment token and verification token in a Payments API request call to process a payment.
- Creating a card on file and storing it with a new customer profile and a card object. When you call
CreateCard
, thesource_id
is thepayment_id
from the Payment API payment response object.
Important
The new payment flow will replace the existing Web Payments SDK card payment acceptance implementation and become the new default card payment flow when Square releases it for General Availability.
When Square releases the new payment flow for General Availability, Square will deprecate the Payments.verifyBuyer() method that performs buyer verification and generates a verification token. Square will provide a migration guide so that you can update your application to take card payments with the new payment flow.
Square recommends updating your application to use the new default payment flow with the Web Payments SDK. However, during Beta, Square will continue to support both payment flows.
Choose one of the following card-on-file payment flows to set up your application to charge and store a card on file with Web Payments SDK integration.
Before updating your application with the CHARGE_AND_STORE
intent, make sure to update your application to support the new payment flow by following the instructions in Take a Card Payment.
In your application and after the
createPayment
method, create a new method calledstoreCard
, pass thepaymentId
andcustomerId
objects as arguments, and add the requisite properties and thestoreCardResponse
as shown in the following code example:async function storeCard(paymentId, customerId) { const body = JSON.stringify({ locationId, sourceId: paymentId, customerId, idempotencyKey: window.crypto.randomUUID(), }); const storeCardResponse = await fetch('/card', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body, }); if (storeCardResponse.ok) { return storeCardResponse.json(); } const errorBody = await storeCardResponse.text(); throw new Error(errorBody); }In the
tokenize
method, update theverificationDetails
object by settingintent
toCHARGE_AND_STORE
.async function tokenize(paymentMethod) { const verificationDetails = { amount: '10.00', billingContact: { givenName: 'John', familyName: 'Doe', email: '[email protected]', phone: '3214563987', addressLines: ['123 Main Street', 'Apartment 1'], city: 'London', state: 'LND', countryCode: 'GB', }, currencyCode: 'GBP', intent: 'CHARGE_AND_STORE', customerInitiated: true, sellerKeyedIn: false, };In the
document.addEventListener
event listener method, change thehandlePaymentMethodSubmission
method tohandleChargeAndStoreCardSubmission
, pass theevent
,card
, andcustomerId
objects as arguments, and modify the rest of the code as shown in the following code example:async function handleChargeAndStoreCardSubmission(event, card, customerId) { event.preventDefault(); try { // disable the submit button as we await tokenization and make a payment request. cardButton.disabled = true; const token = await tokenize(card); const paymentResults = await createPayment(token); console.debug('Payment Success', paymentResults); const storeCardResults = await storeCard( paymentResults.payment.id, customerId, ); console.debug('Store Card Success', storeCardResults); displayPaymentResults('SUCCESS'); } catch (e) { cardButton.disabled = false; displayPaymentResults('FAILURE'); console.error(e.message); } } 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; await handleChargeAndStoreCardSubmission(event, card, customerId); });