چرخه درخواست و پاسخ میان برنامه و API پیام‌رسان و مسیر جداگانه تحویل پیامک به گوشی
پیام رسان بلاگ برنامه نویسی Request و Response چیست؟ ساختار درخواست و پاسخ در وب سرویس

Request و Response چیست؟ ساختار درخواست و پاسخ در وب سرویس

نوشته ای از احمدرضا احمدپور
انتشار در تاریخ 16 آبان 1405
دسته بندی: برنامه نویسی

Request و Response دو پیام اصلی در ارتباط HTTP هستند: کلاینت درخواست را می‌فرستد و سرور با یک پاسخ، نتیجه رسیدگی به آن را اعلام می‌کند. در وب سرویس پیام رسان، درخواست می‌تواند شامل کلید حساب، متن پیامک و شماره گیرنده باشد و پاسخ، نتیجه ثبت درخواست یا اطلاعات گزارش تحویل را برگرداند.

پرسشپاسخ کوتاه
Request چیست؟پیام درخواست برای دریافت اطلاعات یا اجرای یک عملیات
Response چیست؟پیام پاسخ شامل کد وضعیت HTTP، هدرها و در صورت نیاز بادی
کلید پیام‌رسان کجا ارسال می‌شود؟در متدهای POST داخل فیلد ApiKey در بادی JSON؛ در متدهای GET مستندشده داخل Query
آیا HTTP 200 یعنی عملیات موفق بوده؟در پیام‌رسان خیر؛ موفقیت عملیات از فیلد Success در بادی پاسخ مشخص می‌شود
ثبت موفق درخواست یعنی پیامک تحویل شده؟خیر؛ برای تحویل باید گزارش وضعیت پیامک را جداگانه بررسی کنید
پس از Timeout چه کنیم؟اگر هنگام ارسال UserTraceId تعیین کرده‌اید، با StatusByUserTraceId بررسی کنید پیامک ثبت شده است یا نه

وقتی صفحه‌ای را باز می‌کنید، فرم عضویت را می‌فرستید یا بک‌اند فروشگاه شما درخواست ارسال پیامک ثبت سفارش را ثبت می‌کند، این چرخه به کار می‌افتد. البته هر کلیک لزوماً درخواست شبکه ایجاد نمی‌کند؛ بعضی کارها کاملاً داخل مرورگر انجام می‌شوند.

در این راهنما، ساختار درخواست و پاسخ را با متدهای واقعی نسخه V3 پیام‌رسان بررسی می‌کنیم: AccountInfo برای دریافت اطلاعات حساب، SendBulk برای ارسال متن و StatusByUserTraceId برای پیگیری وضعیت پیامک.

تعریف Request و Response به زبان ساده

Request یا ریکوئست، پیامی است که کلاینت برای دریافت یک منبع یا انجام یک عملیات ارسال می‌کند. Response یا ریسپانس، پیامی است که سرور در پاسخ به آن برمی‌گرداند.

کلاینت می‌تواند مرورگر، اپلیکیشن موبایل یا برنامه‌ای روی سرور شما باشد. مثلاً هنگام اتصال فروشگاه به پیام‌رسان، بک‌اند فروشگاه کلاینت وب‌سرویس پیامکی است: درخواست ارسال را می‌سازد، به سرویس می‌فرستد و پاسخ را بررسی می‌کند.

پیام HTTP را نباید با یک بسته شبکه یکسان گرفت. یک درخواست یا پاسخ ممکن است هنگام انتقال به چندین بخش تقسیم شود؛ آنچه در این مقاله بررسی می‌کنیم، ساختار و معنای پیام در لایه HTTP است.

HTTP چیست و چه ارتباطی با درخواست و پاسخ دارد؟

HTTP مخفف Hypertext Transfer Protocol و قرارداد ارتباطی میان کلاینت و سرور است. این قرارداد مشخص می‌کند درخواست‌ها چه معنایی دارند، پاسخ‌ها چگونه تفسیر می‌شوند و کدهایی مانند 200 یا 404 چه چیزی را اعلام می‌کنند. HTTP فقط برای متن نیست؛ HTML، JSON، تصویر و فایل هم می‌توانند با آن منتقل شوند.

URL نشانی مقصد است، HTTP قرارداد ارتباط و API رابط استفاده برنامه‌ها از امکانات سرویس است. برای مثال، در پیام‌رسان آدرس متد SendBulk مقصد درخواست را مشخص می‌کند و مستندات API می‌گویند چه متدی، چه پارامترهایی و چه ساختار پاسخی دارد.

Stateless بودن HTTP یعنی چه؟

Stateless یعنی HTTP به‌خودی‌خود وضعیت احراز هویت کاربر را از یک درخواست به درخواست بعدی منتقل نمی‌کند. برنامه‌ها می‌توانند با سازوکارهایی مانند Cookie، Session یا کلید دسترسی، ارتباط میان درخواست‌ها را برقرار کنند. بنابراین Stateless به معنی ناتوانی سرور در ذخیره اطلاعات نیست.

در پیام‌رسان، درخواست‌های وب‌سرویس به ApiKey نیاز دارند. موفق‌بودن یک درخواست قبلی جای ارسال کلید در درخواست بعدی را نمی‌گیرد. مثلاً برای فراخوانی AccountInfo و سپس SendBulk، کلید باید در بادی هر دو درخواست قرار داشته باشد.

Stateless بودن ارتباطی با قطع اتصال پس از ارسال درخواست ندارد. یک اتصال می‌تواند برای چند درخواست و پاسخ استفاده شود.

تفاوت HTTP و HTTPS در این چرخه چیست؟

HTTPS ارتباط HTTP را با TLS محافظت می‌کند تا داده‌ها در مسیر انتقال رمزگذاری شوند و هویت سرور بررسی شود. بااین‌حال، استفاده از HTTPS جای کنترل دسترسی، حفاظت از کلید حساب و اعتبارسنجی ورودی‌ها را نمی‌گیرد.

آدرس متدهای V3 پیام‌رسان با https://api.sms-webservice.com/api/V3/ شروع می‌شود. کلید حساب را در متغیر محیطی سرور یا سامانه نگهداری اطلاعات محرمانه قرار دهید؛ آن را داخل مخزن کد، جاوااسکریپت عمومی مرورگر یا بسته اپلیکیشن موبایل نگذارید.

الگوی مناسب این است که مرورگر یا اپلیکیشن با بک‌اند شما ارتباط بگیرد و بک‌اند درخواست حاوی ApiKey را به پیام‌رسان بفرستد. جزئیات در راهنمای کلید حساب پیام رسان آمده است.

چه چیزی داخل یک Request گنجانده می‌شود؟

برای ساخت درخواست باید متد، آدرس، هدرهای لازم و بادی را مطابق مستندات همان عملیات انتخاب کنید. نام فیلدها و روش احراز هویت را نباید از روی API سرویس‌های دیگر حدس زد.

متد؛ از سرور چه کاری می‌خواهید؟

GET معمولاً برای دریافت اطلاعات و POST برای ارسال داده جهت پردازش استفاده می‌شود؛ اما متد قابل استفاده برای هر مسیر را قرارداد API تعیین می‌کند. برای مثال، دریافت اطلاعات حساب و استعلام وضعیت در پیام‌رسان هم با POST انجام می‌شوند.

متد HTTPکاربرد عمومیارتباط با مثال‌های پیام‌رسان
GETمعمولاً دریافت اطلاعات؛ رفتار هر مسیر تابع قرارداد API استمتد Send پیام‌رسان با GET پیامک ارسال می‌کند و پارامترها را از Query می‌گیرد
POSTارسال داده برای پردازشAccountInfo، SendBulk و StatusByUserTraceId با POST فراخوانی می‌شوند
PUTایجاد یا جایگزینی وضعیت منبع در نشانی مشخصبرای سه متد مورد استفاده در این مقاله مستند نشده است
PATCHاعمال تغییرات جزئیبرای سه متد مورد استفاده در این مقاله مستند نشده است
DELETEحذف منبعبرای سه متد مورد استفاده در این مقاله مستند نشده است
HEADدریافت هدرهای متناظر با GET بدون محتوای پاسخروش فراخوانی متدهای این مقاله نیست
OPTIONSبررسی گزینه‌های ارتباطی؛ از جمله در پیش‌پرواز CORSطبق مستندات پیام‌رسان، وب‌سرویس به OPTIONS پاسخ 405 می‌دهد

برای ارسال عملیاتی متن، SendBulk را انتخاب کنید. این متد برخلاف Send، کلید را در URL قرار نمی‌دهد و امکان ارسال UserTraceId برای هر گیرنده را دارد. توضیح بیشتر در راهنمای ارسال متن پیام رسان و مقاله متدهای HTTP آمده است.

URL؛ درخواست به کجا می‌رود؟

آدرس واقعی ارسال متن یکسان به یک یا چند گیرنده در نسخه V3 پیام‌رسان:

متن
https://api.sms-webservice.com/api/V3/SendBulk

در این آدرس، https طرح ارتباط، api.sms-webservice.com میزبان و /api/V3/SendBulk مسیر متد است. در این فراخوانی، اطلاعاتی مانند کلید، متن و گیرندگان در بادی JSON قرار می‌گیرند؛ بنابراین لازم نیست به URL اضافه شوند.

پارامتر Query بخشی از URL بعد از علامت سؤال است؛ Body بخش جداگانه محتوای پیام است. در متد Send پیام‌رسان، اطلاعات از Query دریافت می‌شود، اما در SendBulk باید از بادی استفاده کنید. جابه‌جاکردن خودسرانه این دو روش، درخواست را به فراخوانی معتبر تبدیل نمی‌کند.

قرارگرفتن کلید در URL می‌تواند باعث ثبت آن در لاگ‌های دسترسی و ابزارهای ثبت نشانی شود. به همین دلیل، برای اتصال عملیاتی از متد POST مستندشده استفاده کنید.

هدرها دقیقاً چه‌کار می‌کنند؟

هدرها اطلاعاتی درباره پیام و نحوه پردازش آن منتقل می‌کنند. برای مثال، هنگام ارسال JSON باید قالب بادی را با Content-Type مشخص کنید.

هدرمعنای کاربردیوضعیت در مثال پیام‌رسان
Content-Typeنوع محتوای همین پیامبرای بادی JSON از application/json استفاده می‌کنیم
Acceptقالب‌های قابل قبول برای پاسخ از نگاه کلاینتمی‌توان application/json فرستاد؛ جایگزین Content-Type یا کلید حساب نیست
Authorizationهدر رایج احراز هویت در بعضی APIهامحل ارسال کلید در قرارداد V3 پیام‌رسان نیست؛ ApiKey در خود درخواست قرار می‌گیرد

در پیام‌رسان نباید کلید را به شکل Bearer Token در Authorization قرار دهید. در متدهای POST این مقاله، کلید در فیلد ApiKey بادی JSON فرستاده می‌شود. افزودن هدر Authorization جای این فیلد را نمی‌گیرد.

Content-Type و Accept هم یکی نیستند: اولی قالب محتوایی را که فرستاده‌اید مشخص می‌کند و دومی قالب‌های قابل قبول پاسخ را اعلام می‌کند.

ساختار درخواست POST متد SendBulk پیام‌رسان شامل هدر JSON و فیلدهای ApiKey، Text، Sender و Recipients

Body یا Payload چیست؟

Body محل محتوای درخواست است. در SendBulk پیام‌رسان، بادی شامل ApiKey، Text، Sender و آرایه Recipients است. داخل هر عضو Recipients نیز شماره گیرنده و در صورت تعیین، شناسه پیگیری شما قرار می‌گیرد.

JSON
{
  "ApiKey": "123456-XXXXXXXXXXXXXXX",
  "Text": "سفارش شما با شماره ۱۲۵ ثبت شد.",
  "Sender": 30004040,
  "Recipients": [
    {
      "Destination": 9121112222,
      "UserTraceId": 45001
    }
  ]
}

ساختار بالا مطابق متد واقعی SendBulk پیام رسان است. کلید نمونه را با کلید حساب، Sender را با یکی از خطوط فعال حساب و Destination را با شماره گیرنده مورد نظر جایگزین کنید. مقدار UserTraceId را هم برای هر ارسال به هر گیرنده، یکتا تعیین و پیش از درخواست در سیستم خود ذخیره کنید.

شماره گیرنده در این متد عددی و بدون صفر ابتدایی است؛ مانند 9121112222 یا 989121112222. سقف هر درخواست SendBulk نیز طبق مستندات، ۹۹ گیرنده است. فهرست‌های بزرگ‌تر را به درخواست‌های جداگانه تقسیم کنید.

همه درخواست‌های HTTP بادی ندارند. برای GET معمولاً پارامترها در URL قرار می‌گیرند و بادی آن معنای عمومی تعریف‌شده‌ای ندارد. بااین‌حال، مثال‌های POST پیام‌رسان در این مقاله به بادی JSON نیاز دارند.

Request Line چیست؟

در قالب متنی HTTP/1.1، خط آغازین درخواست شامل متد، هدف درخواست و نسخه پروتکل است. برای فراخوانی AccountInfo، ابتدای درخواست چنین شکلی دارد:

متن
POST /api/V3/AccountInfo HTTP/1.1
Host: api.sms-webservice.com
Content-Type: application/json

خط اول مشخص می‌کند درخواست POST برای مسیر AccountInfo است. نام میزبان در Host قرار دارد؛ بنابراین در این شکل رایج، Request Line شامل URL کامل نیست. هدرهای فنی دیگری مانند طول محتوا را ابزار HTTP مدیریت می‌کند.

سرور چطور Response ارسال می‌کند؟

سرور یا واسطه‌ای مانند درگاه API، درخواست را بررسی می‌کند و پاسخ برمی‌گرداند. پاسخ HTTP شامل کد وضعیت، هدرها و در صورت مجازبودن، بادی است. بادی می‌تواند JSON، HTML، فایل یا قالب دیگری داشته باشد.

در متدهای V3 پیام‌رسان، نتیجه عملیات در یک ساختار JSON مشترک برمی‌گردد. برای آشنایی با این قالب، مقاله JSON چیست را بخوانید.

در HTTP/1.1، خط وضعیت یا Status Line می‌تواند به این شکل باشد:

HTTP/1.1 200 OK

200 کد وضعیت HTTP و OK عبارت توضیحی آن است. بعد از خط آغازین، هدرها قرار می‌گیرند و یک خط خالی، هدرها را از بادی احتمالی جدا می‌کند. همه پاسخ‌ها بادی ندارند؛ مثلاً پاسخ 204 و پاسخ به HEAD محتوای بادی ندارند.

نکته نسخه پروتکل: نمایش خط درخواست و خط وضعیت در این مقاله برای آموزش با قالب HTTP/1.1 است. HTTP/2 و HTTP/3 همین مفاهیم را با قالب انتقال متفاوت حمل می‌کنند؛ نمایش ابزارهای توسعه‌دهنده لزوماً متن خام داده‌های روی شبکه نیست.

نمونه کامل Request و Response با توضیح اجزا

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

آدرس واقعی درخواست:

متن
https://api.sms-webservice.com/api/V3/AccountInfo

متد POST، هدر Content-Type برابر application/json و بادی درخواست:

JSON
{
  "ApiKey": "123456-XXXXXXXXXXXXXXX"
}

نمونه پاسخ موفقی که در راهنمای شروع سریع پیام‌رسان آمده است:

JSON
{
  "Success": true,
  "ErrorCode": null,
  "Error": null,
  "Result": {
    "Credit": 154.5,
    "AvailableSenders": [30004040]
  }
}

این اعداد، مقادیر نمونه مستندات هستند و موجودی یا خطوط حساب شما را نشان نمی‌دهند. در پاسخ حساب خودتان، Credit مقدار اعتبار و AvailableSenders فهرست خطوط قابل استفاده به‌عنوان Sender را مشخص می‌کند.

چهار فیلد اصلی پاسخ پیام‌رسان را این‌طور بخوانید:

  • Success: موفق یا ناموفق بودن عملیات در سطح API.
  • Result: داده خروجی؛ شکل آن به متد بستگی دارد.
  • ErrorCode: کد عددی خطا، زمانی که Success برابر false است.
  • Error: توضیح خطا برای نمایش و عیب‌یابی؛ شرط برنامه را روی ErrorCode بگذارید.

در پاسخ موفق، ErrorCode برابر null است، نه صفر. بنابراین موفقیت را با شرط ErrorCode == 0 تشخیص ندهید؛ ابتدا Success را بررسی کنید. جزئیات در راهنمای خواندن پاسخ و خطای پیام رسان آمده است.

در متد SendBulk، Result به‌جای شیء اطلاعات حساب، آرایه‌ای از شناسه‌هاست. نمونه پاسخ مستندشده:

JSON
{
  "Success": true,
  "ErrorCode": null,
  "Error": null,
  "Result": [
    {
      "Id": 9903211,
      "UserTraceId": 45001
    }
  ]
}

Id شناسه پیام در سامانه و UserTraceId شناسه‌ای است که خودتان هنگام ارسال تعیین کرده‌اید. برای هر گیرنده یک عضو، به همان ترتیب درخواست، برمی‌گردد. این پاسخ پذیرش پیام را نشان می‌دهد و هنوز اثبات تحویل به گوشی نیست.

کدهای وضعیت چه چیزی را مشخص می‌کنند؟

در HTTP، کدها به چند خانواده تقسیم می‌شوند. جدول زیر قواعد عمومی را نشان می‌دهد؛ قرارداد پاسخ پیام‌رسان را باید جداگانه در نظر بگیرید.

گروهمفهوم کلینمونه
1xxپاسخ اطلاعاتی100 برای ادامه ارسال محتوا
2xxموفقیت طبق معنای کد200 موفق، 201 ایجاد منبع، 202 پذیرش برای پردازش، 204 موفق بدون محتوا
3xxتغییر مسیر یا استفاده از پاسخ دیگر301 و 302 تغییر مسیر؛ 304 استفاده از نسخه ذخیره‌شده پس از اعتبارسنجی
4xxمشکل مرتبط با درخواست400 درخواست نامعتبر، 401 مشکل احراز هویت، 403 منع دسترسی، 404 منبع یافت نشد
5xxخطای سرور یا واسطه500 خطای داخلی، 502 مشکل پاسخ بالادست، 503 عدم دسترسی سرویس، 504 پایان انتظار درگاه

در پاسخ‌های استاندارد متدهای پیام‌رسان، حتی خطای کلید یا اعتبار هم با HTTP 200 و Success برابر false برمی‌گردد. بنابراین HTTP 200، response.ok یا موفق‌بودن اتصال را به معنی موفق‌بودن عملیات پیامکی نگیرید.

این قاعده به معنی ناممکن‌بودن خطای HTTP در کل مسیر نیست. آدرس اشتباه، درخواست OPTIONS یا پاسخ یک واسطه می‌تواند خارج از پاکت استاندارد API باشد. در Sandbox هم مسیر اشتباه ممکن است 404 بدهد و اصلاً فیلد Success نداشته باشد.

سه مقدار را با هم اشتباه نگیرید: کد HTTP وضعیت ارتباط HTTP را نشان می‌دهد؛ ErrorCode خطای عملیات API را توضیح می‌دهد؛ StatusCode در گزارش تحویل، وضعیت یک پیامک را مشخص می‌کند. مثلاً ErrorCode برابر 20 یعنی تعداد درخواست بیش از حد مجاز، اما StatusCode برابر 20 یعنی اتمام سقف خط اشتراکی.

برای توضیح عمومی کدهای HTTP، مقاله Status Code چیست و برای خطاهای اختصاصی سرویس، جدول کدهای خطای پیام رسان را ببینید.

مقایسه سریع Request و Response

ویژگیRequestResponse
فرستندهکلاینت، مثلاً بک‌اند فروشگاهسرویس پیام‌رسان یا واسطه پاسخ‌دهنده
هدفدرخواست اجرای متدی مانند SendBulkاعلام نتیجه رسیدگی به درخواست
خط آغازین در HTTP/1.1متد، مسیر و نسخه HTTPنسخه HTTP، کد وضعیت و عبارت توضیحی
هدر مرتبط با JSONContent-Type برای معرفی قالب بادیContent-Type برای معرفی قالب پاسخ
بادی در SendBulkApiKey، Text، Sender و RecipientsSuccess، Result، ErrorCode و Error
شناسه پیگیریUserTraceId را شما تعیین می‌کنیدId سامانه و UserTraceId شما برمی‌گردد

برای عیب‌یابی باید هر دو طرف را بررسی کنید: در درخواست، آدرس و ورودی‌ها را ببینید و در پاسخ، علاوه بر HTTP، مقدار Success و داده‌های Result یا ErrorCode را بخوانید.

چرخه کامل یک درخواست از کلیک کاربر تا پاسخ سرور

هنگام بازشدن یک صفحه وب چه اتفاقی می‌افتد؟

اگر پاسخ قابل استفاده در کش نباشد و اتصال آماده‌ای وجود نداشته باشد، مرورگر معمولاً میزبان را با کمک DNS پیدا می‌کند، اتصال مناسب را برقرار می‌کند و در HTTPS مراحل امنیتی لازم را انجام می‌دهد. سپس درخواست HTTP فرستاده می‌شود.

با دریافت HTML، ممکن است برای CSS، JavaScript، تصاویر و فونت‌ها هم درخواست‌های دیگری ارسال شود. پس بازشدن یک صفحه معمولاً حاصل چندین درخواست و پاسخ است. کش، اتصال موجود و Service Worker می‌توانند مسیر واقعی را تغییر دهند.

چرخه ارسال پیامک چگونه است؟

  1. ثبت رویداد و شناسه: سفارش ثبت می‌شود و بک‌اند برای ارسال پیامک به هر گیرنده، یک UserTraceId یکتا ایجاد و ذخیره می‌کند.
  2. ساخت درخواست: برنامه با POST، بادی شامل ApiKey، Text، Sender و Recipients را به SendBulk می‌فرستد.
  3. بررسی پاسخ اولیه: برنامه ابتدا پاسخ HTTP و JSON را دریافت می‌کند و سپس Success را بررسی می‌کند. در شکست، ErrorCode مسیر رفع مشکل را مشخص می‌کند.
  4. ثبت نتیجه ارسال: در موفقیت، Id و UserTraceId خروجی ذخیره یا با رکورد داخلی تطبیق داده می‌شوند. وضعیت داخلی مناسب، «درخواست ثبت شد» است.
  5. پیگیری تحویل: برنامه با StatusByUserTraceId یا StatusById، گزارش وضعیت را جداگانه دریافت و StatusCode را بررسی می‌کند.

آیا پاسخ موفق یعنی پیامک تحویل شده است؟

خیر؛ Success برابر true در SendBulk به معنی تحویل پیامک به گوشی نیست. پاسخ ارسال فقط پذیرش پیام را اعلام می‌کند. برای نتیجه تحویل، باید از متد استعلام وضعیت استفاده کنید.

دسته‌بندی وضعیت پیامک در پیام‌رسان و اقدام مناسب برای انتظار، تحویل موفق، نتیجه نهایی و ارسال‌نشدن

در StatusById، شناسه Id برگشتی از ارسال را می‌فرستید. در StatusByUserTraceId، شناسه‌ای را می‌فرستید که از قبل خودتان تعیین کرده‌اید؛ به همین دلیل، روش دوم پس از گم‌شدن پاسخ ارسال هم کاربرد دارد.

آدرس واقعی استعلام با شناسه شما:

متن
https://api.sms-webservice.com/api/V3/StatusByUserTraceId

این متد با POST و بادی زیر فراخوانی می‌شود:

JSON
{
  "ApiKey": "123456-XXXXXXXXXXXXXXX",
  "UserTraceIds": [45001]
}

نمونه ساختار گزارش تحویل، مطابق مستندات پیام‌رسان:

JSON
{
  "Success": true,
  "ErrorCode": null,
  "Error": null,
  "Result": [
    {
      "Id": 9903211,
      "UserTraceId": 45001,
      "StatusCode": 4,
      "Status": "تحویل به گوشی"
    }
  ]
}

در این پاسخ، Success موفق‌بودن استعلام را نشان می‌دهد و StatusCode برابر 4، تحویل همان پیامک به گوشی را اعلام می‌کند. برای تصمیم برنامه روی StatusCode شرط بگذارید؛ متن Status برای نمایش مناسب است.

StatusCodeبرداشتاقدام
0، 1، 2، 3 و 10وضعیت هنوز در جریان یا نامشخص استبا فاصله مناسب دوباره استعلام کنید؛ دوباره ارسال نکنید
4تحویل به گوشیپیگیری این پیامک را متوقف کنید
5، 6، 7، 9 و 11 تا 16وضعیت نهایی با نتیجه‌ای غیر از تحویل موفقحلقه استعلام را متوقف و اقدام بعدی را از روی معنای دقیق کد تعیین کنید
8شناسه در این حساب پیدا نشده استدرستی شناسه و حساب را بررسی کنید؛ در سناریوی Timeout برای تشخیص ثبت‌نشدن استفاده می‌شود
17 تا 21ارسال به علت محدودیت یا مشکل حساب انجام نشده استمانع را بر اساس کد برطرف کنید و سپس درباره ارسال دوباره تصمیم بگیرید

«نهایی» به معنی «موفق» نیست. مثلاً وضعیت گیرنده مسدود با وضعیت تحویل موفق هر دو نهایی‌اند، اما اقدام یکسانی ندارند. همچنین بعضی خطوط رسید تحویل ندارند و پیام ممکن است روی کد 1 بماند؛ برای استعلام، مهلت و تعداد تلاش محدود تعیین کنید.

طبق راهنمای گزارش تحویل پیام رسان، استعلام‌ها را با فاصله چند دقیقه انجام دهید و شناسه‌ها را دسته‌ای بفرستید. جزئیات همه مقادیر در جدول وضعیت پیامک آمده است.

درخواست‌ها و پاسخ‌ها چه اثری بر سرعت سایت دارند؟

برای ارزیابی سرعت فقط تعداد درخواست‌ها را نشمارید. حجم منابع، زمان انتظار پاسخ، ترتیب بارگذاری و استفاده از کش هم مهم‌اند. چند درخواست کوچک مستقل الزاماً از یک فایل بزرگ مسدودکننده کندتر نیستند.

برای منابع عمومی سایت، کش مناسب و اعتبارسنجی با ETag می‌تواند انتقال دوباره داده را کم کند. پاسخ‌های حاوی اطلاعات حساب، متن پیامک یا کلید دسترسی را بدون سیاست مشخص در کش عمومی قرار ندهید.

در اتصال پیامکی هم لازم نیست پیش از هر ارسال، AccountInfo را فراخوانی کنید. خطوط فعال حساب را در پیکربندی خود نگه دارید و با روال مناسب به‌روز کنید. برای گزارش تحویل نیز به‌جای یک درخواست برای هر پیامک، از آرایه شناسه‌ها استفاده کنید.

Timeout چیست و چرا با خطا فرق دارد؟

Timeout یعنی محدودیت انتظار در بخشی از ارتباط تمام شده است؛ مثلاً اتصال یا دریافت داده بیش از مهلت مجاز طول کشیده. این اتفاق به‌تنهایی ثابت نمی‌کند درخواست ارسال پیامک در سرور ثبت نشده است.

ممکن است SendBulk پیامک را ثبت کرده باشد، اما پیش از رسیدن پاسخ، ارتباط شما قطع شود. در این حالت، برنامه پاسخ موفق را ندیده، ولی تکرار درخواست می‌تواند پیامک دیگری ایجاد کند.

این وضعیت را از پاسخ خطای API جدا کنید. در خطای استاندارد پیام‌رسان، JSON دریافت می‌کنید و Success برابر false است؛ ErrorCode دلیل را مشخص می‌کند. در مشکل شبکه ممکن است اصلاً پاسخ کامل یا JSON معتبر دریافت نکنید. خطای DNS، شکست TLS و قطع اتصال هم همگی Timeout نیستند.

برای بررسی عمومی این مشکلات، مقاله خطای وب سرویس را بخوانید.

تفاوت Timeout کلاینت با 408 و 504 چیست؟

Timeout کلاینت یعنی کتابخانه یا ابزار شما انتظار را متوقف کرده است. اما 408 پاسخ HTTP درباره کامل‌نشدن درخواست در مهلت انتظار سرور است و 504 یعنی درگاه در زمان مناسب از بالادست پاسخ نگرفته است.

این‌ها مفاهیم عمومی HTTP هستند و نباید با ErrorCode پیام‌رسان اشتباه گرفته شوند. برای مثال، ErrorCode برابر 100 در پاسخ JSON پیام‌رسان، خطای داخلی سرویس است؛ HTTP 100 معنای دیگری دارد. در خطای 100 یا Timeout ارسال، پیش از تلاش دوباره وضعیت ثبت پیام را بررسی کنید.

Timeout را چگونه تنظیم کنیم؟

رفتار پیش‌فرض کتابخانه‌ها یکسان نیست. مستندات ابزار خود را بخوانید و مشخص کنید تنظیم شما مربوط به اتصال، انتظار دریافت داده یا کل زمان عملیات است.

برای تمرین با Requests پایتون می‌توانید AccountInfo واقعی پیام‌رسان را فراخوانی کنید. در این مثال، کلید از متغیر محیطی خوانده می‌شود و هیچ پیامکی ارسال نمی‌شود:

Python
import os
import requests

url = "https://api.sms-webservice.com/api/V3/AccountInfo"
payload = {
    "ApiKey": os.environ["PAYAM_RESAN_API_KEY"]
}

try:
    response = requests.post(
        url,
        json=payload,
        timeout=(3, 10),
    )
    response.raise_for_status()
    body = response.json()

except requests.exceptions.Timeout:
    print("مهلت انتظار ارتباط تمام شد.")

except requests.exceptions.RequestException:
    print("خطای ارتباط، HTTP یا دریافت پاسخ رخ داد.")

else:
    if body.get("Success") is True:
        result = body["Result"]
        print("اعتبار:", result["Credit"])
        print("خطوط فعال:", result["AvailableSenders"])
    elif body.get("Success") is False:
        print("کد خطای سرویس:", body.get("ErrorCode"))
        print("شرح خطا:", body.get("Error"))
    else:
        print("ساختار پاسخ با قرارداد مستندشده سازگار نیست.")

در Requests، مقدارهای 3 و 10 برای مهلت اتصال و انتظار خواندن داده‌اند؛ مجموع آن‌ها سقف قطعی کل زمان عملیات نیست. این عددها تنظیم پیشنهادی قطعی پیام‌رسان نیستند و باید با شرایط برنامه تنظیم شوند.

دستور raise_for_status فقط خطای HTTP را بررسی می‌کند؛ چون خطاهای استاندارد عملیات پیام‌رسان هم می‌توانند HTTP 200 داشته باشند، بررسی جداگانه Success ضروری است.

تصمیم‌گیری پس از Timeout ارسال پیامک با استعلام UserTraceId و تفکیک ثبت‌شدن، پیدا نشدن شناسه و شکست استعلام

اگر پاسخ نگرفتیم باید چه‌کار کنیم؟

برای SendBulk، راهکار مستندشده پیام‌رسان استفاده از UserTraceId و StatusByUserTraceId است. این شناسه باید پیش از ارسال برای هر گیرنده تعیین و ذخیره شده باشد؛ تولید شناسه بعد از Timeout کمکی به پیگیری درخواست قبلی نمی‌کند.

  1. پیش از ارسال: برای هر پیام به هر گیرنده یک UserTraceId یکتا بسازید و در رکورد داخلی عملیات ذخیره کنید.
  2. هنگام ارسال: همان شناسه را داخل عضو مربوط به گیرنده در آرایه Recipients بفرستید.
  3. پس از Timeout یا خطای 100: وضعیت داخلی را نامشخص ثبت کنید و فوری درخواست ارسال دیگری نسازید.
  4. استعلام: با همان ApiKey و UserTraceId ذخیره‌شده، StatusByUserTraceId را فراخوانی کنید.
  5. تصمیم: اگر استعلام نشان داد پیام ثبت شده است، دوباره ارسال نکنید. طبق مستندات، StatusCode برابر 8 یعنی شناسه در حساب پیدا نشده است؛ پس از اطمینان از درستی شناسه و حساب، می‌توانید ارسال را دوباره انجام دهید.

اگر خود استعلام Timeout شد، Success برابر false بود یا پاسخ نامعتبر گرفتید، هنوز نتیجه ثبت ارسال روشن نشده است. شکست استعلام را با StatusCode برابر 8 یکی نگیرید.

اگر هنگام ارسال UserTraceId نفرستاده باشید و پاسخ حاوی Id هم نرسیده باشد، شناسه لازم برای این مسیر پیگیری را ندارید. به همین دلیل، این فیلد با وجود اختیاری‌بودن در ساختار SendBulk، برای مدیریت مطمئن ارسال اهمیت زیادی دارد.

Idempotency چگونه از ارسال تکراری جلوگیری می‌کند؟

Idempotency یعنی تکرار یک درخواست، اثر مورد نظر جدیدی نسبت به اجرای نخست ایجاد نکند. بعضی APIها این قابلیت را با کلید اختصاصی درخواست فراهم می‌کنند.

در مستندات V3 بررسی‌شده پیام‌رسان، هدر Idempotency-Key یا تضمین حذف خودکار ارسال تکراری بر اساس UserTraceId معرفی نشده است. نقش مستندشده UserTraceId، پیگیری و تطبیق پیام با شناسه شماست؛ صرف فرستادن دوباره همان شناسه را تضمین جلوگیری از پیامک تکراری ندانید.

برای جلوگیری از تکرار، در بک‌اند هم کنترل کنید یک رویداد توسط چند پردازش هم‌زمان ارسال نشود، تلاش‌های قبلی ثبت شوند و پیش از Retry نامطمئن، استعلام انجام شود. غیرفعال‌کردن دکمه در مرورگر به‌تنهایی کافی نیست.

چطور Request و Response را مشاهده کنیم؟

مشاهده عملی در DevTools مرورگر

برای بررسی ارتباط مرورگر با سایت خودتان، مراحل زیر را انجام دهید:

  1. صفحه سایت را باز کنید و از گزینه Inspect وارد ابزار توسعه‌دهنده شوید.
  2. تب Network را انتخاب و صفحه را تازه‌سازی کنید.
  3. برای دیدن درخواست‌های API سایت از فیلتر Fetch/XHR کمک بگیرید؛ سند اصلی معمولاً در دسته Document قرار دارد.
  4. یک درخواست را باز کنید و در Headers، آدرس، متد، کد HTTP و هدرها را ببینید.
  5. در Payload داده‌های ارسالی، در Response محتوای پاسخ و در Timing زمان‌بندی ارتباط را بررسی کنید.

Preserve log برای حفظ سابقه هنگام جابه‌جایی صفحه و Disable cache برای آزمایش بدون کش مرورگر، در زمان بازبودن DevTools، کاربرد دارند. محل دقیق گزینه‌ها ممکن است با نسخه مرورگر فرق کند.

در اتصال صحیح پیام‌رسان، درخواست مستقیم بک‌اند به سرویس را در Network مرورگر نمی‌بینید. این بخش فقط درخواست مرورگر به سایت شما را نشان می‌دهد. برای ارتباط خروجی بک‌اند با api.sms-webservice.com باید لاگ سرور یا ابزار پایش همان ارتباط را بررسی کنید.

طبق مستندات پیام‌رسان، سرویس هدرهای لازم CORS را ارائه نمی‌کند و پیش‌پرواز OPTIONS می‌تواند 405 بگیرد. استفاده از no-cors هم راه‌حل اتصال قابل پیگیری نیست؛ در بعضی شکل‌های درخواست، عملیات ممکن است اجرا شود اما پاسخ opaque باشد و نتوانید Success یا شناسه پیام را بخوانید.

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

برای اولین آزمایش، به‌جای ارسال پیامک از AccountInfo استفاده کنید:

  1. یک درخواست HTTP جدید بسازید و متد را POST بگذارید.
  2. آدرس https://api.sms-webservice.com/api/V3/AccountInfo را وارد کنید.
  3. در بخش Authorization گزینه No Auth را انتخاب کنید؛ احراز هویت این متد با ApiKey داخل بادی انجام می‌شود.
  4. در Body، حالت raw و قالب JSON را انتخاب کنید و هدر Content-Type را application/json قرار دهید.
  5. کلید را در متغیر خصوصی api_key نگه دارید و بادی زیر را وارد کنید.
  6. Send را بزنید و علاوه بر کد HTTP، مقدار Success و سپس Result یا ErrorCode را بررسی کنید.
JSON
{
  "ApiKey": "{{api_key}}"
}

اگر موفق بود، AvailableSenders خطوط قابل استفاده حساب را نشان می‌دهد. برای آزمودن SendBulk بدون ارسال واقعی، پیام‌رسان محیط Sandbox دارد:

متن
https://api.sms-webservice.com/api/V3SandBox/SendBulk

طبق راهنمای شروع سریع پیام رسان، Sandbox پیامک واقعی ارسال نمی‌کند و اعتبار مصرف نمی‌کند؛ کلید و شکل درخواست مانند محیط عملیاتی است. برای ارسال واقعی، مسیر V3SandBox را به V3 تغییر دهید و شماره‌ها و خط حساب خود را قرار دهید.

همه متدها را در Sandbox یکسان فرض نکنید؛ برای مثال TokenList در محیط آزمایشی پیاده نشده و 404 می‌دهد. کلید واقعی را هم در Collection عمومی، تصویر آموزشی یا فایل خروجی قابل انتشار قرار ندهید.

ساخت همان درخواست با cURL

برای ارسال با SendBulk، بادی JSON بخش قبل را در فایل send-bulk.json قرار دهید و مقادیر کلید، فرستنده، گیرنده و شناسه پیگیری را تنظیم کنید. سپس درخواست زیر را روی سیستم یا سرور مورد اعتماد اجرا کنید:

Shell
curl --request POST 'https://api.sms-webservice.com/api/V3/SendBulk' \
  --header 'Content-Type: application/json' \
  --header 'Accept: application/json' \
  --data-binary @send-bulk.json \
  --include

این دستور به محیط عملیاتی متصل می‌شود و با داده معتبر می‌تواند پیامک واقعی ارسال کند. برای آزمایش بدون ارسال، از آدرس V3SandBox/SendBulk استفاده کنید.

گزینه –include هدرهای پاسخ را کنار بادی نشان می‌دهد. فایل حاوی کلید را محرمانه نگه دارید و وارد مخزن کد نکنید. در برنامه عملیاتی، بهتر است کلید از متغیر محیطی یا مخزن امن اطلاعات محرمانه وارد درخواست شود.

در لاگ سمت سرور چه چیزی ثبت کنیم؟

برای پیگیری اتصال پیام‌رسان، زمان درخواست، نام متد، UserTraceId، مدت انتظار، کد HTTP، مقدار Success و در صورت شکست ErrorCode را ثبت کنید. اگر پاسخ ارسال را گرفتید، Id سامانه را هم می‌توانید کنار رکورد داخلی نگه دارید.

در گزارش تحویل، StatusCode هر پیام را جداگانه ثبت کنید. موفق‌بودن استعلام نباید باعث شود همه پیام‌های موجود در Result را تحویل‌شده علامت بزنید.

چون ApiKey پیام‌رسان در بادی است، پنهان‌کردن هدر Authorization به‌تنهایی کافی نیست. در ابزار ثبت درخواست، فیلد ApiKey را هم حذف یا ماسک کنید. شماره گیرنده و متن پیام را نیز متناسب با نیاز پشتیبانی و سیاست حریم خصوصی، محدود نگه دارید.

چک‌لیست عیب‌یابی سریع

در جدول زیر، عددهای ستون اول ErrorCode اختصاصی پیام‌رسان‌اند، مگر اینکه صراحتاً HTTP یا StatusCode نوشته شده باشد:

نشانهمعنی یا بررسی اولیهاقدام مناسب
HTTP 200 و Success برابر falseارتباط پاسخ داده، اما عملیات API شکست خورده استErrorCode را بررسی کنید؛ صرفاً بر اساس HTTP تصمیم نگیرید
ErrorCode برابر 1کلید فعال معتبری با این مقدار پیدا نشده استکلید حساب را بررسی کنید
ErrorCode برابر 11ساختار ApiKey نادرست استفاصله، خط جدید و قالب کلید را بررسی کنید
ErrorCode برابر 9پارامترها نامعتبرندبادی، فیلدهای خالی و توضیح Error را بررسی کنید
ErrorCode برابر 10IP درخواست‌دهنده مجاز نیستIP خروجی واقعی سرور را با تنظیمات پنل تطبیق دهید
ErrorCode برابر 12خط فرستنده معتبر یا مجاز نیستSender را با AvailableSenders در AccountInfo تطبیق دهید
ErrorCode برابر 13شماره گیرنده یا تعداد گیرندگان مشکل داردقالب شماره و سقف ۹۹ گیرنده SendBulk را بررسی کنید
ErrorCode برابر 19اعتبار کافی نیستحساب را شارژ کنید؛ تکرار بدون اصلاح فایده ندارد
ErrorCode برابر 20تعداد درخواست بیش از حد مجاز استنرخ را کم و تلاش بعدی را با تأخیر فزاینده زمان‌بندی کنید
ErrorCode برابر 100 یا Timeout ارسالنتیجه ثبت پیام ممکن است نامشخص باشدپیش از ارسال مجدد، StatusByUserTraceId را بررسی کنید
HTTP 404 یا پاسخ بدون Successمسیر، محیط یا پاسخ واسطه را بررسی کنیدآدرس و نام متد را با مستندات تطبیق دهید
موفقیت در Postman و خطای مرورگرمحدودیت CORS و OPTIONS محتمل استفراخوانی دارای کلید را به بک‌اند منتقل کنید

در مستندات، خطاهای 4، 5، 20 و 100 در گروه تلاش با تأخیر فزاینده قرار دارند؛ برای 100 ابتدا وضعیت ثبت ارسال را تعیین کنید. خطاهای 15 تا 18 به سقف‌های ارسال مربوط‌اند و نیاز به انتظار تا آزادشدن سقف یا اصلاح محدودیت دارند. سایر خطاها را پیش از تکرار، بر اساس راهکار جدول مستندات اصلاح کنید.

جمع‌بندی

در کار با Request و Response باید مشخص باشد چه درخواستی فرستاده‌اید، سرویس چه نتیجه‌ای اعلام کرده و آیا آن نتیجه برای تأیید پایان عملیات کافی است یا نه.

در پیام‌رسان، این مسیر با سه نکته روشن می‌شود: ApiKey در محل مستندشده درخواست قرار می‌گیرد، موفقیت عملیات از Success خوانده می‌شود و تحویل پیامک با StatusCode گزارش وضعیت بررسی می‌شود. برای مدیریت Timeout هم UserTraceId را پیش از ارسال تعیین کنید تا بتوانید نتیجه ثبت پیام را پیگیری کنید.

برای شروع، AccountInfo را آزمایش کنید؛ سپس SendBulk را در Sandbox بررسی و بعد به محیط عملیاتی متصل کنید. مرجع آدرس‌ها و پارامترها، مستندات وب سرویس پیام رسان است. معرفی امکانات اتصال را هم در صفحه وب سرویس پیامکی بخوانید.

سوالات متداول

این مقاله مفید بود ؟

به این مقاله امتیاز دهید

میانگین رتبه 0 / 5. تعداد رای : 0

هنوز کسی به این مطلب رای نداده ؛ شما اولین نفر باشید !

تحریریه از احمدرضا احمدپور

احمدرضا احمدپور

احمدرضا، متخصص سئوی خلاقی که با بیش از ۴ سال تجربه، همیشه در حال بهینه‌سازی سایت‌ها و کمک به رشد کسب‌وکارهاست. عاشق یادگیری چیزهای جدیده و هر روز با ایده‌های تازه، کارش رو هیجان‌انگیزتر می‌کنه. پادکست‌های توسعه فردی و رشد کسب‌وکار رو هم خیلی دوست داره و همیشه در حال گوش دادن بهشونه. او همیشه حساب‌شده رفتار می‌کنه و با رویکرد دقیق و فکرشده، بهترین تصمیم‌ها رو می‌گیره. با احمدرضا می‌تونی ساعت‌ها در مورد استراتژی‌های دیجیتال حرف بزنی و مطمئن باش که وقت گذروندن باهاش پر از انرژی مثبته!

ارسال کامنت

ثبت نام ورود