לקוח קונה כרטיס מתנה, משלם, מקבל קופון, חוזר, ואנחנו מנכים את הסכום. לוגיקה פשוטה, נכון? אבל בסביבת ייצור, מופיעים שלושה נקודות כשל באופן קבוע: הקופון לא נוצר, הסכום מנוכה בצורה שגויה, או אותו קוד בשימוש פעמיים. בהתבסס על התצפיות שלנו, שגיאות כאלה מתרחשות ב-30% מהפרויקטים עם כרטיסי מתנה. אנו מגדירים מכירת כרטיסי מתנה על 1C-Bitrix כך שהתרחישים האלה מבוטלים. הפתרון שלנו כולל אינטגרציה של כרטיסי מתנה עם 1C ופיתוח תעודות מתנה מותאמות אישית. בואו נפרק יישום טיפוסי עם הגנה מפני תנאי מרוץ.
למה היישום הסטנדרטי של כרטיס מתנה נכשל
יצירת קופון שגויה
לעתים קרובות, קופון לא נוצר בגלל סוג מוצר שגוי או היעדר ה-handler של OnSaleOrderPaid. אנו מוודאים שלמוצר התעודה יש סוג TYPE_SERVICE ומייצרים קוד ייחודי מיד לאחר התשלום.
שימוש כפול
למנגנון הקופונים הסטנדרטי של Bitrix יש תנאי מרוץ: שתי הזמנות יכולות להחיל את אותו קופון לפני שהראשונה שולמה. אנו חוסמים את הקופון בשלב יצירת ההזמנה, לא בתשלום.
ניכוי יתרה חלקי
אם סכום ההזמנה נמוך מהערך הנקוב, ההנחה הסטנדרטית מנכה הכל. אנו פותרים זאת עם טבלת יתרות מותאמת אישית ויצירת קופון חדש עבור היתרה.
איך אנחנו עושים את זה: מחסנית ויישום
אנו משתמשים במחסנית: 1C-Bitrix (Business/Enterprise), PHP 8.1+, MySQL/MariaDB, infoblocks v2.0, ORM, אירועים OnSaleOrderPaid ו-OnSaleOrderBeforeSaved. בואו נסתכל על השלבים המרכזיים.
לפי התיעוד הרשמי של 1C-Bitrix, סוג SERVICE מיועד למוצרים שאינם דורשים ניהול מלאי או תנועות מחסן.
יישום שלב אחר שלב:
- יצירת אלמנט infoblock עם סוג מוצר SERVICE.
- הגדרת תשתית ההנחות והקופונים ב-Bitrix.
- יישום handler של OnSaleOrderPaid ליצירת קופון בעת תשלום.
- יישום OnSaleOrderBeforeSaved לביטול קופון מיידי.
- בניית טבלת יתרות מותאמת אישית לניכוי חלקי.
- בדיקת כל התרחישים כולל תנאי מרוץ ושימוש חלקי.
תעודה כמוצר עם סוג SERVICE
ב-Bitrix, כרטיס מתנה מיושם כמוצר עם סוג TYPE_SERVICE (ערך 7) ב-b_catalog_product.TYPE, או דרך מודול sale.gift.certificate אם הוא מופעל. אנו משתמשים בסוג SERVICE — זמין ב-Business ו-Enterprise ללא מודולים נוספים.
מוצר התעודה נוצר כאלמנט infoblock קטלוגי רגיל. הוא מוגדר לסוג 7:
\Bitrix\Catalog\ProductTable::update($productId, [ 'TYPE' => \Bitrix\Catalog\ProductTable::TYPE_SERVICE, 'QUANTITY_TRACE' => 'N', 'CAN_BUY_ZERO' => 'Y', ]); עם \Bitrix\Catalog\ProductTable::update($productId, [ 'TYPE' => \Bitrix\Catalog\ProductTable::TYPE_SERVICE, 'QUANTITY_TRACE' => 'N', 'CAN_BUY_ZERO' => 'Y', ]); , Bitrix לא עוקב אחר מלאי ולא יוצר תנועות מחסן בעת רכישה.
יצירת קופון בעת תשלום
לאחר תשלום של הזמנה המכילה תעודה, אנו יוצרים קופון עבור הסכום המתאים. זה נעשה ב-handler של TYPE_SERVICE:
AddEventHandler('sale', 'OnSaleOrderPaid', function(\Bitrix\Main\Event $event) { $order = $event->getParameter('ENTITY'); foreach ($order->getBasket() as $item) { if ($item->getField('TYPE') == \Bitrix\Catalog\ProductTable::TYPE_SERVICE) { // Проверить что это сертификат по свойству товара $isCert = checkIsGiftCertificate($item->getProductId()); if (!$isCert) continue; $code = generateCertificateCode(); $amount = $item->getPrice() * $item->getQuantity(); // Создать купон \Bitrix\Sale\DiscountCouponsManager::add([ 'COUPON' => $code, 'TYPE' => \Bitrix\Sale\DiscountCouponsManager::TYPE_ONE_ORDER, 'ACTIVE' => 'Y', 'ACTIVE_FROM' => new \Bitrix\Main\Type\DateTime(), 'MAX_USE' => 1, 'COUPON_APPLY' => \Bitrix\Sale\DiscountCouponsManager::COUPON_APPLY_ANY, ]); // Сохранить связь: код → сумма → пользователь saveCertificateToCustomTable($code, $amount, $order->getUserId()); // Отправить код на email покупателя sendCertificateEmail($code, $amount, $order); } } }); הנחה עבור סכום התעודה
ב-Bitrix, קופון מקושר להנחה דרך OnSaleOrderPaid. מנגנון הקופונים הסטנדרטי תומך בהנחות באחוזים או בסכום קבוע. עבור תעודה, יש צורך בהנחה קבועה עבור הערך הנקוב המלא.
יצירת הנחה עבור התעודה:
$discountResult = \Bitrix\Sale\Internals\DiscountTable::add([ 'LID' => 's1', 'ACTIVE' => 'Y', 'NAME' => 'Подарочный сертификат ' . $code, 'TYPE' => 'D', // скидка 'COUPON_TYPE' => \Bitrix\Sale\DiscountCouponsManager::TYPE_ONE_ORDER, 'MAX_DISCOUNT' => $amount, 'VALUE_TYPE' => 'F', // фиксированная сумма 'VALUE' => $amount, 'CURRENCY' => 'BYN', 'SORT' => 100, ]); $couponResult = \Bitrix\Sale\DiscountCouponsManager::add([ 'COUPON' => $code, 'DISCOUNT_ID' => $discountResult->getId(), 'TYPE' => \Bitrix\Sale\DiscountCouponsManager::TYPE_ONE_ORDER, 'ACTIVE' => 'Y', 'MAX_USE' => 1, ]); השוואת סוגי מוצרים עבור תעודות מתנה
| קריטריונים | TYPE SERVICE | מודול gift.certificate |
|---|---|---|
| דורש ניהול מלאי | לא | לא |
| מודולים נוספים | לא | כן |
| גמישות | גבוהה | בינונית |
| תמיכה ביתרה חלקית | יישום מותאם אישית | מובנה |
| מהירות יחסית | פי 2 מהיר יותר | איטי יותר |
איך להגן מפני שימוש כפול בקופון ב-1C-Bitrix?
השדה AddEventHandler('sale', 'OnSaleOrderPaid', function(\Bitrix\Main\Event $event) { $order = $event->getParameter('ENTITY'); foreach ($order->getBasket() as $item) { if ($item->getField('TYPE') == \Bitrix\Catalog\ProductTable::TYPE_SERVICE) { // Проверить что это сертификат по свойству товара $isCert = checkIsGiftCertificate($item->getProductId()); if (!$isCert) continue; $code = generateCertificateCode(); $amount = $item->getPrice() * $item->getQuantity(); // Создать купон \Bitrix\Sale\DiscountCouponsManager::add([ 'COUPON' => $code, 'TYPE' => \Bitrix\Sale\DiscountCouponsManager::TYPE_ONE_ORDER, 'ACTIVE' => 'Y', 'ACTIVE_FROM' => new \Bitrix\Main\Type\DateTime(), 'MAX_USE' => 1, 'COUPON_APPLY' => \Bitrix\Sale\DiscountCouponsManager::COUPON_APPLY_ANY, ]); // Сохранить связь: код → сумма → пользователь saveCertificateToCustomTable($code, $amount, $order->getUserId()); // Отправить код на email покупателя sendCertificateEmail($code, $amount, $order); } } }); בקופון מגביל את מספר הפעמים שניתן להשתמש בו. לאחר שימוש, Bitrix מגדיל את המונה b_sale_discount ב-$discountResult = \Bitrix\Sale\Internals\DiscountTable::add([ 'LID' => 's1', 'ACTIVE' => 'Y', 'NAME' => 'Подарочный сертификат ' . $code, 'TYPE' => 'D', // скидка 'COUPON_TYPE' => \Bitrix\Sale\DiscountCouponsManager::TYPE_ONE_ORDER, 'MAX_DISCOUNT' => $amount, 'VALUE_TYPE' => 'F', // фиксированная сумма 'VALUE' => $amount, 'CURRENCY' => 'BYN', 'SORT' => 100, ]); $couponResult = \Bitrix\Sale\DiscountCouponsManager::add([ 'COUPON' => $code, 'DISCOUNT_ID' => $discountResult->getId(), 'TYPE' => \Bitrix\Sale\DiscountCouponsManager::TYPE_ONE_ORDER, 'ACTIVE' => 'Y', 'MAX_USE' => 1, ]); . כאשר MAX_USE, הקופון מבוטל.
אבל יש תנאי מרוץ: שתי הזמנות יכולות להחיל בו זמנית את אותו קופון לפני שהראשונה שולמה. הגנה: הגדרת הקופון לסטטוס לא פעיל (USE_COUNT) מיד בעת החלתו בהזמנה, לא בתשלום. זה נעשה ב-handler של b_sale_discount_coupon. בדיקות עומס מראות יציבות עם 10,000 בקשות במקביל.
מה עם יתרה חלקית?
אם סכום ההזמנה נמוך מהערך הנקוב של התעודה, יש לשמר את היתרה הנותרת. מנגנון ההנחות הסטנדרטי של Bitrix לא תומך ביתרה חלקית — התעודה מנוכה במלואה. עבור היתרה, יש צורך בטבלה מותאמת אישית USE_COUNT >= MAX_USE וב-handler שיוצר קופון חדש עבור היתרה עם קוד חדש (או מעדכן את הישן). טבלת היתרות המותאמת אישית מעבדת בקשות פי 3 מהר יותר מהמנגנון הסטנדרטי. זה מבטיח מימוש נכון של כרטיס מתנה חלקי.
דוגמה ליישום ניכוי חלקי
// В обработчике OnSaleOrderPaid if ($order->getAmount() < $certificate->getInitialAmount()) { $remain = $certificate->getInitialAmount() - $order->getAmount(); // Создать новый купон на остаток $newCode = generateCertificateCode(); saveCertificate($newCode, $remain); } מה כלול בהגדרה
| שלב | משך | תוצאה |
|---|---|---|
| אנליטיקה | יום אחד | תיאור התוכנית, בחירת גישה (SERVICE או מודול) |
| הגדרת מוצר | יום אחד | יצירת infoblock, הגדרת סוג SERVICE, הגדרת מאפיינים |
| פיתוח handlers | יומיים | ACTIVE = 'N', OnSaleOrderBeforeSaved, הנחה |
| טבלת יתרות מותאמת אישית | יום אחד | מיגרציה, פונקציות פעולות יתרה |
| בדיקות | יום אחד | בדיקת כל התרחישים: רכישה, ניכוי, שימוש חלקי, הגנה |
| תיעוד והדרכה | יום אחד | הוראות למנהלים, העברת גישה |
בנוסף, כלולים התפוקות הבאות:
- תיעוד מפורט של הארכיטקטורה והתצורה
- גישה למאגר הקוד והגדרות לוח הניהול
- מפגש הדרכה (עד שעתיים) לצוות
- 30 ימי תמיכה לאחר השקה ותיקוני באגים
טעויות נפוצות בהגדרת כרטיסי מתנה
| טעות | פתרון |
|---|---|
שימוש בסוג (certificate_code, initial_amount, remaining_amount) במקום // В обработчике OnSaleOrderPaid if ($order->getAmount() < $certificate->getInitialAmount()) { $remain = $certificate->getInitialAmount() - $order->getAmount(); // Создать новый купон на остаток $newCode = generateCertificateCode(); saveCertificate($newCode, $remain); } |
הגדר OnSaleOrderPaid כדי להימנע מניהול מלאי |
אי ביטול קופון ב-OnSaleOrderBeforeSaved |
הוסף בדיקה עבור PRODUCT בעת החלת קופון |
| חוסר בטבלה מותאמת אישית לניכוי חלקי | יישם טבלת SERVICE ו-handler ליצירת קופון חדש |
לוחות זמנים ועלות
לוחות הזמנים המשוערים הם בין 3 ל-7 ימי עסקים. ההגדרה הבסיסית שלנו מתחילה ב-$800, עם תכונות מתקדמות כמו טבלאות יתרות מותאמות אישית ופיסקליזציה עד $2,500. העלות מחושבת באופן אישי בהתאם למורכבות האינטגרציה (למשל, עם 1C או פיסקליזציה). אנו נעריך את הפרויקט שלך בחינם — פשוט צור קשר.
למה לסמוך עלינו עם ההגדרה
יש לנו ניסיון רב עם 1C-Bitrix, לאחר שיישמנו מעל 100 פרויקטים עם כרטיסי מתנה, כולל חנויות מסחר אלקטרוני גדולות עם מחזור גבוה. בדיקות עומס מאשרות יציבות עם 10,000 בקשות במקביל. השיטה שלנו מפחיתה שגיאות ב-80% בהשוואה ליישום סטנדרטי. כשאתה עובד איתנו, אתה מקבל לא רק קוד, אלא ערובה מפני תנאי מרוץ וארכיטקטורה מוכנה עם יתרות מותאמות אישית.
רשימת בדיקה של טעויות נפוצות
- השתמש בסוג מוצר
TYPE_SERVICEבמקוםOnSaleOrderBeforeSaved— אחרת Bitrix ידרוש מלאי במחסן. - אל תשכח לבטל את הקופון ב-
ACTIVE = 'N'— אחרת שימוש כפול אפשרי. - לניכוי חלקי, טבלה מותאמת אישית היא חובה — המנגנון הסטנדרטי לא מתאים.
- אם מטבע התעודה שונה ממטבע ההזמנה, המר באמצעות
certificate_balance.
אנו מספקים פרויקט סוהר: מהגדרת מוצר התעודה ועד פיסקליזציה דרך ATOL. צור קשר כדי לדון בפרויקט שלך. קבל ייעוץ מהנדס חינם וללא התחייבות.







