WP Manifestindependent plugin directory
manifest / ecommerce / wordpress-integration-plugin

CoinPay Payment Gateway for WooCommerce

Accept cryptocurrency payments through CoinPay in your WooCommerce store.

by CoinPay · github.com/coinpay-finance/wordpress-integration-plugin · website

0stars
0forks

Install

No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:

wp plugin install https://github.com/coinpay-finance/wordpress-integration-plugin/archive/refs/heads/main.zip

Accept cryptocurrency payments through CoinPay in your WooCommerce store.

This plugin talks to the CoinPay merchant payment API (https://platform.coinpay.finance/api/v1/coin-pay) — the same first-party contract implemented by CoinPay's official PHP, Laravel, and Go SDKs. It creates a payment, redirects the customer to CoinPay's hosted checkout, and relies on a signed server-to-server webhook (not the browser redirect) to mark the WooCommerce order as paid once the blockchain transaction actually confirms.

Requirements

  • WordPress 5.8+
  • WooCommerce 3.0+
  • PHP 7.4+ with the curl and json extensions (via WordPress's HTTP API)
  • A CoinPay merchant account and API key
  • A store whose active WooCommerce currency is USD (see Currency below)

Installation

  1. Copy this plugin's folder into wp-content/plugins/ (or zip it and upload via Plugins → Add New → Upload Plugin).
  2. Activate CoinPay Payment Gateway for WooCommerce from the WordPress admin Plugins screen.
  3. Go to WooCommerce → Settings → Payments → CoinPay to configure it.

Configuration

API key

Paste your CoinPay merchant API key into the API Key field. It's sent as-is in the Authorization header of every API request (no Bearer prefix — CoinPay's API expects the raw key). If you paste a key that still has a Bearer prefix from somewhere else, the plugin strips it automatically as a defensive measure, but you shouldn't need to include it.

Staging mode

Check Staging Mode to point the plugin at CoinPay's staging environment (https://staging.coinpay.finance/api/v1/coin-pay) instead of production, for testing. A warning banner appears in the WordPress admin bar while staging mode is on so it's hard to leave on by accident.

Webhook setup

Crypto payments confirm asynchronously — unlike a card payment, there's no single instant "approved/declined" response. Because of that, this plugin never marks an order paid from the customer's browser redirect. Only a webhook from CoinPay does that.

  1. On the CoinPay settings screen, copy the webhook URL shown under "Webhook Settings" — it looks like: https://your-site.example/wp-json/coinpay/v1/webhook
  2. In your CoinPay merchant dashboard, register that URL as the webhook endpoint for this store.
  3. Copy the signing secret CoinPay shows you for that endpoint into the plugin's Webhook Secret field.

The webhook endpoint is a WordPress REST API route (not the older woocommerce_api_* query-var style) specifically because a REST request gives clean access to the raw request body, which is required to verify the HMAC signature — the signature is computed over the raw bytes, not a re-encoded copy of the payload.

Two verification schemes are supported, matching what CoinPay's backend actually sends today:

  • Primary — HMAC-SHA256: the request carries X-Coinpay-Signature: v1=<hex-hmac-sha256>, X-Coinpay-Timestamp, and X-Coinpay-Delivery headers. The plugin recomputes the signature over "{timestamp}.{deliveryId}.{rawBody}" using your webhook secret, compares it with a constant-time comparison, and rejects anything whose timestamp is more than 300 seconds old or in the future (replay protection).
  • Legacy (deprecated, still accepted): a static SECRET header compared directly (constant-time) against your configured webhook secret. CoinPay still sends this for senders that haven't moved to signature verification; new integrations should rely on the HMAC scheme.

The signature-verification logic lives in includes/class-coinpay-webhook-verifier.php and has no WordPress dependency, so it's covered by a PHPUnit test suite in tests/ (see Testing) independent of a real WordPress install.

How the payment flow works

  1. The customer chooses CoinPay at checkout and places the order. WooCommerce redirects them to this gateway's "pay for order" page.
  2. The plugin calls CoinPay's POST /payment endpoint with the order amount (in USD), a redirect_url pointing back to WooCommerce's own order-received ("thank you") page, and a client_ref_id derived from the order ID and order key. CoinPay returns a ready-to-use hosted checkout url and a transaction_id, which the plugin stores on the order and redirects the customer to directly — there's no separate "authorize, then build a start-pay URL" step.
  3. The customer completes (or abandons) payment on CoinPay's hosted page and is redirected back to WooCommerce's order-received page. That page reflects the order's real, database-backed status — it never trusts anything in the redirect's query string — so if the payment hasn't confirmed yet, the customer sees a "your payment is awaiting confirmation" message instead of a false "paid" state.
  4. Once the blockchain transaction actually confirms, CoinPay calls your configured webhook. The plugin verifies the signature, looks up the order by the transaction_id it stored in step 2, and calls $order->payment_complete() — this is the only place in the plugin that ever marks an order as paid.

An order admin can also click Re-check Transaction Status on the order screen to manually call CoinPay's status-check endpoint and reconcile the order if a webhook was somehow missed.

Currency

CoinPay's create payment API takes a plain numeric amount in US dollars — there's no currency code parameter and no built-in FX conversion. This plugin does not perform currency conversion of its own. It only sends wc_get_order()->get_total() as-is, which is only correct if your store's active WooCommerce currency is already USD.

If your store currency is anything else, the plugin:

  • shows a persistent admin notice on WooCommerce → Settings → Payments explaining the mismatch, and
  • refuses to send the customer to CoinPay at checkout (with a clear error) rather than silently charging the wrong amount.

If you need to sell in another currency, set your WooCommerce store currency to USD, or convert the price yourself before checkout — this plugin intentionally does not guess at an exchange rate.

Refunds are not supported

There is currently no known CoinPay refund API. None of CoinPay's first-party SDKs (PHP, Laravel, Go) implement one either. Rather than inventing an endpoint that may not exist, this plugin does not declare refunds support and has no refund code path — if you need to refund a customer, do it manually outside WooCommerce (directly with CoinPay/on-chain) and update the order's status/notes accordingly.

Translations

All customer- and admin-facing strings are in English by default and wrapped for translation under the wc-coinpay text domain. A Persian (fa_IR) translation is provided in languages/wc-coinpay-fa_IR.po, along with the languages/wc-coinpay.pot template for adding further languages.

Note: WordPress loads compiled .mo files, not .po source files. Before shipping a release, compile the .po into a .mo (e.g. msgfmt languages/wc-coinpay-fa_IR.po -o languages/wc-coinpay-fa_IR.mo, or wp i18n make-mo languages/ via WP-CLI) — that step wasn't run here since neither msgfmt nor WP-CLI is available in this workspace.

Testing

The webhook-signature verifier (CoinPay_Webhook_Verifier) is the one piece of this plugin with no WordPress dependency, so it has an isolated PHPUnit suite:

composer install
composer test
# or: php vendor/bin/phpunit

The rest of the plugin is tightly coupled to WordPress/WooCommerce runtime functions (wc_get_order, wp_remote_post, the Settings API, REST API, etc.) and is verified with php -l plus manual review rather than automated tests, since there's no practical way to exercise it without a real WordPress install.

What changed from earlier versions

Earlier code in this repository actually implemented ZarinPal's API (an unrelated Iranian card-payment processor) behind CoinPay-branded labels — a display-only rename that was never backed by a real CoinPay integration. This includes the ZarinPal merchant_id/"authority"/StartPay redirect flow, Iranian Rial currency-multiplier logic (IRT/IRHR/IRHT), and ZarinPal's GraphQL-based refund API. None of that shipped to a real merchant (there were no releases/tags), so it was replaced outright with a genuine CoinPay integration as described above, with no backward-compatibility constraints beyond keeping the WordPress-facing gateway ID (WC_COINPAY) stable.

License

GPLv3 or later.