BlueTheme Docs

Account and one-time code login

Customers log in with a one-time code sent by SMS or email, with a password, or both. The settings are in Theme Options → Shop → Account & login. The code is in inc/Account, and the form's script and styles are in src/frontend/account and src/scss/account (the account bundle, loaded only where a form shows).

How it works

  • Sign in or sign up in one step: the visitor enters a mobile number (or an email, when email codes are on), gets a code, and types it. A number or email that has no account yet gets one when both of these allow it:
    • Registration in Theme Options: mobile, email or both.
    • The site's own registration setting: WooCommerce's "Allow customers to create an account on the My account page", or "Anyone can register" without WooCommerce.
  • New accounts:
    • From a mobile number: the username is the number, with no email. The number is saved to the profile.
    • From an email: WooCommerce's own sign-up is used, with its username rules, hooks and welcome email.
  • Numbers: they are accepted in any common spelling (Persian or Arabic digits, +98, 0098, 98, or without the leading zero) and stored as 09xxxxxxxxx in the user meta bluetheme_mobile. With Save the verified mobile number… on, the billing phone gets it too. An account is found by that meta first, then by the billing phone. When two accounts share one billing phone, neither is used: the number counts as new, so it signs up a new account if registration allows.
  • Codes:
    • Stored as a keyed hash in a transient for Code expires after seconds.
    • Five wrong tries drop the code.
    • Wait before sending again limits how soon a new code can be asked for.
    • Hourly limits apply per number and per IP address. A site behind a proxy can pass the real IP with the bluetheme_otp_ip filter.
    • A complete code (pasted or autofilled too) is checked at once. Codes may be typed with Persian digits.
  • Test mode: codes are not sent. The latest 20 are kept, and Show the latest codes lists them for administrators. The form says it is in test mode. Turn it off on a live site.
  • After logging in: the customer goes back to the page they were on (or My Account). Core's login_redirect filter applies, and the wp_login action fires as with a password login.

Where the form appears

Set in Login form appears in:

  • My Account: "One-time code" and "Password" tabs above WooCommerce's forms. The Password tab shows WooCommerce's login (and register) forms. Shown first picks the starting tab.
    • With Email or username and password off, only the code form shows.
    • With Registration set to mobile only, WooCommerce's email sign-up form is hidden and also refused on submit.
  • Checkout: a "Returning customer? Log in with a one-time code" notice next to WooCommerce's own one. This works on the classic checkout ([woocommerce_checkout]) only; the block checkout does not run these hooks.
  • Popup: the header account icon (classic header and the Account element) opens a login dialog with both tabs and a "Create an account" link. It does not appear on My Account and checkout, which have their own forms.
  • wp-login.php (its own switch): a "Log in with a one-time code" link under the normal form switches between the two. The password form always stays, so administrators can always log in if SMS fails.
  • Account details: signed-in customers add or change their mobile number. A code goes to the new number before it is saved. A number that belongs to another account is refused.

SMS providers

Provider Settings With a pattern Without a pattern
Kavenegar API key, sender (optional) verify/lookup with the template name; the code is token sms/send
Melipayamak Username, password (or the panel's API key), sender BaseServiceNumber with the message id (bodyId); the code is the only variable SendSMS
IPPanel (FarazSMS) API key, sender line Edge API api/send, sending_type: pattern; the code goes under Code variable (default code) sending_type: webservice
SMS.ir API key, line number (without a pattern) v1/send/verify with the template id; the code goes under Code variable (default CODE) v1/send/bulk
  • Patterns: most Iranian providers send codes quickly only through an approved pattern (template), so use one when the provider offers it.
  • Plain messages: without a pattern, the Message is sent, with {code} and {site} replaced. The code is added at the end if {code} is missing.
  • Send test SMS: sends a real SMS with a sample code to the saved Test mobile number, test mode or not, and shows the provider's error if it fails.
  • Failures: when sending fails, the visitor sees a general message and the bluetheme_sms_failed action fires with the provider's error.
  • Other providers: add a class extending BlueTheme\Account\Sms\Gateway with the bluetheme_sms_gateways filter (id => class), and its name with bluetheme_sms_provider_labels.

Compatibility mode

With Step aside for Digits, Persian WooCommerce SMS or WP SMS on, the theme hides all of its code forms while one of those plugins is active. It looks for their plugin folders: digits, persian-woocommerce-sms and wp-sms. The bluetheme_otp_plugin_active filter can decide instead. The header popup then shows only the password form.

Those plugins' forms are not restyled by the theme beyond WooCommerce's general form styles, because they could not be tested here.

Routes (bluetheme/v1)

Route Who Body
POST otp/send Visitors (login), signed-in users (mobile) channel sms or email, target, purpose login or mobile
POST otp/verify Same Also code, remember, redirect
POST otp/test-sms manage_options none
POST otp/test-log manage_options none

The bluetheme_otp_registered action fires after a code sign-up created an account (id, channel, target).

Translate

Theme Options → Translate has new "Shop" and "Account & login" groups. The form's labels and messages, including the script's countdown text, come from PHP, so they can be changed there.