@רק-טוב מה שעשית זה מעולה, רק שבתור המלצה יהיה תמיד עדיף להשתמש ב-PHPMailer מאשר להשתמש ב-mail.
הפוסטים הטובים ביותר שנוצרו על ידי soris1989
-
RE: שליחת מייל בphp
-
RE: עזרה עם מודול API
בסופו של דבר השתמשתי ב-session, ונעזרתי בפוסט:
https://f2.freeivr.co.il/topic/13141/מה-זה-סשן-ואיך-משתמשים-בו/2 -
RE: הוספת משתנים באופן יזום לבקשה
@צדיק-תמים כתב בהוספת משתנים באופן יזום לבקשה:
session_id($_GET['ApiCallId']);
תודה רבה,
זה עזר לי מאוד!! -
RE: עזרה לגבי קליקרים
@אA
ההגדרה הזו מסירה את ההודעה של: "שלוחה 15" בכניסה לשלוחה. -
RE: שליחת מייל בphp
עדיף להשתמש ב-PHPMailer.
קודם כל יש להוריד את החבילה באמצעות composer:
composer require phpmailer/phpmailer
וזה קוד לדוגמא:
<?php use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\Exception; require 'vendor/autoload.php'; // Include Composer's autoloader $mail = new PHPMailer(true); try { // SMTP Configuration $mail->isSMTP(); $mail->Host = 'smtp.example.com'; // Replace with your SMTP host $mail->SMTPAuth = true; $mail->Username = 'your_email@example.com'; // Your email $mail->Password = 'your_email_password'; // Your email password $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // Use `PHPMailer::ENCRYPTION_SMTPS` for SSL $mail->Port = 587; // Change to 465 if using SSL // Sender & Recipient $mail->setFrom('your_email@example.com', 'Your Name'); $mail->addAddress('recipient@example.com', 'Recipient Name'); // Attachments $mail->addAttachment('/path/to/file.pdf'); // Example: Attach a PDF $mail->addAttachment('/path/to/image.jpg', 'CustomFileName.jpg'); // Rename attachment // Email Content $mail->isHTML(true); $mail->Subject = 'Test Email with Attachment'; $mail->Body = '<h3>Hello,</h3><p>This is a test email with an attachment.</p>'; $mail->AltBody = 'Hello, This is a test email with an attachment.'; // Plain text fallback // Send Email $mail->send(); echo 'Email sent successfully!'; } catch (Exception $e) { echo "Email could not be sent. Error: {$mail->ErrorInfo}"; } ?>
-
RE: עזרה לגבי קליקרים
@אופיר מסכים ב-100%.
היו צריכים לדעתי להפריד את זה ל-2 הגדרות שונות. -
RE: בקשת POST בC# יוצרת שגיאה
@צדיק-תמים אני בדקתי, ומה ש@עידו אומר זה אמת.
יש בעיה בסיריאליזציה ב-C#, אגב, בדקתי את זה ב-postman וזה עובד (עם בקשת POST), ובדקתי את זה גם ב-PHP וזה גם עובד (גם עם בקשת POST).אם יש לך השגות על מה שנאמר כאן, אני מזמין אותך לנסות בעצמך את הנ"ל.
-
RE: מדוע נוצרת השגיאה הזו?
@עידו בניתי גם כן קוד ב-C# וקיבלתי את אותה השגיאה כאשר השתמשתי ב- HttpClient.PostAsync, כנראה שיש בעיה בסיראליזציה של ה-body, והטוקן לא מצליח להיות מתורגם כראוי.
למרות שנהוג להשתמש ב-POST לצורך יצירת משאבים (קבצים, נתנוים וכד'), כאן השתמשתי ב-HttpClient.GetAsync לצורך עקיפת הבעיה, וזה אכן הצליח ליצור קובץ לשלוחה הרצויה.
אגב, לצורך שימוש ב-API צריך לבצע 2 בקשות:
- הזדהות דרך מתודת קצה Login, לצורך קבלת ה-token.
- קריאה למתודת קצה המתאימה (שכאן היא UploadTextFile), תוך כדי השתלת ה-token ב-body או ב-header בהתאם לדוקומנטציה בקישור:
https://f2.freeivr.co.il/topic/55/api-גישת-מפתחים-למערכות/33?_=1739774721081
להלן הקוד:
using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; namespace YemotUploadTextFile { internal class Program { static void Main(string[] args) { UploadTextFileWithGet().GetAwaiter().GetResult(); Console.WriteLine("Done!"); } static async Task UploadTextFileWithGet() { var username = "<username>"; var password = "<password>"; var client = new HttpClient(); try { // login yemot system for getting token HttpResponseMessage responseJ = await client.GetAsync( $"https://www.call2all.co.il/ym/api/Login?username={username}&password={password}"); // בדיקת מצב התגובה if (responseJ.IsSuccessStatusCode) { // קריאת התוכן של התגובה string responseContent = await responseJ.Content.ReadAsStringAsync(); Console.WriteLine($"Response: {responseContent}"); var responseObj = JsonConvert.DeserializeObject<JObject>(responseContent); if (responseObj["responseStatus"].ToString() == "OK") { // send a get request to upload file on yemot server string token = responseObj["token"].ToString(); string what = "ivr2:14/text_file.ini"; string contents = "Some test message"; Console.WriteLine($"Response: {token}"); client = new HttpClient(); var responseJ2 = await client.GetAsync($"https://www.call2all.co.il/ym/api/UploadTextFile?token={token}&what={what}&contents={contents}"); // בדיקת מצב התגובה if (responseJ2.IsSuccessStatusCode) { // קריאת התוכן של התגובה var responseContent2 = await responseJ2.Content.ReadAsStringAsync(); Console.WriteLine($"Response: {responseContent2}"); } else { Console.WriteLine($"Error: {responseJ2.StatusCode}"); return; } } else { Console.WriteLine($"Error: {responseObj["message"]}"); return; } } else { Console.WriteLine($"Error: {responseJ.StatusCode}"); return; } } catch (Exception ex) { Console.WriteLine($"Exception: {ex.Message}"); } await Task.Delay(1000); Console.WriteLine("Async work done!"); } } }
-
RE: בקשת POST בC# יוצרת שגיאה
@עידו הרצתי עכשיו דרך ה-bash סידרה של שליחת בקשות CURL של POST, ואכן שבשביל שזה יעבוד, צריך להוריד את ה-flag של -d, ובמקום זה לשים flags של:
\--header "Content-Type: application/json" \--data-raw '{"token":"<username>:<password>","what":"ivr2:14/text_file.ini","contents":"Some test message"}'
לגבי זה שזה עובד במקרים אחרים, אני לא יודע מה לומר לך. מה שכן, בשביל שזה יעבוד בפורמט JSON אתה תצטרך ככל הנראה לבנות CURL באופן ידני, כי ה-httpClient.PostAsync לא בונה נכון את ה-CURL.
בכל אופן, הצעתי לך אתמול פתרון שכן עובד, תשתמש בו.
-
RE: מדוע נוצרת השגיאה הזו?
@עידו החלטתי להגדיל ראש ובדקתי את העניין ע"י שליחת בקשת POST, בפורמט של x-url-encoded (במקום בפורמט של application/json), וזה עבד.
כנראה באמת יש בעיה בסיריאליזציה בפורמט JSON.
להלן הקוד:
static async Task UploadTextFileWithPost() { try { var client = new HttpClient(); // Prepare key-value pairs var formData = new Dictionary<string, string> { { "token", $"{Username}:{Password}" }, { "what", "ivr2:14/text_file.ini" }, { "contents", "Some test message" } }; // Create FormUrlEncodedContent var content = new FormUrlEncodedContent(formData); // Optional: Add headers (Content-Type is set automatically) client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded")); var responseJ2 = await client.PostAsync("https://www.call2all.co.il/ym/api/UploadTextFile", content); // בדיקת מצב התגובה if (responseJ2.IsSuccessStatusCode) { // קריאת התוכן של התגובה var responseContent2 = await responseJ2.Content.ReadAsStringAsync(); Console.WriteLine($"Response: {responseContent2}"); } else { Console.WriteLine($"Error: {responseJ2.StatusCode}"); return; } } catch (Exception ex) { Console.WriteLine($"Exception: {ex.Message}"); } await Task.Delay(1000); Console.WriteLine("Async work done!"); }
-
RE: עזרה לגבי קליקרים
@אA לגבי @מנחם, כתוב בפרופיל שלו:
"הצטרף ב- 18 במאי 2020, 16:11 התחבר לאחרונה 16 בנוב׳ 2022, 21:58",
הוא התחבר לאחרונה לפני שנתיים+, תנסה אולי מנהל פעיל כמו @eliyahu -
RE: UploadFile - העלאת קובץ בAPI
@Freund להלן קוד שעובד להעלאת קובץ:
<?php $url = "https://www.call2all.co.il/ym/api/UploadFile"; // Prepare multipart form data $data = [ "token" => "$username:$password", "path" => "ivr2:14/test.wav", "file" => new CURLFile("audio/test.wav", "audio/wav", "test.wav") // File upload ]; // Make the request $response = curl_post_request($url, $data); echo "Response: " . $response; # POST request helper function function curl_post_request(string $url, $data, array $headers = []) { // Initialize cURL $ch = curl_init(); // Set cURL options curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); // Multipart data // Set headers (DO NOT manually set Content-Type for multipart) curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); // Execute request $response = curl_exec($ch); // Handle errors if (curl_errno($ch)) { throw new Exception(curl_error($ch)); } else { return $response; } }
-
RE: מערכת עדכון/שינוי פרטים אישיים, על בסיס נתונים קיימים
@אאד קוד להמחשה עבור שלוחת API (לא עשיתי על זה debugging), אבל העקרון מומחש היטב.
הקוד בודק בקובץ האם מס' הת.ז קיים באחת מהרשומות בקובץ המקור, במידה וכן, הקוד עובר על כל אחד משדות של הרשומה התואמת ושואל את המשתמש האם לעדכן. במידה ולא, הפרטים הרלוונטים נלקחים מהמשתמש, ורשומה חדשה מוזנת לקובץ המקור.להלן קובץ dataSource בפורמט CSV: (ניתן להמיר את זה בקובץ מקור ב-EXCEL, ולממש את זה בהתאם ע"י שימוש בחבילת: phpoffice/phpspreadsheet, תוריד אותה לפרויקט שלך באמצעות ה-composer)
datasource.csv<?php $apiCallId = $_GET['ApiCallId']; $apiPhone = $_GET['ApiPhone']; if (!$_GET['identity']) { echo 'read=t=אנא הזן את מספר תעודת הזהות=identity,,9,,15,Digits,'; exit; } $csvFile = __DIR__ . '/./datasource.csv'; // קובץ מקור $tempFile = __DIR__ . '/./temp.csv'; // קובץ זמני לשמירה $dataSource = []; $matchRecord = []; $matchIndex = null; // קריאת קובץ CSV המכיל את כל נתוני המשתמשים if (($handle = fopen($csvFile, "r")) !== false) { $headersRow = fgetcsv($handle); // דילוג על השורה הראשונה שמכילה כותרות לעמודות $dataSource[] = $headersRow; $index = 1; while (($row = fgetcsv($handle, 1000, ",")) !== false) { $dataSource[] = $row; // הוספת כל שורה למערך if (trim($row[1]) === trim($_GET['identity'])) { $matchRecord = $row; $matchIndex = $index; break; } $index++; } fclose($handle); } else { echo "שגיאה בפתיחת קובץ ה-CSV!"; } if ($matchRecord) { // מצב עדכון משתמש לאחר מציאת התאמה עם רשומה כלשי בקובץ מקור CSV if ($matchRecord[2]) { // בדיקה האם שם המשתמש הוזן לרשומה if (!$_GET['name_confirmation']) { $name = trim($matchRecord[2]); echo "read=t=שמכם כפי שמופיע הוא $name, לאישור הקש 1, לתיקון הקש 2=name_confirmation,,1,1,8,Digits,"; exit; } // במידה ומקש 2 לתיקון השם הוקש if ($_GET['name_confirmation'] == 2) { if (!$_GET['new_name']) { // הזנת ההקלטה + תמלול - מודול זה כרוך בתשלום של 0.4 יחידות echo "read=t=אנא הקלט את שמך=new_name,,voice,,no,,record,"; exit; } } # וכן על זה הדרך עבור כל השדות שאתה רוצה לבדוק # ..... } else { // השם לא הוזן לרשומה if (!$_GET['new_name']) { echo "read=t=אנא הקלט את שמך=new_name,,voice,,no,,record,"; exit; } } $phone = $matchRecord[0]; $identity = $matchRecord[1]; $name = $_GET['name_confirmation'] == 2 ? trim($_GET['new_name']) : trim($matchRecord[2]); # וכן ניתן להוסיף עוד שדות #.... $updateRecord = [$phone, $identity, $name]; for ($i = 0; $i < $dataSource[$matchIndex]; $i++) { $dataSource[$matchIndex][$i] = $updateRecord[$i]; } } else { // מצב יצירה של משתמש, כאשר אין התאמה של ת.ז עם אף רשומה בקובץ מקור if (!$_GET['name']) { echo "read=t=אנא הקלט את שמך=new_name,,voice,,no,,record,"; exit; } $phone = $apiPhone; $identity = trim($_GET['identity']); $name = trim($_GET['name']); # וכן ניתן להוסיף עוד שדות #.... // יצירת מערך שיהא רשומה חדשה במסמך CSV $newRecord = [$phone, $identity, $name]; $dataSource[] = $newRecord; } $output = fopen($tempFile, "w"); // פתיחת קובץ זמני לכתיבה foreach ($dataSource as $record) { fputcsv($output, $record); // כתיבת השורה המעודכנת } fclose($output); // מחיקת הקובץ הישן והחלפתו בקובץ החדש unlink($csvFile); rename($tempFile, $csvFile);
-
RE: הגדרה בקו כשהשרת מחזיר id_list_message
@עידו אוקיי הבנתי מה עשית. יכול להיות שהבעיה היא הנקודה בסוף - אתה צריך להוריד אותה כי היא לא משוייכת לשום t. תשתמש ב-substr.
-
RE: הגדרה בקו כשהשרת מחזיר id_list_message
@עידו באמצעות שלוחת API באופן הבא:
- משתמשים ב- read, ומגדירים שזה יהיה הקלטה (record) שזה בחינם, לעומת voice שעולה 0.4 יחידות.
- ההקלטה נשמרת על השרת של ימות המשיח.
- אני מוריד את ההקלטה ל-API שלי (שולח בקשה ל-API של ימות המשיח עבור מתודת קצה DownloadFile)
- לאחר שהקובץ יורד לשרת שלי, אני שולח את הקובץ לתמלול ב-API צד ג' (open-api, או google api וכו'), זה נקרא transcription.
- ה-API צד ג' מחזיר לי את התמלול לשרת שלי.
- ומכאן ממשיכים הלאה ב-flow של הקוד.
-
RE: הגדרה בקו כשהשרת מחזיר id_list_message
@עידו כשאני משתמש ב-read עם פרמטר record, אז מה שמוחזר בבקשה העוקבת זה הניתוב לקובץ שהוקלט.
ועם הניתוב הזה אתה עושה DownloadFile.שם ההקלטה הוא לא קבוע מראש, אלא כחלק מהפרמטרים שאתה מזין ב-read (עבור record), כלומר שם התיקיה ושם הקובץ שבהם אתה שומר את ההקלטה בימות המשיח, וזה שרירותי, כלומר אתה בוחר את הפרמטרים הללו.
לדוגמא: (קוד להמחשה שבניתי)
if (!$_GET["target_path_of_name"]) { readRecord("t-אנא הקליטו את שמכם בקול ברור, לסיום הקישו סולמית", "target_path_of_name", "", "/6/1", time() . "_caller_name_record"); exit; } $target_path_of_name= $_GET["target_path_of_name"]; $audio_stream = post({ url: 'https://www.call2all.co.il/ym/api/DownloadFile', token: 'username:password', path: "ivr2:$target_path_of_name" }) $destPath = __DIR__ . '/./audio/' . time() . 'bla.wav'; file_put_contents($destPath, $audio_stream); function readRecord( $prompt, $param_name, $get_new_value = '', $api_dir = '', $file_name = '', $play_menu = '', $save_on_hangup = '', $file_exists_record_append = '', $min_record_time = '', $max_record_time = '' ) { echo "read=$prompt=$param_name,$get_new_value,record,$api_dir,$file_name,$play_menu,$save_on_hangup,$file_exists_record_append,$min_record_time,$max_record_time"; }