WordPress / WooCommerce

WordPress integration.

Three paths in. Drop the official plugin into WooCommerce, build a custom WC_Payment_Gateway on top of the SDK, or use the BlockPay PHP client on a non-WooCommerce site.

Option A

Official WooCommerce plugin

No code, ~5 minutes from download to a live USDC payment method.

The official plugin is a standard WooCommerce gateway. You download a zip, upload it through the WordPress admin, and configure four fields. The plugin handles invoice creation, webhook verification and order status transitions for you.

1. Download the plugin

Grab the latest blockpay.zip from /plugins/woocommerce. That page lists the current version and a changelog.

2. Upload via WP-admin

In your WordPress admin, go to Plugins → Add New → Upload Plugin, pick the zip, click Install Now, then Activate.

3. Configure four fields

Open WooCommerce → Settings → Payments → BlockPay and fill in the form. The four fields the plugin asks for:

API key

Your BlockPay secret key from dashboard.blockpay.dev → Developers. Stored in wp_options, never echoed back to the front-end.

Settlement wallet

The address that receives USDC. Any EVM-compatible address — a Safe, a hardware wallet or a hot wallet.

Settlement chain

Where you receive funds. Pick Arc for cheapest fees or Base for the largest USDC liquidity. Customers can still pay from any supported chain.

Webhook secret

The shared secret used to sign incoming webhooks. The plugin validates every event before it touches the order.

Option B

Custom WooCommerce gateway

Build your own gateway on top of blockpay/woocommerce when the stock plugin is not enough.

When you need bespoke behaviour — different display logic per product type, custom fees, a fork-of-WooCommerce flavour — install the SDK and subclass WC_Payment_Gateway yourself. The SDK ships the API client and a small helpers module that maps a WC_Order to the input shape createInvoice expects.

Install

bashbash
composer require blockpay/woocommerce

The gateway class

A minimum-viable gateway is about 25 lines. The SDK's WooHelpers::orderToInvoiceInput flattens line items, taxes and shipping into the BlockPay invoice schema so you do not have to.

class-wc-mycustom-blockpay.phpphp
<?php
// wp-content/plugins/my-shop/includes/class-wc-mycustom-blockpay.php
use BlockPay\WooCommerce\Client;
use BlockPay\WooCommerce\WooHelpers;
class WC_MyCustomBlockPay_Gateway extends WC_Payment_Gateway {
public function __construct() {
$this->id = 'mycustom_blockpay';
$this->method_title = 'Pay with USDC (custom)';
$this->has_fields = false;
$this->supports = ['products', 'refunds'];
$this->init_form_fields();
$this->init_settings();
}
public function process_payment($order_id) {
$order = wc_get_order($order_id);
$bp = new Client(get_option('blockpay_api_key'));
$invoice = $bp->createInvoice(
WooHelpers::orderToInvoiceInput($order)
);
$order->update_status(
'pending',
__('Awaiting BlockPay settlement.', 'my-shop')
);
return [
'result' => 'success',
'redirect' => $invoice->checkoutUrl,
];
}
}

Webhook handler

Register a single REST route to receive every BlockPay event and dispatch from there. The SDK's Webhooks::verify uses constant-time HMAC comparison.

blockpay-webhooks.phpphp
<?php
// wp-content/plugins/my-shop/includes/blockpay-webhooks.php
use BlockPay\WooCommerce\Webhooks;
add_action('rest_api_init', function () {
register_rest_route('my-shop/v1', '/blockpay-webhook', [
'methods' => 'POST',
'permission_callback' => '__return_true',
'callback' => 'my_shop_handle_blockpay_event',
]);
});
function my_shop_handle_blockpay_event(WP_REST_Request $req) {
$raw = $req->get_body();
$signature = $req->get_header('x_blockpay_signature') ?? '';
$verified = Webhooks::verify([
'raw_body' => $raw,
'signature' => $signature,
'secret' => get_option('blockpay_webhook_secret'),
]);
if (!$verified) {
return new WP_REST_Response('bad signature', 401);
}
$event = json_decode($raw, true);
if ($event['type'] === 'invoice.paid') {
$order_id = $event['data']['metadata']['order_id'] ?? null;
if ($order_id) {
$order = wc_get_order((int) $order_id);
$order->payment_complete($event['data']['txHash']);
}
}
return new WP_REST_Response('ok', 200);
}
Option C

Standalone WordPress

WooCommerce not in the picture? Use the PHP client directly.

Plenty of WordPress sites do not run WooCommerce — a donation form, a paywall on a Substack-style blog, a membership site on a different framework. The SDK's Client talks to the BlockPay API directly without any of the WooCommerce surface.

Install

bashbash
composer require blockpay/woocommerce

A donation shortcode

The snippet below registers a [blockpay_donate amount="25"] shortcode that mints an invoice on render and outputs an anchor to the hosted checkout. Drop it in any post, page or widget.

blockpay-donate.phpphp
<?php
// Standalone use on a non-WooCommerce site:
// a [blockpay_donate amount="25"] shortcode that
// produces a checkout link without touching WC.
use BlockPay\WooCommerce\Client;
add_shortcode('blockpay_donate', function ($atts) {
$atts = shortcode_atts(['amount' => '10'], $atts);
$bp = new Client(get_option('blockpay_api_key'));
$invoice = $bp->createInvoice([
'amount' => (string) $atts['amount'],
'currency' => 'USDC',
'chainKey' => 'arc-testnet',
'merchantAddress' => get_option('blockpay_settlement_wallet'),
'description' => 'Donation to ' . get_bloginfo('name'),
]);
return sprintf(
'<a class="blockpay-donate-btn" href="%s">Donate %s USDC</a>',
esc_url($invoice->checkoutUrl),
esc_html($atts['amount'])
);
});
Reference

Webhook events

Every event BlockPay can send to your WordPress integration.

Each event arrives as a JSON POST with an X-BlockPay-Signature header. If you are not using the SDK, this is the manual verification pattern:

verify.phpphp
<?php
// Manual signature verification, no SDK required.
$raw = file_get_contents('php://input');
$sig = $_SERVER['HTTP_X_BLOCKPAY_SIGNATURE'] ?? '';
$secret = get_option('blockpay_webhook_secret');
$expected = hash_hmac('sha256', $raw, $secret);
if (!hash_equals($expected, $sig)) {
http_response_code(401);
exit('bad signature');
}
$event = json_decode($raw, true);
// dispatch on $event['type']
invoice.createdPOST JSON

Fires the moment an invoice is generated for a WooCommerce order. Use the metadata.order_id to wire the BlockPay invoice id back onto the WC order.

payloadjson
{
"type": "invoice.created",
"data": {
"invoiceId": "inv_01HE2...",
"amount": "49.00",
"currency": "USDC",
"chainKey": "arc-testnet",
"checkoutUrl": "https://blockpay.dev/pay/inv_01HE2...",
"metadata": { "order_id": "1042" }
}
}
invoice.paidPOST JSON

Fires once the full invoice amount has settled on-chain. Wire it to $order->payment_complete($txHash) to flip the WooCommerce order to processing.

payloadjson
{
"type": "invoice.paid",
"data": {
"invoiceId": "inv_01HE2...",
"amount": "49.00",
"currency": "USDC",
"chainKey": "arc-testnet",
"txHash": "0x9b1c...e3f0",
"settledAt": 1715817600,
"metadata": { "order_id": "1042" }
}
}
payment.receivedPOST JSON

Fires for each on-chain transfer attributed to the invoice. Useful for short-pay handling — a single invoice can fire many of these.

payloadjson
{
"type": "payment.received",
"data": {
"invoiceId": "inv_01HE2...",
"amount": "49.00",
"currency": "USDC",
"chainKey": "arc-testnet",
"fromAddress": "0xCustomerWallet",
"txHash": "0x9b1c...e3f0",
"confirmations": 1
}
}
invoice.expiredPOST JSON

Fires when an invoice passes its TTL without settlement. Cancel the WC order or mark the payment attempt failed.

payloadjson
{
"type": "invoice.expired",
"data": {
"invoiceId": "inv_01HE2...",
"expiredAt": 1715819400,
"reason": "ttl"
}
}
webhook.testPOST JSON

Sent from the BlockPay dashboard when you click Send test event. Use it to confirm the endpoint and signature secret before you trust live events.

payloadjson
{
"type": "webhook.test",
"data": {
"deliveredAt": 1715820000,
"endpoint": "https://example.com/wp-json/my-shop/v1/blockpay-webhook"
}
}