Start accepting payments with Primer in 3 simple steps:
- 1Create a client session
- 2Render a secure checkout with Universal Checkout
- 3Listen for notifications via webhooks when a payment is successfully processed
Start accepting payments with Primer in 3 simple steps:
Server-side requests are authenticated using an API key in the X-Api-Key
header.
You can create an API key by visiting your Dashboard.
Learn more about API authentication in our API Reference.
To get started, add the Primer Web SDK to your checkout page. In this example, we will add the SDK using our CDN.
If you prefer to use npm, add the package @primer-io/checkout-web
to your dependencies.
12345
# With Yarnyarn add @primer-io/checkout-web # With npmnpm i -s @primer-io/checkout-web
Learn more about the different ways to include the SDK in the Installation guide.
Prepare a container element for Universal Checkout.
On the client-side, listen to the onCheckoutComplete
callback to be notified when the payment has been successfully completed. Use it to show an order confirmation screen, or to fulfill the order.
A client session is the starting point for integrating payments at Primer. You can attach all the metadata associated with the order to the client session, and generate a clientToken, a temporary key used to initialize Universal Checkout.
The information you include in the client session is used in the Dashboard to conditionally route payments with Workflows, and activate payment methods and other features in Universal Checkout, so pass as much information as you can.
On your server, create a client session with POST/client-session
.
Make sure to pass at least the following data:
Field | Description |
---|---|
Your reference for the payment. Make sure to keep track of orderId - you will later receive updates to the payment via Webhooks. The payment will contain the orderId specified in the client session. | |
The three-letter currency code in ISO 4217 format. e.g. use USD for US dollars. | |
The details of the line items of the order. |
The body of a successful response contains a
Use the generated client token on the client-side to show Universal Checkout by calling Primer.showUniversalCheckout(clientToken, options)
.
Make sure to pass a selector to your container in the options.
This function returns a Promise
that is resolved when Universal Checkout has been properly rendered on the page, and is ready to be used.
When the user selects a payment method and enters their credentials, Universal Checkout will automatically create a payment with the
3DS is supported out of the box by Universal Checkout.
To improve 3DS success rates, it is recommended to pass the following elements in the Client Session:
Field | Description |
---|---|
The customer's email address | |
The customer's billing address |
Learn more about how to configure 3DS!
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://sdk.primer.io/web/v2.0.0/Checkout.css" /> <script src="https://sdk.primer.io/web/v2.0.0/Primer.min.js" crossorigin="anonymous"></script> </head> <body> <div id="checkout-container"></div> <!-- Include your script to initialize the SDK and send data to Primer --> <script src="/static/client.js"></script> </body></html>
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
// This example is built using expressconst path = require('path')const express = require('express')const fetch = require('node-fetch') const API_KEY = process.env.PRIMER_API_KEY // YOUR API KEYconst PRIMER_API_URL = 'https://api.sandbox.primer.io' const app = express() const staticDir = path.join(__dirname, 'static')const checkoutPage = path.join(__dirname, 'checkout.html') app.use(express.json())app.use('/static', express.static(staticDir)) app.get('/', (req, res) => { return res.sendFile(checkoutPage)}) app.post('/client-session', async (req, res) => { const url = `${PRIMER_API_URL}/client-session` const response = await fetch(url, { method: 'post', headers: { 'Content-Type': 'application/json', 'X-Api-Version': '2.1', 'X-Api-Key': API_KEY, }, body: JSON.stringify({ // Create an orderId for this client session // Make sure to keep track of it: you will later receive updates through Webhooks. orderId: 'order-' + Math.random(), // 3-character Currency Code used for all the amount of this session currencyCode: 'EUR', order: { // Line items for this session // If your checkout does not have line items: // > Pass a single line item with the total amount! lineItems: [ { itemId: 'shoes-123', description: 'Some nice shoes!', amount: 2500, // Amount should be in minor units! quantity: 1, }, ], }, }), }).then(data => data.json()) return res.send(response)}) app.post('/webhooks/payment-status', async (req, res) => { const { eventType, payment } = req.body const { id, orderId, status } = payment if (status === 'AUTHORIZED' || status === 'SETTLED') { // Fullfil the order for the Payment / Client Session labelled with `orderId` }}) app.listen(process.env.PORT)
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
// /static/client.js window.addEventListener('load', onLoaded) async function onLoaded() { const clientSession = await fetch('/client-session', { method: 'post', headers: { 'Content-Type': 'application/json' }, }).then(data => data.json()) const { clientToken } = clientSession try { const universalCheckout = await Primer.showUniversalCheckout(clientToken, { // Specify the selector of the container element container: '#checkout-container', /** * When the checkout flow has been completed, you'll receive * the successful payment via `onCheckoutComplete`. * Implement this callback to redirect the user to an order confirmation page and fulfill the order. */ onCheckoutComplete({ payment }) { console.log('Checkout Complete!', payment) }, // Other optional options style: { submitButton: { base: { color: '#ffffff', background: '#000000', borderRadius: '8px', boxShadow: 'none', }, disabled: { color: '#9b9b9b', background: '#e1deda', }, }, }, }) console.log('Universal Checkout is loaded!') } catch (e) { console.log('Universal Checkout failed to load!') }}