Search pages in the SMS Pay documentation.
Payment security depends on protecting API keys, verifying webhook signatures, preventing replay attacks, isolating sandbox/live environments, and keeping fulfillment idempotent.
Good:
SMS_PAY_LIVE_KEY=sk_live_xxxxxxxxxxxxxxxxx
Bad:
<script>
window.SMS_PAY_KEY = "sk_live_xxxxxxxxxxxxxxxxx";
</script>
import crypto from "node:crypto";
export function verifyWebhook(rawBody: Buffer, signature: string, secret: string) {
const expected =
"sha256=" + crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
const left = Buffer.from(signature);
const right = Buffer.from(expected);
return left.length === right.length && crypto.timingSafeEqual(left, right);
}
Signed webhook request:
POST /webhooks/sms-pay
X-Webhook-Id: delivery_123
X-Webhook-Event: payment.paid
X-Webhook-Signature: sha256=<hex>
X-Webhook-Timestamp: 2026-05-05T10:01:00.000Z
Content-Type: application/json
{
"event": "payment.paid",
"environment": "LIVE",
"timestamp": "2026-05-05T10:01:00.000Z",
"data": {
"payment_intent_id": "pi_live_123",
"amount": "500",
"currency": "BDT",
"customer_reference": "SP7A91BC2D0",
"merchant_reference": "ORDER-10045"
}
}
Expected response:
HTTP/1.1 200 OK
Recommended controls:
X-Webhook-Id you process.X-Webhook-Timestamp and reject very old requests when your infrastructure allows.payment.paid cannot ship twice.Install the SMS Pay Android app only from the official SMS Pay download link. The app is not on the Play Store yet.
Use a trusted merchant phone, allow SMS permission only for the SMS Pay app, and keep the device online. If the device is lost or replaced, disable the old device from the dashboard before connecting a new one.