Paystack

Paystack hosted payments in NGN, GHS, ZAR, KES and USD: the secret key, the webhook, verification, refunds and troubleshooting.

The Paystack plugin takes payments through the hosted Paystack page: cards, bank transfer and mobile money in Nigeria, Ghana, South Africa and Kenya. It is free, and it is offered only on invoices in NGN, GHS, ZAR, KES or USD; on an invoice in any other currency the gateway is hidden. It also sends refunds to Paystack from the invoice. What all gateways share is in Payment gateways.

Switching it on

  1. Open Setup → Payment Gateways, tab All Payment Gateways, press Activate on Paystack.
  2. Enter the Secret key (and the public key if you wish) and save.
  3. Paste the Webhook URL into your Paystack dashboard.
  4. Test with your test key first.

Settings

SettingMeaning
Display name, Payment instructions, Fee %, Fixed feeThe settings every gateway has.
Test modePaystack has one API address: use your sk_test_ key. This switch only labels the payment Test mode.
Secret keysk_live_... or sk_test_..., from Settings > API Keys & Webhooks. It also signs the webhook. Leave empty to keep the saved one.
Public keypk_live_... or pk_test_.... Kept for reference; the plugin does not use it.
Webhook URLRead only: https://billing.example.com/callback/paystack. Paste it into Settings > API Keys & Webhooks.

Without a secret key the invoice shows Paystack is not set up yet: the secret key is missing.

What Paystack needs from you

  • A Paystack account (the business must be verified to go live).
  • The secret key, and the Webhook URL pasted into the Paystack dashboard. Paystack signs each webhook with your secret key, so no separate webhook secret exists.
  • HTTPS on your site and the PHP curl extension. No IP address needs to be whitelisted by this plugin.

How a payment goes

  1. The client presses Pay ... with Paystack on an unpaid invoice. The plugin starts a Paystack transaction for the balance due in the invoice currency, with a reference of the form INV12X..., the client's e-mail and the invoice number as metadata, and sends the client to Paystack's page.
  2. The client pays and Paystack sends the browser back to the callback address with the reference.
  3. The plugin verifies the reference with Paystack. The status must be success and the currency the invoice's currency. The amount and the Paystack fee come from Paystack.
  4. The reference becomes the transaction ID and the invoice is marked paid.
  5. Paystack also sends a charge.success webhook. It is accepted only when its signature (an HMAC with your secret key) is right. It records the same payment if the browser never came back. A payment seen twice is recorded once.

Refunds

On the invoice open the Refund tab, choose the transaction, give the amount and choose Refund through the payment gateway. The plugin asks Paystack to refund the reference; Paystack's answer is Refund started because the money moves later. If Paystack refuses, its message is shown. See Invoices and payments.

Testing

  1. Enter the sk_test_ key and switch Test mode on.
  2. Pay a small invoice in NGN (or another allowed currency) with one of Paystack's test cards.
  3. The invoice should turn Paid. In the Paystack dashboard, in test mode, the transaction is listed.
  4. Enter the live key and switch Test mode off.

Troubleshooting

Look in Billing → Gateway Log (filter Paystack) and Utilities → Module Log.

Message or resultCure
Paystack is not offered on an invoiceThe invoice currency is not NGN, GHS, ZAR, KES or USD.
Paystack could not start the payment: ...Paystack's own message follows, such as an invalid key or a currency your business is not enabled for.
verify failed / The payment could not be verified.The secret key is wrong or the server cannot reach Paystack.
bad signature / The webhook signature is not valid.The secret key here is not the one Paystack signs with (live and test keys mixed up).
No Paystack reference was given.Someone opened the callback address by hand.
currency mismatchThe payment currency differs from the invoice.
The payment was not successful.The client abandoned or failed the payment.

You can always record a payment by hand with Add Payment. More in Troubleshooting.

Was this helpful?

Updated 2026-11-03