FivePay payment gateway

FivePay connects a business website to PayChangu so its customers can pay online and the business can confirm which orders have been paid.

The public service currently runs PayChangu sandbox payments. No real money moves during sandbox tests.

How a payment works

FiveBuy checkout flow
  1. Customer orders on FiveBuyChooses to pay at checkout
  2. FiveBuy asks FivePay for a payment linkFivePay creates the link through PayChangu
  3. Customer pays on PayChanguPayChangu tells FivePay the result
  4. FivePay verifies the paymentFivePay checks the result with PayChangu and confirms it to FiveBuy
  5. FiveBuy marks the order as paidThe shop can now process the order
  1. The customer checks out. They place an order on a business website, such as FiveBuy, and choose to pay.
  2. The website asks FivePay for a payment link. It sends FivePay the order number and amount. FivePay creates a checkout link through PayChangu.
  3. The customer pays on PayChangu's checkout page. PayChangu handles the payment and tells FivePay the result.
  4. FivePay confirms the payment. FivePay checks the result with PayChangu and lets the business website know when the order is paid. The business can then process the order.
  5. The business tracks its balance. Its FivePay dashboard shows payments and payout requests. A payout is a separate step that sends money to the business. Payouts in this test environment are simulated.

How FiveBuy will use FivePay

FiveBuy is the shop where customers place orders. FivePay is the payment gateway FiveBuy will use at checkout. FiveBuy's server will use its own FivePay merchant account and API key to create a payment link for each order. Once FivePay confirms payment, FiveBuy can mark that order as paid.

Payment route: FiveBuy → FivePay → PayChangu checkout.

Developer reference

The examples below use the public API address https://test.fivepay.online. Use your merchant token from your website backend.

Authentication

Sign in to the merchant portal and choose Generate website API key. Store the key on your website server and send it with each API request. Generating a new key revokes the previous one.

Authorization: Bearer YOUR_MERCHANT_API_KEY
Content-Type: application/json

POST /api/v1/payments

Create a hosted checkout. Use a positive whole MWK amount and a unique order reference for each order. To retry, send the same reference and amount. A different amount for the same reference returns 409.

curl -X POST https://test.fivepay.online/api/v1/payments \
  -H 'Authorization: Bearer YOUR_MERCHANT_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"order_reference":"order-1001","currency":"MWK","amount":10000}'

The response includes payment_reference, status, and checkout_url. Redirect the customer to the checkout URL once it is present.

POST /api/v1/payments/mobile-money

Start a PayChangu sandbox mobile money payment without opening a checkout link. Send the order total from your backend. The customer approves on their phone. Check the payment reference for confirmation.

{"order_reference":"order-1002","currency":"MWK","amount":100,
 "network":"airtel","phone":"0990000000"}

Use airtel or tnm. Reuse the same order reference and details when retrying an uncertain request. For a confirmed failure, use a new order reference for the next attempt.

GET /api/v1/payments/{payment_reference}

Check the status using the payment reference returned at creation. Fulfill the order once the status is paid. A test payment includes test_mode: true.

GET /api/v1/dashboard

Read your available MWK balance, payments, payouts, and notification delivery history.

POST /api/v1/payouts/{uuid}

Request a simulated payout with {"amount":5000}. Generate a UUID for the request and reuse it on retries. An approved test payout has status simulated_paid.

POST /api/v1/settings

Save an approved HTTPS webhook URL and a test payout destination. Send both fields because omitted fields are cleared.

{
  "webhook_url": "https://your-store.example/payments",
  "payout_destination": "Test bank account"
}

When a webhook URL is configured, the response includes your signing secret. Keep it private.

Payment webhooks

FivePay sends payment.succeeded events to your registered URL and retries failed deliveries. Validate FivePay-Signature as a hex HMAC-SHA256 over timestamp + "." + rawBody, using the merchant signing secret. Read the timestamp from FivePay-Timestamp, reject stale requests, and deduplicate by event id. Return a 2xx response after accepting the event.

Fees and settlement

New payments carry a 5% FivePay fee, which covers PayChangu processing charges. The fee is rounded to the nearest MWK 0.01 and stored with the payment. Confirmed payments remain pending settlement until an administrator approves the provider settlement. The dashboard separates available funds from pending settlements. Sandbox provider payouts require a verified beneficiary. The local simulator marks payouts simulated_paid.

Bank transfer payments

POST /api/v1/payments/bank-transfer with your merchant bearer token and an MWK order total. The response contains bank_transfer with the bank name, account number, account name and expiry timestamp. Display those details on your checkout page and ask the customer to transfer the exact amount. Poll the normal payment status endpoint and fulfil only after verified paid.

{"order_reference":"bank-order-1001","currency":"MWK","amount":100}

Use the same order reference and amount when retrying. The test provider normally approves sandbox bank transfers automatically. A real transfer requires the customer to pay the generated account.

Embedded card payments including Visa

POST /api/v1/payments/card from your backend with the merchant bearer token and the customer email. This prepares a FivePay reference and returns card_checkout for the PayChangu hosted form. Availability requires the provider public key.

{"order_reference":"card-order-1001","currency":"MWK","amount":100,"email":"customer@example.com"}

Load https://checkout.paychangu.com/embed.js on your checkout page, then mount the returned configuration in an empty element.

<div id="card-payment"></div>
PayChangu.mountCheckoutForm({
  ...payment.card_checkout,
  target: '#card-payment',
  onSuccess() { checkOrderOnYourBackend(); },
  onError(error) { showPaymentMessage(error.message); }
});

PayChangu handles the card fields and any required authentication. FivePay verifies the reference, mode, amount and currency separately before changing the order to paid. Treat the browser callback as a prompt to check server status.

GET /api/v1/payment-methods with the merchant token to check enabled methods. An unconfigured card public key returns card=false and card creation returns 503.

Payouts

POST /api/v1/payouts/{uuid} with {"amount":"90.50"}. This reserves available funds. An administrator must first verify the beneficiary account and then approve each payout. Read GET /api/v1/payouts/{uuid} to check requested, processing, unknown, paid, failed or rejected. Uncertain transfers retain their reservation while FivePay queries PayChangu. Reuse the same UUID on retries.

Refunds

POST /api/v1/refunds/{uuid} with {"payment_reference":"payment-uuid","amount":"50.00","reason":"Customer cancellation"}. The merchant needs enough available funds for the full refund. FivePay keeps its platform fee. A refund is approved by an administrator and completed manually through the provider. The administrator records the provider reference after confirming completion. The state completed_external records that manual attestation.

GET /api/v1/refunds lists your refunds. Payment status responses include refunded_amount for externally completed refunds. Compare it with the order total to distinguish partial and full refunds. Payouts and refunds require the merchant bearer token. Refunds currently do not call a mobile money reversal API.

Request recovery

If creation times out, reuse the same reference and request body and check its payment status. An initialization_status of unknown means FivePay is checking whether PayChangu accepted the request. Do not create another charge for the same customer while the first result is uncertain.

Common errors

400 Invalid input. 401 Invalid or missing credentials. 404 Payment not found for this merchant. 409 Conflicting request or insufficient funds. 429 Too many requests, retry after the indicated delay. 502 PayChangu could not initialize checkout.