إرسال رسالة واتساب من Laravel
ترسل هذه الصفحة رسالة واتساب من تطبيق Laravel بعميل HTTP الموجود في Laravel نفسه، ثم تستقبل الرد. الرسالة الأولى تذهب إلى هاتفك أنت، وبعدها مهمة في الطابور.
ما الذي تحتاجه
- حساب على Threadwire.
- رقم مربوط. في لوحة التحكم، اضغط «إضافة رقم» وامسح رمز QR بواتساب على الهاتف (الإعدادات ← الأجهزة المرتبطة). وتجد معرّف الرقم في صفحة الرقم.
- مفتاح API. أنشئه من للمطورين ← مفاتيح API ← مفتاح جديد (للمسؤولين فقط).
- تطبيق Laravel. واجهة
Httpتأتي معه، فلا تحتاج إلى تثبيت أي شيء.
ضع المفتاح ومعرّف الرقم في .env، واقرأهما عبر config/services.php:
// config/services.php
'threadwire' => [
'key' => env('THREADWIRE_KEY'),
'instance_id' => env('THREADWIRE_INSTANCE_ID'),
],
«الرقم» هنا هو رقم واتساب واحد مربوط. يربطه Threadwire كجهاز، مثل WhatsApp Web، فهذه ليست الواجهة الرسمية من Meta. صفحة WhatsApp API بدون موافقة Meta تشرح معنى ذلك.
أرسل الرسالة
أرسل الرسالة الأولى إلى نفسك. اكتب «مرحبًا» إلى رقمك المربوط من واتساب على هاتف آخر لك، ثم أرسل إلى ذلك الهاتف. أمر Artisan هذا يفعل ذلك:
// routes/console.php
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Http;
Artisan::command('whatsapp:hello', function () {
$message = Http::withToken(config('services.threadwire.key'))
->acceptJson()
->post('https://threadwire.net/api/v1/messages', [
'instance_id' => config('services.threadwire.instance_id'),
'to' => 'YOUR_PHONE',
'text' => 'Hello from Threadwire',
])
->throw()
->json('data');
$this->info($message['id'].' '.$message['status']);
});
شغّله بالأمر php artisan whatsapp:hello.
withToken(): يرسل مفتاح API الخاص بك كرمز Bearer، كما يحتاج كل طلب.instance_id: معرّف الرقم من إعداداتك.to: رقم ذلك الهاتف بالصيغة الدولية، مثل201012345678: رمز الدولة، بلا حاجة إلى+، وبلا صفر في البداية.text: نص الرسالة، حتى 4,096 حرفًا.
في مهمة في الطابور
في تطبيقك، أرسل من مهمة في الطابور، وأضف ترويسة Idempotency-Key:
// app/Jobs/SendOrderShipped.php
namespace App\Jobs;
use App\Models\Order;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Support\Facades\Http;
class SendOrderShipped implements ShouldQueue
{
use Queueable;
public function __construct(public Order $order) {}
public function handle(): void
{
Http::withToken(config('services.threadwire.key'))
->acceptJson()
->withHeaders(['Idempotency-Key' => "order-{$this->order->id}-shipped"])
->post('https://threadwire.net/api/v1/messages', [
'instance_id' => config('services.threadwire.instance_id'),
'to' => $this->order->phone,
'text' => "Hi {$this->order->name}, your order {$this->order->id} is on its way.",
])
->throw();
}
}
المفتاح أي نص فريد من عندك، مثل معرّف الطلب. وحين يشغّل الطابور المهمة مرة أخرى، يعيد المفتاح نفسه الرسالة الأولى بدلًا من إرسال ثانية.
اقرأ رد الـ API
يصل الرد فورًا، وjson('data') يقرأ الرسالة منه:
202 {"data": {"id": "01K…", "status": "queued", "phone": "201012345678", "body": "Hello from Threadwire", "…": "…"}}
id: احفظه مع طلب العميل.GET /v1/messages/{id}يعيد الرسالة بحالتها في تلك اللحظة.status: القيمةqueuedتعني أن الرسالة قُبلت وهي في الانتظار حتى يأتي دورها. ثم تُرسل كما يرسلها الإنسان.
بعدها تنتقل status إلى sent ثم delivered ثم read، أو إلى failed مع السبب في error.
رسالتك التجريبية تصل خلال ثوانٍ: أنت كتبت أولًا، فهي رد. أما تحديث طلب إلى عميل لم يراسل رقمك من قبل فهو رسالة أولى. الرسائل الأولى تُرسل متباعدة، ولها حد يومي، ولا تُرسل ليلًا. دليل كيف يحمي الإرسال رقمك فيه كل قاعدة بأرقامها.
استقبل الرد على رسالتك
من للمطورين ← الويب هوك (للمسؤولين فقط)، حدّد رابط الاستقبال لديك: عنوان عام يبدأ بـ https://. يُرسل إليه كل رد وكل تغيّر في الحالة بصيغة JSON:
{"id": "evt_01K…", "type": "message.received", "created_at": "2026-10-01T10:00:00+00:00",
"data": {"id": "01K…", "instance_id": "01K…", "phone": "201012345678", "body": "Hi!", "…": "…"}}
يصل الرد كحدث message.received، ويصل تحديث التسليم كحدث message.status. كل حدث موقّع وفق مواصفة Standard Webhooks. حزمتنا تستقبل الويب هوك لديك كأحداث Laravel، بعد التحقق من التوقيع:
composer require tritech/threadwire-laravel
دليل الأدوات وأمثلة الكود يذكر ما تفعله الحزمة غير ذلك، وفيه رابط مصدرها.
لتتحقق من التوقيع في متحكم (controller) من عندك، انسخ دالة PHP من دليل الويب هوك والأحداث. أعطها الترويسات webhook-id وwebhook-timestamp وwebhook-signature، وجسم الطلب الخام من $request->getContent()، لا JSON بعد تحليله. يبدأ سر التوقيع بـ whsec_، ويظهر عند حفظ الرابط.
ردّ بأي رمز 2xx خلال 15 ثانية، واترك العمل البطيء لمهمة في الطابور.
من المفيد أن تعرف
- فشل الرسالة ليس فشل المهمة. الرسالة التي لا يمكن إرسالها يُرد عليها بـ
202أيضًا. ثم تصبحfailedلاحقًا، والسبب فيerror. throw()يرمي استثناءً عند رفض الطلب. في الردmessageبكلمات بسيطة وcodeثابت، مثلvalidation_failed. اقرأه بـ$e->response->json('code').- أعد محاولة ما يمكن أن ينجح فقط. أعد المهمة إلى الطابور عند
429و502و503، بعدRetry-Afterإن وُجد. أما401و403و404و422فتحتاج إصلاحًا أولًا: راجع ما الذي يعيد نظامك محاولته. - لا تنشئ مهمة لكل شخص في قائمة. يرسل الرقم رسالة واحدة في كل مرة، فالدفعة الكبيرة لا تصنع إلا طابور انتظار: راجع الإيقاع.
التالي
- إرسال الرسائل: الملفات والرسائل الصوتية والاستطلاعات وغيرها.
- الويب هوك والأحداث: كل الأحداث، وإعادة المحاولة، والجلب.
- مرجع الـ API: كل نقاط الاتصال، والأخطاء.
- الأدوات وأمثلة الكود: حزمة Laravel ومجموعة Postman.