WooCommerce integration

Crypto checkout
on WordPress

Our WordPress plugin turns CPT Payment into an ordinary WooCommerce payment gateway. Shoppers pick "pay with crypto" at checkout, pay on our hosted page, and land back on your thank-you page with the order marked complete. Funds settle non-custodially straight to your own wallet.

You write no code. Setup is three things: create a store here, install the plugin, paste one key. The developer sections below (07 onward) are for when you want to change what happens after a payment. Building on something other than WordPress? Use the custom store guide instead.

On this page
01

Payment flow

How it works

The plugin does the API integration for you. This is what it's doing on your behalf.

plain
shopper picks "pay with crypto"
        │
        ▼
┌──────────────────┐   creates an order    ┌─────────────┐
│  WooCommerce      │ ────────────────────▶ │ CPT Payment  │
│  (the plugin)     │ ◀─── payment_url ──── │              │
└──────────────────┘                        └─────────────┘
        │                                          │
        │  redirects the shopper                   │ shopper pays
        ▼                                          │ in crypto
┌──────────────────┐                               │
│  hosted checkout  │ ◀─────────────────────────────┘
└──────────────────┘
        │
        │ back to your thank-you page (success_url)
        ▼
┌──────────────────┐   callback with the order    ┌─────────────┐
│  WooCommerce      │ ◀─── token + status ──────── │ CPT Payment  │
│  ?wc-api=…        │                              └─────────────┘
└──────────────────┘
        │
        ▼
order status moves: pending → on-hold → completed

The redirect is what the shopper sees. The callback is what actually moves the order, which is why it has to be reachable from the internet. If your site is behind a firewall or a "coming soon" plugin, orders will sit at pending forever even though the payment landed.

02

Dashboard setup

Create the store

One entry in the dashboard, which mints the key the plugin authenticates with.

  1. 1

    Open Plugins and pick WooCommerce

    Go to Plugins, select the WooCommerce card, then Add store.

  2. 2

    Name it and give us your site URL

    Nickname is for your own reference. Callback URL is your WordPress site root, e.g. https://yourstore.com.

  3. 3

    Copy the API key

    The store row shows an api_key. You paste it into WordPress in step 04.

FieldWhat to enterNotes
NicknameAnything you'll recogniseShown only in your dashboard.
Callback URLhttps://yourstore.comMust be HTTPS in production. HTTP is accepted only while the backend runs with DEBUG on.
api_keyGenerated for youThe plugin's API Auth Token. Server-side secret, never in a theme or JS file.
03

WordPress plugin

Install the plugin

Grab the zip, then pick whichever install route matches how you deploy WordPress.

WooCommerce plugin

CptPayment for WooCommerce

cptpayment-for-woocommerce-2.2.0.zip
  • Version 2.2.0
  • 68 KB
  • WordPress 5.8+
  • WooCommerce 6.0+
  • PHP 7.4+
Download

Ready to upload as-is. The PHP SDK it needs is bundled, so there is no composer install step and no build to run.

shell
# No terminal needed.
# 1. Download cptpayment-for-woocommerce.zip
# 2. WordPress admin -> Plugins -> Add New -> Upload Plugin
# 3. Choose the zip -> Install Now -> Activate
RequirementVersion
WordPress5.8 or newer
WooCommerce6.0 or newer, classic checkout or the Cart/Checkout blocks
PHP7.4 or newer
Plugin2.2.0 (bundles cptpayment/cptpayment-php ^4.1)
04

Gateway settings

Configure the gateway

WooCommerce→Settings→Payments→Cryptocurrencies via CptPayment.

SettingDefaultWhat it does
Enable CptPaymentoffTurn the gateway on. Nothing shows at checkout until you do.
API Auth TokenemptyPaste your api_key here. This is the one field you must fill in.
TitleCryptocurrencies via CptPaymentThe label the shopper sees in the payment method list.
DescriptionPay with BTC, LTC, ETH, TRX…Helper text under the label at checkout.
Crypto Payment Fee/Discount (%)0Adjusts the total for crypto orders. Negative values are a discount.
Pre-fill CptPayment invoice emailyesSends the billing email so the shopper gets payment-status mail.
Order status mappingsee section 06Which WooCommerce status each crypto status maps to.

If you rebuild staging from scratch often, the same settings are one option row:

shell
# Everything the settings screen writes, scriptable for staging rebuilds.
wp option patch update woocommerce_cptpayment_settings enabled yes
wp option patch update woocommerce_cptpayment_settings api_auth_token "$CPT_API_KEY"
wp option patch update woocommerce_cptpayment_settings title "Pay with crypto"
wp option patch update woocommerce_cptpayment_settings purchaser_email_status yes

wp option get woocommerce_cptpayment_settings --format=json | jq
05

Before launch

Test a checkout

Do this before you announce it. Most setup problems only show on a real order.

  1. 1

    Place a cheap real order

    Add a $1 product, check out, and pick the crypto method. You should be redirected to our hosted checkout with the right amount and your store name on it.

  2. 2

    Confirm the order exists on both sides

    The WooCommerce order should be pending, and the same order should appear under your store's Orders in the dashboard. If it's missing here, the API key is wrong.

  3. 3

    Pay it, and watch the status move

    Once the payment is seen the order goes on-hold, then completed when it confirms. If it stays pending after payment, the callback isn't reaching you: go to section 10.

  4. 4

    Let one expire

    Start a checkout and walk away. After the payment window closes the order should become cancelled and the stock should return.

06

Order states

Status mapping

How a crypto payment status becomes a WooCommerce order status.

Crypto statusWooCommerce statusWhy
paidcompletedConfirmed and settled. This is the one to fulfil on.
awaitingpendingCheckout opened, nobody has paid yet.
confirmingon-holdSeen on chain, waiting for confirmations. Temporary.
underpaidon-holdLess than the total arrived. Needs a human.
overpaidcompletedThey paid. Refund the surplus yourself.
expiredcancelledPayment window closed unpaid.
canceledcancelledShopper abandoned it.
refundedrefundedRefund settled.
invalidfailedSomething was wrong with the payment.

Every row is editable on the settings screen, and your saved choices are merged over these defaults, so callbacks map correctly even before you've ever pressed save. Section 09 shows how to change one in code.

07

Developer detail

How callbacks are trusted

Developer detail. This is where WooCommerce differs from the custom-store API.

We post the status change to https://yourstore.com/?wc-api=wc_gateway_cptpayment. The plugin has to prove the request is really from us before touching the order.

json
{
  "order_id": "1042",
  "status": "paid",
  "price_amount": 49.99,
  "price_currency": "USD",
  "callback_token": "a7f3c1e9d2b84f60a1c5e8d7b3f92a04",

  "event": "order.paid",
  "event_id": "evt_01J8W2Q5N3XK",
  "api_version": "2024-07-27"
}
WooCommerceCustom store
SecretPer-order token, issued at checkoutOne api_secret per store
Checkhash_equals against order metaHMAC-SHA256 over canonical JSON
Scope of a leakOne orderEvery webhook until you rotate
You implement itNo, the plugin doesYes
08

Development

Staging and local dev

The setting you'll want and won't find in the UI.

The bundled SDK defaults to https://api.cptpayment.com/plugins and the settings screen has no field to change it. Define a constant in wp-config.php instead:

wp-config.php
<?php

// Point the plugin at a non-production API. Undocumented in the settings UI:
// the bundled SDK reads this constant and otherwise defaults to
// https://api.cptpayment.com/plugins.
//
// This is the only way to test against staging without editing plugin files.
define('CPTPAYMENT_API_BASE', 'https://api-staging.cptpayment.com/plugins');

// While integrating, log the callbacks the plugin receives.
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
shell
cloudflared tunnel --url http://localhost:8080
# or: ngrok http 8080

# Then set BOTH:
#   - the store's Callback URL in the CPT dashboard  -> https://<tunnel-host>
#   - WordPress site + home URL                      -> https://<tunnel-host>
wp option update siteurl "https://<tunnel-host>"
wp option update home    "https://<tunnel-host>"

Updating siteurl matters: WooCommerce builds the success and cancel URLs from it, so leaving it as localhost sends the shopper somewhere they can't reach after paying.

09

Custom behaviour

Extend it in code

The gateway drives ordinary WooCommerce transitions, so your existing hooks work.

functions.php
<?php
// The settings screen exposes the CPT-status to WC-status mapping, and the
// saved values are merged OVER the defaults, so you only override what differs.
//
// Send confirming orders to processing instead of on-hold:
add_action('init', function () {
    $settings = get_option('woocommerce_cptpayment_settings', []);
    $settings['order_statuses'] = array_merge(
        $settings['order_statuses'] ?? [],
        ['confirming' => 'wc-processing']
    );
    update_option('woocommerce_cptpayment_settings', $settings);
});
10

Diagnose

Troubleshooting

shell
# Is the gateway registered and on?
wp option get woocommerce_cptpayment_settings --format=json | jq '{enabled, api_auth_token: (.api_auth_token | length)}'

# Did a callback ever arrive? The plugin logs failures via error_log().
tail -f wp-content/debug.log | grep -i cptpayment

# Which token did checkout store for an order?
wp post meta get 1042 _cptpayment_order_token

# Is the callback URL we'd hit actually reachable from outside?
curl -sS -o /dev/null -w '%{http_code}\n' \
  "https://yourstore.com/?wc-api=wc_gateway_cptpayment"
# 200 means WordPress answered. A 403/503 usually means a firewall,
# Cloudflare "Under Attack" mode, or a security plugin blocking POSTs.
SymptomCauseFix
No crypto option at checkoutGateway not enabled, or token emptyEnable it and paste the api_key. The gateway hides itself with no token.
Option missing only on block checkoutPlugin older than 2.0Update. Block support is registered separately from the classic gateway.
"Unable to start the CptPayment checkout"Order creation was rejectedWrong api_key, or the store was deleted in the dashboard. Check debug.log.
Order stuck at pending after a real paymentCallback never arrivedCurl the ?wc-api= URL from outside. Firewalls, Cloudflare bot-fight and security plugins block these POSTs.
Callback arrives, order doesn't moveToken mismatchdebug.log shows "callback token does not match". Usually the order was created against a different store or a different API base.
Paid orders land on-hold, never completedAmount guard rejected itThe order total exceeds the amount paid. Check for a fee or currency-conversion difference.
Everything works on live, nothing on stagingStaging points at production APISet CPTPAYMENT_API_BASE in wp-config.php, see section 08.
Site moved and orders brokeStale Callback URLUpdate the store's Callback URL in the dashboard to the new host.
11

Choosing the right path

When to use the API instead

The plugin is the right answer for almost every WooCommerce store. Almost.

You wantUse
Crypto at WooCommerce checkout, minimal workThis plugin
Shoppers to never leave your site during paymentCustom store, Mode B
A checkout that isn't WooCommerce at allCustom store
Payments from a headless WordPress front endCustom store, Mode B
Your own payment screen, but keep WooCommerce ordersCustom store, Mode B, plus your own order sync

The last row is real work and worth naming honestly: you'd be reimplementing the order bookkeeping this plugin already does. Take it on only if the redirect is genuinely unacceptable for your checkout.

Final operational checklist

  • Keep the api_key server-side. It belongs in WordPress options, never in a theme or JS file.
  • Serve your site over HTTPS. Callbacks to plain HTTP are rejected in production.
  • Fulfil on the order status, not on the shopper reaching your thank-you page.
  • Leave the amount guard alone. It's what stops an underpaid order completing.
  • Update the store's Callback URL whenever the site's domain changes.

Full HTTP contract, in six languages: the custom store guide.

Ready to start?

Open Plugins and connect a store.

Open CrypticaPay

Common questions

Integration and checkout questions.

Review store setup, payment confirmation, supported assets, and network requirements before launch.

Browse all common questions
How do I accept crypto payments on WooCommerce?+

Connect a crypto payment plugin, configure your receiving wallets and accepted assets, and test the checkout before launch. CrypticaPay’s WooCommerce integration links store payments to its non-custodial tracking system, with funds going directly to your wallets.

How do I accept Bitcoin payments?+

Add a supported Bitcoin receiving address or an xpub with its matching child address. Then enable Bitcoin in your chosen CrypticaPay payment flow and share the request with your customer. The customer pays your wallet directly, and the platform tracks the transaction.

How do I add crypto payments to a custom online store?+

Use a payment API to create a request for an order, display the payment instructions, and receive status updates. CrypticaPay’s Custom Store API handles payment tracking while your application manages order updates and fulfilment.

How do I accept Ethereum payments?+

Add an eligible ETH receiving address on the supported network and enable it in your payment setup. CrypticaPay presents the payment amount, address, and network instructions to the customer and tracks the incoming payment.

Can I integrate crypto payments using any programming language or stack?+

Yes, provided your application can make the required HTTPS requests and handle payment updates. CrypticaPay’s Custom Store API lets you build a payment flow suited to your store’s technology and checkout design.

How do I accept USDT payments?+

Select a supported USDT network, add a compatible receiving address, and enable USDT in your payment tool. Customers must send USDT on the network specified in the request. CrypticaPay tracks the payment while the tokens go directly to your wallet.