סדר הפעולות האמיתי לחיבור מספר עסקי ל-WhatsApp Cloud API - מנוי ברמת האפליקציה מול מנוי ברמת ה-WABA, קוד ה-PIN לרישום המספר, health_status, והמלכודות ששוברות הודעות נכנסות בשקט.
עיקרי הדברים
- יש שני מנויי webhook, לא אחד. מנוי ברמת האפליקציה לא מספיק - חייבים גם POST ל-/{waba_id}/subscribed_apps, וזה אף פעם לא קורה אוטומטית. דילוג על השלב הזה גורם לכך שהיוצא עובד והנכנס פשוט לא.
- Meta מבצעת את אימות ה-webhook (בקשת GET) בתוך קריאת המנוי עצמה. נקודת הקצה הציבורית שלך חייבת להיות פרוסה ולהחזיר את ה-verify_token השמור לפני הקריאה הזו, אחרת היא נכשלת.
- מספר חייב להירשם פעם אחת דרך POST /{phone_number_id}/register עם קוד PIN בן 6 ספרות לפני שכל שליחה תעבוד. מגבלת הקצב היא 10 ניסיונות למספר ב-72 שעות, כך שניחוש ה-PIN יכול לנעול אותך לשלושה ימים.
- השתמש ב-GET /{phone_number_id}?fields=health_status לפני שאתה מאשים את הקוד. Meta מחזירה AVAILABLE, LIMITED או BLOCKED - זו תשובה ישירה לשאלה "האם המספר הזה יכול לשלוח עכשיו".
חיבור מספר עסקי ל-WhatsApp Cloud API נראה פשוט בתיעוד ומתגלה כרצף של שלבים תלויי-סדר שכשל באחד מהם לא מפיק שגיאה ברורה. המדריך הזה הוא סדר הפעולות בפועל, כולל שלוש נקודות שהתיעוד של Meta מזכיר בקצרה ושבפועל הן הסיבה הנפוצה ביותר לכך ש"הכול מוגדר אבל הודעות נכנסות לא מגיעות".
מה צריך להיות מוכן לפני שמתחילים
- Business Manager עם עסק מאומת. אימות עסקי אינו נדרש כדי לשלוח הודעות בדיקה, אבל כן נדרש כדי לצאת ממגבלות הכמות הנמוכות.
- אפליקציית Meta עם מוצר WhatsApp מוסף, ובידך
app_idו-app_secret. - WhatsApp Business Account (WABA) עם
waba_id, ומספר טלפון עםphone_number_id. - טוקן של System User עם ההרשאה
whatsapp_business_messagingושיוך מפורש לנכסי ה-WABA ומספר הטלפון. טוקן זמני מ-Graph API Explorer יעבוד היום וייפול מחר עם קוד 190. - נקודת קצה ציבורית ב-HTTPS ל-webhook, פרוסה וחיה. לא ngrok זמני, אלא הכתובת שתישאר.
שלב 1: מציאת מזהה מספר הטלפון
מזהה מספר הטלפון אינו מספר הטלפון. שולפים אותו מרשימת המספרים של ה-WABA, ומשתמשים בו כמעט בכל קריאה אחרת. הקריאה היא GET /{waba_id}/phone_numbers.
שלב 2: הגדרת ה-webhook ברמת האפליקציה
הקריאה היא POST /{app_id}/subscriptions, והיא שקולה למה שעושים ידנית ב-App Dashboard תחת WhatsApp ואז Configuration. שדות הבקשה:
object- הערךwhatsapp_business_accountcallback_url- כתובת ה-webhook הציבורית שלךverify_token- המחרוזת ששמרת בצד שלךfields- לכל הפחותmessages; בפועל כדאי גםmessage_template_status_updateו-message_template_quality_updateכדי לדעת מתי תבנית אושרה, נדחתה או הושהתהaccess_token- לא טוקן המשתמש. כאן צריך App Access Token, שהוא פשוטAPP_ID|APP_SECRETעם קו אנכי ביניהם
המלכודת: Meta שולחת את בקשת האימות מסוג GET אל callback_url בתוך הקריאה הזו, בזמן אמת. אם השרת שלך עדיין לא פרוס, או שה-verify_token שאתה שולח לא זהה לזה ששמור אצלך, הקריאה נכשלת. אין כאן ניסיון חוזר מאוחר יותר.
שלב 3: המנוי שכולם שוכחים
זה השלב שגורם לרוב התקלות של "הודעות נכנסות לא מגיעות". מנוי ברמת האפליקציה מגדיר לאן Meta תשלח אירועים, אבל הוא אינו מחבר את חשבון ה-WhatsApp Business שלך לאפליקציה. זו קריאה נפרדת:
POST /{waba_id}/subscribed_apps - עם גוף ריק.
הקריאה אידמפוטנטית ואפשר לחזור עליה בבטחה. היא לעולם לא קורית אוטומטית. בלעדיה שליחה יוצאת תעבוד מצוין, וזה בדיוק מה שמטעה - נראה שהחיבור תקין. אפשר לוודא עם GET /{waba_id}/subscribed_apps.
שלב 4: רישום המספר
לפני שליחה ראשונה כלשהי המספר חייב להירשם ל-Cloud API:
POST /{phone_number_id}/register עם messaging_product: "whatsapp" ו-pin בן שש ספרות.
ה-PIN הוא קוד האימות הדו-שלבי של המספר. אם אימות דו-שלבי כבוי, הקריאה מגדירה אותו. אם הוא כבר פעיל, הקוד חייב להתאים לקוד הקיים. מגבלת הקצב היא 10 ניסיונות למספר ב-72 שעות, ולכן ניחושים חוזרים ינעלו את המספר לשלושה ימים. אם אין לך את הקוד, אפס אותו ב-WhatsApp Manager לפני שתנסה.
מספר לא רשום מחזיר קוד 133010 או 131045 בכל שליחה.
שלב 5: לוודא שהמספר באמת יכול לשלוח
במקום לנחש, Meta חושפת בדיקה ייעודית: GET /{phone_number_id}?fields=health_status. התשובה היא אחת מ-AVAILABLE, LIMITED או BLOCKED. זו הבדיקה הראשונה שכדאי להריץ כשמשהו מפסיק לעבוד, לפני שמחפשים באג בקוד.
אימות ה-webhook הנכנס
נקודת הקצה שלך צריכה לטפל בשני סוגי בקשות:
- GET - אימות. Meta שולחת
hub.mode,hub.verify_tokenו-hub.challenge. אם ה-verify_token תואם, יש להחזיר את ערך ה-hub.challengeכטקסט גולמי. - POST - אירועים. חובה לאמת את החתימה בכותרת
X-Hub-Signature-256, שהיא HMAC-SHA256 של גוף הבקשה הגולמי עם ה-app secret כמפתח.
מלכודת שנייה, ומאוד נפוצה: אימות החתימה חייב לרוץ על הבייטים הגולמיים. אם ה-framework שלך מפרסר את ה-JSON ואז אתה מסדר אותו מחדש למחרוזת, החתימה לא תתאים - אפילו אם התוכן זהה - כי סדר המפתחות והרווחים משתנים. בסביבת proxy יש לוודא שהנתיב של ה-webhook ממופה לפני ה-body parser.
כלל אחרון: תמיד להחזיר 200 לאירועי POST, גם כשהעיבוד הפנימי נכשל. אחרת Meta תשלח את אותו אירוע שוב ושוב, ובסופו של דבר תשבית את המנוי. את השגיאה יש לתעד בצד שלך ולהמשיך.
מה נשאר ידני
אימות העסק ב-Business Manager, העלאת תמונת פרופיל עסקית ובקשת עלייה במדרגת הכמות - כולם עוברים דרך ממשקי Meta ולוקחים ימים ולא דקות. כדאי לפתוח אותם מוקדם, במקביל לפיתוח, ולא לגלות ביום העלייה לאוויר שהחשבון תקוע במגבלה של 250 נמענים ביום.
שאלות נפוצות
למה שליחה ב-WhatsApp Cloud API עובדת אבל הודעות נכנסות לא מגיעות?
כמעט תמיד כי בוצע רק המנוי ברמת האפליקציה. יש קריאה שנייה ונפרדת - POST /{waba_id}/subscribed_apps - שמחברת את חשבון ה-WhatsApp Business לאפליקציה. היא לעולם לא קורית אוטומטית, ובלעדיה שליחה יוצאת עובדת רגיל בזמן שאף אירוע נכנס לא נמסר.
איזה טוקן נדרש ל-POST /{app_id}/subscriptions?
App Access Token, לא טוקן ה-System User שמשמש לשליחת הודעות. ה-App Access Token נבנה מחיבור מזהה האפליקציה וה-app secret עם קו אנכי: APP_ID|APP_SECRET. שליחת טוקן ההודעות כאן תיכשל בשגיאת הרשאות.
האם צריך לרשום את מספר הטלפון לפני שליחה?
כן, פעם אחת לכל מספר, דרך POST /{phone_number_id}/register עם messaging_product בערך whatsapp וקוד PIN בן שש ספרות. עד שזה מצליח, כל שליחה נכשלת עם 133010 או 131045. שים לב למגבלה של 10 ניסיונות רישום למספר ב-72 שעות - ניחוש ה-PIN יכול לנעול את המספר לשלושה ימים.
למה אימות ה-X-Hub-Signature-256 שלי תמיד נכשל?
כי ה-HMAC מחושב על גוף הבקשה הגולמי. אם body parser של JSON רץ קודם ואתה מסדר מחדש את האובייקט למחרוזת, סדר המפתחות והרווחים משתנים והחתימה כבר לא מתאימה, גם אם הנתונים זהים. יש לתפוס את הבייטים הגולמיים לפני כל פרסור, ובסביבת proxy למפות את נתיב ה-webhook לפני ה-body parser.
איך בודקים אם מספר WhatsApp יכול לשלוח כרגע?
קריאה ל-GET /{phone_number_id}?fields=health_status. Meta מחזירה AVAILABLE, LIMITED או BLOCKED. זו בדיקה ייעודית וזו הדרך המהירה ביותר להפריד בין בעיה ברמת החשבון לבין באג באינטגרציה שלך.
האם ה-webhook שלי צריך להחזיר שגיאה כשהעיבוד נכשל?
לא. תמיד להחזיר 200 לאירועי POST. תשובה שאינה 200 גורמת ל-Meta לשלוח את אותו אירוע שוב ושוב, ואם זה נמשך - להשבית את המנוי לגמרי. יש לתעד את הכשל בצד שלך, להחזיר 200, ולטפל בהתאמה בנפרד.
להמשך קריאה
שירות רלוונטי
WhatsApp Cloud API
תבניות, אינבוקס דו-כיווני ותזכורות על ה-API הרשמי של Meta.
על הכותב
יהונתן סעדיה
מהנדס פרילנסר לאוטומציה, אתרים ו-MVP
אני יהונתן סעדיה, מהנדס בכיר שבונה אוטומציה עסקית, אתרים מותאמים ומוצרי MVP לעסקים קטנים ובינוניים בארה"ב, אירופה וישראל. המדריכים האלה נכתבים מתוך עבודה אמיתית עם לקוחות, לא מתיאוריה.
בוא נעבוד יחדיש לך פרויקט דומה?
ספר לי מה אתה מנסה להפוך לאוטומטי או לבנות, ואומר לך מהי הדרך המהירה והאמינה ביותר ליישם את זה.
