وب‌هوک وضعیت پیام

به‌جای پرسش مداوم از GET /sms/messages، آدرسی از سرور خودتان ثبت کنید تا هر تغییر وضعیت پیام به آن اعلام شود. وب‌هوک را در پنل ← وب‌سرویس تعریف می‌کنید.

رویدادها

message.sentپیام به اپراتور تحویل داده شد (هزینه قطعی شد).
message.deliveredگزارش تحویل به گیرنده رسید.
message.failedارسال یا تحویل ناموفق بود؛ هزینه به اعتبار شما بازگشت.
webhook.testرویداد آزمایشی دکمه «آزمایش» در پنل.

پیام‌های آزمایشی (Sandbox) وب‌هوک نمی‌فرستند.

ساختار درخواست

یک POST با بدنه JSON و این هدرها:

  • X-Irnoti-Event — نوع رویداد
  • X-Irnoti-Delivery — شناسه یکتای این ارسال (برای جلوگیری از پردازش تکراری)
  • X-Irnoti-Signature — امضا، به شکل t=<زمان>,v1=<hex>
{
  "id": "4821",
  "event": "message.delivered",
  "createdAt": "2026-10-07T10:20:03.000Z",
  "data": {
    "messageId": "5521",
    "to": "09121234567",
    "status": "delivered",
    "parts": 1,
    "totalPrice": "980",
    "error": null,
    "sentAt": "2026-10-07T10:20:01.000Z",
    "deliveredAt": "2026-10-07T10:20:03.000Z"
  }
}

با هر پاسخ ۲xx ارسال موفق ثبت می‌شود؛ بدنه پاسخ خوانده نمی‌شود. مقادیر مبلغ رشته و به ریال هستند.

تأیید امضا

امضا HMAC-SHA256 روی رشته "<t>.<بدنه خام>" با «کلید امضا» (whsec_…) است. حتما بدنه خام (پیش از JSON parse) را امضا کنید، با مقایسه ثابت‌زمان تطبیق دهید و درخواست‌هایی با t قدیمی‌تر از ۵ دقیقه را رد کنید.

import crypto from 'node:crypto';
import express from 'express';

const app = express();
// Keep the RAW body: the signature covers the exact bytes we sent.
app.post('/irnoti-hook', express.raw({ type: 'application/json' }), (req, res) => {
  const header = req.get('x-irnoti-signature') ?? '';
  const m = /^t=(\d+),v1=([0-9a-f]{64})$/.exec(header);
  if (!m || Math.abs(Date.now() / 1000 - Number(m[1])) > 300) return res.sendStatus(400);

  const expected = crypto.createHmac('sha256', process.env.IRNOTI_WEBHOOK_SECRET)
    .update(`${m[1]}.${req.body.toString('utf8')}`).digest();
  if (!crypto.timingSafeEqual(expected, Buffer.from(m[2], 'hex'))) return res.sendStatus(400);

  const event = JSON.parse(req.body.toString('utf8'));
  // ...handle event.event / event.data (dedupe on event.id) ...
  res.sendStatus(200);
});

تلاش مجدد و محدودیت‌ها

  • در صورت پاسخ غیر ۲xx یا قطع اتصال، ارسال با فاصله‌های ۱ دقیقه، ۵ دقیقه، ۳۰ دقیقه، ۲ ساعت و ۶ ساعت تکرار می‌شود (در مجموع ۶ تلاش).
  • مهلت پاسخ ۸ ثانیه است؛ سریع پاسخ ۲۰۰ بدهید و کار سنگین را بعدا انجام دهید.
  • ترتیب رویدادها تضمین نمی‌شود و ممکن است یک رویداد دوبار برسد؛ با X-Irnoti-Delivery تکراری‌ها را نادیده بگیرید.
  • آدرس باید https و عمومی باشد؛ آدرس‌های شبکه داخلی و ریدایرکت پذیرفته نمی‌شود.
  • پس از ۲۰ ارسال ناموفق پیاپی، وب‌هوک غیرفعال می‌شود و از پنل می‌توانید دوباره فعالش کنید.
وب‌هوک وضعیت تحویل پیامک | ایران ناتیفیکیشن