How to accept Bitcoin payments on WooCommerce in 2026 · Geat.io Blog
← Back to blog
WooCommerce

How to accept Bitcoin payments on WooCommerce in 2026

June 12, 2026·8 min read

Accepting Bitcoin payments on a WooCommerce store is no longer a project — it's a plugin install. The hard parts (address generation, on-chain monitoring, signature verification, refund flows) belong in the payment processor; your store should only hold the customer relationship and the order record.

This guide walks the entire flow end to end: what happens at checkout, where the money goes, how WooCommerce learns the order is paid, and the four mistakes new merchants make when they DIY any of these steps.

The five-minute install

Every reputable Bitcoin payment gateway for WooCommerce ships a plugin. Download the ZIP from the gateway dashboard, upload it under WordPress → Plugins → Add New → Upload, activate, and configure under WooCommerce → Settings → Payments. You will paste three to four secrets: an API key, a profile UUID, a webhook secret, and (optionally) a base URL.

After that, "Pay with crypto" appears as a payment method on the WooCommerce checkout. Customer-side, picking it triggers a redirect to the gateway's hosted checkout page, which mints a fresh Bitcoin address for that specific invoice.

What happens after the customer pays

The customer sends Bitcoin to the address shown on the hosted checkout page. The gateway monitors the Bitcoin network, detects the incoming transaction, waits for the configured number of confirmations (typically 3-6 for Bitcoin), and only then fires a webhook callback to your WooCommerce server.

The callback is an HTTP POST with a JSON body, an X-Signature header (HMAC-SHA256 over the raw body and a timestamp), and an X-Timestamp header. Your WooCommerce plugin verifies the signature, looks up the matching order via the invoice ID, and calls WC_Order::payment_complete() — which advances the order to "Processing" and fires the WooCommerce hooks your fulfilment logic listens for.

The four mistakes new merchants make

These are the things that look fine in testing but break in production:

  • ·Crediting the order on the customer return rather than on the webhook. If you mark the order paid when the customer hits the success_url, an attacker who never actually pays can simply navigate to that URL and get fulfilment. Always credit on the signed webhook, never on the customer-facing redirect.
  • ·Parsing the JSON body before computing the HMAC. The signature commits to the raw byte stream, not your framework's re-serialised object. If WordPress or a middleware touches the body first, the HMAC will not match. Read php://input directly, compute the signature, then parse.
  • ·Not honouring the ±300s timestamp window. An attacker who captures a valid old webhook can replay it. The timestamp check is what blocks that. Reject anything outside the window, period.
  • ·Treating webhook retries as a "problem". Gateways retry until your server returns 2xx — this is correct behaviour, not a bug. Your handler must be idempotent. WooCommerce's payment_complete() is idempotent by default, but custom fulfilment logic often isn't.

Pricing and economics

Most processors charge a per-payment fee somewhere between 0.5% and 2%. There are typically no setup fees, no monthly minimums, no chargebacks (crypto is final on confirmation), and network fees are passed through at cost rather than marked up. For a WooCommerce store currently paying 2.9% + 30 cents on cards, accepting Bitcoin can be meaningfully cheaper on the per-transaction line.

There is no equivalent of card chargebacks in crypto. Once the network confirms, the funds are yours forever — but the flipside is that if you fulfil to the wrong address or send a refund to a bad destination, there is no recourse. The refund flow lives in your dashboard, not as a customer-initiated dispute.

What to check before you ship

Before pointing real customers at the integration, verify these in a test order against your own wallet:

  • ·The order flips to "Processing" on the webhook, not on the redirect
  • ·A second identical webhook (simulated retry) does not double-credit
  • ·A webhook with a tampered body returns 401
  • ·A webhook with a stale timestamp (10 minutes old) returns 401
  • ·A genuine partial payment sits as "On hold" and not "Processing"

If all five pass, you're production-ready. The rest is volume.

Want to try this on your own store?

Geat.io is a crypto payment gateway for online businesses. No percentage fees, no KYC, five-minute setup.

Start free →