integrations/woocommerce/ is a single WordPress plugin exposing two independent gateways, Nomba and Duro; either or both can be enabled. It is HPOS compatible, unit tested (51 tests), and verified against a real WordPress store and the real Nomba sandbox (live card payment and refund). Source: woocommerce/README.md, woocommerce/readme.txt, and woocommerce/includes/.
Structure
Install
From readme.txt:
- Upload the plugin zip via Plugins, Add New, Upload Plugin, then activate. (Build it with
bash tools/build.sh, which produces dist/nomba-woocommerce.zip.)
- Open WooCommerce, Settings, Payments.
- Open the Nomba payment method and enter the Account ID, Client ID, and Client secret from the Nomba dashboard (API Keys). Use the parent (business) Account ID; a sub-account ID is rejected at authentication. Test keys work with test mode on.
- Enter the Webhook signature key from the dashboard webhook settings. Optionally set a Sub-account ID to deposit payments into a sub-account.
- In the Nomba dashboard, set the webhook URL to
https://your-store.example/wp-json/nomba/v1/webhook.
- Enable the gateway and save.
On a fresh WordPress install with Plain permalinks, /wp-json/... silently returns the homepage with a 200 instead of routing to the REST API, so the webhook endpoint would appear to accept everything. Set Settings, Permalinks to any option other than Plain (for example Post name) before relying on the webhook.
Nomba lifecycle
The gateway (class-wc-gateway-nomba.php) implements the shared verification-first lifecycle:
process_payment creates a Nomba checkout order (POST {prefix}/order) and redirects the shopper to data.checkoutLink. The order stores _nomba_order_reference and _nomba_mode.
verify_on_return calls the verify endpoint and completes the order only on paid plus a matching amount.
- The webhook (
POST /wp-json/nomba/v1/webhook) verifies the nine-field HMAC signature from the nomba-signature header with the nomba-timestamp header, enforces a 300-second replay window, then re-verifies the transaction with the Nomba API (verify_order, GET {prefix}/transaction) before doing anything else. The API response is the source of truth, not the webhook payload. It cross-checks the verified amount and currency, stores _nomba_transaction_id from the verified paymentReference, and completes the order. Re-verification applies to payment_success only; payment_failed marks an unpaid order failed and payment_reversal marks a paid order refunded, both from the signed event without an extra API call.
- Refunds run from the WooCommerce order screen through
POST {prefix}/refund with the stored transaction id; partial amounts are supported. Refunds use the mode the order was paid in.
Environments
Test mode (default on) targets https://sandbox.nomba.com; live mode targets https://api.nomba.com. Both use the same /v1/checkout prefix; only the host differs. The base URL can be overridden for local testing with the NOMBA_WC_API_BASE constant or the nomba_wc_api_base_url filter, which the local mock server uses.
The Duro gateway
The same plugin ships a second, independent Duro hosted-checkout gateway (class-wc-gateway-duro.php) with saved cards and recovery:
process_payment creates a Duro checkout session (POST /v1/checkout/sessions, amount in kobo, mandatory Idempotency-Key header) and redirects to the hosted checkout URL. The order stores _duro_session_id, _duro_token, _duro_mode.
verify_on_return calls Duro_Client::get_session and completes the order only when the session status is completed plus a matching amount (kobo).
- The webhook (
POST /wp-json/duro/v1/webhook) verifies the t.rawBody HMAC signature from the duro-signature header, enforces a 300-second replay window, dedupes on duro-event-id, then re-verifies the session with the Duro API before completing on checkout_completed or subscription_payment_success.
- No refunds. A one-off Duro checkout (
kind: one_time) creates no refundable invoice, so the Duro gateway does not declare refunds support; use the Nomba gateway when a refund is required.
The Duro base host follows the secret-key prefix: sk_test_ targets https://sandbox.useduro.com, sk_live_ targets https://api.useduro.com. Overridable via the DURO_WC_API_BASE constant or the duro_wc_api_base_url filter.
Error states
Tests and demo
51 unit tests cover the gateway class (process_payment, return verify, refund) plus the protocol classes (client, signature, webhook), run from the repo root:
A full local checkout, webhook, and refund walkthrough against the mock Nomba server (no credentials) lives in tools/demo/woocommerce/README.md: it stands up WordPress + WooCommerce 9.4.3 in Docker, points the gateway at the mock via NOMBA_WC_API_BASE, and walks six webhook exercises (valid completion, wrong secret, tampered payload, stale timestamp, amount mismatch, reversal) plus an admin refund. Switching to the real sandbox is a documented volume-reset step.