Provider · Card

Card — Visa / Mastercard

Cards are acquired through Waafi's hosted page. You create a PaymentIntent with provider=waafi and metadata.waafi_mode=card, then redirect the customer to Waafi's PCI-compliant page where they enter their card. Raw card data never touches your server (PCI SAQ-A), and 3-D Secure is handled there when the issuer requires it. It's the same redirect shape as the Waafi wallet flow — only the payment method differs.

CardSAQ-A3-D Secure

Same redirect contract as Waafi wallet

If you've already wired the Waafi wallet flow (waafi_mode: "hpp"), cards are a one-word change: waafi_mode: "card". The next_action is the same redirect — there's no PAN field, no OTP, and no MSISDN to collect on your side.

1 · Create the PaymentIntent (server-side)

bashbash
curl -X POST https://api.merashub.com/v1/payment_intents \
  -H "Authorization: Bearer sk_live_..." \
  -H "Idempotency-Key: order_42" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 100,
    "currency": "DJF",
    "provider": "waafi",
    "metadata": { "waafi_mode": "card" },
    "return_url": "https://yoursite.example/orders/42/return",
    "description": "Order #42"
  }'
Response — next_action.type = redirectjson
{
  "id": "pi_01H...",
  "status": "requires_action",
  "next_action": {
    "type": "redirect",
    "redirect_url": "https://hpp.waafipay.com/pay/CD34..."
  }
}

2 · Redirect, then verify on return

javascriptjavascript
// Send the customer to Waafi's hosted page — they enter the card THERE.
if (intent.next_action?.type === 'redirect') {
  res.redirect(303, intent.next_action.redirect_url);
}

// When they finish, Waafi returns them to return_url and fires the webhook.
// Never trust the return redirect alone — re-fetch the intent to confirm:
app.get('/orders/42/return', async (req, res) => {
  const r = await fetch(
    'https://api.merashub.com/v1/payment_intents/' + intentId,
    { headers: { 'Authorization': 'Bearer ' + process.env.MERAS_SECRET_KEY } },
  );
  const fresh = await r.json();
  res.render(fresh.status === 'succeeded' ? 'thank-you' : 'try-again');
});

Don't build a card form

Because the card is entered on Waafi's page, you must not render a PAN/CVV field in your app — doing so pulls you into PCI SAQ-D. Redirect and verify; that's the whole integration.

Alternate acquirer · Cybersource CNP (international)

For international card acceptance (cards issued outside the Horn of Africa, Amex, JCB), MerasPay can route to Cybersource card-not-present with iframed Elements served from js.merashub.com — the card is tokenised inside the iframe and your origin only sees a pm_… handle. This acquirer is enabled per-merchant and is a sandbox stub until live Cybersource credentials are provisioned. See the International Gateway product page for that path.