More
Security
How payments, phones and keys are protected.
Payments#
- One MoMo Transaction ID can verify one payment — enforced by unique constraints and serializable transactions with row locks.
- SMS are accepted only from configured MoMo sender IDs; phone-number senders (spoofing attempts) are rejected.
- Admin decisions are final and audited; review reasons explain every non-automatic case.
Relay phones#
- Each phone gets its own secret at pairing (single-use, 10-minute code). Secrets are encrypted at rest with
DEVICE_SECRET_KEY. - Every request is signed with HMAC-SHA256 over timestamp, nonce, method, path and body hash; stale timestamps and repeated nonces are rejected.
- Revoking a phone takes effect immediately and the app unpairs itself.
- The app can be locked with a PIN, password or biometrics.
API & dashboard#
- API keys are stored as SHA-256 hashes and shown once; rotation is immediate.
- Admin sessions use httpOnly, secure cookies plus a custom header check; login is rate-limited.
- Webhooks are signed and timestamped.
- Public payment pages expose only what the payer needs and are rate-limited.
Your infrastructure#
- All data — SMS, payments, customers — stays in your PostgreSQL database on your server.
- Postgres and the API listen on loopback only; nginx terminates TLS.
- Nightly database backups (gzipped SQL, 14 days) are kept on the server — copy them off-site.
