Hosted checkout

Take a payment on a Watenga page, or in your site or app, for an amount your server decides.

Your server creates a checkout session with its secret key: the amount, currency, your order reference and where to send the customer afterwards. The customer then pays on the session’s hosted page (url), or in your page with Watenga.js, or in your app with a mobile payment sheet, using the session’s client_secret. The browser or app never decides the amount.

The page offers the methods your business accepts in the customer’s market (cards, mobile money, Zimswitch) in your Checkout Studio design.

Keys and scopes

A secret key, or a restricted key with the transactions write scope.

1. Create a checkout session

Amounts are decimal strings. reference is your order number; metadata comes back on the payment and in its webhooks.

typescript
const session = await watenga.checkoutSessions.create({
  amount: '25.00',
  currency: 'USD',
  reference: 'ORD-1001',
  return_url: 'https://shop.example/orders/ORD-1001',
  customer_email: 'ada@example.com',
  metadata: { order_id: 'ORD-1001' },
});
// session.url: the hosted page; session.client_secret: for Watenga.js or a mobile sheet

2. Send the customer to pay

Redirect to session.url, or mount the checkout in your page with Watenga('pk_test_…').mount('#checkout', { clientSecret, amount: 25, currency: 'USD', reference: 'ORD-1001', onSuccess, onError }) (events).

After a card payment the customer comes back to your return_url with watenga_payment (the transaction id) and watenga_status in the address: a hint for the page, never proof of payment.

3. Confirm the payment on your server

Fulfil the order when the payment.capture.completed webhook arrives (its data.object is the transaction, with your metadata), or read the session back: status becomes completed and transaction_id names the payment.

typescript
const paid = await watenga.checkoutSessions.retrieve(session.id);
if (paid.status === 'completed') {
  const txn = await watenga.transactions.retrieve(paid.transaction_id!);
}

4. Close an unpaid session

When the order is cancelled on your side, expire the session so it can no longer be paid. While a payment for it is under way the API answers 409 CHECKOUT_SESSION_IN_PROGRESS.

typescript
await watenga.checkoutSessions.expire(session.id);

Webhook events

EventWhen
payment.capture.pendingA mobile-money prompt waits on the customer’s phone
payment.capture.completedThe payment succeeded: fulfil the order
payment.capture.declinedThe card issuer or wallet declined it
payment.capture.cancelledThe customer cancelled it
payment.capture.expiredNobody paid before the session expired

Each event carries the object in data.object; verify the signature first (Webhooks).

Test it

Use a test secret key (sk_test_…): it never moves money. Pay with the test cards and wallet numbers, and receive the webhooks on your machine with watenga listen --forward-to http://localhost:3000/webhooks (CLI).

Related: Watenga.js · Mobile SDKs · Idempotency