Use the Web Payments SDK Quickstart sample project to set up a web application that is integrated with the Square Web Payments SDK for taking payments.
The following video demonstrates how to build an end-to-end payment flow with the credit card payment method, and shows the code you use to build the flow. For an optimal viewing experience, expand the video window to a desired size or watch the video on YouTube. For a detailed overview of building with the card payment method, see the following sections in this topic.
To accept a card payment from a buyer, you need a web client where the buyer enters payment card information and a backend that takes a payment with the card. The SDK produces a secure one-time-use payment token based on the card. Your web client sends the payment token to your backend where the payment is taken. In summary, a payment is taken with these steps:
- Generate a payment token - Use the Web Payments SDK client library to render a card entry form and generate a payment token that your web client sends to your backend server.
- Create a payment with the token - On your backend, use the Square Payments API to create a payment.
This topic shows you where to add HTML and JavaScript to your web client to integrate the Web Payments SDK and take a payment on your backend.
You can find a full example of the Card payment code in GitHub.
Important
If you're not familiar with building an application using Square's client-side SDKs, Square recommends completing this guide using the GitHub project before you attempt to integrate the Web Payments SDK into your application.
The following shows the card payment method rendered in a web page:
The payment method doesn't initially render input fields for the name or the billing address. When you initially set up the payment method, you don't need to include input fields for contact information (name and billing information). You only need to first set up payment processing with fields for the credit card number, expiration date, the CVV (card verification value), and if required for your region, a zip or postal code.
The form automatically recognizes the credit card type as soon as you enter the credit card number, and the form updates the credit card icon as a result to reflect the type being used.
To request the buyer to provide contact information and other additional information for the payment, you can add additional payment form fields to the page layout.
Start by cloning the quickstart project template into a folder on your computer.
Test the application
The project template isn't initially integrated with the SDK and doesn't render the card payment form.
Follow the GitHub repo README instructions to get the development server running.
Open a browser to http://localhost:3000 to verify that the server is running.
Your web page looks like the following page:
Success
If your web page renders as shown in the previous image, you're ready to write the code that adds the Card payment method to the page.
The walkthrough asks you to update the code in these project files:
- The public/index.html file is an empty static HTML page where you add the Web Payments SDK and application logic.
- The public/app.css file is the stylesheet that contains some preset styles to help with the page layout.
- The top-level server.js file contains the server call to the CreatePayment endpoint for charging the payment source. The quickstart application must include server.js to make the server call; otherwise, the application cannot create a payment. The quickstart project also includes tests in the server.tests.js file.
Important
The value in server.js line 45 sets the currency for the quickstart to US dollars. If your default test account is based in another country, be sure to update server.js with the currency code for your country before you run the quickstart.
// If you're a non-US account, you must change the currency to match the country in which
// you're accepting the payment.
currency: 'USD',
Get the web client ready to accept a payment card and send the resulting token to the server component of the quickstart application.
You need your Sandbox credentials because the quickstart application is configured to send requests to the Square Sandbox instead of your production Square account.
- Open the Developer Dashboard and click the plus symbol under Applications to create a new application.
- Open the application and choose the Credentials page.
- Set the Developer Dashboard mode to Sandbox to get a Sandbox application ID.
- Copy the Sandbox Application ID and Sandbox Access Token.
- Choose the Locations page and copy the Sandbox location ID.
- Paste the application ID, location ID, and Sandbox access token into a temporary text file.
Important
The Sandbox access token is a secure secret. Don't share it with anyone or upload it to the cloud.
The quickstart server code calls the CreatePayment endpoint and needs to be updated to use your Sandbox access token.
- In the project root folder, create a copy of the .env.example file and name it .env.sandbox.
Did you know?
The dotenv library is used to manage secrets that shouldn't be made public. The .env.sandbox file should never be committed.
Open the copied file to edit.
Define
SQUARE_ACCESS_TOKEN
with your Sandbox access token from the Developer Dashboard.SQUARE_ACCESS_TOKEN={SANDBOX_ACCESS_TOKEN}Restart your server for the Sandbox test environment (
npm run dev
) to use this new value.
You need a Sandbox application ID and Sandbox location ID in the following steps. You should paste these values into a text file or leave the Developer Dashboard open in another browser tab so that you can copy the values as needed.
Replace the body of public/index.html with this HTML:
<form id="payment-form"> <button id="card-button" type="button">Pay $1.00</button> </form>This HTML adds an element (``) that the Web Payments SDK attaches the card element to and adds a button that starts the tokenization process.
Did you know?
The SDK also enables the Apple Pay, Google Pay, ACH (bank transfer), Square gift card, and Cash App Pay payment methods.
The following JavaScript instantiates the SDK, provides the Card payment object, attaches it to the page, and generates the payment token:
Add an empty
<script>
tag to the<head>
of index.html after<script type="text/javascript" src="https://sandbox.web.squarecdn.com/v1/square.js"></script>
.<script> </script>Add the following global constants inside the
<script>
tag, substituting the IDs from the Developer Dashboard for the placeholder ({YOUR_SANDBOX_APPLICATION_ID}
and{YOUR_SANDBOX_LOCATION_ID}
) values:const appId = '{YOUR_SANDBOX_APPLICATION_ID}'; const locationId = '{YOUR_SANDBOX_LOCATION_ID}';Add the following code inside the
<script>
tag:async function initializeCard(payments) { const card = await payments.card(); await card.attach('#card-container'); return card; } document.addEventListener('DOMContentLoaded', async function () { if (!window.Square) { throw new Error('Square.js failed to load properly'); } const payments = window.Square.payments(appId, locationId); let card; try { card = await initializeCard(payments); } catch (e) { console.error('Initializing Card failed', e); return; } // Step 5.2: create card payment });
The code does the following:
- Initializes the Web Payments SDK by calling Square.payments(appId, locationId).
- Initializes the Card payment method by calling the Payments
.card()
method and attaching the payment method to the page DOM by calling the Card.attach()
method.
Note
The Card payment method of the Web Payments SDK automatically infers whether to display the ZIP code, postal code, or postcode based on the issuing country of the buyer's credit card. Depending on the card that's used, the SDK automatically removes the postal code if the card's issuing country doesn't require the postal code for the payment.
Test the application
Navigate to http://localhost:3000/ in your browser.
Success
You should now be able to see the payment card input rendered on your page.
Did you know?
If you need to clear the contents of the card entry fields for the buyer, call card.destroy()
to destroy the object and then call the initializeCard(payments)
function again to initialize and attach the card
to your application DOM.
Before you can take a payment, you need to configure your developer credentials, which can be found in the Developer Dashboard.
Note
This example uses the Square Sandbox to accept a payment. You should use the Card-present success state values. However, if you choose to use your own payment card, the Sandbox doesn't charge it.
Add the following code after the
initializeCard
function inside the<script>
tag:// Call this function to send a payment token, buyer name, and other details // to the project server code so that a payment can be created with // Payments API async function createPayment(token) { const body = JSON.stringify({ locationId, sourceId: token, idempotencyKey }); 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); } // This function tokenizes a payment method. // The ‘error’ thrown from this async function denotes a failed tokenization, // which is due to buyer error (such as an expired card). It's up to the // developer to handle the error and provide the buyer the chance to fix // their mistakes. async function tokenize(paymentMethod) { const tokenResult = await paymentMethod.tokenize(); if (tokenResult.status === 'OK') { return tokenResult.token; } else { let errorMessage = `Tokenization failed-status: ${tokenResult.status}`; if (tokenResult.errors) { errorMessage += ` and errors: ${JSON.stringify( tokenResult.errors )}`; } throw new Error(errorMessage); } } // Helper method for displaying the Payment Status on the screen. // status is either SUCCESS or FAILURE; function displayPaymentResults(status) { const statusContainer = document.getElementById( 'payment-status-container' ); if (status === 'SUCCESS') { statusContainer.classList.remove('is-failure'); statusContainer.classList.add('is-success'); } else { statusContainer.classList.remove('is-success'); statusContainer.classList.add('is-failure'); } statusContainer.style.visibility = 'visible'; }Add the following code to the
DOMContentLoaded
event listener in step 4.3 by replacing// Step 5.2: create card payment
with the following code:async function handlePaymentMethodSubmission(event, paymentMethod) { 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 paymentResults = await createPayment(token); displayPaymentResults('SUCCESS'); console.debug('Payment Success', paymentResults); } catch (e) { cardButton.disabled = false; displayPaymentResults('FAILURE'); console.error(e.message); } } const cardButton = document.getElementById( 'card-button' ); cardButton.addEventListener('click', async function (event) { await handlePaymentMethodSubmission(event, card); });
The complete DOMContentLoaded Event Listener
should look like the following code:
document.addEventListener('DOMContentLoaded', async function () {
if (!window.Square) {
throw new Error('Square.js failed to load properly');
}
const payments = window.Square.payments(appId, locationId);
let card;
try {
card = await initializeCard(payments);
} catch (e) {
console.error('Initializing Card failed', e);
return;
}
async function handlePaymentMethodSubmission(event, paymentMethod) {
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 paymentResults = await createPayment(token);
displayPaymentResults('SUCCESS');
console.debug('Payment Success', paymentResults);
} catch (e) {
cardButton.disabled = false;
displayPaymentResults('FAILURE');
console.error(e.message);
}
}
const cardButton = document.getElementById(
'card-button'
);
cardButton.addEventListener('click', async function (event) {
await handlePaymentMethodSubmission(event, card);
});
});
The code does the following:
- Binds the
Card
tokenization to the trigger event, which is clicking the Pay button in this case. - Submits the tokenized card information and payment token by calling the CreatePayment endpoint on the backend.
Navigate to http://localhost:3000/ in your browser.
Input the card number 5105 1051 0510 5100 from the Card-present success state values. Any CVV or postal code works.
Choose the Pay $1.00 button.