הגדרות חיבור'); 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 '
'; } }); } 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 = 'מידע למנהל האתר בלבד. ההודעות נשמרות מוצפנות ונמחקות עם הפנייה. אין להעתיק מידע אישי לפנייה ציבורית לתמיכה.
'; foreach ($errors as $field => $messages) { $html .= '' . esc_html($field) . ': ' . esc_html(implode(' | ', $messages)) . '
'; } if (!$errors) { $html .= 'אין פרטי אבחון שמורים. בצעו בדיקה ושליחה מחדש ביומן.
'; } $html .= ''; 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 ''; } 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 'מהטופס באתר - ישירות למערכת הלידים שלכם.
' . esc_html($notice['text']) . '
ב-Wizup פתחו את כלי המפתחים וצרו מפתח API עם ההרשאות leads:write ו-leads:read. נדרשת חבילה הכוללת גישה ל-API.
שרת: ' . esc_html(WIZUP_FORMS_API) . ' · ' . ($has_token ? 'נשמר Token' : 'טרם הוגדר חיבור') . '
בדיקת החיבור קוראת את רשימת השלבים ואינה יוצרת ליד. לאחר ההגדרה יש לשלוח טופס בדיקה עם מספר שטרם קיים במערכת.
Wizup שומרת ליד אחד לכל מספר טלפון. כשאפשרות זו פעילה, פנייה נוספת תישמר כהערה חדשה אצל איש הקשר ובכרטיס הליד המקושר אליו. ההערה כוללת את פרטי הטופס הממופים ואת מועד הפנייה. פרטי הליד, השלב וההערות הקודמות נשמרים.
נדרשות ב-Token גם הרשאות contacts:read ו-notes:write. איש הקשר מזוהה בהתאמה מדויקת למספר הטלפון. פניות ישנות שנכשלו דורשות בדיקה ושליחה מחדש ביומן.
ערכו את הטופס, הוסיפו Wizup תחת ״פעולות לאחר שליחה״ ופתחו את הגדרות Wizup. בחרו את שדות השם, הטלפון והאימייל מהרשימה או השתמשו בזיהוי אוטומטי. הרשימה מתעדכנת לפי השדות בטופס.
פתחו את הטופס בלוח הבקרה, עברו ללשונית Wizup, הפעילו את החיבור ובחרו את השדות המתאימים.
שם וטלפון הם חובה. ברירת המחדל לקידומת היא ישראל (972). שדות נוספים נשלחים רק לאחר מיפוי מפורש לשדות מותאמים שכבר קיימים ב-Wizup.
יצירת ליד אינה כוללת מקורות, מוצרים או קבצים. אפשר למפות תוכן הודעה לשדה מותאם. פניות חוזרות יישמרו כהערות רק לאחר הפעלת האפשרות והרשאותיה. אין סימון אוטומטי של הסכמה לדיוור.
50 הפניות האחרונות. פרטי הפנייה נמחקים מהתור לאחר יצירת הליד או השלמת הערות הפנייה החוזרת; פניות שלא נשלחו והיומן נשמרים עד 14 ימים. היומן אינו מציג שמות, טלפונים או תוכן טפסים.
'; self::button('process', 'עיבוד פניות שממתינות לשליחה'); echo 'השליחה מתבצעת ברקע באמצעות WP-Cron. באתר עם מעט תנועה מומלץ להגדיר הפעלת Cron בשרת מדי דקה. רעננו את העמוד לצפייה בסטטוס מעודכן.
'; $states = ['pending' => 'ממתין', 'retry' => 'ניסיון חוזר מתוכנן', 'sending' => 'בשליחה', 'sent' => 'נשלח', 'noted' => 'פנייה חוזרת נשמרה', 'warning' => 'נשלח חלקית', 'failed' => 'נכשל', 'attention' => 'דורש בדיקה']; 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 ' |
לכל שדה ב-Wizup יש שם לתצוגה (label) ו-מפתח פנימי (key). במיפוי בתוסף מזינים את המפתח המדויק. למשל, שדה בשם ״הודעה״ יכול לקבל מפתח כמו field_ab12cd34. זו דוגמה בלבד - לכל שדה יכול להיות מפתח אחר.
' . esc_html($command) . 'בטבלה שתופיע חפשו בעמודת label את שם השדה שיצרתם, למשל ״הודעה״, והעתיקו מאותה שורה את הערך בעמודת key, ללא מרכאות. עמודת type מציינת את סוג השדה. אם הטבלה ריקה, ודאו ששמרתם שדה בחשבון הנכון ורעננו את עמוד הגדרות הלידים.
lead-stage.props ואז customFields. פתחו את פריטי הרשימה, מצאו את השדה לפי label והעתיקו את key שלו.אם הבקשה אינה מופיעה, בחרו All ורעננו את העמוד. בבקשת lead-stage פתחו Response וחפשו customFields. אם התשובה מוצגת כ-HTML או באותיות מקודדות, השתמשו בדרך ה-Console שלמעלה.
key שהעתקתם. ב-שדה מהטופס בחרו את שדה ההודעה שלכם, למשל Message (message) באלמנטור או your-message ב-CF7.checkbox) בחרו כן / לא. שמרו או פרסמו את הטופס.שלחו פנייה לבדיקה עם טלפון שטרם קיים כליד. לאחר שיומן התוסף מציג ״נשלח״, פתחו את הליד ב-Wizup ובדקו שתוכן ההודעה מופיע בשדה שיצרתם. יש למפות גם כל שדה נוסף שסומן כחובה ב-Wizup.