Customer Verification Setup via SMS Code in 1C-Bitrix
A registration form with SMS confirmation reduces the number of fictitious accounts and disposable email addresses. For an online store, it also protects loyalty programs from abuse. In 1C-Bitrix, SMS verification is not built into the standard registration flow — it is configured through an event model and integration with an SMS provider.
Choosing an SMS Provider
Bitrix does not have its own SMS gateway. Integration is built through the provider's REST API. Popular options for the RF/CIS market:
- SMSC.ru — direct API, good documentation
- SMS.ru — free test mode
- MTS Exolve / Beeline — corporate rates
- Twilio — for international projects
Provider connection is implemented as a separate wrapper class that implements a unified interface. This allows changing providers if needed without reworking verification logic.
Verification Architecture
Verification consists of two stages: code generation and verification. The code is stored not in the session (vulnerable to session fixation) but in a separate database table:
CREATE TABLE custom_sms_verification (
id INT AUTO_INCREMENT PRIMARY KEY,
phone VARCHAR(20) NOT NULL,
code VARCHAR(6) NOT NULL,
created_at DATETIME NOT NULL,
attempts INT DEFAULT 0,
verified TINYINT DEFAULT 0,
INDEX idx_phone (phone),
INDEX idx_created (created_at)
);
In Bitrix D7 — through \Bitrix\Main\ORM\Data\DataManager:
class SmsVerificationTable extends \Bitrix\Main\ORM\Data\DataManager
{
public static function getTableName(): string
{
return 'custom_sms_verification';
}
public static function getMap(): array
{
return [
new \Bitrix\Main\ORM\Fields\IntegerField('ID', ['primary' => true, 'autocomplete' => true]),
new \Bitrix\Main\ORM\Fields\StringField('PHONE'),
new \Bitrix\Main\ORM\Fields\StringField('CODE'),
new \Bitrix\Main\ORM\Fields\DatetimeField('CREATED_AT'),
new \Bitrix\Main\ORM\Fields\IntegerField('ATTEMPTS'),
new \Bitrix\Main\ORM\Fields\BooleanField('VERIFIED'),
];
}
}
Code Sending and Verification Logic
Sending code:
function sendVerificationCode(string $phone): bool {
$code = str_pad(random_int(0, 999999), 6, '0', STR_PAD_LEFT);
// Rate limit check — no more than once per 60 seconds
$recent = SmsVerificationTable::getList([
'filter' => [
'=PHONE' => $phone,
'>CREATED_AT' => new \Bitrix\Main\Type\DateTime(date('Y-m-d H:i:s', time() - 60))
]
])->fetch();
if ($recent) return false; // Too many requests
SmsVerificationTable::add([
'PHONE' => $phone,
'CODE' => $code,
'CREATED_AT' => new \Bitrix\Main\Type\DateTime(),
'ATTEMPTS' => 0,
'VERIFIED' => false,
]);
return SmsProvider::send($phone, "Your verification code: $code");
}
Code verification includes brute force protection: after 3 failed attempts, the code is blocked regardless of expiration. Code lifetime is 5–10 minutes.
Integration with Registration and Checkout
Verification is embedded in two places:
-
Registration — through the
OnBeforeUserRegisterevent handler. If the phone number is not verified, registration is blocked until SMS verification is passed. -
Checkout — through the
bitrix:sale.order.ajaxcomponent. A verification step is added before final order confirmation. Especially important for stores accepting orders without registration.
For AJAX verification form, a controller is used:
class SmsVerifyController extends \Bitrix\Main\Engine\Controller {
public function sendAction(): array { ... }
public function checkAction(string $phone, string $code): array { ... }
}
Fraud Prevention and Rate Limiting
Required security measures:
- No more than 3 codes per hour per phone number
- No more than 5 codes per day per IP
- CAPTCHA before requesting code on suspicious activity
- Phone number normalization before storage (format: +7XXXXXXXXXX)
Execution Timeline
| Scope | Timeline |
|---|---|
| Code sending + verification, basic flow | 1–2 days |
| Integration with registration + checkout | 2–3 days |
| Fraud prevention, rate limiting, normalization | +1 day |
SMS verification is an investment in customer base quality. One clean account is worth more than ten fake ones.

