راهنمای اتصال نمایندگان (API)

آدرس پایه: https://pay.tomanpay.online

شروع سریع

  1. در ربات، از منوی 🔑 کلید API یک کلید بسازید. کلید فقط یک‌بار نمایش داده می‌شود؛ آن را امن ذخیره کنید.
  2. از منوی ⚙️ تنظیمات وب‌هوک:
  3. آدرس وب‌هوک را تنظیم کنید.
  4. کلید امضا را دریافت کنید.
  5. در صورت تمایل، دامنه‌های مجاز بازگشت را تعیین کنید.
  6. در سایت خود:
  7. با request پرداخت بسازید و کاربر را به payment_url بفرستید.
  8. پس از بازگشت کاربر، امضا را بررسی کنید یا با inquiry وضعیت را بپرسید.
curl -X POST https://pay.tomanpay.online/v1/payments/request   -H "Authorization: Bearer tp_xxxxxxxxxxxx_xxxxxxxx"   -H "Content-Type: application/json"   -d '{"amount": 250000, "callback_url": "https://shop.com/payment/return", "order_id": "1001"}'

قواعد کلی

همه درخواست‌ها POST با بدنه JSON هستند و هدر زیر را لازم دارند:

Authorization: Bearer <کلید API شما>

محدودیت: ۶۰ درخواست در دقیقه برای هر کلید API (خطای 60، با هدر Retry-After).

همه پاسخ‌ها با کد HTTP 200 برمی‌گردند. موفقیت: "status": "success"؛ خطا: {"status": "error", "error_code": "..", "error_message": ".."}. مشخصات OpenAPI (برای Postman و ابزارهای مشابه): https://pay.tomanpay.online/openapi.json

ایجاد پرداخت — POST /v1/payments/request

فیلد نوع توضیح
amount عدد صحیح (تومان) حداقل ۱۰٬۰۰۰ (یا حداقل تعیین‌شده برای شما)، حداکثر ۵۰۰٬۰۰۰٬۰۰۰
callback_url رشته آدرس http(s) که کاربر پس از پرداخت به آن هدایت می‌شود
description رشته، اختیاری حداکثر ۲۵۵ کاراکتر
order_id رشته، اختیاری شناسه سفارش خودتان؛ در بازگشت به شما برگردانده می‌شود
customer_fee_percent عدد ۰ تا ۱۰۰، اختیاری چند درصد از کارمزد به مبلغ مشتری اضافه شود. اگر ارسال نشود، از تنظیم پیش‌فرض شما در ربات («⚙️ تنظیمات» ← «💳 سهم مشتری از کارمزد») استفاده می‌شود.

پاسخ: {"status": "success", "payment_id": "...", "payment_url": "...", "amount": 100000, "paid_amount": 120000, "customer_fee": 20000}

مثال با کارمزد ۲۰٪: اگر سهم مشتری ۱۰۰٪ باشد، مشتری ۱۲۰٬۰۰۰ می‌پردازد و ۱۰۰٬۰۰۰ به موجودی شما اضافه می‌شود. اگر ۰٪ باشد، مشتری ۱۰۰٬۰۰۰ می‌پردازد و ۸۰٬۰۰۰ به شما می‌رسد. کاربر را به payment_url هدایت کنید.

مسیر پرداخت مشتری

  1. payment_url صفحه‌ی پیش از پرداخت تومن‌پی است (https://pay.tomanpay.online/p/<payment_id>): نام نمایشی و لوگوی شما (پس از تأیید مدیریت)، مبلغ و جزئیات کارمزد، توضیحات و زمان باقی‌مانده تا انقضای لینک.
  2. با زدن دکمه‌ی «پرداخت»، فاکتور درگاه ساخته می‌شود و مشتری به صفحه‌ی درگاه (FastPay) برای وارد کردن اطلاعات کارت منتقل می‌شود. رفرش صفحه یا چند بار زدن دکمه، فاکتور تکراری نمی‌سازد.
  3. پس از پرداخت، وضعیت با استعلام از درگاه تأیید و رسید تومن‌پی به مشتری نمایش داده می‌شود:
  4. موفق: دکمه‌ی «بازگشت به فروشگاه» و بازگشت خودکار به callback_url شما پس از ۵ ثانیه، با پارامترهای امضاشده.
  5. ناموفق / لغو / منقضی: دلیل به فارسی و دکمه‌ی «بازگشت به فروشگاه» (بدون بازگشت خودکار).
  6. اگر callback_url نفرستاده باشید (لینک پرداخت بدون سایت)، فقط رسید نمایش داده می‌شود.

تا وقتی مشتری «پرداخت» را نزده، وضعیت پرداخت در استعلام pending است. لینک‌هایی که تا مهلتشان باز نشوند expired می‌شوند. خطاهای موقت درگاه (مثل تکمیل ظرفیت) به‌جای پاسخ API شما، در همان صفحه به مشتری نمایش داده می‌شوند تا دوباره تلاش کند.

استعلام — POST /v1/payments/inquiry

بدنه: {"payment_id": "..."} پاسخ: payment_status یکی از pending، paid، canceled، failed، expired به‌همراه amount، paid_amount، customer_fee و amount، order_id، tracking_number، created_at، paid_at.

فقط وضعیت paid یعنی پول دریافت شده است. قبل از تحویل سفارش همیشه یا امضا را بررسی کنید یا استعلام بگیرید.

بازگشت کاربر به callback_url

کاربر (از روی رسید تومن‌پی) با GET و این پارامترها به آدرس شما هدایت می‌شود: payment_id، status، amount، paid_amount، order_id، tracking_number، signature

بررسی امضا

signature = HMAC-SHA256 با «کلید وب‌هوک» شما (از منوی ربات) روی رشته زیر، به‌صورت hex: همه پارامترهای بالا به‌جز signature، مرتب‌شده بر اساس نام، به شکل name=value و با & به هم وصل شده. مثال:

amount=100000&order_id=ord-1&paid_amount=120000&payment_id=5f0c...&status=paid&tracking_number=123456

PHP:

$p = $_GET;
$sig = $p['signature'];
$keys = ['amount', 'order_id', 'paid_amount', 'payment_id', 'status', 'tracking_number'];
$parts = [];
foreach ($keys as $k) { $parts[] = $k . '=' . ($p[$k] ?? ''); }
$expected = hash_hmac('sha256', implode('&', $parts), $WEBHOOK_SECRET);
if (!hash_equals($expected, $sig)) { http_response_code(400); exit('bad signature'); }
if ($p['status'] === 'paid') { /* مبلغ و order_id را با سفارش خود مقایسه و سفارش را تأیید کنید */ }

Python:

import hmac, hashlib
keys = ["amount", "order_id", "paid_amount", "payment_id", "status", "tracking_number"]
msg = "&".join(f"{k}={params.get(k, '')}" for k in keys)
expected = hmac.new(secret.encode(), msg.encode(), hashlib.sha256).hexdigest()
ok = hmac.compare_digest(expected, params["signature"])

علاوه بر امضا، amount و order_id را با سفارش خود مقایسه کنید و هر payment_id را فقط یک‌بار تحویل دهید.

کدهای خطا

کد معنی
10 کلید API نامعتبر یا ارسال‌نشده
11 حساب نماینده فعال نیست
12 حساب نماینده هنوز تنظیم نشده
20 خطای اعتبارسنجی ورودی
21 مبلغ نامعتبر (کمتر از حداقل یا بیشتر از حداکثر)
22 callback_url نامعتبر یا خارج از دامنه‌های مجاز
30 سقف تعداد درخواست روزانه
31 سقف مبلغ روزانه
40 پرداخت یافت نشد
50 سرویس موقتاً در دسترس نیست — کمی بعد دوباره تلاش کنید
51 ایجاد پرداخت ممکن نشد
60 تعداد درخواست بیش از حد مجاز
99 خطای داخلی

وب‌هوک سرور-به-سرور

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

PHP:

$raw = file_get_contents('php://input');
$sig = [];
foreach (explode(',', $_SERVER['HTTP_X_TOMANPAY_SIGNATURE'] ?? '') as $part) {
    [$k, $v] = array_pad(explode('=', $part, 2), 2, '');
    $sig[$k] = $v;
}
$expected = hash_hmac('sha256', ($sig['t'] ?? '') . '.' . $raw, $WEBHOOK_SECRET);
if (!hash_equals($expected, $sig['v1'] ?? '') || abs(time() - (int)($sig['t'] ?? 0)) > 300) {
    http_response_code(400); exit;
}
$event = json_decode($raw, true);
// سفارش را با $event['payment_id'] پیدا کنید، مبلغ را بررسی و فقط یک‌بار تحویل دهید
http_response_code(200);