OTP verification
Channels, code rules, rate limits, templates and the returning-customer skip.
A one-time code confirms that the person at the cart controls the phone number they entered. Until it is verified, they cannot place a COD order — they can still pay prepaid, or leave.
Settings
| Setting | Default | What it does |
|---|---|---|
otpEnabled | true | Require OTP before COD checkout. |
otpChannel | SMS | SMS, WHATSAPP or BOTH. Delivery in the current build is WhatsApp. |
otpMaxRetries | 3 | Maximum sends and wrong-code attempts per window. |
otpResendCooldown | 30 | Seconds a customer must wait between resends. |
otpSkipReturning | false | Skip verification for phone numbers that already cleared an OTP. |
otpMsgTemplate | Your verification code is {otp}. Valid for 10 minutes. | The message body. {otp} is substituted at send time. |
Code rules
- Length: 6 digits.
- Expiry: 10 minutes.
- Storage: SHA-256 hashed. The plaintext code is never written to the database.
- Rate limit:
otpMaxRetriessends per phone number per 10-minute window. Exceeding it returns HTTP 429. - Wrong codes: each attempt increments a counter and the response includes the number of attempts remaining. After
otpMaxRetrieswrong codes the number is locked for the rest of the window.
Delivery
Messages go out through the Meta WhatsApp Cloud API using an approved template — verifynumber by default. All credentials are held server-side as environment variables; nothing sensitive is exposed to the storefront.
Choosing settings
Do not exempt low-value orders. It sounds harmless, but low-value COD is where impulse ordering — and non-delivery — concentrates.
Do turn on the returning-customer skip once you have a base of verified numbers. A customer who verified before and took delivery is the strongest signal available, and re-verifying them is friction with no information behind it.
Leave the retry limit at three. Two is tight enough to punish real customers who mistype a code or lose the message under other notifications.
