פיתוח Telegram Mini App עם אינטגרציה ל-Bitrix24
מנהל בשטח פותח את Telegram, רואה ליד, ומעביר אותו לסטטוס הבא תוך 30 שניות. במקום 5 דקות של חיפוש בדפדפן. זהו תרחיש טיפוסי שאנו מכסים עם שילוב של Telegram Mini App + Bitrix24 REST API. ה-Mini App פועל כלוח מחוונים ל-CRM ישירות בצ'אט: רשימת עסקאות, שלבים, פרטי קשר, אפשרות להגיב. אנו מפתחים פרויקט מפתח עם ניתוב OAuth מלא, אחסון טוקנים והגדרת webhooks.
בעיות שהאינטגרציה פותרת
אימות ללא דפדפן. Bitrix24 REST API דורש access_token מסוג OAuth, אבל Mini App הוא דף אינטרנט ב-Telegram WebView שבו הפנייה (redirect) בלתי אפשרית. הפתרון הוא שרת מתווך שמאמת את ה-initData של Telegram ומספק קישור OAuth או טוקן מוכן. יישמנו גישה זו ביותר מ-15 פרויקטים.
עיכובים בטיפול בלידים. מנהלים מבזבזים עד 5 דקות בפתיחת דפדפן, התחברות ל-CRM וחיפוש כרטיס. ה-Mini App מצמצם זאת ל-30 שניות: העובד רואה את הליד מיד ומשנה את הסטטוס בנגיעה אחת. לפי המדידות שלנו, מהירות התגובה לליד נכנס עולה ב-60–70% — ה-Telegram Mini App מעבד לידים פי 3 מהר יותר מאשר דרך ממשק האינטרנט.
התראות בזמן אמת. ללא אינטגרציה, מנהל לומד על עסקה חדשה דרך תקצירי דוא"ל עם עיכוב של דקות. Bitrix24 event webhooks שולחים בקשת POST לשרת, אשר שולח הודעה ל-Telegram. ההתראה מגיעה תוך 1–2 שניות.
מקרי שימוש
| תרחיש | תיאור | קהל יעד |
|---|---|---|
| לוח מחוונים נייד ל-CRM | צפייה בלידים ועסקאות, שינוי סטטוס, הוספת תגובות | מנהלי שטח, מחלקות מכירות |
| הזמנות ארגוניות | הגשת בקשות על ידי סוחרים/סוכנים דרך Mini App | חברות רשת, מפיצים |
| פורטל שירות עצמי | הלקוח רואה את סטטוס הבקשה והיסטוריית התקשורת | שירותי B2C, תמיכה טכנית |
| מנהל משימות | רשימת משימות, שינוי סטטוס, צירוף קבצים | צוותים המשתמשים ב-Bitrix24 |
ארכיטקטורה: OAuth ושרת פרוקסי
תהליך האימות:
- המשתמש פותח את ה-Mini App. הפרונטאנד שולח initData לשרת.
- השרת מאמת את ה-hash של initData, מחלץ user_id, ומחפש רשומה בטבלת
tg_bx24_tokens. - אם נמצא טוקן והוא לא פג — מחזיר JWT עבור ה-Mini App. אם לא — מחזיר קישור הרשאת OAuth עבור Bitrix24.
- לאחר אישור, השרת מחליף את
codeב-access_tokenושומר אותו מקושר ל-user_id של Telegram.
| שלב | פעולה | משתתף |
|---|---|---|
| 1 | פתיחת Mini App, שליחת initData | משתמש -> Mini App |
| 2 | אימות initData, חיפוש טוקן | שרת |
| 3 | החזרת JWT או קישור OAuth | שרת -> Mini App |
| 4 | אישור OAuth (אם נדרש) | משתמש -> Bitrix24 |
| 5 | החלפת קוד לטוקן, שמירה | שרת |
קוד הטיפול ב-OAuth callback הוא סטנדרטי עבור כל האינטגרציות שלנו:
class Bx24OAuthController {
public function callback(Request $request): Response {
$code = $request->get('code');
$tgUserId = $request->session()->get('pending_tg_user_id');
$tokenData = $this->exchangeCode($code);
\Local\TgBx24\TokenStorage::save($tgUserId, [
'access_token' => $tokenData['access_token'],
'refresh_token' => $tokenData['refresh_token'],
'expires_at' => time() + $tokenData['expires_in'],
'domain' => $tokenData['domain'],
'user_id' => $tokenData['user_id'],
]);
$this->bot->sendMessage($tgUserId, 'Авторизация в Битрикс24 прошла успешно.');
return redirect('/auth/success');
}
private function exchangeCode(string $code): array {
$response = Http::post('https://oauth.bitrix.info/oauth/token/', [
'grant_type' => 'authorization_code',
'client_id' => config('bx24.client_id'),
'client_secret' => config('bx24.client_secret'),
'code' => $code,
]);
return $response->json();
}
}הטוקנים נשמרים בטבלה נפרדת או ב-Redis. אנו משתמשים בחידוש אוטומטי 5 דקות לפני פקיעה כדי להבטיח שמשתמשים לא יאבדו גישה. כל הסודות מוצפנים.
class TokenStorage {
private const TABLE = 'tg_bx24_tokens';
public static function save(int $tgUserId, array $tokenData): void {
$encrypted = \Local\Crypto::encrypt(json_encode($tokenData));
\Bitrix\Main\Application::getConnection()->queryExecute(
"INSERT INTO " . self::TABLE . " (tg_user_id, token_data, updated_at) VALUES (?, ?, NOW()) ON DUPLICATE KEY UPDATE token_data = ?, updated_at = NOW()",
[$tgUserId, $encrypted, $encrypted]
);
}
public static function getValidToken(int $tgUserId): ?array {
$result = \Bitrix\Main\Application::getConnection()->query(
"SELECT token_data FROM " . self::TABLE . " WHERE tg_user_id = ?",
[$tgUserId]
);
$row = $result->fetch();
if (!$row) return null;
$data = json_decode(\Local\Crypto::decrypt($row['token_data']), true);
if ($data['expires_at'] < time() + 300) {
$data = self::refreshToken($data);
}
return $data;
}
private static function refreshToken(array $data): array {
$response = \Bitrix\Main\Web\HttpClient::post(
'https://oauth.bitrix.info/oauth/token/',
[
'grant_type' => 'refresh_token',
'client_id' => \Bitrix\Main\Config\Option::get('local.tg_bx24', 'client_id'),
'client_secret' => \Bitrix\Main\Config\Option::get('local.tg_bx24', 'client_secret'),
'refresh_token' => $data['refresh_token'],
]
);
return $newData;
}
} למה שרת מתווך?
בקשה ישירה מה-Mini App ל-API של Bitrix24 בלתי אפשרית בגלל CORS והיעדר אחסון מאובטח של טוקנים בצד הלקוח. שרת המתווך פועל כמתג קריפטוגרפי: כל הבקשות ל-REST API עוברות דרכו, והטוקנים לעולם לא עוזבים את השרת. זהו תקן האבטחה עבור OAuth ביישומים ניידים.
החלפת נתונים בזמן אמת עם Webhooks
Bitrix24 מאפשר להגדיר event webhooks — לדוגמה, class Bx24OAuthController { public function callback(Request $request): Response { $code = $request->get('code'); $tgUserId = $request->session()->get('pending_tg_user_id'); $tokenData = $this->exchangeCode($code); \Local\TgBx24\TokenStorage::save($tgUserId, [ 'access_token' => $tokenData['access_token'], 'refresh_token' => $tokenData['refresh_token'], 'expires_at' => time() + $tokenData['expires_in'], 'domain' => $tokenData['domain'], 'user_id' => $tokenData['user_id'], ]); $this->bot->sendMessage($tgUserId, 'Авторизация в Битрикс24 прошла успешно.'); return redirect('/auth/success'); } private function exchangeCode(string $code): array { $response = Http::post('https://oauth.bitrix.info/oauth/token/', [ 'grant_type' => 'authorization_code', 'client_id' => config('bx24.client_id'), 'client_secret' => config('bx24.client_secret'), 'code' => $code, ]); return $response->json(); } } . כאשר אירוע מופעל, Bitrix24 שולח POST לשרת שלנו. השרת מזהה את האחראי (ASSIGNED_BY_ID), מוצא את ה-user_id שלו ב-Telegram דרך טבלת הטוקנים, ושולח הודעה דרך class TokenStorage { private const TABLE = 'tg_bx24_tokens'; public static function save(int $tgUserId, array $tokenData): void { $encrypted = \Local\Crypto::encrypt(json_encode($tokenData)); \Bitrix\Main\Application::getConnection()->queryExecute( "INSERT INTO " . self::TABLE . " (tg_user_id, token_data, updated_at) VALUES (?, ?, NOW()) ON DUPLICATE KEY UPDATE token_data = ?, updated_at = NOW()", [$tgUserId, $encrypted, $encrypted] ); } public static function getValidToken(int $tgUserId): ?array { $result = \Bitrix\Main\Application::getConnection()->query( "SELECT token_data FROM " . self::TABLE . " WHERE tg_user_id = ?", [$tgUserId] ); $row = $result->fetch(); if (!$row) return null; $data = json_decode(\Local\Crypto::decrypt($row['token_data']), true); if ($data['expires_at'] < time() + 300) { $data = self::refreshToken($data); } return $data; } private static function refreshToken(array $data): array { $response = \Bitrix\Main\Web\HttpClient::post( 'https://oauth.bitrix.info/oauth/token/', [ 'grant_type' => 'refresh_token', 'client_id' => \Bitrix\Main\Config\Option::get('local.tg_bx24', 'client_id'), 'client_secret' => \Bitrix\Main\Config\Option::get('local.tg_bx24', 'client_secret'), 'refresh_token' => $data['refresh_token'], ] ); return $newData; } } . העיכוב הוא לא יותר משתי שניות.
איך עובד חידוש טוקן אוטומטי
אנו מאחסנים טוקנים בטבלת `tg_bx24_tokens` עם שדה `expires_at`. 5 דקות לפני פקיעה, השרת מבקש אוטומטית טוקן חדש דרך refresh_token. אם גם ה-refresh_token פג, המשתמש מתבקש לעבור שוב OAuth. כל הסודות מוצפנים.React Mini App: לוח מחוונים לעובדי CRM
הפרונטאנד בנוי עם React באמצעות Telegram WebApp SDK. זה מאפשר להטמיע את הממשק בכפתור של בוט ולהשתמש בפקדים מקוריים (לדוגמה, משוב הפטי).
import { useEffect, useState } from 'react';
const tg = window.Telegram.WebApp;
interface Deal {
ID: string;
TITLE: string;
OPPORTUNITY: string;
STAGE_ID: string;
CONTACT_NAME: string;
}
function CrmDashboard() {
const [deals, setDeals] = useState<Deal[]>([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
tg.ready();
tg.expand();
loadDeals();
}, []);
async function loadDeals() {
const res = await fetch('/tg-api/crm/deals', {
headers: {
'X-Tg-Init-Data': tg.initData,
},
});
const data = await res.json();
setDeals(data.deals);
setLoading(false);
}
async function updateStage(dealId: string, stageId: string) {
await fetch(`/tg-api/crm/deals/${dealId}/stage`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'X-Tg-Init-Data': tg.initData,
},
body: JSON.stringify({ stage_id: stageId }),
});
tg.HapticFeedback.notificationOccurred('success');
loadDeals();
}
// ... рендер
}בשרת, מחלקת פרוקסי עוטפת קריאות ל-REST API. היא מביאה אוטומטית את הטוקן מהאחסון ומטפלת בשגיאות הרשאה:
class CrmDealsProxy {
public function getDeals(int $tgUserId): array {
$tokenData = TokenStorage::getValidToken($tgUserId);
if (!$tokenData) {
throw new \RuntimeException('Not authorized', 401);
}
$bx24 = new \Local\TgBx24\Bx24Client($tokenData['access_token'], $tokenData['domain']);
$result = $bx24->call('crm.deal.list', [
'filter' => ['ASSIGNED_BY_ID' => $tokenData['user_id'], 'CLOSED' => 'N'],
'select' => ['ID', 'TITLE', 'OPPORTUNITY', 'STAGE_ID', 'CONTACT_ID'],
'order' => ['DATE_MODIFY' => 'DESC'],
'start' => 0,
]);
return $result['result'] ?? [];
}
public function updateDealStage(int $tgUserId, int $dealId, string $stageId): bool {
$tokenData = TokenStorage::getValidToken($tgUserId);
$bx24 = new \Local\TgBx24\Bx24Client($tokenData['access_token'], $tokenData['domain']);
$result = $bx24->call('crm.deal.update', [
'id' => $dealId,
'fields' => ['STAGE_ID' => $stageId],
]);
return !empty($result['result']);
}
} מה כלול בעבודה
- רישום אפליקציית Bitrix24 (OAuth), הגדרת Mini App ב-@BotFather
- שרת מתווך: אימות initData, אחסון וחידוש טוקני OAuth (PHP 8.1, MariaDB)
- React Mini App עבור התרחיש הנבחר (לוח עסקאות, בקשות, משימות)
- פרוקסי REST ל-API של Bitrix24 עם חידוש טוקן אוטומטי
- Bitrix24 event webhooks להתראות Telegram
- הדרכת משתמשים: קישור חשבון והשקה לבדיקה
- תיעוד התקנה ותמיכה
תהליך ולוחות זמנים
אנו פועלים בגישה מובנית: איסוף נתונים → ביקורת/ניתוח → עיצוב → הערכת עלות → פיתוח → בדיקות → השקה.
- MVP לתרחיש אחד: בין 3 ל-5 שבועות
- יישום מלא עם מספר סעיפים: בין 8 ל-14 שבועות
העלות נקבעת באופן אישי לאחר ניתוח המפרט הטכני. אנו מספקים אחריות ל-30 יום על תפקוד האינטגרציה. ניסיון: 10+ שנים, מעל 50 אינטגרציות עם שירותים חיצוניים. מפתחי Bitrix מוסמכים.
צרו קשר לייעוץ — נערוך ביקורת של ה-CRM שלכם ונציע ארכיטקטורה שתקצר את זמן התגובה של צוות המכירות שלכם.

