راهنمای عملی · پاسخ مستند

وب‌هوک‌های Resend چگونه کار می‌کنند؟

وب‌هوک‌های Resend این‌گونه کار می‌کنند: وقتی رویدادی مربوط به ایمیل، مخاطب، دامنه یا توقف ارسال رخ می‌دهد، یک درخواست HTTPS POST با payload رویداد به‌صورت JSON به endpoint ثبت‌شده شما فرستاده می‌شود. endpoint شما باید امضا را روی بدنه خام درخواست تأیید کند، رویداد را به‌صورت idempotent پردازش کند و به‌سرعت پاسخ موفق برگرداند.

گردش‌کار وب‌هوک Resend

گردش‌کار با ساختن یک endpoint عمومی HTTPS و ثبت آن در Resend همراه با انواع رویدادهایی که برنامه شما نیاز دارد آغاز می‌شود. وقتی رویداد منطبقی رخ دهد، Resend یک درخواست POST حاوی payload از نوع JSON می‌فرستد. payload شامل یک type مانند email.sent، email.delivered، email.bounced یا email.complained، زمان ایجاد و داده‌های مختص رویداد است. پردازش را بر اساس فیلد type مسیریابی کنید و فرض نکنید همه payloadها ساختار یکسانی دارند.

پیش از پردازش، درخواست را تأیید کنید

درخواست را به‌صورت متن خام بخوانید و آن را با secret امضای وب‌هوک به همراه هدرهای svix-id، svix-timestamp و svix-signature تأیید کنید. این کار را پیش از parse کردن payload یا انجام هر اقدامی بر اساس آن انجام دهید. parse کردن JSON و سپس سریال‌سازی دوباره آن می‌تواند بایت‌ها را تغییر دهد و باعث شکست امضای یک درخواست مشروع شود. درخواست‌هایی را که تأیید نمی‌شوند رد کنید و secret امضا را به‌جای کد منبع، در یک secret manager یا متغیر محیطی محافظت‌شده نگه دارید.

مدیریت رویدادها را idempotent کنید

Resend در مستندات خود ارسال at-least-once را اعلام کرده است، پس ممکن است یک رویداد بیش از یک بار به endpoint شما برسد. svix-id را با یک قید یکتایی ذخیره کنید و اگر آن شناسه قبلاً پردازش شده، منطق کسب‌وکار را اجرا نکنید. به ترتیب رسیدن رویدادها هم تکیه نکنید، چون تلاش‌های مجدد و تأخیرهای شبکه می‌توانند ترتیب رویدادها را به هم بزنند. وقتی ترتیب اهمیت دارد از مقدار created_at رویداد استفاده کنید و تغییرات وضعیت را طوری مدل کنید که رویداد قدیمی‌تر نتواند به‌طور تصادفی وضعیت جدیدتر را بازنویسی کند.

سریع تأیید دریافت کنید و با اطمینان پردازش کنید

پس از تأیید رویداد و ثبت ماندگار آن، HTTP 200 برگردانید و سپس کارهای کندتر را از طریق یک صف یا worker پس‌زمینه انجام دهید. timeout یا پاسخ ناموفق باعث تلاش دوباره برای ارسال می‌شود، بنابراین handlerهای همگام طولانی باعث تکرارهای غیرضروری می‌شوند. دریافت رویداد را از اثرات جانبی مانند به‌روزرسانی رکورد توقف ارسال، اطلاع‌رسانی به پشتیبانی یا ثبت برگشت ایمیل جدا کنید. هر اثر جانبی هم باید قابل‌تکرار ایمن باشد یا با شناسه ذخیره‌شده رویداد محافظت شود.

تلاش مجدد، replay و بازیابی پس از خطا را آزمایش کنید

پیش از محیط عملیاتی، endpoint را با انواع نماینده رویدادها آزمایش کنید، از جمله امضاهای نامعتبر، شناسه‌های تکراری، timestampهای خارج از ترتیب و خرابی‌های موقت پایگاه‌داده. Resend ارسال‌های ناموفق را طبق یک زمان‌بندی backoff دوباره تلاش می‌کند و به شما امکان می‌دهد پیام‌های وب‌هوک ناموفق و موفق را replay کنید. از replay برای بازیابی پس از قطعی یا اعتبارسنجی کد به‌روزشده handler استفاده کنید، اما حذف موارد تکراری را فعال نگه دارید تا بازیابی، اثرات جانبی قابل‌مشاهده برای مشتری را تکرار نکند.

پرسش‌هایی که تیم‌ها می‌پرسند

endpoint وب‌هوک Resend باید چه پاسخی برگرداند؟

پس از تأیید درخواست و پذیرش ماندگار رویداد، HTTP 200 برگردانید. کارهای کند باید به‌صورت ناهمگام ادامه یابند تا ارائه‌دهنده به دلیل timeout دوباره تلاش نکند.

چرا باید بدنه خام درخواست حفظ شود؟

امضا روی بایت‌های اصلی درخواست محاسبه شده است. parse و سریال‌سازی دوباره JSON می‌تواند این بایت‌ها را تغییر دهد و باعث شکست تأیید شود، حتی وقتی درخواست مشروع است.

آیا یک رویداد وب‌هوک Resend ممکن است بیش از یک بار ارسال شود؟

بله. Resend ارسال at-least-once را اعلام کرده است، پس handlerها باید رویدادهای تکراری را حذف کنند؛ معمولاً با ذخیره svix-id یکتا پیش از اعمال اثرات جانبی کسب‌وکار.

آیا رویدادهای وب‌هوک Resend به ترتیب ارسال می‌شوند؟

خیر. تأخیرهای شبکه و تلاش‌های مجدد می‌توانند ترتیب رسیدن را تغییر دهند. وقتی برنامه شما باید توالی قابل‌اعتمادی را بازسازی کند، از timestamp رویدادها و قواعد گذار وضعیت استفاده کنید.

ارسال‌های ناموفق وب‌هوک Resend را چگونه باید بازیابی کرد؟

Resend ارسال‌های ناموفق را به‌طور خودکار دوباره تلاش می‌کند و از replay دستی هم پشتیبانی می‌کند. ابتدا endpoint را اصلاح کنید، سپس رویدادهای لازم را replay کنید و بررسی‌های idempotency را فعال نگه دارید.

منابع اصلی