Build your checkout
Fully customize your checkout, handle 3D Secure and alternative payments with Universal Checkout and Checkout Components.

Our checkout libraries enable you to build a best-in-class checkout, offering alternative payment methods and securely capturing sensitive payment information. Primer offers two modes of integration, providing varying degrees of out-the-box functionality: Universal Checkout, and Checkout Components.
PCI considerations
Both libraries handle the secure collection of card data, which means you will only need to complete the SAQ (A) Self assessment (the lowest level of PCI compliance). Your server is never exposed to sensitive payment data.
Installation
The Primer Web SDK is available on npm: @primer-io/checkout-web.
123
yarn add @primer-io/checkout-webnpm install --save @primer-io/checkout-web
1
import Primer from '@primer-io/checkout-web'
Alternatively, you can add the Primer Web SDK to your HTML page:
12345
<!-- Use the latest development version when building your integration --><script src="https://assets.primer.io/primer-sdk-web/v1-latest/Primer.js"></script><!-- Use the minified version for your production environment --><script src="https://assets.primer.io/primer-sdk-web/v1-latest/Primer.min.js"></script>
- Vue 2.x: @primer-io/checkout-vue
- React: Coming soon...
Initializing the SDK
Generate, and fetch a client token from your server and initialize the Primer SDK.
1234567891011
// checkout.jswindow.addEventListener('load', onLoaded)async function onLoaded() {const primer = new Primer({credentials: {clientToken: '<YOUR_CLIENT_TOKEN>', // Your server generated client token},})}
Building your checkout page
The Universal Checkout is a managed checkout experience for all payment types, and handles 3D Secure.
To render the checkout, load the Primer SDK and specify a container element.
Checkout.css
in your page.123456789101112131415161718192021
<!DOCTYPE html><!-- checkout.html --><html><!-- This added styling and css is entirely optional --><head><style>#checkout-container {display: flex;flex-direction: column;padding: 12px 24px;}</style><link rel="stylesheet" href="https://assets.primer.io/primer-sdk-web/v1-latest/Checkout.css" /></head><body><div id="checkout-container"></div><script src="https://assets.primer.io/primer-sdk-web/v1-latest/Primer.js"></script><!-- Include your script to initialize the SDK and send data to Primer --><script src="static/checkout.js"></script></body></html>
Assign your container, and specify callbacks for payment method tokenization and error handling:
123456789101112131415161718192021222324252627282930
// checkout.jswindow.addEventListener('load', onLoaded)async function onLoaded() {const primer = new Primer({credentials: {clientToken: '<YOUR_CLIENT_TOKEN>', // Your server generated client token},})// Use `.checkout()` to initialize and render the UIawait primer.checkout({// specify the selector of the container elementcontainer: '#checkout-container',/*** When a payment method is chosen and the customer clicks 'Pay',* the payment method is tokenized and you'll receive a token in the* `onTokenizeSuccess` callback which you can send to your server* to authorize a transaction.*/onTokenizeSuccess(paymentMethod) {// Send the payment method token to your serverreturn fetch('<YOUR_SERVER_URL>', {method: 'post',headers: { 'Content-Type': 'application/json' },body: JSON.stringify(paymentMethod),})},
Adding alternative payment methods
Universal Checkout automatically displays your alternative payment methods.
For Apple Pay and Google Pay, you'll need to provide some additional information:Additional information | Description |
---|---|
countryCode | The alpha2 ISO 3166 country code that your company operates in. |
purchaseInfo | The currency and sale amount you want the alternative payment method to display. |
123456789101112131415161718192021
// checkout.jswindow.addEventListener('load', onLoaded)async function onLoaded() {await primer.checkout({// In addition to the other options above// Add your company's alpha2 ISO country codecountryCode: 'FR',// Add the total sale amount for the APM to displaypurchaseInfo: {totalAmount: {currency: 'EUR',value: 700,},},// Carry on with sending the token to your server for authorization.onTokenizeSuccess(paymentMethod) {
3D Secure
To enable 3D Secure provide threeDSecure
options in .checkout()
.
12345678910111213141516171819202122232425262728
// checkout.jsawait primer.checkout({// ... other options/*** Provide authentication information about your customer and the order.* For the best result, provide as much information as you can.* The options for 3DS are as follows:*/threeDSecure: {// All of the order properties are mandatory and should be provided.order: {orderId: 'my-order-id',email: 'john.doe@email.com',billingAddress: {firstName: 'John',lastName: 'Doe',addressLine1: '123 Fake St',city: 'Paris',countryCode: 'FR',postalCode: '123456',},amount: {currency: 'EUR',value: 1199,},},
Customization
You can override the styles provided in Checkout.css
for most elements. All class names follow BEM naming conventions. In order to style the inputs of the card form you must provide the card.css
option in .checkout()
.
The <input>
elements are assigned classes which describe the state: error
, valid
, active
, dirty
and touched
. When the customer attempts to submit their card details, the containing <form>
element is assigned a submitted
class.
12345678910111213141516
// checkout.jsawait primer.checkout({// ... other optionscard: {css: `input {font-family: 'Open Sans', sans-serif;}form.submitted input.error {color: #f44336;}`,},})
The checkout experience is split into scenes
, each with the css class PrimerCheckout__scene
.
When one scene transitions to the next, a series of modifier classes are added and removed which you can use to apply your own styles.
PrimerCheckout--enter
PrimerCheckout--entering
PrimerCheckout--entered
PrimerCheckout--exit
PrimerCheckout--exiting
PrimerCheckout--exited
In addition to the css classes, you can specify transitions
options in .checkout()
:
1234567891011121314151617181920212223242526
// checkout.jsawait primer.checkout({// ... other options// transitions describes the scene transitions in the Universal Checkouttransitions: {// You can specify the duration of an enter/exit transition in millisecondsduration: {enter: 200,exit: 200,},/*** You can subscribe to various points of the transition* for a scene using the following callback options.* Each callback receives the html element of the scene* as the first argument.*/onEnter(node) {},onEntering(node) {},onEntered(node) {},onExiting(node) {},onExited(node) {},onExit(node) {},},})
During a transition from scene A to scene B, the following sequence occurs:
enter
entering
andentered
are removed from scene Aexit
andexiting
are applied to scene A- There is a delay of
duration.exit
milliseconds exited
is applied to scene Aexit
exiting
andexited
are removed from scene Benter
andentering
are applied to scene B- There is a delay of
duration.enter
milliseconds entered
is applied to scene B
Building your custom checkout page
If you want want more control over your checkout page, Checkout Components enables you to securely build your checkout page from scratch.
To get started accepting card details you'll need to add elements for cardNumber
, expiryDate
and cvv
.
123456789101112131415161718192021222324252627282930313233343536373839
<!DOCTYPE html><!-- checkout.html --><html><head><!-- This added styling is entirely optional --><style>.form-container {padding: 20px;display: flex;flex-direction: column;}.form-input {height: 32px;background-color: white;border: 1px solid rgba(0, 0, 0, 0.05);border-radius: 4px;padding: 0px 5px;}.form-input + .form-input {margin-top: 15px;}</style></head><body><div class="form-container"><div class="form-input" id="number-input"></div><div class="form-input" id="date-input"></div><div class="form-input" id="cvv-input"></div></div><button id="pay-now-button">Pay Now</button><script src="https://assets.primer.io/primer-sdk-web/v1-latest/Primer.min.js"></script><!-- Include your script to initialize the SDK and send data to Primer --><script src="checkout.js"></script></body></html>
Render the card form as follows:
1234567891011121314151617181920
// checkout.jswindow.addEventListener('load', onLoaded)async function onLoaded() {// Create a client as described in the 'Initializing the SDK' sectionconst client = new Primer({credentials: { clientToken: '<YOUR_CLIENT_TOKEN>' }, // Your server generated client token})// Use `.render()` to initialize and render the componentsawait primer.render({// Card form optionscard: {/*** This is the selector of your button which submits the* card details for tokenization.*/submitButton: '#pay-now-button',
Alternatively, you can omit the submitButton
option and attach the event listener yourself.
123
button.addEventListener('click', () => {checkout.card.tokenize()})
Adding alternative payment methods
To add APMs such as Apple Pay, Google Pay and PayPal - add containers for your payment method buttons.
123
<div id="pay-with-apple-pay"></div><div id="pay-with-google-pay"></div><div id="pay-with-paypal"></div>
And now assign these containers in render()
.
12345678910111213141516171819202122232425
// checkout.jsprimer.render({// other options as described before// These APMs will require your company's country alpha2 country codecountryCode: 'FR',// You'll also need to tell them how much you're going to charge the customerpurchaseInfo: {totalAmount: {currency: 'EUR',value: 1995,},},// Now just add the selectors of your buttons to the options for each APMapplePay: { container: '#pay-with-apple-pay' },googlePay: { container: '#pay-with-google-pay' },paypal: { container: '#pay-with-paypal' },onTokenizeSuccess(paymentMethod) {// Send the payment method token to your server for authorization},})
When the customer completes the payment flow, a one-time use payment method token is returned just as with cards - through the onTokenizeSuccess
callback.
3D Secure
Add a container to display the 3DS challenge to your customers:
123456789101112
<!-- checkout.html --><style>#threeds-modal {position: absolute;width: 100%;height: 100%;background-color: white;display: none;}</style><div id="threeds-modal"></div>
Provide some authentication information about your customer and the order. For the best result, provide as much information as you can. The options for 3DS are as follows:
1234567891011121314151617181920
// checkout.jsconst threeDSecureOptions = {// All of the order properties are mandatory and should be provided.order: {orderId: 'my-order-id',email: 'john.doe@email.com',billingAddress: {firstName: 'John',lastName: 'Doe',addressLine1: '123 Fake St',city: 'Paris',countryCode: 'FR',postalCode: '123456',},amount: {currency: 'EUR',value: 1199,},},
Once the card has been tokenized, you can pass the payment method token to threeDSecure.verify
. If successful, a new token (containing the 3DS authentication data) will be returned which you should use to authorize the transaction:
12345678910111213141516171819202122232425
// checkout.jsawait primer.render({card: {submitButton: '#pay-now',fields: {cardNumber: { container: '#number-input' },cvv: { container: '#cvv-input' },expiryDate: { container: '#date-input' },},},onTokenizeSuccess: onCardTokenized,})async function onCardTokenized(paymentMethod) {const authorization = await primer.threeDSecure.verify({token: paymentMethod.token,container: '#threeds-modal',onChallengeStart: () => toggleModalVisible(true),onChallengeEnd: () => toggleModalVisible(false),order: threeDSecureOptions.order,additionalInfo: threeDSecureOptions.additionalInfo,})if (authorization.status === Primer.ThreeDSecureStatus.SUCCESS) {
API References are available on our npm packages:
- Vanilla JS SDK: @primer-io/checkout-web
- Vue 2.x: @primer-io/checkout-vue