Skip to content

ZenoPay

Collect payments with ZenoPay

ZENOPAY pushes a payment request to the payer’s mobile-money wallet. The payer authorizes it on their handset, and the order is polled to completion.

Available to ISPs in Tanzania (TZ), alongside ClickPesa, AzamPay, PalmPesa, PawaPay, PesaPal, Relworx, PayPal, and DPO.

Before you start

  1. Complete ZenoPay merchant onboarding in an account owned by the ISP.
  2. Collect the API key from the ZenoPay merchant dashboard.
  3. Confirm your workspace is reachable from the public internet, so ZenoPay can deliver its webhook.

Configure the gateway

  1. Open Settings → Payments → ZenoPay

    Select ZenoPay from the payment marketplace.

  2. Enter the API key

    API key (required) is stored as a secret and is not echoed back into the form after saving. It is sent as the x-api-key header on every request.

  3. Leave the API host blank unless ZenoPay told you otherwise

    API host (optional) overrides the endpoint Centipid Billing calls. Leave it empty to use the default ZenoPay host.

  4. Run a controlled test payment

    Pay a small amount from the captive portal. Verify the wallet prompt arrives, the payment lands in the ledger with method ZenoPay, and the subscriber’s package is applied.

Credentials

Field Required Notes
API key Yes Secret. From the ZenoPay merchant dashboard. The only field required to switch to ZenoPay.
API host No Falls back to the default ZenoPay host. Enter a full URL.

Callback URLs

The webhook address is sent with every payment request, so there is nothing to register in the ZenoPay dashboard. Settings → Payments still shows it under Callback URLs (https://<your-host>/api/zenopay/webhook) so you can confirm the address ZenoPay will call, and check it is not blocked by a firewall or WAF rule.

What the payer must provide

  • Email address (supplied automatically). ZenoPay rejects an order without one, but no payer is asked to type an address. The subscriber’s saved profile email is used when there is one; otherwise an address is derived from the phone number being paid with, on an unroutable domain. A hotspot payer with no account can therefore pay normally. If ZenoPay ever emails a receipt, only payers with a real profile email will receive it.
  • Tanzanian phone number (required). Accepted in local or international form; it is normalized before it is sent.
  • Amount. Rounded to a whole number before the request is sent.

Because authorization happens on the payer’s handset rather than in a hosted checkout page, no ZenoPay domain needs to be added to the captive walled garden.

How a payment completes

  1. Request

    Centipid Billing posts the order to /api/payments/mobile_money_tanzania with an order id it generates itself. That id is the local transaction reference, so the handle everything reconciles against exists before ZenoPay answers.

  2. Authorization

    The payer approves the request on their phone.

  3. Confirmation

    A background job polls /api/payments/order-status every 5 seconds, for up to 40 attempts (about 3 minutes 20 seconds), until the order reaches a terminal state. This poller — not the webhook — is what completes the payment, so a payment still completes when the payer closes the captive browser mid-checkout.

  4. Provisioning

    On COMPLETED, a payment is recorded with method ZenoPay and the subscriber’s package is applied asynchronously. On FAILED, the reason is stored against the transaction and nothing is credited.

A failed request is deliberately not retried automatically. An automatic retry after a lost response could raise a second prompt on the same order and charge the payer twice. The payer retries by choice instead.

Troubleshooting

Symptom What it means What to do
“ZenoPay API key not configured.” No API key is saved. Enter it in Settings → Payments → ZenoPay.
“ZenoPay authentication failed. Check the API key.” ZenoPay rejected the key. Re-copy it from the merchant dashboard. Confirm the account is live.
“A valid Tanzanian phone number is required for ZenoPay payments.” The number could not be normalized. Re-enter it in local or international form.
“Could not reach ZenoPay. Please try again.” The request could not reach ZenoPay. Check outbound connectivity from the application host, and any custom API host value.
A message from ZenoPay on a failed request ZenoPay refused the order and its own reason is shown. Read the message — it usually names the field at fault.
Payer paid, but the transaction sits pending The order never reached a terminal state within the polling window. Confirm the payment on the ZenoPay dashboard, then raise it with support with the order id and the payer’s phone number.

For symptoms that are not specific to ZenoPay, see Payment troubleshooting. For every other gateway’s fields, see the credential reference.