M

MyOTP Phone Verification

0/5 (0 ratings) — active installs Updated Sep 25, 2026

MyOTP Phone Verification sends a one-time code to a visitor’s phone and checks it before they can continue. It uses the MyOTP.App API (https://myotp.app), one key for SMS, WhatsApp and Telegram.

What it does:

  • WooCommerce checkout: a Send code button under the billing phone. The order cannot be placed until the billing number is verified. Optionally only for guests.
  • WordPress registration: a phone field with the same flow on wp-login.php?action=register. The verified number is saved as user meta myotp_verified_phone.
  • Shortcode [myotp_verify]: the same widget on any page. Fires a myotp:verified event on document with the number in event.detail.phone.
  • Settings page (Settings > MyOTP): API key, channel, code length, validity, brand, and a Send test code button.

How it stays safe:

  • The API key never leaves the server. The browser talks to admin-ajax.php only.
  • Every AJAX call carries a nonce. Admin actions check manage_options.
  • Send limits, enforced together with atomic counters: 5 codes per visitor, 10 per client IP, 3 per destination number, each per 10 minutes, plus a site-wide ceiling (default 100, setting and myotp_pv_site_hourly_cap filter). The site-wide count uses a fixed one-hour window that starts at the first send, so up to twice the ceiling can go out across a window boundary. It exists to bound what an attacker with many addresses and many numbers can make the site spend. A code that was not billed (provider answered 409 or a server error) is not counted against it.
  • A visitor can only verify the code they requested: the challenge reference from the provider is stored with the pending record and sent back on every check. If the provider still has an active code that this visitor did not request, a fresh code is sent for this visitor instead (still within every send limit).
  • 5 wrong codes put this visitor on a 15-minute cooldown for that number. Sending and checking are both refused for that visitor while it lasts; other visitors are not affected, and nothing is keyed on the phone number alone, so nobody can lock a number’s owner out. Only a provider answer of “wrong code” counts; an expired code, a network failure or a provider error never does.
  • A verification is valid for 30 minutes and is claimed by exactly one checkout or one registration at validation time, then consumed when the order or account exists. If checkout fails after validation (a declined payment, for example) the visitor verifies again.
  • Phone numbers are reduced to digits before they are sent. Leading zeros are kept.

Not in this version: the WooCommerce block checkout. The classic shortcode checkout is supported.

External service

This plugin sends the phone number a visitor enters to the MyOTP.App API at https://api.myotp.app to deliver a one-time code and to check the code the visitor types. No other data is sent. MyOTP.App privacy policy: https://myotp.app/privacy-policy/. Terms: https://myotp.app/term-condition/.

Data stored on your site

  • A cookie myotp_pv_sid (random id, one day) so a guest’s verification can be tied to their browser.
  • Rows in the options table (myotp_pv_kv_ prefix, not autoloaded): rate-limit counters (a row lives for one window after the last send it counted: 10 minutes, site-wide 1 hour), the pending number with its code reference and attempt count (kept for the configured code validity, at most 4 hours), a 15-minute per-visitor cooldown row after five wrong codes, and the verified number (30 minutes). Expired rows are removed on the next read of that row and by a daily WP-Cron sweep (myotp_pv_sweep). WP-Cron runs on page visits, so on a quiet site the sweep can run later than scheduled.
  • Order meta _myotp_verified_phone on each verified WooCommerce order.
  • User meta myotp_verified_phone on each account registered through the verified form.

Uninstalling removes the settings, the scheduled sweep, the counters, the pending records and the verified records. Order meta and user meta are part of your customer records and are kept. The plugin registers suggested text for your privacy policy under Settings > Privacy.