ملی ای‌پی‌آی

خطاها و هزینهٔ API استعلام قبض ایرانسل

در API استعلام قبض ایرانسل، پاسخ بدون رکورد با کد ۲۰۰ و ok:false برمی‌گردد و هزینه دارد، پس تلاش مجدد را فقط روی خطاهای گذرا بگذارید.

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

این مقاله برای کسی است که می‌خواهد API استعلام قبض ایرانسل را در یک محصول واقعی بگذارد و باید برای هر نتیجه تصمیم بگیرد که چه نشان بدهد، چه تکرار کند و چه را حساب کند.

فراخوان چه شکلی است

نشانی هر سرویس با slug آن ساخته می‌شود و فقط POST می‌پذیرد. برای این سرویس slug برابر bill-irancell است و ورودی تنها یک فیلد دارد.

bash curl -X POST 'https://BASE/api/v1/bill-irancell/' \ -H 'Authorization: Bearer melli_live_…' \ -H 'Content-Type: application/json' \ -d '{"mobile":"09121234567"}'

BASE را با نشانی خودتان عوض کنید. شمارهٔ بالا نمونه است. شماره با صفر، با +98 یا با ارقام فارسی هر سه پذیرفته می‌شود، ولی بهتر است خودتان در یک شکل نگهش دارید.

در پاسخ موفق، data همان دو بلوک final_term و mid_term است که هرکدام مبلغ، شناسهٔ قبض و شناسهٔ پرداخت دارند. کنار آن requestId را نگه دارید؛ برای پیگیری با پشتیبانی تنها چیز لازم است.

نتیجه‌ها را به چهار گروه تقسیم کنید

جدول خطاهای مستندات یک فهرست بلند است. برای این سرویس کافی است همه را به چهار رفتار تقسیم کنید.

گروهکدهای نمونهکار شما
درست و معنادارموفقنمایش دو بخش
درست ولی بدون رکوردnot_found با HTTP ۲۰۰پیام «قبضی نیست»
تکرارکردنیprovider_failed_retryable، temporarily_unavailable، rate_limitedتکرار با فاصله
بی‌فایدهٔ تکرارinvalid_input، provider_failed، not_inquirableاصلاح ورودی یا نمایش پیام

کلیدی‌ترین ردیف دومی است. not_found با کد ۲۰۰ برمی‌گردد ولی ok:false دارد. اگر فقط به وضعیت HTTP نگاه کنید، آن را موفق می‌گیرید و بعد وقتی data را می‌خوانید به خطا برمی‌خورید. همیشه فیلد ok را بخوانید.

کدام فراخوان از موجودی کم می‌شود

قاعده این است که هزینه فقط وقتی کسر می‌شود که سرویس مرجع جواب قابل‌استفاده داده باشد. در عمل:

  • پاسخ موفق: حساب می‌شود.
  • not_found: حساب می‌شود، چون استعلام انجام شده و جواب «رکوردی نیست» یک پاسخ معتبر است.
  • provider_failed، یعنی پاسخ قطعی منفی: حساب می‌شود.
  • provider_failed_retryable، temporarily_unavailable، invalid_input، rate_limited و خطاهای احراز: حساب نمی‌شود.

مبلغ هر فراخوان را از صفحهٔ تعرفه بخوانید؛ من اینجا عدد نمی‌نویسم چون تعرفه زنده است. اما در هر پاسخی که به مرحلهٔ تسویه رسیده باشد، فیلد billing می‌گوید همان لحظه چقدر کسر شد. این فیلد برای تطبیق حساب بهترین مرجع است: نبودنش یعنی هیچ مبلغی جابه‌جا نشده.

تلهٔ رایج: تکرار روی not_found

برنامه‌نویس‌ها یاد گرفته‌اند «پاسخ خالی را دوباره بپرس». برای این سرویس این عادت پول می‌خورد. not_found یعنی استعلام انجام شد و رکوردی نبود. تکرارش همان جواب را با هزینهٔ دوباره می‌دهد.

فرض کنید یک سوپراپ پرداخت دارید و کاربر شمارهٔ یک خط اعتباری را وارد می‌کند. اگر لایهٔ تلاش مجدد شما روی «پاسخ بدون مبلغ» سه بار تکرار کند، برای یک کاربر سه بار هزینه داده‌اید و نتیجه همان است. تلاش مجدد را فقط روی کدهای گروه سوم بگذارید.

تکرار درست چه شکلی دارد

برای rate_limited، هدر Retry-After را بخوانید و به همان اندازه صبر کنید. پیش‌فرض سقف نرخ در مستندات آمده است و عبور از آن هزینه ندارد، ولی در سابقهٔ مصرف ما هم ثبت نمی‌شود. اگر شمارش می‌خواهید، خودتان ۴۲۹ها را بشمارید.

برای temporarily_unavailable و provider_failed_retryable، تلاش مجدد با فاصلهٔ فزاینده و سقف سه بار کافی است. بعد از آن به کاربر بگویید «الان نتیجه در دسترس نیست» و پیشنهاد کنید بعداً امتحان کند. در پاسخ ممکن است source.stale برابر درست باشد؛ یعنی سرویس مرجع در دسترس نبود و آخرین پاسخ معتبر با زمان fetchedAt برگردانده شد. برای قبض، پاسخ چندساعته معمولاً ایرادی ندارد ولی مبلغ را همراه تاریخش نشان دهید، نه به‌عنوان وضعیت لحظه‌ای.

ثبت برای حسابداری و پشتیبانی

برای هر فراخوان چهار چیز ذخیره کنید:

  1. requestId
  2. کد نتیجه (موفق یا error.code)
  3. billing.amountRial اگر وجود داشت
  4. شمارهٔ پوشانده‌شده، نه کامل

با همین چهار ستون هم گزارش ماهانهٔ هزینه می‌سازید و هم وقتی کاربری می‌گوید «جواب نگرفتم ولی پول رفت» در چند ثانیه می‌توانید ردیفش را پیدا کنید. شمارهٔ کامل را در لاگ ننویسید.

آنچه این سرویس برای شما انجام نمی‌دهد

در مجموع، استعلام قبض ایرانسل یک آینه است، نه یک موتور تصمیم.

  • بین خط دائمی و اعتباری فرق نمی‌گذارد و در خط اعتباری نتیجهٔ معنادار نمی‌دهد. این تفکیک را در رابط خودتان بپرسید.
  • اپراتور شماره را تشخیص نمی‌دهد؛ شما سرویس درست را انتخاب می‌کنید و برای شمارهٔ منتقل‌شده به اپراتور دیگر ممکن است سرویس اشتباهی صدا بزنید.
  • پرداخت را انجام نمی‌دهد.
  • تضمین نمی‌کند رکورد بعد از پرداخت فوراً عوض شود. این قبلاً در راهنمای پرداخت‌شدهٔ بدون تسویه برای قبض‌های خدماتی توضیح داده شده و منطقش برای موبایل هم شبیه است: استعلام آینهٔ رکورد است.

نمونهٔ تصمیم در کد

منطق کلی را در یک تابع کوچک نگه دارید که کد نتیجه را به رفتار تبدیل می‌کند، تا هیچ‌جای دیگر برنامه به رشتهٔ خطا وابسته نباشد:

```ts type Action = 'show' | 'empty' | 'retry' | 'fix';

function actionFor(code: string | null): Action { if (code === null) return 'show'; if (code === 'not_found') return 'empty'; if (['rate_limited', 'temporarily_unavailable', 'provider_failed_retryable'].includes(code)) return 'retry'; return 'fix'; } ```

وقتی کد جدیدی در مستندات اضافه شد، فقط همین تابع را عوض می‌کنید. پیش‌فرض را fix بگذارید تا کد ناشناخته تکرار خودکار ایجاد نکند و فراخوان بی‌پایان نسازد.

آزمون پیش از انتشار

پیش از انتشار، حداقل چهار حالت را بیازمایید: شمارهٔ دائمی با بدهی، شمارهٔ دائمی بدون بدهی، شمارهٔ اعتباری و شمارهٔ نامعتبر. حالت سوم را مخصوصاً ببینید چون رفتارش را باید از خودتان بدانید، نه از این مقاله. نتیجه را کنار فیلد billing ثبت کنید تا ببینید کدام حالت هزینه داشته است.

نکتهٔ آخر

برای این سرویس سه قاعده کافی است: فیلد ok را همیشه بخوانید، تلاش مجدد را فقط روی خطاهای گذرا بگذارید، و requestId و billing را هر بار ذخیره کنید. مرجع کامل کدها در مستندات API است.

آخرین بازبینی: تیم تحریریه ملی ای‌پی‌آی

وب‌سرویس مرتبط با این راهنما

API استعلام قبض ایرانسل

صورتحساب خط دائمی ایرانسل.

مشاهده مشخصات فنی و تعرفه

راهنماهای مرتبط

پرسش و تجربه کاربران

اگر این راهنما جوابتان را نداد، همین‌جا بپرسید. پرسش‌ها را تیمملی ای‌پی‌آی پاسخ می‌دهد و هر نظر پیش از انتشار بررسی می‌شود.

هنوز پرسشی ثبت نشده، اولین نفر باشید.