Card payment with Payment components
A complete card payment built with Payment components: the backend creates a Checkout Session, shift4.js mounts the card fields in the page's own checkout form, and the Pay button confirms the payment. It follows the flow described in Card payments.
The email and cardholder name are regular inputs on the page. The card number, expiry, and CVC are Shift4-hosted components that render in Shift4's own secure frames, so card data never reaches the page and Shift4 handles it along with the PCI scope.
This example runs in the sandbox. Pay with one of the test cards below; no real payment is made.
Test cards
- 4242 4242 4242 4242Payment succeeds
- 4024 0071 1846 8684Declined: insufficient funds
- 4012 0001 0000 0114Succeeds after frictionless 3D Secure
- 4012 0018 0000 0016Succeeds after a 3D Secure challenge
Use any future expiry date and any 3-digit CVC. More scenarios in Test cards.
How it works
- 1
Create a Checkout Session
Your backend creates a Checkout Session for the order and passes its
clientSecretto the page. The Access Token stays on the server; theclientSecretis the only value the browser needs. See Create a Checkout Session for all the options.# Run on your backend. SHIFT4_ACCESS_TOKEN is your Access Token - keep it on the server. curl -X POST https://api.shift4.com/api/rest/v1/checkoutsessions/create \ -H "AccessToken: $SHIFT4_ACCESS_TOKEN" \ -H "InterfaceVersion: 1.0" \ -H "InterfaceName: YourApp" \ -H "CompanyName: YourCompany" \ -H "Content-Type: application/json" \ -d '{ "checkoutSession": { "lineItems": [ { "product": { "name": "Potted plant", "currencyCode": "USD", "amount": { "total": 24.99 } } } ] } }' - 2
Mount the card fields and take the payment
On the page, load shift4.js, initialise it with your Platform Public Key, and open the Checkout Session with its
clientSecret. Each card field is a component mounted into an empty element of your own form. Your Pay button callscheckout.continue(), and the result of each attempt arrives as acheckout_session.succeededorpayment.failedevent.The public key and
clientSecretbelow are placeholders: use your own public key and theclientSecretreturned in step 1. See Card payments and Events & error handling.<script src="https://js.shift4.com/v1/shift4.js"></script> <form id="payment-form"> <input id="email" type="email" placeholder="Email" /> <div id="number"></div> <div id="expiry"></div> <div id="cvc"></div> <input id="cardholder" type="text" placeholder="Cardholder name" /> <button type="submit">Pay $24.99</button> </form> <script> (async function () { // Replace with your own values: // - your Platform Public Key (sandbox keys start with pk_sandbox_) // - the clientSecret your backend received in step 1 var shift4 = Shift4('pk_sandbox_XXXXXXXXXXXXXXXXXXXX'); var checkout = await shift4.createCheckout('{{clientSecret}}'); checkout.createComponent('number').mount('#number'); checkout.createComponent('expiry').mount('#expiry'); checkout.createComponent('cvc').mount('#cvc'); checkout.addEventListener('checkout_session.succeeded', function () { // show a confirmation, then confirm the Checkout Session on your backend }); checkout.addEventListener('payment.failed', function (event) { // show event.error.message to the customer }); document.getElementById('payment-form').addEventListener('submit', function (e) { e.preventDefault(); checkout.continue({ email: document.getElementById('email').value, billing: { name: document.getElementById('cardholder').value } }); }); })(); </script> - 3
Confirm the payment
When
checkout_session.succeededfires, show the customer a confirmation. The browser event is a convenience signal, not proof of payment. Before you fulfil the order, retrieve the Checkout Session on your backend and check that its status ispaid, or receive Checkout Session webhooks so you don't depend on the customer's browser. See Confirm the payment.# Run on your backend: retrieve the Checkout Session and check that its status is paid. curl https://api.shift4.com/api/rest/v1/checkoutsessions/retrieve \ -H "AccessToken: $SHIFT4_ACCESS_TOKEN" \ -H "InterfaceVersion: 1.0" \ -H "InterfaceName: YourApp" \ -H "CompanyName: YourCompany" \ -H "CheckoutSessionId: {{checkoutSessionId}}"