Skip to content

WooCommerce

The Xaalis for WooCommerce plugin (in integrations/woocommerce/xaalis-for-woocommerce) adds a “Wave / Orange Money (Xaalis)” payment method. The customer is redirected to the Xaalis hosted checkout, pays with Wave or Orange Money, and the order is marked paid when Xaalis confirms it.

Requirements: WordPress 6.4+, WooCommerce 8.2+ (tested with 11.1), PHP 8.1+, store currency CFA franc (XOF). Works with the classic checkout and the Cart/Checkout blocks, and with HPOS (High-Performance Order Storage).

  1. Zip the xaalis-for-woocommerce folder, upload it in Plugins → Add New → Upload, activate it.
  2. WooCommerce → Settings → General: currency CFA franc (XOF), number of decimals 0.
  3. WooCommerce → Settings → Payments → Wave / Orange Money (Xaalis):
Setting Value
Test mode on until you have tested the whole flow
Test secret key sk_test_…
Live secret key sk_live_…
Webhook secret whsec_… (given once when your account is created)
API base URL https://api.xaalis.sn (leave the default)
  1. Copy the webhook URL shown at the top of that page — https://your-store/wp-json/xaalis/v1/webhook — and set it as your account’s webhook_url (PATCH /v1/account, must be https://; see Webhooks).

Saved secrets are never shown again: the fields stay empty with a masked hint (sk_test_••••ab12). Leave a field empty to keep its value. Live mode is refused without a sk_live_ key and an https:// API URL, and test mode never uses a live key.

The payment method is hidden at checkout when the currency isn’t XOF or when the current mode has no valid key; an admin notice says why.

sequenceDiagram
    participant C as Customer
    participant W as WooCommerce
    participant X as Xaalis
    C->>W: Place order (Wave / Orange Money)
    W->>X: POST /v1/payments (Idempotency-Key wc:mode:order:amount)
    X-->>W: payment + checkout_url
    W-->>C: redirect to checkout_url (order "Pending payment")
    C->>X: pays with Wave / Orange Money
    X->>W: signed payment.succeeded webhook
    W->>W: verify, check order/amount/mode, payment_complete() once
    X-->>C: back to the order-received page
  • The payment is created with the order total as an integer XOF amount, client_reference = order number, metadata = {order_id, order_key}, success_url = the order-received page.
  • A total with decimals (e.g. 15000.50) is refused with an error, never rounded. Totals must be between 100 and 100 000 000 XOF.
  • Retrying the checkout returns the same Xaalis payment (same Idempotency-Key). If the cart total changes, a new payment is created. If the customer retries after a failed or expired payment, a new one is created too.

Only when Xaalis confirms it — never because the customer reached the “thank you” page (Never trust the redirect):

  1. the signed payment.succeeded webhook, or
  2. when the customer lands on the order-received page, the plugin asks GET /v1/payments/{id} server-side.

Either way the same checks run before anything changes: the payment is the one created for this order (id, order_id and order_key in metadata), livemode matches the store’s mode, the currency is XOF and the amount equals the order total. Until then the page says “Payment awaiting confirmation”.

Event Order
payment.succeeded Processing (stock reduced, emails sent) — exactly once, even if the webhook is replayed or races the return page
payment.failed Failed (the customer can retry from their account; a new payment is created)
payment.expired Cancelled (if still pending)
succeeded, but the order total changed since On hold with a note: review, then refund or adjust
a second payment succeeds on a paid order note “refund one payment”

The webhook answers 400 to a bad, missing or expired signature, 503 while no webhook secret is configured (so Xaalis retries), and 200 otherwise. Every order shows its Xaalis payment id on the order screen; the transaction id is the payment id once paid. Logs: WooCommerce → Status → Logs, source xaalis (ids and codes only, never keys).

With a sk_test_ key no real money moves. Place an order, then approve it on the hosted checkout, or from your server with POST /v1/payments/{id}/simulate {"outcome":"succeeded"} (see Test mode). The order should move to Processing within seconds.

integrations/woocommerce/dev has a disposable WordPress + WooCommerce (Docker, http://localhost:8480) wired to a local Xaalis API and a fresh test merchant:

Terminal window
integrations/woocommerce/tests/docker-test.sh # php -l + unit tests
integrations/woocommerce/dev/setup.sh # WordPress, WooCommerce, XOF store, 15 000 FCFA product, plugin configured
integrations/woocommerce/dev/e2e.sh # payment, webhooks, replays, forged signatures, failure, expiry, blocks
docker compose -p xaalis-woo -f integrations/woocommerce/dev/docker-compose.yml down -v

Details: integrations/woocommerce/xaalis-for-woocommerce/README.md. Building your own PHP integration instead? Use the PHP SDK.