הגדרות חיבור'); return $links; }); add_action('admin_notices', static function () { $screen = get_current_screen(); if (!current_user_can('manage_options') || !$screen || $screen->id !== 'settings_page_wizup-forms') { return; } global $wpdb; $count = (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM %i WHERE status IN ('failed','attention','warning')", Queue::table())); if ($count) { echo '

Wizup Forms: ' . esc_html((string) $count) . ' פניות דורשות בדיקה ביומן השליחה.

'; } }); } public static function handle(): void { if (!current_user_can('manage_options')) { wp_die('אין הרשאה.'); } check_admin_referer('wizup_forms_admin'); $action = sanitize_key(wp_unslash($_POST['operation'] ?? '')); $message = ''; $error = false; if ($action === 'save') { $token = is_string($_POST['token'] ?? null) ? sanitize_text_field(wp_unslash($_POST['token'])) : ''; if ($token !== '') { if (strlen($token) < 16 || strlen($token) > 1024 || preg_match('/\s/', $token)) { $message = 'ה-Token אינו תקין. יש להדביק את הערך בלבד, ללא Bearer וללא רווחים.'; $error = true; } else { try { update_option('wizup_forms_token', Crypto::seal($token), false); delete_option('wizup_forms_stages'); $message = 'ה-Token נשמר. כעת אפשר לבדוק חיבור ולטעון שלבים.'; } catch (\Throwable $e) { $message = 'שמירת ה-Token נכשלה. נדרשת תמיכת OpenSSL בשרת.'; $error = true; } } } else { $message = 'ה-Token הקיים נשמר ללא שינוי.'; } } elseif ($action === 'disconnect') { delete_option('wizup_forms_token'); delete_option('wizup_forms_stages'); $message = 'החיבור נותק. פניות קיימות נשארות מוצפנות בתור עד תום תקופת השמירה.'; } elseif ($action === 'repeat_notes') { update_option('wizup_forms_repeat_notes', sanitize_key(wp_unslash($_POST['repeat_notes'] ?? '')) === 'yes' ? 'yes' : '', false); $message = 'הגדרת הפניות החוזרות נשמרה. פניות ישנות שנכשלו לא יישלחו מחדש ללא לחיצה על בדיקה ושליחה מחדש ביומן.'; } elseif ($action === 'test') { $result = Client::refresh_stages(); $error = is_wp_error($result); $message = $error ? $result->get_error_message() : 'החיבור והרשאת הקריאה תקינים. נטענו ' . count($result) . ' שלבים. הרשאת הכתיבה תיבדק בשליחת טופס בפועל.'; } elseif ($action === 'process') { Queue::tick(); $message = 'עובדו עד 3 פניות שמועד שליחתן הגיע. הסטטוסים מופיעים ביומן.'; } elseif ($action === 'retry') { $ok = Queue::retry(absint($_POST['id'] ?? 0)); $error = !$ok; $message = $ok ? 'הפנייה הוחזרה לתור עם הנתונים המקוריים ואותו מזהה פעולה.' : 'לא ניתן לנסות שוב: הפנייה כבר נשלחה, תקופת השמירה הסתיימה או שה-Token השתנה.'; } elseif ($action === 'diagnostic') { global $wpdb; $row = $wpdb->get_row($wpdb->prepare('SELECT workflow,connection FROM %i WHERE id=%d', Queue::table(), absint($_POST['id'] ?? 0)), ARRAY_A); $errors = []; try { if ($row && hash_equals($row['connection'], Settings::fingerprint()) && !empty($row['workflow'])) { $context = json_decode(Crypto::open($row['workflow']), true); if (($context['kind'] ?? '') === 'validation_error') { $errors = $context['errors'] ?? []; } } } catch (\Throwable $e) { /* Do not expose encryption failures or stored data. */ } $html = '

פרטי הדחייה מ-Wizup

מידע למנהל האתר בלבד. ההודעות נשמרות מוצפנות ונמחקות עם הפנייה. אין להעתיק מידע אישי לפנייה ציבורית לתמיכה.

'; foreach ($errors as $field => $messages) { $html .= '

' . esc_html($field) . ': ' . esc_html(implode(' | ', $messages)) . '

'; } if (!$errors) { $html .= '

אין פרטי אבחון שמורים. בצעו בדיקה ושליחה מחדש ביומן.

'; } $html .= '

חזרה ליומן Wizup Forms

'; wp_die(wp_kses_post($html), 'פרטי דחייה', ['response' => 200]); } elseif ($action === 'delete') { global $wpdb; $wpdb->query($wpdb->prepare("DELETE FROM %i WHERE id=%d AND status != 'sending'", Queue::table(), absint($_POST['id'] ?? 0))); $message = 'הרשומה הוסרה מהיומן אם לא הייתה בשליחה פעילה.'; } set_transient('wizup_forms_notice_' . get_current_user_id(), ['text' => $message, 'error' => $error], 60); wp_safe_redirect(admin_url('options-general.php?page=wizup-forms')); exit; } private static function button(string $operation, string $label, int $id = 0): void { echo '
'; wp_nonce_field('wizup_forms_admin'); echo ''; echo '
'; } public static function page(): void { if (!current_user_can('manage_options')) { return; } $notice = get_transient('wizup_forms_notice_' . get_current_user_id()); delete_transient('wizup_forms_notice_' . get_current_user_id()); $has_token = Settings::token() !== ''; echo '

Wizup Forms

מהטופס באתר - ישירות למערכת הלידים שלכם.

'; if ($notice) { echo '

' . esc_html($notice['text']) . '

'; } echo '

1. חיבור לחשבון Wizup

ב-Wizup פתחו את כלי המפתחים וצרו מפתח API עם ההרשאות leads:write ו-leads:read. נדרשת חבילה הכוללת גישה ל-API.

'; echo '

שרת: ' . esc_html(WIZUP_FORMS_API) . ' · ' . ($has_token ? 'נשמר Token' : 'טרם הוגדר חיבור') . '

'; echo '
'; wp_nonce_field('wizup_forms_admin'); echo '

המפתח נשמר מוצפן בשרת ואינו נכלל בדפי הטפסים או בייצוא Elementor.

'; self::button('test', 'בדיקת חיבור וטעינת שלבים'); if ($has_token) { self::button('disconnect', 'ניתוק החיבור'); } echo '

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

'; echo '

פניות חוזרות מאותו מספר

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

נדרשות ב-Token גם הרשאות contacts:read ו-notes:write. איש הקשר מזוהה בהתאמה מדויקת למספר הטלפון. פניות ישנות שנכשלו דורשות בדיקה ושליחה מחדש ביומן.

'; wp_nonce_field('wizup_forms_admin'); echo '

'; echo '

2. חיבור הטפסים

Elementor Pro

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

Contact Form 7

פתחו את הטופס בלוח הבקרה, עברו ללשונית Wizup, הפעילו את החיבור ובחרו את השדות המתאימים.

שם וטלפון הם חובה. ברירת המחדל לקידומת היא ישראל (972). שדות נוספים נשלחים רק לאחר מיפוי מפורש לשדות מותאמים שכבר קיימים ב-Wizup.

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

'; self::custom_fields_guide(); echo '

3. יומן שליחה

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

'; self::button('process', 'עיבוד פניות שממתינות לשליחה'); echo '

השליחה מתבצעת ברקע באמצעות WP-Cron. באתר עם מעט תנועה מומלץ להגדיר הפעלת Cron בשרת מדי דקה. רעננו את העמוד לצפייה בסטטוס מעודכן.

'; $states = ['pending' => 'ממתין', 'retry' => 'ניסיון חוזר מתוכנן', 'sending' => 'בשליחה', 'sent' => 'נשלח', 'noted' => 'פנייה חוזרת נשמרה', 'warning' => 'נשלח חלקית', 'failed' => 'נכשל', 'attention' => 'דורש בדיקה']; echo '
'; $rows = Queue::recent(); if (!$rows) { echo ''; } foreach ($rows as $row) { echo ''; } echo '
מועד (UTC)טופססטטוסתוצאהפעולות
עדיין אין פניות. חברו טופס ושלחו פנייה לבדיקה.
' . esc_html($row['created_at']) . '' . esc_html($row['source'] . ' / ' . $row['form_id']) . '' . esc_html($states[$row['status']] ?? $row['status']) . '
' . esc_html('ניסיונות: ' . $row['attempts']) . '
' . esc_html($row['note']) . '
HTTP ' . esc_html($row['http_code']) . ($row['lead_id'] ? ' · Lead #' . esc_html($row['lead_id']) : '') . '
'; if (in_array($row['status'], ['failed', 'attention'], true)) { self::button('retry', 'בדיקה ושליחה מחדש', (int) $row['id']); } if ($row['status'] === 'failed' && (int) $row['http_code'] === 422) { self::button('diagnostic', 'פרטי הדחייה', (int) $row['id']); } if ($row['status'] !== 'sending') { self::button('delete', 'מחיקה', (int) $row['id']); } echo '
'; } private static function custom_fields_guide(): void { $command = "console.table(\n JSON.parse(document.querySelector('#app').getAttribute('data-page'))\n .props.customFields.map(({ label, key, type }) => ({ label, key, type }))\n);"; echo '

מדריך: חיבור הודעה ושדות נוספים

לכל שדה ב-Wizup יש שם לתצוגה (label) ו-מפתח פנימי (key). במיפוי בתוסף מזינים את המפתח המדויק. למשל, שדה בשם ״הודעה״ יכול לקבל מפתח כמו field_ab12cd34. זו דוגמה בלבד - לכל שדה יכול להיות מפתח אחר.

'; echo '

1. יצירת השדה בחשבון Wizup

  1. היכנסו לחשבון Wizup שאליו שייך ה-Token שבתוסף ופתחו את הגדרות הלידים.
  2. עברו ללשונית שדות וחיבורים, ובאזור שדות מותאמים אישית הזינו שם ובחרו סוג. לתוכן הודעה בחרו טקסט ארוך ולחצו הוסף שדה. אם השדה כבר קיים, השתמשו בו.
  3. לאחר השמירה רעננו את עמוד הגדרות הלידים כדי לטעון את רשימת השדות העדכנית.
'; echo '

2. איתור המפתח באמצעות DevTools בדפדפן

  1. בעמוד הגדרות הלידים של Wizup, לחצו לחיצה ימנית ובחרו בדיקה / Inspect. בכלי המפתחים עברו ללשונית Console.
  2. הזינו את הפקודה שלהלן ולחצו Enter. היא קוראת את הגדרות השדות מהעמוד הפתוח ומציגה רק את השם, המפתח והסוג שלהם.
' . esc_html($command) . '

בטבלה שתופיע חפשו בעמודת label את שם השדה שיצרתם, למשל ״הודעה״, והעתיקו מאותה שורה את הערך בעמודת key, ללא מרכאות. עמודת type מציינת את סוג השדה. אם הטבלה ריקה, ודאו ששמרתם שדה בחשבון הנכון ורעננו את עמוד הגדרות הלידים.

'; echo '
דרך נוספת: איתור המפתח בלשונית Network
  1. פתחו את לשונית Network בכלי המפתחים ובחרו Fetch/XHR.
  2. השאירו את כלי המפתחים פתוחים. מתוך תפריטי Wizup עברו לעמוד אחר וחזרו להגדרות הלידים כדי שתופיע בקשה בשם lead-stage.
  3. בחרו בבקשה ובכרטיסיית Preview פתחו props ואז customFields. פתחו את פריטי הרשימה, מצאו את השדה לפי label והעתיקו את key שלו.

אם הבקשה אינה מופיעה, בחרו All ורעננו את העמוד. בבקשת lead-stage פתחו Response וחפשו customFields. אם התשובה מוצגת כ-HTML או באותיות מקודדות, השתמשו בדרך ה-Console שלמעלה.

'; echo '

3. הדבקת המפתח במיפוי הטופס

  1. באלמנטור: פתחו את הטופס, עברו אל Wizup, ובאזור שדות מותאמים לחצו הוספת פריט. ב-Contact Form 7: עברו ללשונית Wizup ולשורת מיפוי תחת שדות מותאמים.
  2. ב-מפתח השדה ב-Wizup הדביקו את ערך key שהעתקתם. ב-שדה מהטופס בחרו את שדה ההודעה שלכם, למשל Message (message) באלמנטור או your-message ב-CF7.
  3. לשדה הודעה בחרו סוג ערך טקסט / מספר / תאריך. לשדה מסוג תיבת סימון (checkbox) בחרו כן / לא. שמרו או פרסמו את הטופס.

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

'; } }