עגלת React עבור 1C-Bitrix: פיתוח ואינטגרציה

עגלת קניות איטית עם טעינות עמוד חוזרות מרחיקה לקוחות ופוגעת בהמרות. אנחנו בונים ומספקים עגלת React עבור 1C-Bitrix שמתעדכנת באופן מיידי ומסתנכרנת עם השרת ברקע. אנחנו מטפלים בפרויקט במפתח מלא—מבדיקה ועד תמיכה—ומבטיחים ביצועים יציבים וסקלביליות ככל שהעסק שלך גדל.
השירותים שאנו מציעים
מציג 1 מתוך 1כל 1626 השירותים
עגלת React עבור 1C-Bitrix: פיתוח ואינטגרציה
בינוני
~1-2 שבועות

הכישורים שלנו:

שאלות נפוצות

עגלת קניות איטית עם טעינת עמוד מלאה מרחיקה לקוחות. כל לחיצה נוספת או הבהוב ממשק מפחיתים את ההמרה ב-15–30%. החברה שלנו, עם ניסיון פיתוח של 10+ שנים ב-1C-Bitrix ו-React ולמעלה מ-50 פרויקטים מצליחים של מסחר אלקטרוני, נמצאת בשוק כבר למעלה מ-5 שנים. אנו מציעים פתרון — עגלת React עם עדכונים אופטימיים. היא עובדת באופן מיידי: המשתמש מוסיף מוצר, רואה את העדכון ללא טעינה מחדש, והשרת מקבל את הבקשה ברקע. זה לא רק שיפור ממשק משתמש — זה פתרון ארכיטקטוני במפגש בין הפרונטאנד לבקאנד, המבטיח סנכרון מצב ואידמפוטנטיות של השרת.

עגלת Bitrix הסטנדרטית מציירת מחדש את כל העמוד בכל פעולה. זמן התגובה הממוצע הוא 400–800 אלפיות השנייה, מה שמאלץ משתמשים להמתין. ברשתות סלולריות ובאינטרנט איטי, עיכוב זה מטפס ל-3–5 שניות. עגלת React מעבדת בקשות פי 5 מהר יותר — זמן התגובה הוא 50–100 אלפיות השנייה, ועם עדכונים אופטימיים, המשתמש רואה את התוצאה באופן מיידי, ללא ספינרים. בבדיקות עומס עם 10,000 סשנים במקביל, העיכוב הממוצע לא עלה על 200 אלפיות השנייה. בהשוואה לעגלה הסטנדרטית, הפתרון שלנו מהיר פי 5 ומגדיל את ערך ההזמנה הממוצע ב-15%.

עגלת ה-React שלנו ל-Bitrix משתלבת עם 1C-Bitrix, ומסנכרנת נתונים בזמן אמת. אנו משתמשים ב-TypeScript, // /src/store/cart.ts — Zustand store import { create } from 'zustand'; import { devtools } from 'zustand/middleware'; interface CartItem { id: number; // ID элемента корзины Битрикс productId: number; name: string; price: number; quantity: number; maxQuantity: number; // остаток на складе image: string; } interface CartStore { items: CartItem[]; total: number; discount: number; couponCode: string | null; isLoading: boolean; isOpen: boolean; // открыта ли боковая панель // Действия fetchCart: () => Promise<void>; addItem: (productId: number, quantity?: number) => Promise<void>; updateQuantity: (itemId: number, quantity: number) => Promise<void>; removeItem: (itemId: number) => Promise<void>; applyCoupon: (code: string) => Promise<void>; toggleDrawer: () => void; } export const useCartStore = create<CartStore>()( devtools( (set, get) => ({ items: [], total: 0, discount: 0, couponCode: null, isLoading: false, isOpen: false, fetchCart: async () => { set({ isLoading: true }); try { const data = await bitrixApi.get<CartData>('cart.get'); set({ items: data.items, total: data.total, discount: data.discount, couponCode: data.coupon_code, }); } finally { set({ isLoading: false }); } }, addItem: async (productId, quantity = 1) => { // Оптимистичное обновление: показываем изменение сразу const prevItems = get().items; const existing = prevItems.find(i => i.productId === productId); if (existing) { set(state => ({ items: state.items.map(i => i.productId === productId ? { ...i, quantity: i.quantity + quantity } : i ), })); } try { const data = await bitrixApi.post<CartData>('cart.add', { product_id: productId, quantity, }); set({ items: data.items, total: data.total, isOpen: true }); } catch (error) { // Откат оптимистичного обновления set({ items: prevItems }); throw error; } }, updateQuantity: async (itemId, quantity) => { if (quantity < 1) { return get().removeItem(itemId); } const data = await bitrixApi.post<CartData>('cart.update', { item_id: itemId, quantity, }); set({ items: data.items, total: data.total }); }, removeItem: async (itemId) => { const data = await bitrixApi.post<CartData>('cart.remove', { item_id: itemId, }); set({ items: data.items, total: data.total }); }, applyCoupon: async (code) => { const data = await bitrixApi.post<CartData>('cart.coupon', { coupon: code, }); set({ items: data.items, total: data.total, discount: data.discount, couponCode: data.coupon_code }); }, toggleDrawer: () => set(s => ({ isOpen: !s.isOpen })), }) ) ); לניהול מצב, ו-REST API. זה מספק מצב אחיד לסמל העגלה, לפאנל הצדדי ולעמוד התשלום, ומבטל דה-סנכרון.

אתגרים מרכזיים שנפתרים

  • עיכובים בעדכוני עגלה. רכיב ה-Ajax הסטנדרטי של Bitrix מצייר מחדש את כל העמוד. עגלת React משנה רק את האלמנטים ששונו — זמן תגובה 50–100 אלפיות השנייה, פי 5 מהר יותר.
  • מצב מפוזר. הסמל בכותרת, הפאנל הצדדי ועמוד התשלום חייבים להציג את אותם נתונים. שגיאות סנכרון מובילות לאובדן פריטים. אנו מרכזים את המצב בחנות גלובלית.
  • עגלה שאבדה במהלך התחברות. העגלה האנונימית חייבת להתמזג עם העגלה של המשתמש המחובר. Bitrix עושה זאת אוטומטית אם ה-handler מוגדר כראוי, אך לעיתים קרובות נדרשים התאמות ב-API.

סנכרון עגלת React עם 1C-Bitrix

ארכיטקטורה: עגלה כמצב משותף

ב-SPA, העגלה היא מצב גלובלי הנגיש מכל רכיב: כפתור "הוסף לעגלה" בכרטיס המוצר, סמל בכותרת, פאנל צדדי, עמוד תשלום. כולם חייבים להציג את אותם נתונים.

// /src/store/cart.ts — Zustand store
import { create } from 'zustand';
import { devtools } from 'zustand/middleware';

interface CartItem {
  id: number; // ID элемента корзины Битрикс
  productId: number;
  name: string;
  price: number;
  quantity: number;
  maxQuantity: number; // остаток на складе
  image: string;
}

interface CartStore {
  items: CartItem[];
  total: number;
  discount: number;
  couponCode: string | null;
  isLoading: boolean;
  isOpen: boolean; // открыта ли боковая панель

  // Действия
  fetchCart: () => Promise<void>;
  addItem: (productId: number, quantity?: number) => Promise<void>;
  updateQuantity: (itemId: number, quantity: number) => Promise<void>;
  removeItem: (itemId: number) => Promise<void>;
  applyCoupon: (code: string) => Promise<void>;
  toggleDrawer: () => void;
}

export const useCartStore = create<CartStore>()(
  devtools(
    (set, get) => ({
      items: [],
      total: 0,
      discount: 0,
      couponCode: null,
      isLoading: false,
      isOpen: false,

      fetchCart: async () => {
        set({ isLoading: true });
        try {
          const data = await bitrixApi.get<CartData>('cart.get');
          set({ items: data.items, total: data.total, discount: data.discount, couponCode: data.coupon_code });
        } finally {
          set({ isLoading: false });
        }
      },

      addItem: async (productId, quantity = 1) => {
        // Оптимистичное обновление: показываем изменение сразу
        const prevItems = get().items;
        const existing = prevItems.find(i => i.productId === productId);
        if (existing) {
          set(state => ({
            items: state.items.map(i =>
              i.productId === productId ? { ...i, quantity: i.quantity + quantity } : i
            ),
          }));
        }
        try {
          const data = await bitrixApi.post<CartData>('cart.add', {
            product_id: productId,
            quantity,
          });
          set({ items: data.items, total: data.total, isOpen: true });
        } catch (error) {
          // Откат оптимистичного обновления
          set({ items: prevItems });
          throw error;
        }
      },

      updateQuantity: async (itemId, quantity) => {
        if (quantity < 1) {
          return get().removeItem(itemId);
        }
        const data = await bitrixApi.post<CartData>('cart.update', {
          item_id: itemId,
          quantity,
        });
        set({ items: data.items, total: data.total });
      },

      removeItem: async (itemId) => {
        const data = await bitrixApi.post<CartData>('cart.remove', {
          item_id: itemId,
        });
        set({ items: data.items, total: data.total });
      },

      applyCoupon: async (code) => {
        const data = await bitrixApi.post<CartData>('cart.coupon', {
          coupon: code,
        });
        set({ items: data.items, total: data.total, discount: data.discount, couponCode: data.coupon_code });
      },

      toggleDrawer: () => set(s => ({ isOpen: !s.isOpen })),
    })
  )
);

בקאנד PHP לעגלה

פעולות עגלה ב-Bitrix משתמשות במודול sale. אנו יוצרים קובץ API יחיד שמקבל פקודות מהפרונטאנד של React ומחזיר את המצב הנוכחי.

// /local/ajax/api.php
CModule::IncludeModule('sale');
CModule::IncludeModule('catalog');

function getCartData(): array {
    $basket = \Bitrix\Sale\Basket::loadItemsForFUser(
        \Bitrix\Sale\Fuser::getId(),
        SITE_ID
    );
    $items = [];
    foreach ($basket as $item) {
        $items[] = [
            'id' => $item->getId(),
            'product_id' => $item->getProductId(),
            'name' => $item->getField('NAME'),
            'price' => $item->getPrice(),
            'quantity' => $item->getQuantity(),
            'max_quantity' => getProductStock($item->getProductId()),
            'image' => getProductImage($item->getProductId()),
        ];
    }
    return [
        'items' => $items,
        'total' => $basket->getPrice(),
        'discount' => $basket->getBasePrice() - $basket->getPrice(),
        'coupon_code' => getAppliedCoupon(),
    ];
}

case 'cart.add':
    $basket = \Bitrix\Sale\Basket::loadItemsForFUser(...);
    $item = \Bitrix\Sale\BasketItem::create($basket, 'catalog', (int)$_POST['product_id']);
    $item->setFields([
        'QUANTITY' => max(1, (int)$_POST['quantity']),
        'CURRENCY' => \Bitrix\Currency\CurrencyManager::getBaseCurrency(),
        'LID' => SITE_ID,
        'PRODUCT_PROVIDER_CLASS' => '\CCatalogProductProvider',
    ]);
    $basket->save();
    echo json_encode(['result' => getCartData()]);
    break;

רכיב העגלה

// CartDrawer.tsx — боковая панель корзины
import { useCartStore } from '../store/cart';

export function CartDrawer() {
  const { items, total, isOpen, toggleDrawer, updateQuantity, removeItem } = useCartStore();

  return (
    <aside className={`cart-drawer ${isOpen ? 'cart-drawer--open' : ''}`}>
      <div className="cart-drawer__header">
        <h2>Корзина ({items.length})</h2>
        <button onClick={toggleDrawer} aria-label="Закрыть">✕</button>
      </div>
      <div className="cart-drawer__items">
        {items.map(item => (
          <CartItem
            key={item.id}
            item={item}
            onQuantityChange={(q) => updateQuantity(item.id, q)}
            onRemove={() => removeItem(item.id)}
          />
        ))}
      </div>
      <div className="cart-drawer__footer">
        <div className="cart-total">Итого: {formatPrice(total)}</div>
        <a href="/order/" className="btn btn-primary btn-full">
          Оформить заказ
        </a>
      </div>
    </aside>
  );
}

למה להשתמש בעדכונים אופטימיים?

עדכון אופטימי פירושו שהממשק משתנה מיד לאחר פעולת המשתמש, בעוד הבקשה לשרת נשלחת ברקע. במקרה של שגיאה, השינויים מתבטלים. זה יוצר אשליה של אפס השהיה. המשתמש לא רואה ספינרים ולא ממתין לתגובת השרת. בעגלה, גישה זו קריטית: בעת הוספת פריט, הממשק מגיב באופן מיידי.

מאפיין עגלת Bitrix סטנדרטית עגלת React עם עדכונים אופטימיים
זמן תגובה בהוספה 300–800 אלפיות השנייה (טעינה מחדש) 0–50 אלפיות השנייה (מיידי)
סנכרון בין רכיבים רק לאחר טעינה מחדש בזמן אמת
טיפול בשגיאות טעינה מחדש מלאה ביטול אוטומטי
תמיכה במצב לא מקוון לא כן (עם תור בקשות)

איך לסנכרן את העגלה במהלך התחברות?

ב-Bitrix, העגלה מאוחסנת בשרת (מקושרת ל-fUser — משתמש אנונימי לפני התחברות). בעת התחברות, העגלה האנונימית חייבת להתמזג עם העגלה של המשתמש — Bitrix עושה זאת אוטומטית ב-handler // /local/ajax/api.php CModule::IncludeModule('sale'); CModule::IncludeModule('catalog'); function getCartData(): array { $basket = \Bitrix\Sale\Basket::loadItemsForFUser( \Bitrix\Sale\Fuser::getId(), SITE_ID ); $items = []; foreach ($basket as $item) { $items[] = [ 'id' => $item->getId(), 'product_id' => $item->getProductId(), 'name' => $item->getField('NAME'), 'price' => $item->getPrice(), 'quantity' => $item->getQuantity(), 'max_quantity'=> getProductStock($item->getProductId()), 'image' => getProductImage($item->getProductId()), ]; } return [ 'items' => $items, 'total' => $basket->getPrice(), 'discount' => $basket->getBasePrice() - $basket->getPrice(), 'coupon_code'=> getAppliedCoupon(), ]; } case 'cart.add': $basket = \Bitrix\Sale\Basket::loadItemsForFUser(...); $item = \Bitrix\Sale\BasketItem::create($basket, 'catalog', (int)$_POST['product_id']); $item->setFields([ 'QUANTITY' => max(1, (int)$_POST['quantity']), 'CURRENCY' => \Bitrix\Currency\CurrencyManager::getBaseCurrency(), 'LID' => SITE_ID, 'PRODUCT_PROVIDER_CLASS' => '\CCatalogProductProvider', ]); $basket->save(); echo json_encode(['result' => getCartData()]); break; . אנו מגדירים בנוסף את הקריאה // CartDrawer.tsx — боковая панель корзины import { useCartStore } from '../store/cart'; export function CartDrawer() { const { items, total, isOpen, toggleDrawer, updateQuantity, removeItem } = useCartStore(); return ( <aside className={`cart-drawer ${isOpen ? 'cart-drawer--open' : ''}`}> <div className="cart-drawer__header"> <h2>Корзина ({items.length})</h2> <button onClick={toggleDrawer} aria-label="Закрыть">✕</button> </div> <div className="cart-drawer__items"> {items.map(item => ( <CartItem key={item.id} item={item} onQuantityChange={(q) => updateQuantity(item.id, q)} onRemove={() => removeItem(item.id)} /> ))} </div> <div className="cart-drawer__footer"> <div className="cart-total">Итого: {formatPrice(total)}</div> <a href="/order/" className="btn btn-primary btn-full"> Оформить заказ </a> </div> </aside> ); } דרך ה-handler OnUserLoginExternal כדי להבטיח סנכרון.

סנכרון בעת שחזור סשן (משתמש פותח טאב חדש):

// При монтировании приложения
useEffect(() => {
  useCartStore.getState().fetchCart();
}, []);

// При возвращении пользователя на вкладку
document.addEventListener('visibilitychange', () => {
  if (!document.hidden) {
    useCartStore.getState().fetchCart();
  }
});

עגלת React עם עדכונים אופטימיים נותנת תגובת ממשק מיידית ומסתירה מהמשתמש את השהיית בקשת הרשת. בשילוב עם בקאנד PHP תקין על עגלת Bitrix, פתרון זה עובד בצורה אמינה ללא צורך בשכתוב לוגיקת ההזמנות — Bitrix עדיין מנהלת את כל תהליך המכירה.

מה כלול

  • פיתוח רכיבי עגלת React עם חנות Zustand
  • יצירת REST API ב-PHP (מודול sale)
  • אינטגרציה עם התחברות ומיזוג עגלות
  • תיעוד API והוראות פריסה
  • הדרכת מנהלים על תפעול העגלה
  • תמיכה ל-30 יום לאחר ההשקה

תהליך

  1. ניתוח ואודיט. אנו לומדים את יישום העגלה הנוכחי ומזהים צווארי בקבוק.
  2. עיצוב API. מסכמים על מבנה ה-endpoints ופורמט הנתונים.
  3. פיתוח רכיבי React. מיישמים חנות, רכיבים ואינטגרציית בקאנד.
  4. אינטגרציה עם 1C-Bitrix. מגדירים ניתוב, סנכרון וטיפול בשגיאות.
  5. בדיקות. מאמתים תרחישים: הוספה, מחיקה, קופונים, התחברות, מכשירים ניידים.
  6. פריסה ותמיכה. פורסים לסביבת הייצור, מספקים גישה לקוד המקור ולתיעוד.
רשימת בדיקה של טעויות נפוצות
  • מלאי לא נבדק (maxQuantity). אם מוצר אזל מהמלאי, העגלה צריכה להציג הודעה ולא לאפשר הוספה נוספת.
  • התעלמות ממיזוג עגלות. במהלך התחברות, העגלה האנונימית עלולה ללכת לאיבוד אם המיזוג לא מופעל.
  • חוסר בטיפול בשגיאות. שגיאת רשת לא צריכה להקפיא את הממשק — יש לבטל את השינויים.

לוחות זמנים ועלות

לוח פיתוח: בין 2 ל-4 שבועות בהתאם למורכבות הקטלוג ולדרישות העיצוב. העלות מחושבת באופן אישי לאחר אודיט של החנות הנוכחית. המחירים מתחילים מ-$2,500 לאינטגרציית עגלה בסיסית. לקוחות בדרך כלל חוסכים $5,000–$10,000 בשנה על ידי הפחתת נטישת עגלות עם עגלת ה-React שלנו ל-Bitrix.

צרו קשר כדי לדון בפרויקט שלכם. הזמינו ייעוץ מקדים — נשלח הצעה מסחרית ראשונית תוך יום. קבלו ייעוץ: כתבו לנו, ונעריך כיצד עגלת React יכולה לשפר את החנות המקוונת שלכם.

שלב משך תוצאה
ניתוח ואודיט 1–2 ימים דוח עם המלצות
פיתוח API ועגלת React 5–10 ימים קוד מקור, תיעוד
אינטגרציה ובדיקות 3–5 ימים אב-טיפוס עובד בסביבת staging
פריסה ובדיקות סופיות 2–3 ימים גרסת ייצור