Connect a custom payment gateway

The “Other” checkout provider lets your store take payments through your own payment gateway. You give MallBasket two things in Store setup: a payment-URL endpoint (your server) and a shared secret. MallBasket signs a request to your endpoint to get a payment link, and your gateway signs a webhook back to MallBasket when the payment finishes. This is a developer integration.

Set it up in the app

In Store setup → Online payments (Enabled) → Advanced → Checkout provider, choose “Other”, then enter your payment-URL endpoint and your shared secret (used to sign every message in both directions). Keep the secret private — anyone who has it can authorize orders.

1 — MallBasket requests a payment URL from you

When a buyer checks out, MallBasket sends a signed POST to your endpoint. Verify the signature, create a payment/checkout session on your side for exactly this amount and currency, and return its URL.

POST → your endpoint · body (application/json)
{
  "orderId": "6f2a…",              // your MallBasket order id
  "transactionId": "o_6f2a…",     // echo this back in the webhook
  "storeId": "store_abc",
  "userId": "user_123",
  "amount": "12.50",              // decimal string, charge exactly this
  "currency": "USD",
  "email": "buyer@example.com",
  "webhookUrl": "https://europe-west3-mallbasket.cloudfunctions.net/otherWebhook",
  "successUrl": "https://www.mallbasket.com/en/payment/complete?orderId=6f2a…&status=success",
  "cancelUrl": "https://www.mallbasket.com/en/payment/complete?orderId=6f2a…&status=cancelled",
  "nonce": "b1d9…",
  "metadata": { "itemId": "item_1" }
}
Header
x-mb-signature: <hex hmac-sha256 of the raw body with your secret>

Return the hosted payment URL. MallBasket opens it for the buyer. (data.paymentURL and url are also accepted.)

Your response · 200 (application/json)
{
  "paymentURL": "https://your-gateway.example.com/pay/abc123"
}

2 — Your gateway notifies MallBasket (webhook)

After the buyer pays, POST a signed message to the webhookUrl we sent you. MallBasket verifies the signature, confirms the amount matches the order, and marks the order paid. Only send status “success” once the payment has truly settled.

POST → webhookUrl · body (application/json)
{
  "orderId": "6f2a…",           // same order id
  "transactionId": "o_6f2a…",  // the transactionId we sent you
  "status": "success",          // only send this once payment truly succeeded
  "amount": "12.50",            // must equal the amount we sent
  "currency": "USD",
  "reference": "your-gateway-txn-id"   // optional, shown on the receipt
}
Header
x-mb-signature: <hex hmac-sha256 of the raw body with your secret>

3 — Signing (both directions)

Every request carries an x-mb-signature header: the hex HMAC-SHA256 of the RAW request body using your shared secret. Compute it over the exact bytes sent, and verify incoming ones over the raw bytes you receive (not a re-serialized object).

// Node.js — sign the EXACT raw body bytes you are about to send
const crypto = require("crypto");

const rawBody = JSON.stringify(payload);          // the bytes you POST
const signature = crypto
  .createHmac("sha256", MALLBASKET_SECRET)        // your restricted key
  .update(rawBody, "utf8")
  .digest("hex");

// send header:  x-mb-signature: <signature>
Verify an incoming request
// Node.js — verify a request MallBasket sent to your endpoint
const crypto = require("crypto");

function verify(rawBody, headerSig, secret) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(rawBody, "utf8")                        // RAW bytes, not re-parsed JSON
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(expected), Buffer.from(headerSig || "")
  );
}

Rules & guarantees

  • Amounts must match: the webhook amount must equal the amount MallBasket sent, in the same currency, or it is rejected.
  • Echo the transactionId exactly — MallBasket matches the payment to the order by it.
  • MallBasket authenticates your webhook with your store's secret only; another store cannot complete your orders.
  • Finalization is idempotent: it is safe to retry the webhook. MallBasket returns 2xx once the order is recorded; retry on any non-2xx.
  • Never send status “success” before the money has actually been captured.
MallBasket | Connect a custom payment gateway