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 هم یکی نیستند: اولی قالب محتوایی را که فرستادهاید مشخص میکند و دومی قالبهای قابل قبول پاسخ را اعلام میکند.

Body یا Payload چیست؟
Body محل محتوای درخواست است. در SendBulk پیامرسان، بادی شامل ApiKey، Text، Sender و آرایه Recipients است. داخل هر عضو Recipients نیز شماره گیرنده و در صورت تعیین، شناسه پیگیری شما قرار میگیرد.
{
"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 OK200 کد وضعیت 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 و بادی درخواست:
{
"ApiKey": "123456-XXXXXXXXXXXXXXX"
}نمونه پاسخ موفقی که در راهنمای شروع سریع پیامرسان آمده است:
{
"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 بهجای شیء اطلاعات حساب، آرایهای از شناسههاست. نمونه پاسخ مستندشده:
{
"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
| ویژگی | Request | Response |
|---|---|---|
| فرستنده | کلاینت، مثلاً بکاند فروشگاه | سرویس پیامرسان یا واسطه پاسخدهنده |
| هدف | درخواست اجرای متدی مانند SendBulk | اعلام نتیجه رسیدگی به درخواست |
| خط آغازین در HTTP/1.1 | متد، مسیر و نسخه HTTP | نسخه HTTP، کد وضعیت و عبارت توضیحی |
| هدر مرتبط با JSON | Content-Type برای معرفی قالب بادی | Content-Type برای معرفی قالب پاسخ |
| بادی در SendBulk | ApiKey، Text، Sender و Recipients | Success، Result، ErrorCode و Error |
| شناسه پیگیری | UserTraceId را شما تعیین میکنید | Id سامانه و UserTraceId شما برمیگردد |
برای عیبیابی باید هر دو طرف را بررسی کنید: در درخواست، آدرس و ورودیها را ببینید و در پاسخ، علاوه بر HTTP، مقدار Success و دادههای Result یا ErrorCode را بخوانید.
چرخه کامل یک درخواست از کلیک کاربر تا پاسخ سرور
هنگام بازشدن یک صفحه وب چه اتفاقی میافتد؟
اگر پاسخ قابل استفاده در کش نباشد و اتصال آمادهای وجود نداشته باشد، مرورگر معمولاً میزبان را با کمک DNS پیدا میکند، اتصال مناسب را برقرار میکند و در HTTPS مراحل امنیتی لازم را انجام میدهد. سپس درخواست HTTP فرستاده میشود.
با دریافت HTML، ممکن است برای CSS، JavaScript، تصاویر و فونتها هم درخواستهای دیگری ارسال شود. پس بازشدن یک صفحه معمولاً حاصل چندین درخواست و پاسخ است. کش، اتصال موجود و Service Worker میتوانند مسیر واقعی را تغییر دهند.
چرخه ارسال پیامک چگونه است؟
- ثبت رویداد و شناسه: سفارش ثبت میشود و بکاند برای ارسال پیامک به هر گیرنده، یک UserTraceId یکتا ایجاد و ذخیره میکند.
- ساخت درخواست: برنامه با POST، بادی شامل ApiKey، Text، Sender و Recipients را به SendBulk میفرستد.
- بررسی پاسخ اولیه: برنامه ابتدا پاسخ HTTP و JSON را دریافت میکند و سپس Success را بررسی میکند. در شکست، ErrorCode مسیر رفع مشکل را مشخص میکند.
- ثبت نتیجه ارسال: در موفقیت، Id و UserTraceId خروجی ذخیره یا با رکورد داخلی تطبیق داده میشوند. وضعیت داخلی مناسب، «درخواست ثبت شد» است.
- پیگیری تحویل: برنامه با StatusByUserTraceId یا StatusById، گزارش وضعیت را جداگانه دریافت و StatusCode را بررسی میکند.
آیا پاسخ موفق یعنی پیامک تحویل شده است؟
خیر؛ Success برابر true در SendBulk به معنی تحویل پیامک به گوشی نیست. پاسخ ارسال فقط پذیرش پیام را اعلام میکند. برای نتیجه تحویل، باید از متد استعلام وضعیت استفاده کنید.

در StatusById، شناسه Id برگشتی از ارسال را میفرستید. در StatusByUserTraceId، شناسهای را میفرستید که از قبل خودتان تعیین کردهاید؛ به همین دلیل، روش دوم پس از گمشدن پاسخ ارسال هم کاربرد دارد.
آدرس واقعی استعلام با شناسه شما:
https://api.sms-webservice.com/api/V3/StatusByUserTraceIdاین متد با POST و بادی زیر فراخوانی میشود:
{
"ApiKey": "123456-XXXXXXXXXXXXXXX",
"UserTraceIds": [45001]
}نمونه ساختار گزارش تحویل، مطابق مستندات پیامرسان:
{
"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 واقعی پیامرسان را فراخوانی کنید. در این مثال، کلید از متغیر محیطی خوانده میشود و هیچ پیامکی ارسال نمیشود:
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 ضروری است.

اگر پاسخ نگرفتیم باید چهکار کنیم؟
برای SendBulk، راهکار مستندشده پیامرسان استفاده از UserTraceId و StatusByUserTraceId است. این شناسه باید پیش از ارسال برای هر گیرنده تعیین و ذخیره شده باشد؛ تولید شناسه بعد از Timeout کمکی به پیگیری درخواست قبلی نمیکند.
- پیش از ارسال: برای هر پیام به هر گیرنده یک UserTraceId یکتا بسازید و در رکورد داخلی عملیات ذخیره کنید.
- هنگام ارسال: همان شناسه را داخل عضو مربوط به گیرنده در آرایه Recipients بفرستید.
- پس از Timeout یا خطای 100: وضعیت داخلی را نامشخص ثبت کنید و فوری درخواست ارسال دیگری نسازید.
- استعلام: با همان ApiKey و UserTraceId ذخیرهشده، StatusByUserTraceId را فراخوانی کنید.
- تصمیم: اگر استعلام نشان داد پیام ثبت شده است، دوباره ارسال نکنید. طبق مستندات، StatusCode برابر 8 یعنی شناسه در حساب پیدا نشده است؛ پس از اطمینان از درستی شناسه و حساب، میتوانید ارسال را دوباره انجام دهید.
اگر خود استعلام Timeout شد، Success برابر false بود یا پاسخ نامعتبر گرفتید، هنوز نتیجه ثبت ارسال روشن نشده است. شکست استعلام را با StatusCode برابر 8 یکی نگیرید.
اگر هنگام ارسال UserTraceId نفرستاده باشید و پاسخ حاوی Id هم نرسیده باشد، شناسه لازم برای این مسیر پیگیری را ندارید. به همین دلیل، این فیلد با وجود اختیاریبودن در ساختار SendBulk، برای مدیریت مطمئن ارسال اهمیت زیادی دارد.
Idempotency چگونه از ارسال تکراری جلوگیری میکند؟
Idempotency یعنی تکرار یک درخواست، اثر مورد نظر جدیدی نسبت به اجرای نخست ایجاد نکند. بعضی APIها این قابلیت را با کلید اختصاصی درخواست فراهم میکنند.
در مستندات V3 بررسیشده پیامرسان، هدر Idempotency-Key یا تضمین حذف خودکار ارسال تکراری بر اساس UserTraceId معرفی نشده است. نقش مستندشده UserTraceId، پیگیری و تطبیق پیام با شناسه شماست؛ صرف فرستادن دوباره همان شناسه را تضمین جلوگیری از پیامک تکراری ندانید.
برای جلوگیری از تکرار، در بکاند هم کنترل کنید یک رویداد توسط چند پردازش همزمان ارسال نشود، تلاشهای قبلی ثبت شوند و پیش از Retry نامطمئن، استعلام انجام شود. غیرفعالکردن دکمه در مرورگر بهتنهایی کافی نیست.
چطور Request و Response را مشاهده کنیم؟
مشاهده عملی در DevTools مرورگر
برای بررسی ارتباط مرورگر با سایت خودتان، مراحل زیر را انجام دهید:
- صفحه سایت را باز کنید و از گزینه Inspect وارد ابزار توسعهدهنده شوید.
- تب Network را انتخاب و صفحه را تازهسازی کنید.
- برای دیدن درخواستهای API سایت از فیلتر Fetch/XHR کمک بگیرید؛ سند اصلی معمولاً در دسته Document قرار دارد.
- یک درخواست را باز کنید و در Headers، آدرس، متد، کد HTTP و هدرها را ببینید.
- در Payload دادههای ارسالی، در Response محتوای پاسخ و در Timing زمانبندی ارتباط را بررسی کنید.
Preserve log برای حفظ سابقه هنگام جابهجایی صفحه و Disable cache برای آزمایش بدون کش مرورگر، در زمان بازبودن DevTools، کاربرد دارند. محل دقیق گزینهها ممکن است با نسخه مرورگر فرق کند.
در اتصال صحیح پیامرسان، درخواست مستقیم بکاند به سرویس را در Network مرورگر نمیبینید. این بخش فقط درخواست مرورگر به سایت شما را نشان میدهد. برای ارتباط خروجی بکاند با api.sms-webservice.com باید لاگ سرور یا ابزار پایش همان ارتباط را بررسی کنید.
طبق مستندات پیامرسان، سرویس هدرهای لازم CORS را ارائه نمیکند و پیشپرواز OPTIONS میتواند 405 بگیرد. استفاده از no-cors هم راهحل اتصال قابل پیگیری نیست؛ در بعضی شکلهای درخواست، عملیات ممکن است اجرا شود اما پاسخ opaque باشد و نتوانید Success یا شناسه پیام را بخوانید.
ساخت درخواست در Postman
برای اولین آزمایش، بهجای ارسال پیامک از AccountInfo استفاده کنید:
- یک درخواست HTTP جدید بسازید و متد را POST بگذارید.
- آدرس https://api.sms-webservice.com/api/V3/AccountInfo را وارد کنید.
- در بخش Authorization گزینه No Auth را انتخاب کنید؛ احراز هویت این متد با ApiKey داخل بادی انجام میشود.
- در Body، حالت raw و قالب JSON را انتخاب کنید و هدر Content-Type را application/json قرار دهید.
- کلید را در متغیر خصوصی api_key نگه دارید و بادی زیر را وارد کنید.
- Send را بزنید و علاوه بر کد HTTP، مقدار Success و سپس Result یا ErrorCode را بررسی کنید.
{
"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 قرار دهید و مقادیر کلید، فرستنده، گیرنده و شناسه پیگیری را تنظیم کنید. سپس درخواست زیر را روی سیستم یا سرور مورد اعتماد اجرا کنید:
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 برابر 10 | IP درخواستدهنده مجاز نیست | 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 بررسی و بعد به محیط عملیاتی متصل کنید. مرجع آدرسها و پارامترها، مستندات وب سرویس پیام رسان است. معرفی امکانات اتصال را هم در صفحه وب سرویس پیامکی بخوانید.

