Get started
Learn how to embed a form in your website or application to accept payments from your customers. We'll walk you through a payment flow using our Frames product, which collects card details through an iframe. The information is sent directly to us, so it never touches your server, and you remain PCI-compliant.
In this guide, we combine our Frames tokenization product with our core Unified Payments API. You can also take advantage of our end-to-end products, Hosted Payments Page and Payment Links, while retaining the same level of PCI compliance.
Frames payment flow
You embed the Frames payment form into your website or application.
Your customer enters payment details through the payment form.
We receive your customer's sensitive information and return a token representing those details. This process is called tokenization.
You use the token to make a payment request.
You present the payment request to the customer.
Before you start
Make sure you have an account with us. Once you've signed in, navigate to Developers > Keys and create your keys. You'll need a public key to use Frames, and a way to authenticate your payment request. We support OAuth 2.0 and secret keys as authentication mechanisms.
Step 1: Set up your project
The Frames payment flow requires both a client-side and a server-side.
- Client-side: Reference the Frames script and define where the payment form is displayed.
- Server-side: Securely send the payment request using your server.
Download project template (optional)
If you use this template, you must set up your own server.
1<!DOCTYPE html>2<html lang="en">3 <head>4 <meta charset="utf-8" />5 <meta name="viewport" content="width=device-width, initial-scale=1.0" />6 <title>Checkout Frames v2: Single Frame</title>7 <link rel="stylesheet" href="normalize.css" />8 <link rel="stylesheet" href="style.css" />9 </head>10
11 <body>12 <form13 id="payment-form"14 method="POST"15 action="https://merchant.com/charge-card"16 >17 <div class="one-liner">18 <div class="card-frame"></div>19 <button id="pay-button" disabled>PAY GBP 24.99</button>20 </div>21 <p class="error-message"></p>22 <p class="success-payment-message"></p>23 </form>24
25 <script src="https://cdn.checkout.com/js/framesv2.min.js"></script>26 <script src="app.js"></script>27 </body>28</html>
Step 2: Render Frames Client side
Add the script to your project in your index.html
file.
1<script src="https://cdn.checkout.com/js/framesv2.min.js"></script>
If you use server-side rendering (using your backend), using a framework like Next.js, you can add the script in the head
component.
1<head>2 <script src="https://cdn.checkout.com/js/framesv2.min.js"></script>3</head>
To remain PCI-compliant, payment details must be sent directly to us without interacting with your server. Always load framesv2.min.js
from cdn.checkout.com
. Do not host the script yourself.
Define the payment form
Add the code for your payment form in your html
file. The amount on the payment button has been hard coded for this example.
The Frames script looks for an empty div
tag to insert an iframe containing the payment form. If you do not include div
tags, the payment form will not be visible in your website or application.
1<form id="payment-form" method="POST" action="https://merchant.com/charge-card">2 <div class="one-liner">3 <div class="card-frame">4 <!-- Frames will be added here -->5 </div>6 <button id="pay-button" disabled>PAY GBP 24.99</button>7 </div>8 <p class="error-message"></p>9 <p class="success-payment-message"></p>10</form>
Initialize Frames
In your js
file, you need to initialize Frames using your public key. Without this, the iframe will not appear in your website or application.
In our example, we use the init
method on the Frames
object, which we accessed from the Frames script.
1Frames.init("pk_sbox_XXXX");
If the iframe is not rendering on your website or application:
- Check you are using public the sandbox key, pk_sbox, not just pk_.
- Some networks block our frames script - check the Network tab to make sure that resources are loaded.
Step 3: Generate token Client side
Now that Frames is loaded in your website or application, we can use it to tokenize card details.
Add logic to payment button
In your js
file, add the example code. This tells Frames to submit the card details and begin the tokenization process.
1var form = document.getElementById("payment-form");2
3form.addEventListener("submit", function (event) {4 event.preventDefault();5 Frames.submitCard();6});
Listen for card tokenization
Use the Frames.Events.CARD_TOKENIZED
event to listen for when details have successfully been tokenized. When this event is triggered, you can access the token value through event.token
.
The value returned is the token you need to use to request your payment, so make a note. Tokens begin with tok_
. For our example, you can simply copy the token that appears in the example iframe.
1Frames.addEventHandler(Frames.Events.CARD_TOKENIZED, (event) => {2 console.log(event.token);3});
Enter card details
Use these test card details using either the interactive iframe on this webpage, or on your local machine:
Card Number: | 4242424242424242 |
---|---|
Expiry Date: | Any date in the future |
CVV: | 100 |
If you are testing on your local machine, you will likely only be able to test with Visa, Mastercard and American Express card numbers. If you try and use a test card number for a different scheme, the tokenization will fail and the CARD_TOKENIZATION_FAILED
handler will be called.
When you select the pay button in this example iframe, we show you the token underneath the payment form. This is for demonstration purposes only and does not reflect what your customer will see.
Send the token to your server
You need to send the token to your server, so your server has access to it when you request the payment.
Send the token either with the form action when we submit our card details, or with a simple HTTPS post request.
Step 4: Request the payment Server side
We are now working in your server. Because you have a token that simply represents card details, you can handle it on your own server and remain PCI-compliant.
When payment details are tokenized, the token can only be used once and within 15 minutes. If you request a payment using an expired token, the payment will fail.
Send payment request
View our API Reference for authentication guidance, and a complete reference of optional and required fields.
https://api.sandbox.checkout.com/payments
In the source
object:
type
should have the valuetoken
.token
should have your stored token as the value.
1{2 "source": {3 "type": "token",4 "token": "tok_XXX"5 },6 "amount": 24.99,7 "currency": "USD",8 "processing_channel_id": "pc_XXX"9}
1<?php2
3require '../vendor/autoload.php';4
5use Checkout\CheckoutApiException;6use Checkout\CheckoutException;7use Checkout\CheckoutSdk;8use Checkout\Common\Currency;9use Checkout\Environment;10use Checkout\Payments\Request\PaymentRequest;11use Checkout\Payments\Request\Source\RequestTokenSource;12use Monolog\Handler\StreamHandler;13use Monolog\Logger;14
15$log = new Logger("checkout-sdk-php-sample");16$log->pushHandler(new StreamHandler("php://stdout"));17
18// Initialize Checkout API19try {20 $api = CheckoutSdk::builder()->staticKeys()21 ->environment(Environment::sandbox())22 ->secretKey(getenv("sk_sbox_XXX"))23 ->build();24} catch (CheckoutException $e) {25 $log->error("An exception occurred while initializing Checkout SDK : {$e->getMessage()}");26 http_response_code(400);27}28
29$postData = file_get_contents("php://input");30$request = json_decode($postData);31
32// The token generated by Frames on the client side33$requestTokenSource = new RequestTokenSource();34$requestTokenSource->token = $request->token;35
36$request = new PaymentRequest();37$request->source = $requestTokenSource;38$request->currency = Currency::$GBP;39$request->amount = 2499;40$request->processing_channel_id = "pc_XXX";41
42try {43 echo json_encode($api->getPaymentsClient()->requestPayment($request));44} catch (CheckoutApiException $e) {45 $log->error("An exception occurred while processing payment request");46 http_response_code(400);47}
Receive request response
That's it! You've just built your first payment flow with Checkout.com. Continue reading to find out more about different responses and next steps.
If you receive a 201 Success response with approved
set to true
, your request was successful.
1{2 "id": "pay_qzpz6fv4dv2etnarerhvqxsvlm",3 "action_id": "act_agaoqbtsccie5j2zd6jwdodpg4",4 "amount": 24.99,5 "currency": "USD",6 "approved": true,7 "status": "Authorized",8 "auth_code": "631973",9 "response_code": "10000",10 "response_summary": "Approved",11 "balances": {12 "total_authorized": 24.99,13 "total_voided": 0,14 "available_to_void": 24.99,15 "total_captured": 0,16 "available_to_capture": 24.99,17 "total_refunded": 0,18 "available_to_refund": 019 },20 "risk": {21 "flagged": false22 },23 "source": {24 "id": "src_usxsfdifd2pebamd734fwsihg4",25 "type": "card",26 "phone": {},27 "expiry_month": 1,28 "expiry_year": 2027,29 "scheme": "Visa",30 "last4": "4242",31 "fingerprint": "2FE6B057E42927009AA100493441AD7C8E88A82573FCAE69C02D8C919F017895",32 "bin": "424242",33 "card_type": "CREDIT",34 "card_category": "CONSUMER",35 "issuer_country": "GB",36 "product_id": "F",37 "product_type": "Visa Classic",38 "avs_check": "G",39 "cvv_check": "Y",40 "payment_account_reference": "V001763436387291028"41 },42 "processed_on": "2022-10-20T13:28:05.5201442Z",43 "scheme_id": "581305702984089",44 "processing": {45 "acquirer_transaction_id": "541740228271589217340",46 "retrieval_reference_number": "462197862661"47 },48 "expires_on": "2022-11-19T13:28:05.5201442Z",49 "_links": {50 "self": {51 "href": "https://api.sandbox.checkout.com/payments/pay_qzpz6fv4dv2etnarerhvqxsvlm"52 },53 "actions": {54 "href": "https://api.sandbox.checkout.com/payments/pay_qzpz6fv4dv2etnarerhvqxsvlm/actions"55 },56 "capture": {57 "href": "https://api.sandbox.checkout.com/payments/pay_qzpz6fv4dv2etnarerhvqxsvlm/captures"58 },59 "void": {60 "href": "https://api.sandbox.checkout.com/payments/pay_qzpz6fv4dv2etnarerhvqxsvlm/voids"61 }62 }63}
202 Payment asynchronous / further action required
If you requested 3D Secure to be used in the payment, or you have a risk rule that triggers 3D Secure, you will see a 202 response. This indicates that you need to redirect the customer to a page to authenticate the payment.
To check on the status of a pending payment, you can use our get payment details endpoint.
If you need to redirect your customer, there will be a _links.redirect.href
property in the response.
1{2 "redirect": {3 "href": "https://api.checkout.com/3ds/pay_mbabizu24mvu3mela5njyhpit4"4 }5}
422 Invalid data was sent
A 422 response means there has been a user error. This response could mean the token expired after 15 minutes, or it was used more than once. You can also review the error_codes
array to see what needs to be corrected.
1{2 "request_id": "b4ea9ea1-3af6-4b34-8c8e-74cc7e456654",3 "error_type": "processing_error",4 "error_codes": ["token_expired"]5}
Next steps
Set up webhooks to receive updates
Webhooks are automated messaging sent when something happens in the payment lifecycle.
Integrate additional payment methods
You can accept Visa, Mastercard and American Express payments straight away. To accept alternative payment methods, like PayPal and Apple Pay, you’ll need to set them up.
Use 3D Secure to authenticate your payments
Require your customers to complete an additional verification step with the card issuer when paying – you can do this with 3D Secure.
Store payment details for faster checkout
Store and reuse payment information, so your customers don’t have to enter payment details every time.