67even

Paynow Integration Skill

Integrating the Paynow Zimbabwe payment gateway without the bugs that cost merchants money.

GitHub stars Tests MIT licence Last commit


Paynow’s documentation tells you to gate order fulfilment on paid(). Follow that advice and you will lose orders.

A transaction is fully paid in three states — Paid, Awaiting Delivery and Delivered. But the PHP SDK implements its helper as:

public function paid()
{
    return $this->status() === 'paid';
}

So Awaiting Delivery returns false. The money arrives, your callback returns 200, Paynow never retries, the dashboard shows the transaction as paid — and your customer gets nothing. Silently, with no error and no log line.

The Node SDK is worse: it has no paid() method at all, yet the published quickstart still shows if (status.paid()). That throws TypeError at runtime.

Paynow’s own worked example of a successful O’mari payment carries status=Awaiting+Delivery. The evidence was always there.

Every claim on this site was checked against paynow/php-sdk and npm paynow v2.2.2 directly, not taken from the documentation.


Where to start

   
Installing the skill Put the skill in Claude Code or on claude.ai, and confirm it loaded.
Troubleshooting Something is broken right now. Symptom-to-cause table.
Hashing & signatures Hash mismatches, and the two fixtures Paynow publishes.
PHP & Laravel SDK surface, the exceptions it throws, complete wiring.
Node.js & Express The SDK’s two defects, raw client, callback route.
HTTP API reference Every endpoint and field — for Python, Go, Java, C#.
Testing & go-live Test numbers, card tokens, and the go-live checklist.

The five rules that stop money going missing

  1. The returnurl is cosmetic — never fulfil from it. Only the server-to-server resulturl callback is authoritative.
  2. paid() does not mean paid. Check the status word yourself against all three paid states.
  3. Verify the hash over every value, in arrival order — never a documented field list. Paynow returns fields the docs omit, and they are inside the digest.
  4. Persist the pollUrl before you redirect, and send a unique merchanttrace on Express Checkout. Otherwise a lost response is unrecoverable.
  5. Make the callback idempotent and reconcile the amount. Paynow retries up to ten times and legitimately sends the same update more than once.

Install the skill

This reference also ships as a skill for Claude, so the guidance applies itself while you write the integration.

git clone https://github.com/67even/paynow-integration-skill.git
cp -r paynow-integration-skill/paynow-skills/paynow-integration ~/.claude/skills/

It includes two tools that need only Python and no dependencies: one that proves a hashing implementation against Paynow’s published fixtures in any language, and one that scans an existing codebase for the mistakes above.

cd paynow-integration-skill/paynow-skills/paynow-integration
python3 scripts/paynow_hash.py selftest              # 4/4 expected
python3 scripts/audit_integration.py /path/to/project

Known upstream documentation defects

Places where the Paynow Developer Hub is wrong about its own SDKs, verified against the shipped packages on 20 September 2026.

The hub says The shipped SDK does Severity
paid() covers the paid states status() === 'paid' only Critical
status.paid() (Node) No paid() exists Critical
let status = paynow.pollTransaction(url) Returns a promise; must be awaited High
Link-encoding recipe Published examples are not reproducible from the documented steps High
InnBucks com.innbucks.customer:// npm paynow builds schinn.wbpycode:// Medium
Initiate response has four fields Also returns paynowreference, which is inside the hash Medium
PHP constructor example Missing a comma — does not parse Medium
Shopify listed as a plugin No self-serve setup; email sales@paynow.co.zw first Low

If you re-check these against the hub later and find them disagreeing, the hub is the stale one — but please open an issue if the packages have changed.


Back to top

MIT licensed. Written and maintained by John Mugabe under 67even. Independent and community-maintained - not affiliated with or endorsed by Paynow Zimbabwe.