Pay
Checkout Plugin

Accepting Payments via the Checkout Plugin

Learn when and how to integrate an embedded payment checkout form using the Checkout Plugin


The Checkout Plugin provides a secure, PCI-compliant payment form that can be embedded directly into your application. It handles payment collection, customer enrollment, and Autopay setup while keeping sensitive payment data out of your application scope.

Prerequisites

Before integrating the Checkout Plugin, it's helpful to learn about the following topics.


When to Use the Checkout Plugin


Use the Checkout Plugin when you need an embedded payment form inside your application that handles sensitive payment data in a PCI-compliant manner. The plugin provides a turnkey solution for payment acceptance without requiring you to build and maintain your own payment forms or handle card/bank account details directly.

Common use cases

  • Invoice Payments: Allow customers to pay invoices directly from your application with an embedded checkout form.
  • One-Time Purchases: Accept payments for products or services with a simple, secure checkout experience.
  • Donation Forms: Accept variable amounts with an editable amount field, ideal for fundraising and tip jars.
  • Custom Payment Flows: Embed checkout at specific points in your application flow rather than redirecting to external pages.

Usage


There are two steps to using the Checkout Plugin: creating an intent on your backend and rendering the plugin on the frontend.

The examples below show both steps in two different form factors.

import payload
pl = payload.Session('secret_key_3bW9...', api_version='v2')
 
from flask import Flask, jsonify
 
app = Flask(__name__)
 
@app.route('/create-checkout-intent', methods=['POST'])
def create_checkout_intent():
    # Create a checkout intent token on your backend server
    intent = pl.Intent.create(
        type='checkout_plugin',
        checkout_plugin={
            'payment_template': {
                'amount': 100.00,
                'description': 'Order #12345',
                'receiver': {
                    'account_id': 'acct_receiver123'
                }
            }
        }
    )
 
    # Send the token to your frontend
    return jsonify({'token': intent.token})
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Checkout Button - Vanilla JS</title>
  <script src="https://payload.com/Payload.js"></script>
</head>
<body>
  <button id="checkout-btn" disabled>Pay Now</button>
 
  <script src="modal.js"></script>
</body>
</html>
const btn = document.getElementById('checkout-btn');
 
// Fetch token and enable button
fetch('/checkout_intent')
  .then(r => r.json())
  .then(data => {
    btn.disabled = false;
    btn.onclick = () => {
      Payload(data.token);
      new Payload.Checkout()
        .on('success', evt => {
          console.log('Payment successful!', evt.transaction_id);
          window.location.href = `/payment/success?txn=${evt.transaction_id}`;
        })
        .on('declined', evt => {
          console.error('Payment declined:', evt.transaction_id);
          alert(`Payment declined: ${evt.transaction_id}`);
        })
        .on('closed', () => {
          console.log('Customer closed checkout');
        });
    };
  })
  .catch(err => console.error('Failed to load checkout token:', err));

This example shows the steps to setting up the plugin as a modal overlay and capturing the payment result.

  1. Create intent token with type='checkout_plugin' and configure checkout options on the backend
  2. Use the token to launch the CheckoutPlugin on the frontend
  3. Use the onSuccess(evt) listener to capture the transaction ID when payment completes
  4. Use onClose() to handle when the customer closes the checkout without completing payment

This pattern provides a focused checkout experience that overlays your application, guiding the customer through payment without navigation away from the current page.

import payload
pl = payload.Session('secret_key_3bW9...', api_version='v2')
 
from flask import Flask, jsonify
 
app = Flask(__name__)
 
@app.route('/create-checkout-intent', methods=['POST'])
def create_checkout_intent():
    # Create a checkout intent token on your backend server
    intent = pl.Intent.create(
        type='checkout_plugin',
        checkout_plugin={
            'payment_template': {
                'amount': 100.00,
                'description': 'Order #12345',
                'receiver': {
                    'account_id': 'acct_receiver123'
                }
            }
        }
    )
 
    # Send the token to your frontend
    return jsonify({'token': intent.token})
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Checkout Form - Vanilla JS</title>
  <script src="https://payload.com/Payload.js"></script>
</head>
<body>
  <h3>Complete Your Purchase</h3>
  <div id="checkout-container">Loading...</div>
  <div id="success-message" style="display:none;">
    <h2>Payment Successful!</h2>
    <p id="transaction-id"></p>
  </div>
 
  <script src="inline.js"></script>
</body>
</html>
// Fetch token and mount inline form
fetch('/checkout_intent')
  .then(r => r.json())
  .then(data => {
    Payload(data.token);
    new Payload.Checkout({
      inline: true,
      container: document.getElementById('checkout-container')
    })
      .on('success', evt => {
        console.log('Payment successful!', evt.transaction_id);
        document.getElementById('checkout-container').style.display = 'none';
        document.getElementById('success-message').style.display = 'block';
        document.getElementById('transaction-id').textContent =
          `Transaction ID: ${evt.transaction_id}`;
      })
      .on('declined', evt => {
        console.error('Payment declined:', evt.transaction_id);
        alert(`Payment declined: ${evt.transaction_id}`);
      });
  })
  .catch(err => {
    console.error('Failed to load checkout token:', err);
    document.getElementById('checkout-container').textContent = 'Failed to load checkout form';
  });

This example shows the steps to setting up the plugin as an inline form embedded directly in your page.

  1. Create intent token with type='checkout_plugin' and configure checkout options on the backend
  2. Use the token to mount the inline form using inline: true and specify a container element
  3. Use the onSuccess(evt) listener to capture the transaction ID when payment completes

This pattern embeds the checkout form directly into your page layout, providing a seamless experience where the checkout is part of your application's natural flow rather than an overlay.

Configuring Checkout Options


The Checkout Plugin provides extensive configuration options to control payment methods, fees, billing fields, and UI behavior.

Payment Methods

Control which payment types are available to customers during checkout using the allowed_methods configuration:

import payload
pl = payload.Session('secret_key_3bW9...', api_version='v2')
 
# Configure allowed payment methods
intent = pl.Intent.create(
    type='checkout_plugin',
    checkout_plugin={
        'checkout_options': {
            'allowed_methods': {
                'card': 'enabled',
                'bank_account': 'disabled',
                'apple_pay': 'enabled',
                'google_pay': 'enabled'
            }
        },
        'payment_template': {
            'amount': 100.00,
            'description': 'Order #12345',
            'receiver': {
                'account_id': 'acct_receiver123'
            }
        }
    }
)
 
token = intent.token

This configuration:

  • Enables card payments (Visa, Mastercard, American Express, Discover)
  • Disables bank account payments
  • Enables Apple Pay for customers on Apple devices
  • Enables Google Pay for customers on Android devices

Convenience Fees

Add a convenience fee to offset payment processing costs:

import payload
pl = payload.Session('secret_key_3bW9...', api_version='v2')
 
# Add a 3% convenience fee
intent = pl.Intent.create(
    type='checkout_plugin',
    checkout_plugin={
        'checkout_options': {
            'enable_sender_fee': 'enabled'
        },
        'payment_template': {
            'amount': 100.00,
            'description': 'Order #12345',
            'receiver': {
                'account_id': 'acct_receiver123'
            }
        }
    }
)
 
token = intent.token

This example adds a 3% convenience fee to the total payment amount. The fee is calculated and displayed to the customer before they complete the payment.

Editable Amount

Allow customers to change the payment amount, useful for donations or tip jars:

import payload
pl = payload.Session('secret_key_3bW9...', api_version='v2')
 
# Allow customers to change the payment amount
intent = pl.Intent.create(
    type='checkout_plugin',
    checkout_plugin={
        'checkout_options': {
            'allow_editable_amount': True
        },
        'payment_template': {
            'amount': 50.00,
            'description': 'Donation',
            'receiver': {
                'account_id': 'acct_receiver123'
            }
        }
    }
)
 
token = intent.token

This configuration:

  • Displays the initial amount as $50
  • Allows customers to change the amount to any value they choose
  • Useful for donation forms, tips, or customer-determined payments

Autopay Enrollment

Enable the Autopay toggle to let customers enroll in automatic billing:

import payload
pl = payload.Session('secret_key_3bW9...', api_version='v2')
 
# Enable Autopay enrollment with toggle defaulted to on
intent = pl.Intent.create(
    type='checkout_plugin',
    checkout_plugin={
        'checkout_options': {
            'show_autopay_toggle': True
        },
        'payment_template': {
            'amount': 100.00,
            'description': 'Order #12345',
            'receiver': {
                'account_id': 'acct_receiver123'
            },
            'sender': {
                'account_id': 'acct_customer456',
                'method': {
                    'account_defaults': {
                        'paying': 'payments'
                    }
                }
            }
        }
    }
)
 
token = intent.token

This configuration:

  • Shows an Autopay enrollment checkbox in the checkout form
  • Sets Autopay to enabled by default (customers can opt out)
  • Automatically saves the payment method and links it to the customer account
  • Sets the payment method as the default for future automatic payments

Billing Address Requirements

Control which billing address fields are required during checkout:

import payload
pl = payload.Session('secret_key_3bW9...', api_version='v2')
 
# Require full billing address
intent = pl.Intent.create(
    type='checkout_plugin',
    checkout_plugin={
        'checkout_options': {
            'require_full_billing_address': True
        },
        'payment_template': {
            'amount': 100.00,
            'description': 'Order #12345',
            'receiver': {
                'account_id': 'acct_receiver123'
            }
        }
    }
)
 
token = intent.token

This configuration:

  • Requires postal code for address verification
  • Optionally collects full address (street, city, state)
  • Use required_fields to specify exactly which fields must be completed

Checkout for Existing Customers


If you already have a customer account, pass the account_id to pre-populate customer information and link the payment:

import payload
pl = payload.Session('secret_key_3bW9...', api_version='v2')
 
# Checkout for existing customer account
intent = pl.Intent.create(
    type='checkout_plugin',
    checkout_plugin={
        'payment_template': {
            'amount': 100.00,
            'description': 'Order #12345',
            'receiver': {
                'account_id': 'acct_receiver123'
            },
            'sender': {
                'account_id': 'acct_customer456'
            }
        }
    }
)
 
token = intent.token

This configuration:

  • Links the payment to the existing customer account
  • Automatically associates saved payment methods with the account
  • Enables faster checkout for returning customers
  • Allows the customer to use saved payment methods

Handling Checkout Results


The Checkout Plugin provides event listeners to track the checkout lifecycle and handle results.

Success Event

When a payment completes successfully, the onSuccess event fires with the transaction details:

checkout.on('success', (evt) => {
  console.log('Payment successful!')
  console.log('Transaction ID:', evt.transaction_id)
 
  // Redirect to success page or show confirmation
  window.location.href = `/payment/success?txn=${evt.transaction_id}`
})

Error Event

If the payment fails or encounters an error, the onError event fires:

checkout.on('error', (evt) => {
  console.error('Payment failed:', evt.message)
 
  // Show error message to customer
  alert(`Payment failed: ${evt.message}`)
 
  // Optionally retry or redirect
})

Close Event

When the customer closes the checkout without completing payment:

checkout.on('closed', (evt) => {
  console.log('Customer closed checkout')
 
  // Return to cart or previous page
  window.location.href = '/cart'
})

Schema Reference


The following fields are available when configuring the Checkout Plugin intent. For complete API reference documentation, see Intent API Reference.

Intent Configuration

Configuration options passed when creating the checkout intent on your backend:

checkout_plugin
object
Configuration for the checkout plugin intent. Use this type to embed a payment checkout form directly in your application using the Payload JavaScript SDK. The checkout plugin renders an overlayed or inline payment form that customers can use to complete their purchase. Returns a token that can be used with the SDK to render the checkout UI. Required when type is checkout_plugin.
checkout_options
object
Checkout form configuration including which payment methods are allowed, convenience fees, address requirements, and UI options like autopay toggles or amount editability. Controls the behavior and appearance of the checkout form.
allow_editable_amount
boolean
When set to true, allows the customer to change the payment amount in the checkout form. Useful for donation forms, tip jars, or scenarios where the customer determines the amount. When false, the amount is fixed and cannot be modified by the customer.
allowed_methods
object
Configuration for which payment methods are available in the checkout. Controls whether customers can pay with cards, bank accounts, digital wallets (Apple Pay, Google Pay), or Plaid. Use this to restrict or enable specific payment options based on your business needs.
apple_pay
enum[string]
Controls whether Apple Pay digital wallet is available in the checkout. Set to "enabled" to allow Apple Pay payments or "disabled" to hide this payment option. Apple Pay provides a fast, secure checkout experience for customers on Apple devices.
Values: enabled, disabled
bank_account
enum[string]
Controls whether bank account payments are allowed in the checkout. Possible values: "default" (use processing account settings), "enabled" (allow bank account payments), or "disabled" (disallow bank account payments). When enabled, customers can pay by bank with their bank account.
Values: default, enabled, disabled
card
enum[string]
Controls which card payments are allowed in the checkout. Possible values: "default" (use processing account settings), "enabled" (allow all card types), "disabled" (disallow card payments), "credit" (only credit cards), or "debit" (only debit cards). When enabled, customers can pay with their payment cards.
Values: default, enabled, disabled, credit, debit
google_pay
enum[string]
Controls whether Google Pay digital wallet is available in the checkout. Set to "enabled" to allow Google Pay payments or "disabled" to hide this payment option. Google Pay provides a fast, secure checkout experience for customers on supported devices.
Values: enabled, disabled
plaid
enum[string]
Controls whether Plaid instant bank account verification is available in the checkout. Set to "enabled" to allow customers to connect their bank accounts via Plaid or "disabled" to use Payload's built-in verification methods.
Values: enabled, disabled
enable_sender_fee
enum[string]
Controls whether a convenience fee is charged to the payer. Possible values: "default" (use processing account settings), "enabled" (charge fee for all payment methods), "disabled" (no convenience fee), "card" (charge fee only for card payments), or "bank_account" (charge fee only for bank account payments). Convenience fees help offset processing costs by passing them to the payer.
Values: default, enabled, disabled, card, bank_account
require_full_billing_address
boolean
When set to true, requires the customer to provide their complete billing address (street, city, state, postal code, country) during checkout. When false, only postal code and country may be required. Full addresses improve fraud prevention and address verification (AVS) but increase checkout friction.
show_autopay_toggle
boolean
When set to true, adds a checkbox allowing the customer to set the payment method as their default for automatic billing. Useful for subscription and recurring billing scenarios where future payments should be charged automatically. The customer opts in by checking the box.
show_disclosure
boolean
When set to true, displays terms, conditions, and disclosure information in the checkout form. Use this to show important legal text, refund policies, or transaction terms that customers should be aware of before completing payment. Helps with compliance and transparency.
show_keep_active_toggle
boolean
When set to true, adds a checkbox allowing the customer to save the payment method for future use. When checked, the payment method will be stored securely and can be used for subsequent payments without re-entering details. Improves convenience for returning customers.
show_payment_method_preview
boolean
When set to true, displays a graphical preview of the payment method (card image, bank icon) above the checkout form. Provides visual confirmation of the payment method being used, improving user experience and reducing errors.
payment_template
object
Payment details and configuration including amount, receiver, sender, invoice allocations, and transaction settings. Defines what payment is being collected and from/to whom.
amount
number (double)
The payment amount to charge. This is the total amount that will be charged to the customer, before any convenience fees if enabled.
attrs
object
Custom attributes for the transaction as a JSON object. Use this to store additional metadata or custom fields specific to your application. These attributes are stored with the transaction and can be retrieved later for reporting or integration purposes.
clearing_timing
enum[string]Immutable
The clearing speed for this transaction, determining how quickly funds are made available to the recipient. Instant clearing makes funds available immediately, same_day within the same business day, and next_day by the following business day. Defaults to next_day if not specified. Same-day and instant are only available in certain circumstances.
Values: instant, same_day, next_day
description
string
Description of what the payment is for. This appears on receipts, transaction records, and bank statements. Examples include "Order #1234", "Monthly subscription", or "Invoice payment". Helps customers identify the transaction.
funding_timing
enum[string]Immutable
The funding speed for this transaction, determining how quickly the merchant or processing account receives settlement of funds. Standard timing follows normal settlement schedules, while rapid timing accelerates the funding process for faster access to funds. Defaults to standard if not specified. Rapid and instant funding only available in certain circumstances.
Values: standard, instant, rapid
invoice_allocations
array
List of invoices that this payment should be applied to. When provided, the payment will be allocated across these invoices, reducing their outstanding balances. Use this for paying multiple invoices with a single payment or specifying which invoice a payment is for.
order_number
string
Custom order or transaction number for this payment. Use this to link the payment to an order in your system or to provide a customer-facing transaction reference. Providing this value ensures duplicate protection is applied per order; otherwise, duplicate protection applies across payments without an order reference.
receiver
object
Information about who will receive the payment and optionally the specific payment method for receiving funds. The receiver is the party being paid.
account_id
string
The unique identifier of the account that will receive this payment. This may represent a merchant, service provider, vendor, or other authorized recipient of funds. Required to identify who is receiving the funds.
method_id
string
The unique identifier of the payment method where funds will be deposited. If not specified, the receiver account's default method will be used.
sender
object
Information about who is making the payment. Includes the account and optionally pre-filled payment method details. The sender is the party being charged.
account_id
string
The unique identifier of the account making the payment. This is the payer who will be charged or the party who will fund the transfer. Used to associate the payment with the correct account.
method
object
Pre-filled values for the payment method that will be created or used for this payment. Allows you to set defaults like billing address, account holder name, or transfer type. These values populate the checkout form or are used when creating the payment method.
account_defaults
object
Default transaction types that this payment method will be used for. Controls whether the payment method is the default for paying or funding transactions, and which specific types of transactions it applies to.
funding
enum[string]
Controls which funding transaction types this payment method can be used for. Possible values: "all" (use for all funding transactions), "deposits" (use only for receiving deposits), or "withdraws" (use only for withdrawals). Determines the default usage for receiving funds.
Values: all, deposits, withdraws
paying
enum[string]
Controls which paying transaction type this payment method will be the default for. Possible values: "all" (use for all paying transactions), "payments" (use only for sending payments), or "payouts" (use only for receiving payouts). Determines the default usage for sending funds. If the account default is set for payments, that payment method will be used for any automatic invoice payments.
Values: all, payments, payouts
account_holder
string
Pre-filled name of the account holder for the payment method. For bank accounts, this is the name on the account. For cards, this is the cardholder name. When provided, this value will be used to populate the form.
account_id
string
The ID of the account that will own this payment method. Links the payment method to a specific customer or processing account. Used to associate the payment method with the correct account when it is created.
bank_account
object
Configuration specific to bank account payment methods. Contains bank account-specific settings such as the currency.
currency
enum[string]
The currency for bank account transactions. Must be either "USD" (US Dollars) or "CAD" (Canadian Dollars). Determines the currency for transactions using this bank account.
Values: USD, CAD
billing_address
object
Pre-filled billing address for the payment method. When provided, these values will be used to populate the address fields in the checkout form. Customers may be able to edit these values depending on checkout configuration.
address_line_1
string
Street address of the address
address_line_2
string
Unit number of the address
city
string
City of the company
country_code
string
Country code of the address
postal_code
string
Postal code of the address
state_province
string
State of the address
id
string
The unique identifier of an existing payment method to update. When provided, the form will be used to update the payment method, such as revalidating the CVV, updating the expiration date, or changing the billing address.
transfer_type
enum[string]
The transfer capabilities for this payment method. Possible values: "send_only" (can only send payments/fund payouts), "receive_only" (can only receive payouts/deposits), or "two_way" (can both send and receive). Controls how the payment method can be used for transactions.
Values: send_only, receive_only, two_way
source
enum[string]Immutable
The method by which this transaction was initiated or captured. This indicates whether the transaction was manually keyed, initiated via digital wallets like Google Pay or Apple Pay, or processed as a check conversion.
Values: keyed, googlepay, applepay, check
status
object
Target status configuration for the payment transaction. Controls whether the payment should be authorized only or immediately processed and captured.
value
enum[string]
The desired final status for the transaction. Possible values: "authorized" (authorize the payment but do not capture funds yet, useful for delayed capture), or "processed" (immediately process and capture the payment). Determines whether the payment is captured immediately or held for later capture.
Values: authorized, processed
transfers
array
List of transfer allocations for splitting a payment across multiple receivers. Each transfer specifies a receiver and an amount, allowing a single payment to be distributed to multiple accounts. Useful for marketplace or platform payments where funds need to be split between multiple parties.

Next Steps

Enhance your checkout implementation


Create Customer Accounts

Create customer accounts to enable saved payment methods and faster checkout.

Handle Refunds

Process refunds and voids for cancellations and returns after payments complete.

Monitor Payment Events

Subscribe to webhook notifications to track payment status and automate order fulfillment.


Related articles