Zpět na domů

Integrace Next.js s 1C Bitrix: asynchronní přenos leadů

Praktická příručka k asynchronní integraci Next.js 16 s 1C Bitrix. Použití after() pro zpracování leadů na pozadí, nastavení retry mechanismů a schémat PostgreSQL. Řešení problémů s timeouty a duplikáty.

Next.js a 1C Bitrix: jak odesílat leady bez front a workerů
Advertisement 728x90

# Asynchronní přenos leadů z Next.js do 1C Bitrix: vzorec bez front a workerů

Synchronní odesílání leadů do CRM přes REST API vede k kritickým problémům: uživatel čeká na odpověď až do dokončení externího požadavku, nestabilita API 1C Bitrix způsobuje timeouty a chyby. Nabízíme řešení na Next.js 16, které vylučuje fronty a pozadíové procesy. Implementace ukládá lead do lokální PostgreSQL, okamžitě odpovídá uživateli a integraci s Bitrixem provádí přes after() – mechanismus pozadíového zpracování po odeslání HTTP odpovědi.

Architektura bez front: tři vrstvy odpovědnosti

Klíčový princip – rozdělení operací na synchronní a asynchronní části. Při přijetí formuláře:

  • Validace dat přes zod
  • Uložení do PostgreSQL s bitrix_id=NULL
  • Okamžitá odpověď 200 OK
  • Pozadíové odeslání do Bitrix přes after()

To zaručuje:

Google AdInline article slot
  • Nezávislost na stabilitě Bitrix REST API
  • Absence blokování uživatelského rozhraní
  • Možnost manuálního zpracování nedoručených leadů přes SELECT * FROM leads WHERE bitrix_id IS NULL

Výhodou přístupu je odmítnutí Redis/BullMQ. Všechny operace se vejdou do API route Next.js, používajíc vestavěný after() pro post-odpovědní zpracování. To snižuje složitost infrastruktury a zjednodušuje nasazení na VPS přes systemd/nginx.

after() v Next.js 16: technická implementace

Metoda after() řeší problém „ogň-and-forget“ v serverless prostředích. Na rozdíl od Promise.resolve().then() zaručuje provedení úlohy i po odeslání odpovědi, bez ukončení procesu před dokončením operace. Příklad zpracování formuláře:

export async function POST(request: Request) {
  // ... validatsiya and antidubl
  
  const [lead] = await pgQuery(...);

  after(async () => {
    try {
      const bitrixId = await sendToBitrix24(payload);
      await pgQuery(
        `UPDATE leads SET bitrix_id = $1 WHERE id = $2`,
        [bitrixId, lead.id]
      );
    } catch (error) {
      console.error("[Leads API] Error otpravki in Bitriks:", error);
    }
  });

  return Response.json({ ok: true, id: lead.id });
}

Důležité nuancí:

Google AdInline article slot
  • Anti-duplicita je realizována přes okno 10 minut v PostgreSQL, ne přes Bitrix (CRM přijímá duplicity bez varování)
  • bitrix_id je uloženo jako nullable text – odráží asynchronní povahu operace
  • Chyby integrace se logují do journalctl, neovlivňují uživatelskou odpověď

Spolehlivý HTTP klient pro 1C Bitrix

Kritické parametry pro stabilní práci s nestabilním API:

  • MAX_ATTEMPTS = 2 – rovnováha mezi spolehlivostí a zátěží
  • REQUEST_TIMEOUT_MS = 8000 – nad p95 latencí Bitrix (400-700 ms)
  • RETRY_DELAY_MS = 1500 – lineární backoff bez exponenciální složitosti

Implementace klienta zahrnuje:

async function bitrixRequest(method: string, payload: Record<string, unknown>) {
  for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
    const controller = new AbortController();
    const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);

    try {
      const response = await fetch(url, {
        signal: controller.signal,
        // ...
      });

      const text = await response.text();
      const json = text ? JSON.parse(text) : {};

      if (!response.ok || json.error) {
        throw new Error(json.error_description || `HTTP ${response.status}`);
      }

      return json;
    } catch (error) {
      if (attempt >= MAX_ATTEMPTS) throw error;
      await new Promise(r => setTimeout(r, RETRY_DELAY_MS));
    } finally {
      clearTimeout(timer);
    }
  }
}

Tři klíčové momenty:

Google AdInline article slot
  • Manuální parsování přes response.text() místo response.json() – obchází chyby Bitrix s prázdnými odpověďmi
  • Zpracování dvou typů chyb: HTTP statusy a interní chyby CRM
  • Zaručené vyčištění timeru v finally – zabraňuje únikům paměti

Vlastnosti autentizace a schématu dat

Pro integraci byl vybrán incoming webhook místo OAuth:

  • Žádná závislost na Marketplace a schvalováních
  • Jednoduché řízení env proměnné BITRIX_WEBHOOK_URL
  • Scopy se nastavují v admince Bitrix

Riziko úniku tokenu v URL se minimalizuje pravidlem: v logách a kódu se uvádí jen metoda API, ne úplná URL.

Schématu tabulky leads:

CREATE TABLE leads (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  name text NOT NULL,
  phone text NOT NULL,
  source text,
  bitrix_id text,
  created_at timestamptz NOT NULL DEFAULT now()
);

Proč bitrix_id text, ne integer?

  • Bitrix vrací ID jako řetězec v JSON
  • Není potřeba převodu typů
  • UUID v PostgreSQL zajišťuje idempotenci

Co je důležité

  • Zdroj pravdy – lokální DB: lead se ukládá před voláním Bitrixu, což zaručuje data i při selhání CRM
  • Post-odesílací zpracování: after() nahrazuje fronty, odstraňuje složitost infrastruktury
  • Řízení chyb: retry s timeouty a logování do journalctl zajišťuje pozorovatelnost
  • Anti-duplicita na úrovni DB: okno 10 minut podle telefonu zabraňuje duplicitám nezávisle na CRM
  • Bezpečná autentizace: webhook vyžaduje přísnou kontrolu logování URL

Tento vzorec je vhodný pro projekty s zatížením do 50 požadavků za minutu. Pro vysoce zatížené systémy se doporučuje přidat monitorování přes SELECT COUNT(*) FROM leads WHERE bitrix_id IS NULL a automatické retry přes cron. V aktuální implementaci je manuální zpracování chyb preferováno před automatickými opakovanými pokusy – to snižuje riziko duplikování leadů při dočasných selháních.

— Editorial Team

Advertisement 728x90

Číst dál