پرش به محتوا
مستندات مهراد

پیاده‌سازی خرید حضوری

سوپر اپلیکیشن مهراد

این سند راهنمای پیاده‌سازی خرید حضوری برای توسعه‌دهندگان پذیرنده است؛ حالتی که مشتری به صورت فیزیکی در فروشگاه حاضر است و با اپلیکیشن مهراد پرداخت می‌کند.


معرفی خرید حضوری

در جریان آنلاین (بخش مستندات سفارش) مشتری در سایت پذیرنده سبد خرید می‌سازد و برای پرداخت به مهراد هدایت می‌شود.

در خرید حضوری سبد خرید و مرورگری در کار نیست؛ مشتری روبه‌روی صندوق ایستاده است. بنابراین:

  1. پذیرنده اقلام خرید را ثبت می‌کند و یک خرید حضوری (Order Draft) می‌سازد.
  2. مهراد یک کد پیگیری ۸ رقمی و یک لینک پرداخت برمی‌گرداند که پذیرنده آن را به شکل QR یا عدد به مشتری نشان می‌دهد.
  3. مشتری در اپلیکیشن مهراد کد را وارد یا QR را اسکن می‌کند، خرید را باز می‌کند و از دارایی‌های خود پرداخت می‌کند.
  4. پذیرنده پرداخت را تأیید (Verify) می‌کند و مبلغ برای او نهایی می‌شود.

تفاوت کلیدی با جریان آنلاین: در خرید حضوری، پذیرنده هیچ‌گاه authority (ID تلاش پرداخت) را دریافت نمی‌کند، چون پرداخت در دستگاه مشتری انجام می‌شود. به همین دلیل تأیید پرداخت با order_id انجام می‌شود، نه با authority.

مرحلهٔ ۳ کاملاً توسط اپلیکیشن مهراد انجام می‌شود و پیاده‌سازی آن بر عهدهٔ پذیرنده نیست.


روش‌های استفاده

خرید حضوری به دو روش قابل استفاده است:

روشکاربردنیاز به پیاده‌سازی
پنل پذیرندهٔ مهرادساخت خرید، نمایش QR و تأیید پرداخت از طریق رابط کاربری پنلندارد
سیستم فروشگاهی پذیرنده (صندوق یا اپلیکیشن فروشگاهی)ساخت خرید و تأیید پرداخت از سرور پذیرندهدارد؛ طبق ادامهٔ همین سند

استفاده از پنل پذیرنده

در پنل پذیرنده، سرویس، اقلام خرید، هزینه‌های جانبی، تخفیف و در صورت نیاز توضیح سفارش وارد می‌شود. مبلغ نهایی و ID سفارش به‌صورت خودکار توسط پنل محاسبه و تولید می‌شوند. پس از ساخت خرید، پنل QR، کد پیگیری ۸ رقمی و زمان انقضای خرید را نمایش می‌دهد. پس از پرداخت مشتری، تأیید پرداخت از صفحهٔ جزئیات همان سفارش در بخش سفارش‌های حضوری پنل انجام می‌شود.

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

یکپارچه‌سازی با سیستم فروشگاهی پذیرنده

ادامهٔ این سند برای تیم‌هایی است که ساخت خرید و تأیید پرداخت را از سیستم فروشگاهی خود انجام می‌دهند. این ارتباط سرور-به-سرور است و با token اپلیکیشن پذیرنده انجام می‌شود.

endpointکاربرد
POST /gateway/order/draft/requestساخت خرید حضوری
POST /gateway/order/payment/verifyتأیید پرداخت با order_id

هر دو endpoint با token اپلیکیشن پذیرنده در header Authorization فراخوانی می‌شوند؛ نحوهٔ دریافت token در مستندات ارتباط پذیرندگان آمده است.


پیش‌نیازها

برای یکپارچه‌سازی با سیستم فروشگاهی، موارد زیر لازم است:

  • حساب پذیرنده فعال در مهراد.
  • client_id و client_secret اپلیکیشن پذیرنده برای دریافت token.
  • service_id یکی از سرویس‌های فعال حساب پذیرنده؛ این مقدار برای ساخت خرید الزامی است و باید از اطلاعات پیکربندی یکپارچه‌سازی دریافت شود.
  • امکان تولید و نمایش QR یا نمایش کد ۸ رقمی به مشتری.
  • یک ID یکتا برای هر سفارش در سیستم پذیرنده (external_order_id).

مرحله ۱ — ساخت خرید حضوری

POST/gateway/order/draft/request

Authentication: token اپلیکیشن پذیرنده در header Authorization.

مقادیری که توسط پذیرنده تولید می‌شوند

فیلدتوضیح
external_order_idID سفارش در سیستم پذیرنده؛ باید برای هر سفارش یکتا باشد
amountمبلغ نهایی که بر اساس اقلام محاسبه می‌شود
shipments / services / discount_amountمرسوله‌ها و اقلام، هزینه‌های جانبی و تخفیف

مقادیری که API تولید می‌کند

draft_id، tracking_code، expires_at و draft_url را API می‌سازد؛ این مقادیر نباید ارسال شوند.

ورودی (Request Body)

پارامترهای ورودی10 فیلد
service_iduuidالزامی
ID یکی از سرویس‌های فعال همین پذیرنده.
amountintegerالزامی
مبلغ نهایی سفارش (ریال)؛ باید با اقلام، هزینهٔ ارسال مرسوله‌ها، خدمات و تخفیف هم‌خوانی داشته باشد.
external_order_idstringالزامی
ID یکتای سفارش در سیستم پذیرنده.
shipmentsarray of objectsالزامی
اقلام سفارش به‌تفکیک مرسوله؛ در سفارش و صورت‌حساب مشتری نمایش داده می‌شود. ساختار آن همان `shipments` در [مستندات سفارش](/docs/order) است. معمولاً یک مرسوله با `shipping_fee` برابر صفر کفایت می‌کند.
فیلدهای هر عضو لیست shipments3 فیلد
idstringالزامی
ID مرسوله در سیستم پذیرنده (حداکثر ۲۵۵ کاراکتر)؛ در یک سفارش یکتاست. برای ثبت ارسال و تحویل همین مرسوله و برای اصلاح سفارش به همین مقدار نیاز است.
shipping_feeinteger
هزینهٔ ارسال همین مرسوله به ریال (حداقل صفر)؛ به مبلغ سفارش اضافه می‌شود.

پیش‌فرض: 0

itemsarray of objectsالزامی
اقلام این مرسوله (با `product` و `variant`).
فیلدهای هر عضو لیست items5 فیلد
productobjectالزامی
اطلاعات کالا.
فیلدهای product6 فیلد
idstringالزامی
ID کالا در سیستم پذیرنده (حداکثر ۲۵۵ کاراکتر)؛ همراه با ID تنوع، کلید یکتای کالا در سفارش است. برای اصلاح سفارش در مرحلهٔ بعد به همین مقدار نیاز است.
titlestringالزامی
عنوان کالا (حداکثر ۵۱۱ کاراکتر).
urlstringالزامی
لینک صفحهٔ کالا در سیستم پذیرنده (حداکثر ۵۱۱ کاراکتر).
is_domesticboolean
مشخص می‌کند کالا تولید داخل است یا خارجی؛ جایگزین فیلد منسوخ `brand_origin`.
imageobjectالزامی
تصویر کالا.
فیلدهای image2 فیلد
urlstringالزامی
آدرس تصویر اصلی کالا (حداکثر ۵۱۱ کاراکتر)؛ در صورت‌حساب کاربر نمایش داده می‌شود.
thumbnail_urlstringالزامی
آدرس تصویر کوچک کالا (حداکثر ۵۱۱ کاراکتر).
variantobjectالزامی
تنوع انتخاب‌شدهٔ کالا (مانند رنگ یا سایز).
فیلدهای variant2 فیلد
idstringالزامی
ID تنوع در سیستم پذیرنده (حداکثر ۲۵۵ کاراکتر)، مثلاً ID رنگ یا سایز مشخص.
titlestringالزامی
عنوان تنوع (حداکثر ۲۵۵ کاراکتر)، مثلاً «قرمز - سایز ۴۲».
priceintegerالزامی
قیمت واحد کالا به ریال؛ باید بزرگ‌تر از صفر باشد.
quantityinteger
تعداد کالا؛ حداقل ۱.

پیش‌فرض: 1

categorystringالزامی
دسته‌بندی کالا در سیستم پذیرنده (حداکثر ۵۱۱ کاراکتر)؛ سلسله‌مراتب دسته‌ها با ویرگول از هم جدا می‌شود، مثلاً «لوازم خانگی برقی,یخچال و فریزر». این مقدار با category_id سیستم که در response‌ها می‌آید یکی نیست.
extra_dataobject
داده‌ای آزاد در قالب JSON برای اطلاعات تکمیلی کالا که در سایر فیلدها پیش‌بینی نشده است؛ ساختار آن توسط پذیرنده تعیین می‌شود و بدون تغییر در response‌های سفارش بازگردانده می‌شود.
servicesarray of objects
هزینه‌های جانبی مانند نصب یا ارسال؛ مجموع آن‌ها به عنوان کارمزد خدمات روی سفارش ثبت می‌شود.
فیلدهای هر عضو لیست services2 فیلد
titlestringالزامی
عنوان هزینه، مثلاً هزینهٔ ارسال.
amountintegerالزامی
مبلغ هزینه به ریال؛ باید بزرگ‌تر از صفر باشد.
discount_amountinteger
مبلغ تخفیف کل سفارش؛ نباید منفی باشد.
descriptionstring
توضیح سفارش.
order_urlstring
آدرس پیگیری سفارش در سیستم پذیرنده.
external_payment_idstring
ID پرداخت در سیستم پذیرنده.
callback_urlstring
آدرس بازگشت مشتری. اختیاری است. اگر ارسال شود، پس از پرداخت یا لغو در اپلیکیشن به همین آدرس می‌رود؛ اگر ارسال نشود در اپلیکیشن می‌ماند.

این endpoint از فیلد items (ساختار منسوخ جریان آنلاین) پشتیبانی نمی‌کند و اقلام تنها از طریق shipments ثبت می‌شوند؛ فیلد items در صورت ارسال نادیده گرفته می‌شود. اگر shipments ارسال نشود، response آن با کد ۴۲۲ و خطای VALIDATION_ERROR برگردانده می‌شود.

در صورت وجود دو قلم با ID کالا (product.id) و تنوع (variant.id) یکسان در یک request، حتی در مرسوله‌های متفاوت، کل request با خطای DUPLICATE_ORDER_ITEM رد می‌شود.

توجه: services با service_id یکی نیست. service_id سرویس پذیرنده است و services ردیف‌های هزینهٔ جانبی همین سفارش است.

قاعدهٔ مبلغ

مقدار amount باید دقیقاً برابر باشد با:

amount = SUM(price × quantity همهٔ اقلام) + SUM(shipments.shipping_fee) + SUM(services.amount) - discount_amount

اگر این تساوی برقرار نباشد request با INVALID_ORDER_AMOUNT رد می‌شود و اگر حاصل صفر یا منفی شود با ORDER_AMOUNT_NOT_POSITIVE.

نمونه request

نمونه ساخت خرید حضوری
{
  "service_id": "2f1b7d6e-2f4e-4a1a-9c22-6f0c0a1d5b31",
  "amount": 3100000,
  "external_order_id": "POS-2026-000184",
  "description": "خرید از شعبه مرکزی",
  "shipments": [
    {
      "id": "S1",
      "shipping_fee": 0,
      "items": [
        {
          "product": {
            "id": "SKU-7781",
            "title": "هدفون بی‌سیم",
            "url": "https://shop.example.com/product/SKU-7781",
            "image": {
              "url": "https://shop.example.com/media/SKU-7781.webp",
              "thumbnail_url": "https://shop.example.com/media/SKU-7781-thumb.webp"
            },
            "variant": {
              "id": "SKU-7781-black",
              "title": "مشکی"
            }
          },
          "price": 1250000,
          "quantity": 2,
          "category": "لوازم جانبی"
        },
        {
          "product": {
            "id": "SKU-1042",
            "title": "کابل USB-C یک متری",
            "url": "https://shop.example.com/product/SKU-1042",
            "image": {
              "url": "https://shop.example.com/media/SKU-1042.webp",
              "thumbnail_url": "https://shop.example.com/media/SKU-1042-thumb.webp"
            },
            "variant": {
              "id": "SKU-1042-white",
              "title": "سفید"
            }
          },
          "price": 150000,
          "quantity": 3,
          "category": "لوازم جانبی"
        }
      ]
    }
  ],
  "services": [
    {
      "title": "نصب",
      "amount": 200000
    },
    {
      "title": "بسته‌بندی",
      "amount": 50000
    }
  ],
  "discount_amount": 100000
}

محاسبهٔ مبلغ این نمونه:

(1250000 × 2) + (150000 × 3) + 0 + (200000 + 50000) - 100000 = 3100000

Response

فیلدهای پاسخ4 فیلد
draft_iduuid
ID خرید؛ پس از باز شدن خرید توسط مشتری، همین مقدار order_id سفارش است و باید ذخیره شود.
tracking_codestring
کد پیگیری ۸ رقمی برای ورود دستی در اپلیکیشن مشتری.
expires_atdatetime
زمان انقضای خرید (۵ دقیقه پس از ساخت).
draft_urlstring
لینکی که باید به شکل QR به مشتری نمایش داده شود.
نمونه پاسخ
{
  "success": true,
  "data": {
    "draft_id": "9b1c4f52-1f2a-4f33-8a77-2c0b9b0d51aa",
    "tracking_code": "48219307",
    "expires_at": "2026-09-20T10:35:12.480000+00:00",
    "draft_url": "https://pwa.mehrad.app/purchase/9b1c4f52-1f2a-4f33-8a77-2c0b9b0d51aa"
  },
  "meta": null
}

مقادیر قابل ذخیره و نمایش

مقادیر لازم برای ذخیره: draft_id (برای تأیید پرداخت در مرحلهٔ ۳ لازم است) و expires_at.

موارد قابل نمایش به مشتری: مبلغ نهایی، تصویر QR ساخته‌شده از draft_url، کد پیگیری ۸ رقمی به عنوان روش جایگزین، و زمان باقی‌مانده تا انقضا.

خرید ساخته‌شده ۵ دقیقه اعتبار دارد. تا وقتی مشتری آن را باز نکرده باشد، هیچ سفارشی ثبت نشده است و پس از انقضا باید خرید جدیدی ساخته شود.


مرحله ۲ — باز کردن خرید و پرداخت توسط مشتری

این مرحله کاملاً در اپلیکیشن مهراد انجام می‌شود و به پیاده‌سازی توسط پذیرنده نیاز ندارد. آنچه پذیرنده باید از این مرحله بداند:

  • مشتری با اسکن QR یا وارد کردن کد ۸ رقمی، محتوای خرید (اقلام، خدمات، تخفیف، مبلغ و نام پذیرنده) را می‌بیند.
  • با باز شدن خرید توسط مشتری، سفارش با channel = IN_PERSON ساخته می‌شود و order_id آن همان draft_id است. در همین لحظه یک تلاش پرداخت با وضعیت PENDING ایجاد می‌شود.
  • هر خرید فقط یک‌بار قابل باز شدن است؛ پس از باز شدن یا انقضا، همان کد یا QR دیگر قابل استفاده نیست.
  • با پرداخت موفق، مبلغ از حساب مشتری برداشت و نگهداری می‌شود و وضعیت تلاش پرداخت به PAID تغییر می‌کند. مبلغ تا تأیید پذیرنده برای او نهایی نمی‌شود.
  • callback_url اختیاری است. اگر ارسال شود، پس از پرداخت یا لغو مشتری به آن هدایت می‌شود. اگر ارسال نشود، مشتری در اپلیکیشن می‌ماند.

مرحله ۳ — تأیید پرداخت

POST/gateway/order/payment/verify

Authentication: token اپلیکیشن پذیرنده در header Authorization.

تأیید پرداخت مرحلهٔ نهایی و الزامی است؛ بدون آن مبلغ برای پذیرنده نهایی نمی‌شود. در خرید حضوری، تأیید با order_id انجام می‌شود.

ورودی

پارامترهای ورودی2 فیلد
order_iduuidالزامی
ID سفارش؛ همان draft_id که در مرحلهٔ ۱ دریافت شده است.
amountintegerالزامی
مبلغ سفارش؛ باید دقیقاً برابر مبلغ ثبت‌شدهٔ خرید باشد.
{
  "order_id": "9b1c4f52-1f2a-4f33-8a77-2c0b9b0d51aa",
  "amount": 3100000
}

Response

نمونه پاسخ
{
  "success": true,
  "data": {
    "ref_id": "5f7d1a30-1c77-4a2b-b6d1-0f3f41f9c5e2",
    "status": "VERIFY_OK",
    "fee": 15500
  },
  "meta": null
}
  • status برابر VERIFY_OK یعنی تأیید موفق بوده است.
  • ref_id، ID تراکنش نهایی است و برای پیگیری و تطبیق حساب باید ذخیره شود.
  • fee کارمزد سامانه برای این تراکنش است.

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

تشخیص انجام‌شدن پرداخت

authority در اختیار پذیرنده نیست؛ وضعیت پرداخت از همین endpoint تأیید مشخص می‌شود:

responseمعنیاقدام لازم
ORDER_NOT_FOUNDمشتری هنوز خرید را باز نکرده استتکرار request پس از چند لحظه؛ پس از انقضای خرید، ساخت خرید جدید
ORDER_ATTEMPT_NOT_PAIDخرید باز شده ولی پرداخت انجام نشده استتکرار request پس از چند لحظه
status = VERIFY_OKپرداخت انجام و تأیید شده استتحویل کالا و ثبت ref_id
ORDER_ALREADY_PAIDپرداخت قبلاً تأیید شده استپرداخت موفق تلقی می‌شود؛ تأیید دوباره لازم نیست

مبلغ تأیید

مبلغ ارسالی با مبلغ پرداخت‌شده مقایسه می‌شود. اگر این دو برابر نباشند، تأیید با ORDER_AMOUNT_NOT_MATCHED رد می‌شود و تلاش پرداخت باطل می‌شود؛ یعنی دیگر امکان تأیید همان پرداخت وجود ندارد.

اگر سفارش متعلق به پذیرندهٔ دیگری باشد، request با ORDER_MERCHANT_NOT_MATCHED رد می‌شود و پرداخت دست‌نخورده باقی می‌ماند.

محدودیت زمانی تأیید

تأیید باید حداکثر تا ۳۰ دقیقه پس از ایجاد تلاش پرداخت انجام شود. پس از آن پرداخت به صورت خودکار بسته و مبلغ به مشتری بازگردانده می‌شود و وضعیت تلاش پرداخت VERIFY_TIMEOUT خواهد شد.


مرحله ۴ — مدیریت نتیجهٔ نهایی

سناریونحوهٔ تشخیصاقدام لازم
پرداخت موفق و تأییدشدهresponse تأیید با status = VERIFY_OKتحویل کالا، ثبت ref_id، نمایش «پرداخت موفق»
پرداخت انجام نشدهORDER_ATTEMPT_NOT_PAIDمشتری باید پرداخت را در اپلیکیشن کامل کند
قبلاً تأیید شدهORDER_ALREADY_PAIDپرداخت موفق تلقی می‌شود؛ تأیید دوباره لازم نیست
خرید باز نشده یا منقضی شدهORDER_NOT_FOUNDپس از انقضای ۵ دقیقه‌ای، ساخت خرید جدید و ارائهٔ کد تازه به مشتری
مبلغ سفارش با مبلغ پرداخت‌شده برابر نیستORDER_AMOUNT_NOT_MATCHEDپرداخت باطل شده است؛ خرید جدید باید ساخته شود
سفارش متعلق به پذیرندهٔ دیگری استORDER_MERCHANT_NOT_MATCHEDبررسی order_id؛ پرداخت دست‌نخورده باقی مانده است
مهلت تأیید گذشتهORDER_ATTEMPT_NOT_PAID پس از ۳۰ دقیقه از ایجاد تلاش پرداختمبلغ به مشتری بازگشته است؛ خرید جدید باید ساخته شود

وضعیت‌ها

وضعیت سفارش

وضعیتمعنی
PENDINGسفارش ساخته شده ولی هنوز تأیید نشده است
SUCCESSپرداخت تأیید شده است
FAILEDپرداخت انجام یا تأیید نشده و سفارش بسته شده است

وضعیت تلاش پرداخت

وضعیتمعنی
PENDINGخرید باز شده ولی مشتری هنوز پرداخت نکرده است
PAIDپرداخت انجام شده و منتظر تأیید پذیرنده است
VERIFY_OKپرداخت تأیید شده است
VERIFY_FAILEDتأیید با مبلغ نادرست انجام شده و پرداخت باطل شده است
VERIFY_TIMEOUTمهلت تأیید گذشته و مبلغ به مشتری بازگردانده شده است
CANCELEDپرداخت انجام‌نشده پس از انقضا لغو شده است
USER_CANCELEDلغو توسط مشتری

سفارش‌های این جریان همیشه channel = IN_PERSON دارند و در پنل پذیرنده در بخش سفارش‌های حضوری نمایش داده می‌شوند.


قواعد اعتبارسنجی و محدودیت‌ها

قواعدی که API اعمال می‌کند

قاعدهخطا در صورت نقض
amount باید بزرگ‌تر از صفر باشدORDER_AMOUNT_NOT_POSITIVE
amount باید با اقلام، خدمات و تخفیف هم‌خوان باشدINVALID_ORDER_AMOUNT
کالاهای تکراری (همان ID کالا + همان تنوع) در یک request نباشندDUPLICATE_ORDER_ITEM
سرویس باید متعلق به پذیرنده و فعال باشدSERVICE_NOT_OFFERED_BY_MERCHANT
مبلغ تأیید باید با مبلغ پرداخت‌شده برابر باشدORDER_AMOUNT_NOT_MATCHED
سفارش باید متعلق به همین پذیرنده باشدORDER_MERCHANT_NOT_MATCHED
سفارش باید پرداخت انجام‌شده داشته باشدORDER_ATTEMPT_NOT_PAID

محدودیت‌های زمانی

موردمقدار
اعتبار خرید ساخته‌شده۵ دقیقه
مهلت تأیید پرداخت۳۰ دقیقه پس از ایجاد تلاش پرداخت

قواعد اعتبارسنجی

در صورت رعایت نشدن هر یک از این موارد، request رد می‌شود:

  • shipments ارسال شده باشد.
  • مبلغ نهایی با اقلام، shipping_fee مرسوله‌ها، خدمات و تخفیف برابر و بزرگ‌تر از صفر باشد.
  • قیمت هر قلم و مبلغ هر خدمت بزرگ‌تر از صفر باشد.
  • تعداد هر قلم عدد صحیح و حداقل ۱ باشد.
  • shipping_fee و تخفیف منفی نباشد.
  • یک کالا با ID و تنوع یکسان بیش از یک‌بار نیامده باشد.
  • طول فیلدهای متنی از حداکثر مجاز بیشتر نباشد.

external_order_id هنگام ساخت خرید برای یکتا بودن بررسی نمی‌شود. اثر آن در لحظهٔ باز کردن خرید است: اگر این مقدار به سفارشی پرداخت‌شده تعلق داشته باشد، خرید باز نمی‌شود و اگر به سفارشی پرداخت‌نشده تعلق داشته باشد، پرداخت به همان سفارش قبلی وصل می‌شود و draft_id جدید سفارش تازه‌ای نخواهد ساخت. اگر سفارش پرداخت‌نشده متعلق به مشتری دیگری باشد، خرید باز نمی‌شود.


فهرست خطاها

اگر request با خطا مواجه شود، response آن کدی غیر از ۲xx دارد و success در آن false است. کد خطا در فیلد error.code و متن قابل نمایش در error.message برگردانده می‌شود. ساختار کامل خطا در بخش مقدمه آمده است. خطاهای مشترک همهٔ endpoint‌ها (VALIDATION_ERROR، FINANCIAL_OPERATIONS_FROZEN و نبود header Authorization) در همان بخش آمده‌اند.

ساخت خرید حضوری

POST/gateway/order/draft/request
کد خطاHTTPتوضیح و اقدام پیشنهادی
MERCHANT_APP_TOKEN_EXPIRED_OR_INVALID401token اپلیکیشن پذیرنده نامعتبر یا منقضی است؛ token تازه باید دریافت شود.
MERCHANT_APP_IP_ADDRESS_NOT_ALLOWED403آی‌پی request در لیست سفید اپلیکیشن پذیرنده نیست.
VALIDATION_ERROR422ساختار request نامعتبر است؛ برای مثال ارسال نکردن shipments، قیمت یا مبلغ خدمت صفر یا منفی، تعداد کمتر از ۱، یا shipping_fee یا تخفیف منفی.
SERVICE_NOT_OFFERED_BY_MERCHANT400service_id متعلق به پذیرنده نیست یا غیرفعال است.
ORDER_AMOUNT_NOT_POSITIVE400مبلغ نهایی صفر یا منفی است؛ معمولاً تخفیف بیش از حد.
DUPLICATE_ORDER_ITEM400یک کالا با همان ID و همان تنوع بیش از یک‌بار در shipments آمده.
INVALID_ORDER_AMOUNT400amount با اقلام، خدمات و تخفیف هم‌خوان نیست؛ محاسبه باید اصلاح شود.
نمونه پاسخ
{
  "success": false,
  "error": {
    "code": "SERVICE_NOT_OFFERED_BY_MERCHANT",
    "message": "برای این پذیرنده، سرویس مورد نظر وجود ندارد.",
    "details": null
  }
}

تأیید پرداخت

POST/gateway/order/payment/verify
کد خطاHTTPتوضیح و اقدام پیشنهادی
HTTP_EXCEPTION401header Authorization ارسال نشده یا token اپلیکیشن پذیرنده نامعتبر یا منقضی است. message در این حالت Unauthorized است. یک‌بار token تازه باید دریافت و request تکرار شود.
VALIDATION_ERROR422order_id یا amount ارسال نشده، order_id قالب UUID ندارد، یا order_id و authority با هم ارسال شده‌اند.
ORDER_NOT_FOUND404سفارشی با این ID وجود ندارد؛ مشتری هنوز خرید را باز نکرده یا خرید منقضی شده است.
ORDER_MERCHANT_NOT_MATCHED400سفارش متعلق به پذیرندهٔ دیگری است؛ پرداخت تغییری نمی‌کند.
ORDER_ATTEMPT_NOT_PAID400پرداختی برای تأیید وجود ندارد؛ تأیید باید پس از انجام پرداخت توسط مشتری انجام شود.
ORDER_ALREADY_PAID400این سفارش قبلاً تأیید شده است؛ تأیید دوباره لازم نیست.
ORDER_AMOUNT_NOT_MATCHED400مبلغ سفارش با مبلغ پرداخت‌شده برابر نیست و پرداخت باطل شده است.
نمونه پاسخ
{
  "success": false,
  "error": {
    "code": "ORDER_ATTEMPT_NOT_PAID",
    "message": "برای این سفارش پرداختی انجام نشده است.",
    "details": null
  }
}

سایر خطاهای token اپلیکیشن پذیرنده در مستندات ارتباط پذیرندگان آمده است.


چک‌لیست پیاده‌سازی

  • دریافت token اپلیکیشن پذیرنده و مدیریت انقضای آن
  • نگهداری service_id سرویس فعال پذیرنده در تنظیمات سیستم فروشگاهی
  • تولید external_order_id یکتا برای هر سفارش
  • ساخت اقلام، خدمات و تخفیف و محاسبهٔ amount طبق قاعدهٔ مبلغ
  • اعتبارسنجی مقادیر پیش از ارسال (تعداد، قیمت، تخفیف)
  • فراخوانی POST /gateway/order/draft/request
  • ذخیرهٔ draft_id و expires_at از response
  • نمایش QR (از draft_url)، کد پیگیری و مبلغ به مشتری
  • نمایش زمان باقی‌مانده و ساخت خرید جدید پس از انقضای ۵ دقیقه‌ای
  • فراخوانی POST /gateway/order/payment/verify با draft_id به عنوان order_id و مبلغ دقیق
  • ذخیرهٔ ref_id و نمایش نتیجهٔ نهایی به مشتری
  • مدیریت خطاهای تأیید (ORDER_NOT_FOUND، ORDER_ATTEMPT_NOT_PAID، ORDER_AMOUNT_NOT_MATCHED، ORDER_ALREADY_PAID)
  • رعایت مهلت ۳۰ دقیقه‌ای تأیید و مدیریت VERIFY_TIMEOUT

در این صفحه