CentraPoint

Guides

Payment flow

The hosted checkout lifecycle: payment page, gateway, return and cancel URLs, gateway notifications, verification and statuses.

On this page

Overview#

Payment flow sequence
#WhoWhat happens
1Your server → CentraPointCreate a payment link (POST /api/v1/payment-links) with your order ID as externalReference, and send the url to the payer.
2Payer → CentraPointOpens /pay/{token}, enters details, chooses a payment method. CentraPoint creates a pending transaction with a new reference.
3Payer → GatewayIs redirected (or auto-posted) to the gateway's hosted page, or approves a prompt on their phone for mobile money.
4Gateway → CentraPointSends a server-to-server notification. CentraPoint verifies it and updates the transaction.
5Gateway → Payer → CentraPointPayer returns to /payment/return?ref=… (or /payment/cancel?ref=…). While still pending, CentraPoint asks the gateway directly.
6CentraPoint → Your serverSends a signed webhook such as payment.complete to your endpoint(s).
7Your serverVerifies the webhook and fulfils on complete. Fallback: finds references with GET /api/v1/payment-links?externalReference=… and checks them with GET /api/v1/transactions/{reference}.

1. Hosted payment page#

The link URL (https://app.centrapoint.co.za/pay/{token}) shows your organisation's name, the title, description and amount (with the billing period for recurring products). The payer enters first name, last name, email and mobile number (needed for mobile money). If the link is attached to a customer, these are pre-filled.

If more than one of your enabled gateways supports the link's currency, the payer picks a method under Pay with. Your default gateway is listed first.

Before creating a transaction, CentraPoint checks that the link:

  • exists and its signature is valid (amount and currency have not been tampered with);
  • is active, not expired, and (for single-use links) not already paid;
  • is not for an invoice that is paid or cancelled;
  • belongs to an account that is not read-only and still within its monthly transaction limit.

2. Hand-off to the gateway#

CentraPoint creates the transaction with status pending and a unique reference, then starts checkout with the selected gateway, passing:

  • the reference as the gateway's merchant reference;
  • a return URL https://app.centrapoint.co.za/api/payment/return?ref={reference} (which accepts the gateway's GET or POST and redirects the payer to /payment/return?ref=…) and a signed cancel URL https://app.centrapoint.co.za/payment/cancel?ref={reference}&sig={signature};
  • a notification URL https://app.centrapoint.co.za/api/webhooks/{type}?provider={providerId} (see Gateway notification URLs).

Depending on the gateway, the payer is then:

  • redirected to a hosted page (e.g. Yoco, Peach Payments, Paystack, Flutterwave, DPO Pay, Pesapal);
  • auto-posted via an HTML form (e.g. PayFast, Ozow, PayGate, Netcash Pay Now); or
  • prompted on their phone (M-Pesa STK Push, MTN MoMo). The page shows the gateway's instructions and an I have approved the payment button that goes to the return page.

If the gateway rejects the checkout request (for example an unsupported currency or invalid phone number), the transaction is marked failed and the payer sees the error and can try again, which creates a new transaction.

3. Return and cancel URLs#

Return page#

/payment/return?ref=… shows the payment status, amount and reference. The return URL is never trusted as proof of payment: anyone can open it. If the transaction is still pending, CentraPoint queries the gateway directly (for gateways that support on-demand verification) before showing the page, and the page refreshes every 5 seconds for about two minutes while it waits.

If the payment link has a returnUrl, the result page sends the payer on to it once the status is final, adding ?reference=…&status=complete|failed|cancelled. The cancel page offers a "Return to …" button with status=cancelled.

Cancel page#

The cancel URL carries an HMAC signature (&sig=) generated for that payment. Only a correctly signed cancel URL marks a still-pending transaction as cancelled and offers a Try again button while the link is still active. Opening /payment/cancel?ref=… without a valid signature shows a generic message and changes nothing, so knowing a reference is not enough to cancel a payment. Because statuses only move forward to stronger outcomes, a verified success from the gateway that arrives later still moves the transaction to complete.

4. Gateway notification and verification#

The gateway calls CentraPoint's notification URL server-to-server. For every notification CentraPoint:

  1. logs the raw request in the organisation's Webhook log (dashboard);
  2. authenticates it with the gateway's mechanism (signature, shared secret, and/or a server-side status query to the gateway);
  3. checks the amount and currency match the transaction;
  4. applies the new status idempotently, and runs fulfilment once.

If a notification never arrives, a background job re-queries the gateway for payments still pending after 5 minutes (for up to 24 hours), on gateways that support on-demand verification.

Details per gateway are on each gateway page; the security model is described in Gateway notification URLs & security.

5. Your server confirms#

Recommended: subscribe to webhooks. CentraPoint sends a signed payment.complete, payment.failed, payment.cancelled, payment.refunded or payment.partially_refunded event to your endpoint as soon as the status changes. Verify the signature, de-duplicate on the event ID, and fulfil.

Fallback: look up the payments for your order with GET /api/v1/payment-links?externalReference=… (or by link ID), then call GET /api/v1/transactions/{reference}. Fulfil the order only when status is complete, the externalReference is your order, and the amount and currency match what you expect. See Finding the references for your order.

Status lifecycle#

Transaction status lifecycleA transaction starts as pending. Verified gateway updates move it to cancelled, failed or complete. Cancelled can move to failed or complete, and failed can move to complete. Complete can become partially refunded or refunded, and partially refunded can become refunded. Statuses never move backwards.late successlate successverified successrefunds: dashboard onlypendingcancelledfailedcompletepartially_refundedrefunded
Transaction status lifecycle. Arrows show the only allowed transitions.
  • Gateway updates are ranked pending < cancelled < failed < complete, and a status can only move up. A late failed cannot undo complete.
  • refunded and partially_refunded are set only when a refund is recorded in the dashboard, and gateway notifications no longer change such transactions.
  • A notification whose amount or currency differs from the transaction is rejected and the transaction stays unchanged.
  • Debit order collections follow their own lifecycle and can move from complete to failed on a bank unpaid; see Debit orders.

What happens on completion#

When a transaction first becomes complete, CentraPoint automatically:

  • records paidAt, and the gateway fee and net amount when reported;
  • increments the link's paid count and deactivates it if it is single-use;
  • adds the amount to the linked invoice and marks it paid when fully paid;
  • stores the subscription token for recurring payments, so renewals can be tracked.