التثبيت وأول رسالة SMS
npm install envoisms، ثم const client = new EnvoiSMSClient(process.env.ENVOISMS_API_KEY!). تعيد await client.send({ to: '+212600000000', message: '…', from: 'MonBusiness' }) معرّف الرسالة، الذي تتابعه عبر getMessage() وتجده في الويب هوك.
- import { EnvoiSMSClient } from 'envoisms';
- from: اسم المرسل المعتمد، أو احذفه لاستعمال المرسل الافتراضي
- sendBulk({ messages: [...], from }) للإرسال الجماعي؛ وlistMessages(50, 0) لآخر عمليات الإرسال
إرسال آمن عند الإعادة وأخطاء مُنمَّطة
يحمل كل استدعاء send() وsendBulk() مفتاح Idempotency-Key — مولَّدًا، أو مرّر idempotencyKey — فلا تُفوتر إعادة المحاولة بعد انتهاء المهلة الرسالة نفسها مرتين أبدًا. ويعيد العميل محاولة ردود 5xx وأخطاء الشبكة أو المهلة حتى maxRetries مرة (2 افتراضيًا) بمهلة متزايدة، ثم يرمي EnvoiSMSError مع الخاصيتين statusCode وcode.
- new EnvoiSMSClient({ apiKey, maxRetries: 3, timeoutMs: 20000 })
- err instanceof EnvoiSMSError ← err.statusCode وerr.code
SMS أم واتساب، والانتقال التلقائي
SMS افتراضيًا: تصل إلى كل الهواتف المغربية دون أي إعداد غير مفتاح API. أما channel: 'whatsapp' فترسل من رقم WhatsApp Business الخاص بك المربوط بالمنصة — 403 WHATSAPP_NOT_CONNECTED بدونه، و400 OUT_OF_24H_WINDOW للنص الحر خارج نافذة 24 ساعة، ولا خصم في الحالتين. خارج النافذة مرّر قالبًا معتمدًا. وcascade: true تعيد الرسالة إلى SMS إذا تعذر الوصول إلى الرقم أو لم يكن لديه واتساب.
- template: { name: 'order_shipped', language: 'fr', variables: ['89240'] }
- خطأ شائع: نص من نوع SMS مع channel: 'whatsapp' لأن الزبون يستخدم واتساب — أرسله كـ SMS
OTP والويب هوك والحساب
تعيد client.sendOtp({ to, brand, code_length: 6, expiry: 600 }) معرّف session_id؛ وتعيد client.checkOtp({ session_id, code }) الحقل verified؛ وتقرأ getOtpSession() الجلسة دون استهلاك محاولة. وتتحقق EnvoiSMSClient.verifyWebhookSignature(rawBody, signatureHeader, secret) من الترويسة X-EnvoiSMS-Signature على الجسم الخام لا على JSON المفكك.
- sendOtp({ ..., channel: 'whatsapp' }): رمز عبر واتساب من المرسل المشترك، دون ربط
- getBalance() وlistPacks() وlistPaymentMethods() وcreateTopup()
- analytics(30) وcreateApiKey() وcreateOptout()