Zahlo’s WooCommerce plugin supports a capability-gated Zahlo Checkout gateway: the plugin discovers the merchant’s current card and wallet capabilities and creates a hosted card session.

Requirements

  • WordPress 6.0+
  • WooCommerce 8.0+ (9.5 tested)
  • PHP 8.0+
  • A Zahlo merchant account that is ready for hosted payment methods
  • A public HTTPS store origin for return and signed callback delivery

Install and configure

  1. Install and activate the zahlo-pay plugin.
  2. Open WooCommerce → Settings → Payments → Zahlo Checkout.
  3. Enter the server-side Merchant API Key and Merchant API Origin. Saving verifies the key with GET /api/v1/payment-methods.
  4. Enter the browser public_api_url. Use the HTTPS tunnel origin for a local store; an HTTPS store cannot load the SDK from HTTP.
  5. Enter the public store_public_url used for hosted return and callback URLs. Do not use localhost for a remote sandbox or production store.
  6. Enable card in the Zahlo merchant account and clear WooCommerce transients after capability changes.

Environment selection

Use the Demo environment while integrating and testing. Set the plugin’s Merchant API Origin to https://merchant-demo.zahlo.eu, use a Demo API key, and keep return and callback URLs on an HTTPS Demo store origin. Before going live, switch all three values together to https://merchant.zahlo.eu, a production API key, and the production store origin. Never mix a Demo key with the production origin or a production key with Demo.
Configure Zahlo Checkout with your merchant API origin and active server-side API key. Use hosted checkout sessions for store orders.

Supported methods and checkout modes

The plugin requests GET /api/v1/payment-methods with the API key. If the response is unavailable, malformed, or reports no supported method, Zahlo Checkout is hidden. The hosted session then uses POST /api/v1/checkout-sessions with mode: "hosted" and method: "card". Both Classic checkout and WooCommerce Checkout Blocks use the same gateway ID, order correlation, hosted redirect, and callback path. Wallet visibility also depends on the shopper’s device/browser and the configured hosted domain. The plugin does not collect raw card data or add OAuth; it delegates payment interaction to the hosted checkout.

Order and callback lifecycle

  1. WooCommerce creates one hosted session with the order amount in integer minor units, EUR currency, return URLs, callback URL, and an order-scoped idempotency key.
  2. The order stores _zahlo_session_id and _zahlo_client_token, moves to on-hold, and the cart is emptied.
  3. The thank-you page loads the Zahlo SDK from public_api_url. The client token is sent as a form/body or bearer credential; it is never put in a URL.
  4. A browser success return is reconciled with the authoritative session. It is not by itself proof of payment.
  5. Zahlo sends a signed POST /?wc-api=zahlo_webhook. The plugin verifies the raw-body HMAC, correlates session/reference, gateway method, amount, and currency, and applies the order transition once.
  6. Duplicate confirmations are acknowledged without a second transition. Failed and cancelled events leave the order unpaid; pending or expired sessions show retry guidance without a redirect loop.

Security

  • Keep the Merchant API Key in server-side WordPress settings or protected configuration. It is also the HMAC callback secret and is never placed in browser scripts.
  • Use HTTPS for the merchant origin, browser origin, public store origin, and callback delivery in production.
  • Fulfill only from the confirmed order status / signed callback path. Do not fulfill from a thank-you URL alone.
  • Keep the plugin’s server API origin and browser API origin distinct when a local server is exposed through an HTTPS tunnel.

Upgrade, uninstall, and troubleshooting

Upgrading preserves orders, gateway settings, and hosted session metadata. After changing an origin, clear WooCommerce transients and flush rewrite rules, then run one Classic and one Blocks test order. Deactivation does not delete orders or options; remove old options only as an operator-controlled cleanup after confirming no pending orders depend on them.
  • Gateway missing: verify the API key and check the card/wallet capability response; the plugin fails closed when capability discovery fails.
  • SDK or redirect fails: check public_api_url is HTTPS and store_public_url is publicly reachable.
  • Order remains on hold: inspect _zahlo_session_id and callback delivery; do not mark the order paid manually from the browser return.
  • Invalid signature: confirm the matching merchant API key and verify that the callback URL is the generated /?wc-api=zahlo_webhook endpoint.