WP Manifestindependent plugin directory
manifest / ecommerce / xorro-direct-wallet-payments-woocommerce

Xorro Direct Wallet Payments for WooCommerce self-updates

WooCommerce cryptocurrency payment gateway — pay directly to your wallets

by xorro · github.com/x-o-r-r-o/xorro-direct-wallet-payments-woocommerce · 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/x-o-r-r-o/xorro-direct-wallet-payments-woocommerce/archive/refs/heads/main.zip

Ships its own WordPress updater (built-in updater), so new versions show up under Dashboard → Updates.

Accept cryptocurrency in WooCommerce straight into your own wallets — no payment processor, no custody, no license keys, no phone-home. 234 coins and tokens across 75 blockchains, with automatic on-chain payment detection.

How it works

  1. At checkout the customer picks a coin and sees the exact amount due, live.
  2. The order gets a payment page with the amount, your wallet address, a wallet-app QR code, and a countdown for the payment window.
  3. The plugin watches the blockchain through public explorer APIs and marks the order paid as soon as a matching payment arrives. The page updates on its own.
  4. Funds go directly from the customer's wallet to yours. The plugin only ever stores public receiving addresses — never private keys or seed phrases.

Each order gets a slightly unique amount (usually a few base units, e.g. 10 satoshis), so many customers can pay to the same address at the same time and every payment is still matched to the right order.

Features

  • 234 coins and tokens — 70 native coins plus ERC-20, BEP-20, TRC-20, SPL (Solana) and TON jetton tokens
  • USDT and USDC on 9 networks each — Ethereum, Arbitrum, Optimism, BNB Chain, Polygon, Avalanche, Base, Solana, TRON — plus DAI on 5
  • Automatic payment detection on every coin except three manual-only ones (see below), with confirmations you can tune per coin, or by order value
  • Classic and block checkout (WooCommerce Checkout Blocks), and both order storages — High-Performance Order Storage or the older posts table
  • Live crypto quote at checkout; payment page with Copy buttons, QR code (BIP-21, EIP-681, Solana Pay and other wallet URI formats) and countdown
  • Backup exchange-rate sources (Coinbase, Kraken, Binance) when CoinGecko is unavailable, with a 5% agreement check
  • Stablecoins priced 1:1 with your store currency (optional)
  • Payment window, expiry grace period, underpayment tolerance and minimum confirmations
  • Wallet rotation — several addresses per coin, used in turn, or a fresh address per order from your own extended public key (BTC, LTC, DOGE)
  • Optional crypto price next to product prices
  • Checkout branding: title, description, custom icon and size, icon/text/both
  • Manual "Mark payment received" on the order screen, with transaction-ID reuse protection
  • Coin search and per-coin order limits at checkout, with coin names under each icon
  • Confirmations suited to each chain, overridable per coin
  • Destination tag / memo per order on the chains that carry one
  • Re-quote an expired order — the customer gets a fresh amount, you keep the order
  • No lost payments: payment details in customer emails, a reminder before the window closes, partial-payment handling (customer is asked for the rest), overpayment notes, and a late-payment scan that alerts you when money arrives after an order expired
  • Payments screen listing every crypto order, with a "needs you" filter, plus a crypto payment column on the orders list
  • Admin alerts when an explorer API rejects requests (e.g. a missing or limited API key), so verification never fails silently
  • Refunds without custody — you create a claim link, the customer gives an address they control on the right network, you send it from your own wallet and record the transaction. The plugin never holds or moves your money
  • Alerts — signed webhooks (HMAC-SHA256 over a timestamp and the exact body) and Telegram messages for part payments, overpayments, late money, a payment that vanished, and refunds waiting to go out, plus a daily summary
  • Reports — what you took, the typical wait from quote to confirmed, how many customers were quoted and never paid, and how many sent too little; overall and per coin, for the last 7, 30 or 90 days
  • Find any payment — search your orders by transaction id or receiving address, and every order keeps a timeline of what happened to its payment
  • Per-coin discount or surcharge — shown on the order as its own line, so the total the customer sees is the total they pay
  • Settings backup and restore — every setting in one file, with API keys held back unless you ask for them
  • Help screen in the plugin, and translations for sixteen languages (98–100% complete)
  • Automatic updates from GitHub Releases — every package must carry the maintainer's Ed25519 signature

Supported coins

Native coins (70): BTC, BCH, ETH, LTC, DOGE, DASH, ZEC, XEC, BNB, SOL, TRX, XMR, XRP, POL (MATIC), AVAX, XLM, DOT, ATOM, SCRT, SEI, INJ, EOS, ETC, FIL, ALGO, HBAR, CRO, FTM, EGLD, NEAR, ADA, APT, KAS, TON, BTG, FIRO, RVN, PIVX, NEO, GAS, THETA, TFUEL, DGB, KMD, QTUM, ARK, AE, ICX, ONT, KLV, TET, XEM, XYM, RUNE, IOTX, STRAX, IOTA, ONE, PLS, SYS (NEVM), BRISE, XDC, XTZ, XNO, WAVES, KAIA and more.

Tokens (164): stablecoins (USDT, USDC, DAI, TUSD, USDP, GUSD, PYUSD, USDe, USDD, EURT, XAUT…) and popular tokens such as LINK, UNI, AAVE, SHIB, PEPE, FLOKI, APE, LDO, GRT, 1INCH, CAKE, Notcoin, DOGS, Hamster Kombat and LayerZero.

The full list, with each coin's network and auto-verify status, is on Xorro Wallet Payments → Coins.

Manual-only coins: Monero (XMR), Polkadot (DOT) and IoTeX (IOTX) are payable but confirmed by hand with Mark payment received on the order. Each for its own reason: Monero because of the protocol — incoming payments are visible only to the holder of the private view key, which this plugin will never ask for; Polkadot because Subscan is the only service that will list an address's transfers and its key is a paid product; IoTeX because its only address-history API answers HTTP 500 in production, even to its own block explorer.

Kaia (KAIA) is confirmed automatically once you add a free Kaiascan key under Prices & APIs. Without one it behaves as a manual coin, and the Coins tab says so.

Requirements

Version
WordPress 6.9+ (tested up to 7.1)
WooCommerce 10.0+ (tested up to 11.1)
PHP 7.4 – 8.5 (8.2+ recommended) — every one of 7.4, 8.0, 8.1, 8.2, 8.3, 8.4 and 8.5 runs the full test suite on every change
Order storage Either — High-Performance Order Storage or the older posts table

HTTPS is strongly recommended.

Installation

  1. Download xorro-direct-wallet-payments-woocommerce-x.y.z.zip from the latest release and upload it under Plugins → Add New → Upload Plugin (or clone this repository into wp-content/plugins/).
  2. Activate Xorro Direct Wallet Payments for WooCommerce.
  3. Xorro Wallet Payments → Coins — tick the coins you accept.
  4. Xorro Wallet Payments → Wallets — add a receiving address for each coin (+ Add address for rotation).
  5. Xorro Wallet Payments → Prices & APIs — add API keys (recommended, see below).
  6. WooCommerce → Settings → Payments — enable Pay with Cryptocurrency.
  7. Optional: Xorro Wallet Payments → General — payment window, order status after payment, confirmations and checkout branding.

API keys

Everything works without keys, but free keys raise rate limits and some chains need one for automatic detection.

Key Needed for Get one
CoinGecko Exchange rates. Recommended for busy stores — the keyless API is rate-limited. coingecko.com/en/api
Etherscan (API V2) Automatic detection on Ethereum and other EVM chains. Some chains (e.g. BNB Chain, Base) may need a paid plan; the plugin tells you if Etherscan rejects them. etherscan.io/apis
TronGrid Higher TRON limits trongrid.io
Helius Solana and SPL tokens helius.dev
Aptos Aptos (APT) — must be a mainnet key; a devnet key is refused by the mainnet API aptoslabs.com
Kaiascan Kaia (KAIA). Kaia runs no free public index of its own, so without this key Kaia payments must be confirmed by hand. kaiascan.io
Blockchair Optional. Dogecoin, Bitcoin Cash, Zcash, Dash and eCash are read through Blockchair, which stops answering once the day's free allowance is used. Only worth it on a busy shop. blockchair.com/api/plans

Keys can also be set in wp-config.php so they are never stored in the database: XDWP_COINGECKO_API_KEY, XDWP_ETHERSCAN_API_KEY, XDWP_TRONGRID_API_KEY, XDWP_HELIUS_API_KEY, XDWP_APTOS_API_KEY, XDWP_BLOCKCHAIR_API_KEY, XDWP_KAIASCAN_API_KEY.

Updates

The plugin checks this repository's Releases and shows updates in the normal WordPress update screen. Turn on Enable auto-updates under Plugins to install them automatically. Draft and pre-release tags are ignored. From 1.5.37, an update is offered only if the release is signed with the maintainer's Ed25519 release key, and the downloaded ZIP is checked against both its SHA-256 and that signature before WordPress installs it. The signature covers the plugin name, version and file hash, so a hijacked GitHub account can't push a modified ZIP or re-label an old release as new.

Compatibility

Tested end to end on WordPress 7.1 and WooCommerce 11.1 — guest checkout on both classic and block checkout, live quote, order placement, payment page, status polling, the "I have sent the payment" path, and a PHP error-log check on every single run. The theme, plugin and coin sweeps below were run against 1.19.3; the PHP and order-storage results are current as of 1.19.7.

PHP — 7.4 through 8.5. Every release runs all four test suites on 7.4, 8.0, 8.1, 8.2, 8.3, 8.4 and 8.5, and the build fails if any version raises so much as a single deprecation or warning. That is stricter than it sounds: a deprecation printed while a page is sending a file ends up inside the file, so on PHP 8.4+ the payments CSV export used to download corrupt on any shop with error display switched on. Fixed in 1.19.7, and the gate stops it coming back. 7.4 remains supported and is tested on every change, so nothing here drops an older shop.

Order storage — both. WooCommerce keeps orders either in its own tables (High-Performance Order Storage) or in the posts table, and the two do not behave alike: the posts table silently ignores the meta filters wc_get_orders() is given. Until 1.19.6 that meant a shop not yet migrated got unfiltered results from every order lookup the plugin made — payments were rejected as duplicates and never confirmed. Both storages are now covered by their own test suite (tests/order-query-tests.php), which models each and runs the plugin's real queries against both. If you are on the older storage you do not need to migrate.

Themes — 44 of 44 clean, on both checkouts: Astra, Avada (and its child theme), Beratung, Betheme, Blocksy, Bricks, Divi, Dokan, Electro, Enfold, Fixera, Flatsome, GeneratePress, Hello Elementor, Impreza, Kadence, Martfury, Neve, Newspaper, OceanWP, Ohio, Porto, Saira, Salient, Savoy (and child), Shoptimizer, Storefront, The7, Thrive Theme, Uncode (and child), Vault, Wolmart, Woodmart, X, XStore, asri, bb-theme, and Twenty Twenty-One / Three / Four / Five.

Plugins — 239 tested one at a time, 237 clean. Every plugin on the test site was activated on its own alongside the gateway and taken through a full crypto checkout. The list spans caching and performance (WP Rocket, LiteSpeed, W3 Total Cache, WP Super Cache, WP Fastest Cache, Autoptimize, Perfmatters, Breeze, Cache Enabler, Hummingbird, SiteGround Optimizer, Jetpack Boost, RabbitLoader, SpeedyCache, Seraphinite, Asset CleanUp Pro, WP-Optimize), security (Wordfence, Solid Security, All-In-One Security, Sucuri, SecuPress, Shield, Defender, SiteGuard, Loginizer, Limit Login Attempts Reloaded, WPS Hide Login, Really Simple SSL), the WooCommerce ecosystem (Subscriptions, Bookings, Product Add-ons, Product Vendors, Warranty, Order Barcodes, Services, Payments, Stripe, PayPal Payments, AutomateWoo, CartFlows, CommerceKit, Checkout Field Editor, Flexible Checkout Fields, CURCY, FOX, Google Listings & Ads, WooLoyalty, Easy Digital Downloads), marketplaces (Dokan Lite and Dokan Pro), page builders (Elementor and Elementor Pro, WPBakery, Beaver Builder, Fusion/Avada Builder, Kadence Blocks Pro, Royal/Premium/Essential/Sky addons, Element Pack, ElementsKit), multilingual and SEO (WPML and its add-ons, Polylang, TranslatePress, GTranslate, Loco Translate, Yoast Premium + Video + WooCommerce SEO, Rank Math Pro, AIOSEO), forms and membership (Gravity Forms, Contact Form 7, WPForms, Fluent Forms, Forminator, Ninja Forms, SureForms, ARMember, Indeed Membership Pro, MasterStudy LMS, FluentCommunity), and site tooling (ACF Pro, Meta Box, Redux, JetPack, UpdraftPlus, Duplicator Pro, All-in-One WP Migration, WPvivid, Backuply, MainWP Child, Query Monitor, Code Snippets, WP File Manager, TablePress, The Events Calendar, Smush, EWWW, Imagify, and more).

Stacks — all clean: cache-heavy (WP Rocket + Perfmatters + Autoptimize + WP-Optimize), security-heavy (Wordfence + Solid Security + Shield + Limit Login Attempts), builder-heavy (Elementor

  • WPBakery + Slider Revolution + LayerSlider + Kirki), store-heavy (Subscriptions + Bookings + Product Add-ons + AutomateWoo + CartFlows), and translation + multi-currency (Polylang + TranslatePress + CURCY + FOX). A 30-plugin stack was also run on Woodmart, Divi, Betheme and Flatsome.

Coins — all 234 priced and quoted against live market data, and 44 coins were driven against their real explorers with real addresses to confirm a payment in that coin is actually detected — including USDT on TRON, Ethereum and BNB Chain, and USDC on Solana.

Order export and currency switchers — tested directly, all clean. Run on PHP 8.5.3 with WooCommerce 11.1.1, against both order storages, one plugin at a time and then all of them together:

Plugin Version Result
WooCommerce Currency Switcher (WOOCS / FOX) 1.5.4 Clean
WooCommerce Multi Currency (CURCY) 2.2.16 Clean
Advanced Order Export For WooCommerce 4.1.0 Clean — its HPOS extractor finds all 36 _xdwp_* fields as exportable columns
Order Import Export for WooCommerce (WebToffee) 1.5.0 / 1.6.0 Clean
All four together Clean

Both switchers hook woocommerce_currency, which is the value this plugin reads, so a quote follows the active currency without any integration. Verified by quoting the same £25/€25/$25 order in USD, EUR, GBP, JPY and NGN — each got the right rate for that currency — and, more importantly, by taking a quote in USD and then creating the order in EUR: the USD quote is not reused, so a currency change mid-checkout cannot charge a stale cross-currency amount.

Problems found in other products while testing, none of them caused by this plugin:

  • WooCommerce Multi Currency (CURCY) 2.2.16 logs PHP 8.5 deprecations on every page load — case statements followed by ; in frontend/shortcode.php lines 658 and 661. Harmless today, but it will be a fatal error in PHP 9.

  • Order Import Export for WooCommerce (WebToffee) 1.6.0 logs a PHP 8.5 deprecation — a non-canonical (boolean) cast in helpers/class-wt-import-export-helper.php line 1048.

  • Dokan Pro's Booking module takes the whole site down with a fatal error (DependencyNotice class missing from the package). Verified with this plugin fully deactivated — the site still fails. Keep that module off until Dokan fix it.

  • Ultimate Affiliate queries a wp_uap_referrals table its own installer never created, logging a database error on every order from any gateway.

  • WP Reviews Plugin for Google redirects the site's front page on its own — reproduced with this plugin fully deactivated.

  • Avada's child theme enqueues child-style against an unregistered avada-stylesheet, which WordPress 6.9+ logs as an incorrect-usage notice. Present with this plugin deactivated.

  • LiteSpeed Cache "JS Combine", and Autoptimize with "Also optimize for checkout", break WooCommerce's own block checkout. Leave both off on checkout pages.

  • A 30-plugin stack on Woodmart needs more than 256 MB of PHP memory, with or without this plugin.

Plugins that need a partner were retested with it and pass: Elementor Pro with Elementor, Dokan Pro with Dokan Lite, Bit Integrations Pro, Bit Social Pro and Presto Player Pro with their free base plugins, and Essential Addons for Elementor with Elementor. Two could not be activated at all on the test site and so could not be exercised: Stellar (refuses activation) and Uncode Wireframes (wants the Uncode theme's own framework).

Built-in compatibility handling:

  • Checkout and payment pages are never page-cached (WooCommerce's no-cache rules are respected).
  • Payment-page scripts opt out of "delay JavaScript", defer and combine features (LiteSpeed, WP Rocket, Perfmatters, SiteGround Optimizer, Jetpack Boost, Cloudflare Rocket Loader), so the QR code and countdown appear without the customer having to touch the page.
  • The checkout script stays out of combined JS bundles, so an error in another plugin's script can't break the coin picker.
  • Customer-facing requests use WooCommerce's ?wc-ajax= endpoint, which security plugins and admin redirects don't interfere with.
  • No inline event handlers — works with strict Content-Security-Policy headers.

Security

  • Only public receiving addresses are stored — never private keys.
  • A payment counts only if it goes to your address, is the right asset (token contract / mint / jetton master checked), is newer than the order, is a successful transaction with the required confirmations, and is within the amount band. Amounts are compared with exact integer math.
  • Each transaction ID can pay only one order. Explorer errors, missing fields and unexpected responses always count as "not paid" (fail closed).
  • An explorer's answer is treated as data, not as a number. A value that is not exactly the expected shape is no value at all, never a best effort — PHP's own lenient conversions would otherwise turn a malformed reply into a plausible amount (before 1.19.7, hexdec() read the word nineteen as 921312).
  • All explorer and price requests use HTTPS to fixed endpoints — no user-supplied URLs.
  • Admin actions require manage_woocommerce plus nonces. Customers can only see their own order (order key or account owner).
  • Frontend endpoints are nonce-protected and rate-limited per IP. Use the xdwp_rate_limit_client_ip filter to trust a CDN's client-IP header.
  • Payout-address changes are notified to the site admin.
  • Refund claim links are 24 random bytes, stored only as an HMAC, compared in constant time, expiring after 14 days, rate-limited per visitor, and dead once the refund is recorded. The plugin has no code path that sends money — a refund is always made by a person from their own wallet.
  • Webhooks are signed with HMAC-SHA256 over a timestamp and the exact body sent, so a receiver can verify the shop sent it and reject a replayed one.
  • Every explorer response is capped at 8 MB and two redirects, so a third-party service cannot stall a customer's payment page by answering with something enormous.
  • Updates are verified with an Ed25519 signature from a key that never touches GitHub releases (see Release signing).

Found a vulnerability? Please open a private security advisory rather than a public issue.

Developer hooks

Hook Type Fires when
xdwp_order_paid ( $order, $txid ) action An order is confirmed paid
xdwp_order_underpaid ( $order, $received, $remainder, $txid ) action A partial payment arrives
xdwp_order_overpaid ( $order, $excess ) action An order is paid with more than was due
xdwp_order_expired ( $order, $previous_status ) action The payment window closes unpaid
xdwp_late_payment_detected ( $order, $txid, $amount ) action Money arrives for an expired order
xdwp_ambiguous_payment ( $order, $txid, $amount ) action A non-exact transfer could belong to more than one order
xdwp_send_payment_reminder ( $order ) action The pre-expiry reminder is due
xdwp_payment_detected ( $order, $txid, $amount ) action A matching transfer is seen on chain, before it has the confirmations required
xdwp_payment_renewed ( $order ) action A customer re-quotes an expired order
xdwp_refund_address_given ( $order, $address ) action A customer gives an address for their refund
xdwp_refund_sent ( $order, $txid ) action The shop records the refund it sent
xdwp_coins filter The coin list is built
xdwp_payment_window_minutes ( $minutes, $order, $coin ) filter The payment window is set for an order
xdwp_confirmations_required ( $confirmations, $coin ) filter Confirmations for a coin are resolved
xdwp_order_confirmations_required ( $confirmations, $coin, $order ) filter Confirmations are resolved for one order, after any value tier
xdwp_coin_adjustment ( $percent, $coin_id ) filter A coin's discount or surcharge is read
xdwp_backup_rate_symbols ( $renamed ) filter Tickers to ask a backup rate source for, where a coin has been renamed
xdwp_notification_payload ( $payload, $event, $order ) filter An alert is about to be queued
xdwp_wallet_add_chain ( $params, $coin, $chain_id ) filter A browser wallet does not know the chain (empty by default: no RPC is supplied)
xdwp_coin_allowed_for_total ( $allowed, $coin_id, $total ) filter A coin is offered (or hidden) for an order total
xdwp_order_memo ( $memo, $order, $coin ) filter A destination tag / memo is generated
xdwp_payment_uri ( $uri, $coin_id, $address, $amount, $memo ) filter The wallet link / QR code is built
xdwp_rate_limit_client_ip filter Rate limiting identifies the client IP

The refund claim page can be overridden at yourtheme/xorro-direct-wallet-payments-woocommerce/xdwp-refund-claim.php. Email templates can be overridden in your theme under woocommerce/emails/ (xdwp-payment-details.php, xdwp-payment-reminder.php, xdwp-partial-payment.php, xdwp-payment-alert.php, plus plain/ versions).

External services

The plugin never contacts the author's servers. It calls public price and blockchain APIs (CoinGecko, Etherscan, mempool.space, Blockchair, TronGrid, toncenter and others) only when a checkout quote is shown or a payment is being verified. The full list — purpose, data sent, terms and privacy links — is in readme.txt under External services. Suggested privacy-policy text is added under Settings → Privacy.

Troubleshooting

Symptom Fix
"We could not prepare this crypto payment right now" at checkout The order note says why. Usually the exchange-rate API is rate-limited — add a CoinGecko key.
EVM orders never confirm automatically Add an Etherscan API V2 key. If the Prices & APIs page shows an Etherscan error for a chain, that chain needs a paid Etherscan plan.
A payment arrived but the order didn't update Check WooCommerce → Status → Logs (source xorro-wallet-payments), make sure WP-Cron runs, then use Mark payment received with the transaction ID.
QR code or countdown missing on the payment page Clear your cache/optimization plugin's cache. If the problem persists, exclude xorro-direct-wallet-payments-woocommerce/assets/js/ from JS optimization.
"Test this coin" says the explorer has no record of your address Normal for an address nothing has been sent to. XRP and Stellar only create an account on chain once it receives its first payment.
Dogecoin, Bitcoin Cash, Zcash, Dash or eCash stop confirming on a busy day Those are read through Blockchair, which stops answering once the day's free allowance is used. Add a free Blockchair key under Prices & APIs.
A customer says they were asked to pay for an order you already completed Fixed in 1.19.2. Before that, completing an order in WooCommerce did not stop the payment page asking for payment.

Development

docs/DEVELOPMENT-HISTORY.md is the engineering record: what every release put into the code, which planned work is still outstanding and why, where each piece of machinery lives, and the invariants a change must not break. Read it before adding a feature — several things that look missing were decided against for a stated reason.

# Offline smoke tests (PHP CLI; not shipped in the release ZIP)
php tests/smoke-test.php
php tests/matching-tests.php
php tests/hd-tests.php

# Build a release ZIP
bin/build-zip.sh

Pushing a vX.Y.Z tag runs the Release workflow, which builds the ZIP, its SHA-256 file and an Ed25519 signature (.sig) and attaches all three to the GitHub release.

Release signing

  • The workflow signs xdwp-release:1 / plugin / version / sha256 with the private key in the XDWP_SIGNING_KEY Actions secret (PKCS#8 PEM), then checks the signature against the public key(s) in Xdwp_Updater::RELEASE_PUBLIC_KEYS before publishing. A missing or wrong key fails the release instead of shipping a package sites would refuse.
  • Keep an offline backup of the private key (e.g. a password manager). If it is lost, sites can only move to a new key through a release signed with the old one.
  • Rotating the key: add the new public key to RELEASE_PUBLIC_KEYS and release that version signed with the old key; then replace the secret with the new key for later releases, and remove the old public key once sites have updated.
  • Generate a key pair with OpenSSL 3: openssl genpkey -algorithm ed25519 -out release.pem; the public key for the plugin is openssl pkey -in release.pem -pubout -outform DER | tail -c 32 | base64.

Changelog

Full details for every release are in readme.txt.

1.28.0 — who covers the sending fee

  • New: absorb a small shortfall instead of asking for it. The usual cause is an exchange taking its withdrawal fee out of the amount sent — the customer can't see it and can't prevent it. Off by default
  • Deliberately not the underpayment tolerance. Tolerance decides which order a transfer belongs to and stays tight so two customers on one address can't be confused. This applies after a payment is already claimed for an order, so it can safely be larger — and does not widen the matching band by a single unit, which a test enforces

1.27.0 — a setup wizard that asks three questions

  • New: setup wizard. Seven tabs of settings, but only three things have no sensible default and block a first payment — pick a coin, give it an address, switch the gateway on. It asks for those and nothing else
  • The final step runs the real address / rate / chain checks before offering to switch on, so "ready" means tested
  • Writes into ordinary settings at each step — no draft state, and leaving halfway just means you got that far. Addresses go through the same validation as the Wallets tab
  • Dismissable, and shown only on WooCommerce screens, the plugins list, and this plugin's pages

1.26.0 — a second road out, and two figures worth counting

  • Security: a payout-address change now also leaves by webhook and Telegram, and names the IP it came from. Whoever takes over an admin account usually controls the mailbox it can reset — email alone is the warning they can intercept. Not switchable off with the ordinary alerts
  • New: conversion rate and average paid order on the Payments report, from numbers already counted
  • New: an unfinished payment is reachable from My Account — "Finish paying", or "Get a new amount" after expiry. Replaces WooCommerce's Pay button, which would re-quote an order that already has a quote

1.25.1 — the marketplace function names, checked against source

  • Fixed: vendor payouts never activated on Dokan — the function looked for doesn't exist, and the real one returns an object unless asked for an id. Guarded calls meant it did nothing rather than breaking, but it did nothing
  • Fixed: on WC Vendors, a deleted product could attribute a line item to user 1 (usually the admin), because that plugin answers 1 for a missing post and -1 for a non-product. The answer is now confirmed to be a vendor first

1.25.0 — pay marketplace vendors directly

  • New: on Dokan, WCFM or WC Vendors, an order's payment goes straight from the customer to the vendor's own wallet. No float, no payout queue, nothing owed — the thing non-custodial makes easy and every custodial gateway makes hard
  • Single stores are untouched. The setting only appears if a marketplace is installed, it's off by default, and with no marketplace no filter is registered at all. A test suite exists mainly to keep that true
  • A multi-vendor order pays the shop — one transfer can't be split between people — and a vendor with no address for that coin is skipped so the sale still completes. Both are noted on the order
  • Commission isn't deducted from the transfer; your marketplace accounts for it as before
  • An address invalid for the coin is never quoted, whatever supplied it — it falls back to your own

1.24.0 — WalletConnect, opt-in and kept small

  • New: pair a phone wallet with a desktop browser. Off unless you paste a Reown project ID — empty means the feature does not exist
  • The one part that runs someone else's code, so: fetched only on a button press, never on an ordinary payment page; pinned to one exact version named in the plugin, so page code can't change without a signed update; address and amount still come from the plugin; the wallet still shows the destination before approval; the order is still confirmed only on chain
  • Not needed for customers already on a phone — the deep link and QR already cover that, and load nothing
  • xdwp_walletconnect_src lets a shop serve the library itself

1.23.1 — a wallet link in the payment email

  • New: "Pay from a wallet on this device" in the payment email, opening the wallet with address, amount and memo prefilled. That email is read on a phone, where a QR is useless — you can't scan your own screen
  • The address and amount stay printed in full, since some clients strip non-http links; the payment-page button remains for desktop readers

1.23.0 — rehearse what happens after the money arrives

  • New: "Rehearse a payment" — one order, quoted against your real wallet and today's rate, then confirmed through the same code a real payment uses. Checks order status, the customer email, and webhook/Telegram alerts in seconds
  • The other half of test mode: test mode proves the chain reading; this proves everything that happens after the money is seen, none of which involves a blockchain
  • One at a time, addressed to your own email, and excluded from the payments list and the figures. Deleting it gives back the unique amount it was holding
  • Confirming marks an order paid without payment, so it acts only on an order it created and flagged — enforced in the code, not just the UI

1.22.0 — rehearse the whole thing, with free coins

  • New: test mode — a real quote, address, payment page, on-chain transfer, confirmed order, email and webhook, on networks where coins are worthless
  • Bitcoin testnet3, Ethereum Sepolia and TRON Nile, and only those: a test network has to be one the plugin can genuinely read, with a faucet you can use today
  • Other coins are hidden while testing rather than half-working, and tokens are excluded — a token's contract differs on every test network
  • The Wallets tab accepts only test addresses while it's on, and refuses them when it's off. Your real addresses are kept
  • Impossible to leave on by accident: an undismissable admin banner, a readiness-check warning, and a payment-page notice that real coins sent there are lost

1.21.0 — money with no order

  • New: a reconciliation screen that reads your receiving addresses and subtracts every transfer the plugin can account for. What's left is money no order explains — invisible to the ordinary check, which only ever asks about one expected amount
  • It refuses to overstate itself. BTC, BCH, LTC, DOGE, DASH, ZEC, XEC, all EVM chains, BTG, FIRO, RVN, PIVX, ONE, PLS, SYS, BOBA and BRISE can be listed. The rest are named as unchecked, and an explorer that refused to answer is reported separately — an empty result never reads as an all-clear
  • Reads and reports only: no order is altered by a scan, and it runs only when you ask
  • Integer arithmetic throughout, so an 18-decimal amount beyond PHP's number range stays exact

1.20.0 — tell the customer what actually happened

  • New: "I have sent the payment" now answers. It reads the chain and reports confirmed / arrived and confirming / part-paid with the exact shortfall / nothing yet. The confirming answer is what stops a second payment
  • New: an optional transaction ID box. Never used to match a payment — only a transfer to the shop's address does that — but recorded so a transfer that went astray can be traced
  • New: when nothing has arrived, the answer names the wrong network and the missing memo, the two mistakes that actually cause it
  • New: an order where the customer reported paying and the window then closed with nothing found lands in "Needs you" — only after expiry, so it can't be flooded
  • New: two self-test checks for failures that come from outside the plugin — WP_HTTP_BLOCK_EXTERNAL, and a loopback probe that catches a security plugin or coming-soon mode intercepting the payment page
  • New: eight accounting columns in the payments export, and the quoted rate is now recorded on the order rather than recovered later

1.19.9 — take the configuration out in parts

  • New: export and restore everything, wallet addresses and extended keys only, or API keys only. A wallets file never carries secrets even if the box is ticked; a keys file always does, and says to treat it as a password
  • New: the controls now sit on Wallets and Prices & APIs as well as General, each opening on the part that tab is about
  • A restore changes only what the file contains — anything it leaves out stays as it is on this site
  • New: WooCommerce shows "Set up" instead of an enable toggle until at least one coin has somewhere to receive
  • New: the transaction id on the WooCommerce order screen is now a link to that coin's explorer

1.19.8 — one readme, and compatibility said plainly

  • The release ZIP no longer carries README.md. readme.txt is what WordPress reads for the plugin's "View details" screen; this file is for GitHub and was shipping alongside it saying the same things twice
  • Requirements now state PHP 7.4 – 8.5, every version tested on each release, in place of the old open-ended "7.4+"
  • Requirements and FAQ now say the plugin works with either order storage, HPOS or the older posts table — previously only HPOS was claimed, which undersold it after 1.19.6

1.19.7 — PHP 8.5 audit: a corrupt CSV, and an amount read from a word

  • Fixed: on PHP 8.4+ the payments CSV could download corrupt — PHP deprecated leaving the CSV escape character unstated, and with error display on that text was printed into the file
  • Fixed: explorer amounts were parsed with hexdec(), which drops unrecognised characters instead of failing. nineteen was read as the amount 921312. Anything that is not a clean 256-bit hex integer is now no amount at all
  • Fixed: that conversion ran one bcmath operation per character, unbounded — a large enough explorer reply could tie up the site
  • Hardened: decimal places bounded before padding, non-text coin identifiers refused, partial coin definitions from third-party filters tolerated, addresses normalised before matching
  • Fixed: uninstall left a cached option behind. The HD address index is still kept on purpose — deleting it would re-use addresses belonging to past orders
  • CI now runs every suite on PHP 7.4, 8.0, 8.1, 8.2, 8.3, 8.4 and 8.5, and fails on a single deprecation or warning

1.19.6 — Order lookups work on shops that still store orders as posts

  • Fixed: on a shop not yet on High-Performance Order Storage, WooCommerce silently drops the meta_query from wc_get_orders(), so none of the plugin's order lookups were filtered. "Has another order already claimed this transaction?" became "does this shop have any other order?" — true on every real shop — and payments were rejected as duplicates and never confirmed
  • Fixed, same cause: the Payments screen listed every order in the shop, its filters and counts did nothing, and the attention badge counted orders that needed none
  • Fixed, same cause: an expired order with no wallet index could still lend one back, and an empty index reads as 0 — the first address, handed out twice
  • HPOS shops were never affected and are unchanged

1.19.5 — Kaia confirmed automatically, Polkadot back as a manual coin

  • New: Kaia (KAIA) is confirmed on chain with a free Kaiascan key. Without a key it stays manual and says so
  • Polkadot (DOT) returns as a payable coin, confirmed by hand — Subscan, the only service that lists an address's transfers, is a paid product
  • IoTeX stays manual: its only address-history API answers HTTP 500 in production, to us and to its own explorer

1.19.4 — Payments table columns, and the payment page buttons

  • Fixed: pressing Copy beside the address made the address look as though it changed — the button grew while it said "Copied!", squeezing the address box and re-wrapping the address
  • Fixed: on a phone the "Open in wallet app" button hung 31px past the edge of the payment box and was wider than the button beneath it
  • Fixed: on a narrower admin window the order date painted over the customer's email address, and long amounts were cut off
  • The table now scrolls sideways inside its own panel instead of dragging the whole admin page with it; the reports table did the same and is fixed too

1.19.3 — Polkadot and Zilliqa withdrawn

  • Removed: Polkadot (DOT) and Zilliqa (ZIL). Neither can be checked on chain without a key that is not freely available — Subscan is a paid product and ViewBlock no longer issues keys — so both could only ever be confirmed by hand
  • The Subscan and ViewBlock key fields are gone with them, and the External Services list now names the sources actually contacted
  • 233 coins remain, all of which can be priced, quoted and checked on their own chain, except Monero, IoTeX and Kaia which are documented as manual

1.19.2 — the payment page as a customer sees it

  • Fixed: an order completed in WooCommerce still asked the customer to pay, and they could pay twice
  • Fixed: a confirmed payment kept counting down beside "Payment confirmed"
  • Fixed: after a part payment, the remaining amount was shown beside the full ord

This README is longer than the copy stored here. Read the rest on GitHub →