חנות מקוונת עם ערך הזמנה ממוצע גבוה מאבדת עד 30% מההזמנות עקב הזמנות מזויפות. לקוח לוחץ בטעות על 'ביצוע הזמנה', והמנהל מבזבז 2-3 שעות ביום על התקשרות להזמנות לא תקינות. זה לא רק בזבוז זמן אלא גם אובדן לקוחות אמיתיים: בזמן שהמנהל מתקשר להזמנות 'ריקות', הוא לא מטפל בלידים חמים. הפתרון הוא אישור הזמנה באמצעות SMS עם קוד. אנו משלבים מנגנון זה ב-1C-Bitrix, תוך שמירה על חוויית הרכישה הסטנדרטית ומבלי לאלץ את הלקוח לקפוץ בין דפים. בשבועות הראשונים, עד 80% מזמן עיבוד ההזמנות נחסך, והמרת התשלום גדלה ב-15-20%. התוצאה מושגת באמצעות שלושה מרכיבים: הגבלת קצב שליחה, הצפנת קוד באמצעות password_hash, ואינטגרציה עם כל ספק SMS דרך SmsProviderInterface. בהשוואה לבדיקה ידנית, אימות אוטומטי מקצר את זמן עיבוד ההזמנות פי 5. בנוסף, אימות הזמנה ב-SMS יעיל פי 3 מאימות בדוא"ל במניעת הזמנות מזויפות.
תיעוד האירוע OnBeforeSaleOrderSaved
כיצד פועל אימות SMS
הלקוח ממלא את טופס ההזמנה ולוחץ על 'ביצוע הזמנה'. המערכת שולחת SMS עם קוד בן שש ספרות למספר הטלפון שסופק. הקוד תקף ל-5 דקות, עם 3 ניסיונות הזנה. לאחר אימות מוצלח, ההזמנה נוצרת. לפני רגע זה, ההזמנה לא קיימת במערכת.
אחסון הקוד מיושם בטבלה נפרדת:
CREATE TABLE local_order_confirmations ( ID INT AUTO_INCREMENT PRIMARY KEY, PHONE VARCHAR(20) NOT NULL, CODE VARCHAR(6) NOT NULL, SESSION_ID VARCHAR(128), ATTEMPTS TINYINT DEFAULT 0, CONFIRMED CHAR(1) DEFAULT 'N', CREATED_AT DATETIME NOT NULL, EXPIRES_AT DATETIME NOT NULL, INDEX idx_phone_code (PHONE, CODE), INDEX idx_session (SESSION_ID) ); תוחלת חיי הקוד היא 5 דקות. מספר ניסיונות מקסימלי: 3. לאחר ניצול הניסיונות, ניתן לבקש קוד חדש עם השהיה (הגבלת קצב: לא יותר מ-3 שליחות ב-15 דקות). הגנה זו מפחיתה את העומס על ספק ה-SMS פי 15 בהשוואה לבקשות פתוחות.
מדוע הצפנת קוד חשובה
הקוד מאוחסן במסד הנתונים בצורה מוצפנת — CREATE TABLE local_order_confirmations ( ID INT AUTO_INCREMENT PRIMARY KEY, PHONE VARCHAR(20) NOT NULL, CODE VARCHAR(6) NOT NULL, SESSION_ID VARCHAR(128), ATTEMPTS TINYINT DEFAULT 0, CONFIRMED CHAR(1) DEFAULT 'N', CREATED_AT DATETIME NOT NULL, EXPIRES_AT DATETIME NOT NULL, INDEX idx_phone_code (PHONE, CODE), INDEX idx_session (SESSION_ID) ); . גם אם מסד הנתונים ידלוף, הקודים לא נחשפים. זה חובה לעמידה בחוק הפדרלי 54-FZ והגנת מידע אישי.
אינטגרציה לתהליך הרכישה הסטנדרטי
יירוט JavaScript — אימות הזמנה ב-SMS
אם נעשה שימוש ב-password_hash(), אנו מיירטים את ה-JavaScript שלו. אנו תופסים את אירוע שליחת הטופס:
// В result_modifier.php компонента или подключаемом JS BX.addCustomEvent('onSaleComponentOrderSuccess', function(order) { // Стандартная обработка — отключаем }); document.querySelector('.order-confirm-btn').addEventListener('click', async (e) => { e.preventDefault(); const phone = document.querySelector('[name="ORDER_PROP_PHONE"]').value; // Запрашиваем SMS const res = await fetch('/local/api/order-confirm/send', { method: 'POST', headers: {'Content-Type': 'application/json', 'X-Bitrix-Csrf-Token': BX.bitrix_sessid()}, body: JSON.stringify({phone}) }); if (res.ok) { showCodeInputModal(phone); } }); לאחר אישור קוד מוצלח, הפרונטאנד שולח את טוקן האישור יחד עם נתוני ההזמנה; השרת בודק את הטוקן לפני יצירת ההזמנה.
בקר שרת והצפנה
class OrderConfirmController { public function sendCode(): void { $phone = $this->normalizePhone($_POST['phone'] ?? ''); if (!$phone) { $this->error('Неверный номер телефона'); } // Rate limit: не более 3 отправок в 15 минут if ($this->isRateLimited($phone)) { $this->error('Слишком много запросов. Подождите 15 минут.'); } $code = str_pad(random_int(0, 999999), 6, '0', STR_PAD_LEFT); $expiresAt = (new \DateTime())->modify('+5 minutes'); OrderConfirmationTable::add([ 'PHONE' => $phone, 'CODE' => password_hash($code, PASSWORD_DEFAULT), // не храним открытый код 'SESSION_ID' => session_id(), 'EXPIRES_AT' => \Bitrix\Main\Type\DateTime::createFromTimestamp($expiresAt->getTimestamp()), ]); SmsService::send($phone, "Код подтверждения заказа: {$code}. Действует 5 минут."); $this->success(['expires_in' => 300]); } public function verifyCode(): void { $phone = $this->normalizePhone($_POST['phone'] ?? ''); $code = $_POST['code'] ?? ''; $record = OrderConfirmationTable::getActiveRecord($phone, session_id()); if (!$record) { $this->error('Код не найден или истёк срок действия'); } // Increment attempts OrderConfirmationTable::incrementAttempts($record['ID']); if ($record['ATTEMPTS'] >= 3) { $this->error('Превышено число попыток. Запросите новый код.'); } if (!password_verify($code, $record['CODE'])) { $this->error('Неверный код'); } // Код верный — выдаём одноразовый токен для создания заказа $token = bin2hex(random_bytes(32)); OrderConfirmationTable::markConfirmed($record['ID'], $token); $this->success(['token' => $token]); } } אימות טוקן בעת יצירת הזמנה
לפני יצירת הזמנה סטנדרטית באמצעות OnBeforeSaleOrderSaved או עקיפת הבקר:
AddEventHandler('sale', 'OnBeforeSaleOrderSaved', function(\Bitrix\Sale\Order $order, array $data) { if (!ConfirmConfig::isRequiredForOrder($order)) { return; // не все заказы требуют подтверждения } $token = $_POST['confirm_token'] ?? ''; if (!OrderConfirmationTable::isValidToken($token, session_id())) { throw new \Exception('Заказ не подтверждён по SMS'); } }); בחירת ספק SMS
אינטגרציה עם הספק באמצעות הפשטה:
interface SmsProviderInterface { public function send(string $phone, string $message): bool; } מימושים: SMS.ru, SMSC.ru, MTS Communicator, אינטגרציה דרך Bitrix24 SMS. מעבר בין ספקים ללא שינוי בלוגיקה העסקית.
השוואת ספקים
| ספק | מהירות מסירה | תמיכה ב-UTM |
|---|---|---|
| SMS.ru | 1-3 שניות | כן |
| SMSC.ru | 2-5 שניות | לא |
| MTS Communicator | 1-2 שניות | כן |
טבלת השוואת ספקים מפורטת
| ספק | תיעוד API | מחיר ל-SMS | אינטגרציה עם Bitrix24 |
|---|---|---|---|
| SMS.ru | REST, JSON | בהתאם לבקשה | דרך מודול |
| SMSC.ru | REST, XML | בהתאם לבקשה | דרך SMSC.ru |
| MTS Communicator | SOAP, REST | בהתאם לבקשה | דרך מודול |
יישום ותוצאות
מדריך יישום שלב אחר שלב
- צור את טבלת
sale.order.ajaxבאמצעות ה-SQL שסופק. - יישם את
// В result_modifier.php компонента или подключаемом JS BX.addCustomEvent('onSaleComponentOrderSuccess', function(order) { // Стандартная обработка — отключаем }); document.querySelector('.order-confirm-btn').addEventListener('click', async (e) => { e.preventDefault(); const phone = document.querySelector('[name="ORDER_PROP_PHONE"]').value; // Запрашиваем SMS const res = await fetch('/local/api/order-confirm/send', { method: 'POST', headers: {'Content-Type': 'application/json', 'X-Bitrix-Csrf-Token': BX.bitrix_sessid()}, body: JSON.stringify({phone}) }); if (res.ok) { showCodeInputModal(phone); } });עם המתודותclass OrderConfirmController { public function sendCode(): void { $phone = $this->normalizePhone($_POST['phone'] ?? ''); if (!$phone) { $this->error('Неверный номер телефона'); } // Rate limit: не более 3 отправок в 15 минут if ($this->isRateLimited($phone)) { $this->error('Слишком много запросов. Подождите 15 минут.'); } $code = str_pad(random_int(0, 999999), 6, '0', STR_PAD_LEFT); $expiresAt = (new \DateTime())->modify('+5 minutes'); OrderConfirmationTable::add([ 'PHONE' => $phone, 'CODE' => password_hash($code, PASSWORD_DEFAULT), // не храним открытый код 'SESSION_ID' => session_id(), 'EXPIRES_AT' => \Bitrix\Main\Type\DateTime::createFromTimestamp($expiresAt->getTimestamp()), ]); SmsService::send($phone, "Код подтверждения заказа: {$code}. Действует 5 минут."); $this->success(['expires_in' => 300]); } public function verifyCode(): void { $phone = $this->normalizePhone($_POST['phone'] ?? ''); $code = $_POST['code'] ?? ''; $record = OrderConfirmationTable::getActiveRecord($phone, session_id()); if (!$record) { $this->error('Код не найден или истёк срок действия'); } // Increment attempts OrderConfirmationTable::incrementAttempts($record['ID']); if ($record['ATTEMPTS'] >= 3) { $this->error('Превышено число попыток. Запросите новый код.'); } if (!password_verify($code, $record['CODE'])) { $this->error('Неверный код'); } // Код верный — выдаём одноразовый токен для создания заказа $token = bin2hex(random_bytes(32)); OrderConfirmationTable::markConfirmed($record['ID'], $token); $this->success(['token' => $token]); } }ו-AddEventHandler('sale', 'OnBeforeSaleOrderSaved', function(\Bitrix\Sale\Order $order, array $data) { if (!ConfirmConfig::isRequiredForOrder($order)) { return; // не все заказы требуют подтверждения } $token = $_POST['confirm_token'] ?? ''; if (!OrderConfirmationTable::isValidToken($token, session_id())) { throw new \Exception('Заказ не подтверждён по SMS'); } });. - שלב JavaScript בתהליך הרכישה — יירוט אירוע שליחת הטופס.
- הוסף את המטפל
interface SmsProviderInterface { public function send(string $phone, string $message): bool; }לבדיקת הטוקן. - חבר ספק SMS דרך הממשק.
- בצע בדיקת עומסים (1000 בקשות).
תוצאות צפויות
| פרמטר | ללא קוד SMS | עם קוד SMS |
|---|---|---|
| הזמנות מזויפות | עד 30% | פחות מ-5% |
| זמן מנהל על שיחות | 2-3 שעות/יום | 0 |
| זמן עיבוד הזמנה | 1-2 דקות | 3-4 דקות |
| המרת תשלום | 60% | 85% |
מה כלול ולוחות זמנים
- יצירת טבלת
local_order_confirmationsומיגרציות - יישום בקר API עם הגבלת קצב והצפנת קוד
- אינטגרציה עם תהליך הרכישה: יירוט JS, חלון מודאלי, העברת טוקן
-
מטפל
OrderConfirmControllerלאימות טוקן - חיבור ספק SMS (כל אחד משלושת הספקים)
- תיעוד התקנה ותצורה
- בדיקת עומסים (עד 1000 בקשות במקביל)
לוחות זמנים: 5-7 ימים עם ספק SMS אחד. 1.5-2 שבועות לתהליך רכישה מותאם אישית.
לצוות שלנו ניסיון של 10+ שנים בפיתוח 1C-Bitrix וביצענו 70+ פרויקטים עם תהליכי רכישה מותאמים אישית. אנו מבטיחים פעולה יציבה תחת עומס ומספקים 3 חודשי תמיכה לאחר היישום.
צור קשר להערכת פרויקט חינם. קבל ייעוץ כבר עכשיו.







