{"openapi":"3.1.0","info":{"title":"درگاه پرداخت ارز دیجیتال نِت اَرز — API مرچنت","version":"1.0.0","description":"درگاه واسطِ ارز دیجیتال نِت اَرز به فروشگاه شما اجازه می‌دهد از مشتریانش **تتر (USDT)** روی شبکه‌های **TRON (TRC20)، اتریوم (ERC20) و بایننس (BEP20)** دریافت کند. مبلغ پس از تایید روی زنجیره، معادلِ تومانی (منهای کمیسیون پرداخت) به **کیف پول نِت اَرز** شما واریز می‌شود و هر زمان بخواهید می‌توانید درخواست **تسویه** به کیف پول شخصی‌تان بدهید.\n\n## ۱) دریافت کلیدها\nاز پنل کاربری ← **درگاه واسط** حساب مرچنت را فعال کنید. دو مقدار دریافت می‌کنید:\n- `sk_live_…` — **رمز API** (محرمانه، فقط سمت سرور). در هدر `Authorization: Bearer sk_live_…` ارسال می‌شود.\n- `whsec_…` — **راز امضای وبهوک** برای تایید صحّتِ رویدادهای دریافتی.\n\n> رمزها فقط یک‌بار نمایش داده می‌شوند؛ آن‌ها را امن نگه دارید. در صورت لو رفتن، از پنل «چرخش کلید» بزنید.\n\n## ۲) جریان پرداخت\n1. با `POST /charges` یک فاکتور بسازید (مبلغ به تومان یا تتر + `order_id` خودتان).\n2. مشتری را به `hosted_url` (صفحهٔ پرداختِ میزبانیِ نِت اَرز) هدایت کنید؛ آنجا آدرس/QR/مبلغ و انتخاب شبکه را می‌بیند.\n3. پس از پرداخت و تایید شبکه، نِت اَرز رویداد `charge.confirmed` را به `webhook_url` شما می‌فرستد و معادل تومانی را به کیف پولتان واریز می‌کند.\n4. مشتری به `success_url` شما بازگردانده می‌شود. **همیشه** پرداخت را با وبهوک یا `GET /charges/{id}` تایید کنید، نه صرفاً با بازگشت به `success_url`.\n\n## ۳) احراز هویت\nهمهٔ درخواست‌ها باید هدر زیر را داشته باشند:\n```\nAuthorization: Bearer sk_live_XXXXXXXXXXXXXXXX\n```\n\n## ۴) وبهوک‌ها و تایید امضا\nهر رویداد با `POST` به `webhook_url` شما ارسال می‌شود و شامل این هدرهاست:\n- `X-NetArz-Event` — نوع رویداد (مثل `charge.confirmed`)\n- `X-NetArz-Delivery` — شناسهٔ یکتای تحویل (برای idempotency)\n- `X-NetArz-Signature` — امضا به‌فرم `t=<timestamp>,v1=<hmac_sha256>`\n\nامضا با `HMAC-SHA256` روی رشتهٔ `\"{timestamp}.{raw_body}\"` و با کلید `whsec_…` محاسبه می‌شود. **بدنهٔ خام** (raw) را قبل از هر پردازشی امضا بسنجید:\n\n```php\n<?php\n// تایید امضای وبهوک (PHP)\n$payload   = file_get_contents('php://input');\n$header    = $_SERVER['HTTP_X_NETARZ_SIGNATURE'] ?? '';   // \"t=1700000000,v1=abcdef…\"\n$secret    = getenv('NETARZ_WEBHOOK_SECRET');              // whsec_…\n\nparse_str(str_replace(',', '&', $header), $parts);\n$expected  = hash_hmac('sha256', $parts['t'] . '.' . $payload, $secret);\n\nif (! hash_equals($expected, $parts['v1'] ?? '')) {\n    http_response_code(400); exit('bad signature');\n}\n// اختیاری: رد رویدادهای قدیمی‌تر از ۵ دقیقه (ضدِ replay)\nif (abs(time() - (int) $parts['t']) > 300) { http_response_code(400); exit('stale'); }\n\n$event = json_decode($payload, true);\n// $event['event'] === 'charge.confirmed' → سفارش را تحویل بده\nhttp_response_code(200); echo 'ok';\n```\n\n```javascript\n// تایید امضای وبهوک (Node.js / Express با bodyParser.raw)\nconst crypto = require('crypto');\napp.post('/netarz/webhook', bodyParser.raw({ type: '*/*' }), (req, res) => {\n  const header = req.get('X-NetArz-Signature') || '';           // t=…,v1=…\n  const parts  = Object.fromEntries(header.split(',').map(p => p.split('=')));\n  const body   = req.body.toString('utf8');\n  const expected = crypto.createHmac('sha256', process.env.NETARZ_WEBHOOK_SECRET)\n                         .update(`${parts.t}.${body}`).digest('hex');\n  if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1 || ''))) {\n    return res.status(400).send('bad signature');\n  }\n  const event = JSON.parse(body);\n  // event.event === 'charge.confirmed' → سفارش را تحویل بده\n  res.sendStatus(200);\n});\n```\n\n```python\n# تایید امضای وبهوک (Python / Flask)\nimport hmac, hashlib, time\nfrom flask import request, abort\n\ndef verify():\n    header = request.headers.get('X-NetArz-Signature', '')\n    parts  = dict(p.split('=') for p in header.split(','))\n    body   = request.get_data(as_text=True)\n    expected = hmac.new(SECRET.encode(), f\"{parts['t']}.{body}\".encode(), hashlib.sha256).hexdigest()\n    if not hmac.compare_digest(expected, parts.get('v1', '')):\n        abort(400)\n    if abs(time.time() - int(parts['t'])) > 300:\n        abort(400)\n    return request.get_json()\n```\n\nسرور شما باید در کمتر از ۱۵ ثانیه کد `2xx` برگرداند؛ در غیر این صورت با backoff نمایی (تا ۸ بار) دوباره تلاش می‌شود. رویدادها ممکن است بیش از یک‌بار ارسال شوند — با `X-NetArz-Delivery` آن‌ها را idempotent پردازش کنید.\n\n**رویدادها:** `charge.created` · `charge.pending` · `charge.confirmed` · `charge.underpaid` · `charge.canceled` · `settlement.paid`\n\n## ۵) کم‌پرداخت / اضافه‌پرداخت\nمبلغِ هر فاکتور یکتاست (با دلتای کوچک) تا تشخیص خودکار شود. اگر مشتری کمتر بفرستد، رویداد `charge.underpaid` ارسال و همان مقدارِ دریافتی واریز می‌شود؛ اگر بیشتر، مقدار واقعی واریز می‌گردد.\n\n## ۶) کدهای خطا\n- `401` رمز API نامعتبر/ارسال‌نشده\n- `403` حساب معلق یا غیرفعال\n- `422` خطای اعتبارسنجی/قوانین کسب‌وکار (مثلاً موجودی ناکافی برای برداشت)\n- `429` عبور از محدودیت نرخ (۳۰۰ درخواست در دقیقه)\n- `404` منبع یافت نشد\n\nپاسخِ خطا همیشه `{ \"message\": \"...\" }` است.","contact":{"name":"پشتیبانی نِت اَرز","url":"https://netarz.ir"}},"servers":[{"url":"https://netarz.ir/api/v1/gateway","description":"سرور اصلی"}],"security":[{"merchantSecret":[]}],"tags":[{"name":"فاکتورها","description":"ساخت و پیگیری درخواست‌های پرداخت"},{"name":"برداشت","description":"درخواست تسویه به کیف پول شخصی"},{"name":"حساب","description":"موجودی، کمیسیون و شبکه‌ها"}],"components":{"securitySchemes":{"merchantSecret":{"type":"http","scheme":"bearer","description":"رمز API مرچنت (`sk_live_…`) از پنل کاربری ← درگاه واسط."}},"schemas":{"PaymentOption":{"type":"object","properties":{"network":{"type":"string","enum":["trc20","erc20","bep20"],"example":"trc20"},"network_label":{"type":"string","example":"ترون (TRC20)"},"chain":{"type":"string","example":"TRON"},"asset":{"type":"string","example":"USDT"},"address":{"type":"string","example":"TXYZ…"},"amount":{"type":"string","description":"مبلغِ دقیقِ قابل‌پرداخت (USDT)","example":"12.07"}}},"Charge":{"type":"object","properties":{"id":{"type":"string","example":"a1b2c3d4-…"},"status":{"type":"string","enum":["new","pending","underpaid","overpaid","confirmed","completed","expired","canceled"],"example":"new"},"status_label":{"type":"string","example":"در انتظار پرداخت"},"amount_toman":{"type":"integer","example":2185000},"amount_usdt":{"type":"string","example":"12"},"usd_rate":{"type":"integer","example":190000},"asset":{"type":"string","example":"USDT"},"hosted_url":{"type":"string","example":"https://netarz.ir/pay/a1b2c3d4-…"},"expires_at":{"type":"string","format":"date-time"},"merchant_order_id":{"type":"string","nullable":true,"example":"ORDER-1024"},"payment_options":{"type":"array","items":{"$ref":"#/components/schemas/PaymentOption"}},"payment":{"type":"object","nullable":true,"description":"پس از تایید پر می‌شود","properties":{"network":{"type":"string"},"tx_hash":{"type":"string"},"explorer_url":{"type":"string"},"confirmations":{"type":"integer"},"received_usdt":{"type":"string"},"received_toman":{"type":"integer"},"commission_toman":{"type":"integer"},"net_toman":{"type":"integer","description":"واریزی خالص به کیف پول"}}},"created_at":{"type":"string","format":"date-time"}}},"Withdrawal":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["pending","approved","processing","paid","rejected"]},"status_label":{"type":"string"},"network":{"type":"string","example":"trc20"},"destination_address":{"type":"string"},"amount_toman":{"type":"integer","description":"مبلغ ناخالصِ کسرشده از کیف پول"},"commission_toman":{"type":"integer"},"net_toman":{"type":"integer"},"amount_usdt":{"type":"string","description":"مقدار USDT ارسالی"},"tx_hash":{"type":"string","nullable":true},"paid_at":{"type":"string","format":"date-time","nullable":true}}},"Error":{"type":"object","properties":{"message":{"type":"string","example":"کلید API نامعتبر است."}}}}},"paths":{"/charges":{"post":{"tags":["فاکتورها"],"summary":"ساخت فاکتور","description":"یک درخواست پرداخت جدید می‌سازد و `hosted_url` و آدرس‌های پرداخت را برمی‌گرداند.","x-codeSamples":[{"lang":"cURL","source":"curl -X POST https://netarz.ir/api/v1/gateway/charges \\\n  -H 'Authorization: Bearer sk_live_XXX' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"amount\": 500000, \"currency\": \"toman\", \"order_id\": \"ORDER-1024\", \"success_url\": \"https://shop.example/thanks\"}'"},{"lang":"PHP","source":"$res = Http::withToken('sk_live_XXX')->post('https://netarz.ir/api/v1/gateway/charges', [\n    'amount' => 500000, 'currency' => 'toman', 'order_id' => 'ORDER-1024',\n    'success_url' => 'https://shop.example/thanks',\n]);\n$hostedUrl = $res['data']['hosted_url'];"},{"lang":"JavaScript","source":"const r = await fetch('https://netarz.ir/api/v1/gateway/charges', {\n  method: 'POST',\n  headers: { Authorization: 'Bearer sk_live_XXX', 'Content-Type': 'application/json' },\n  body: JSON.stringify({ amount: 500000, currency: 'toman', order_id: 'ORDER-1024' }),\n});\nconst { data } = await r.json();\nwindow.location = data.hosted_url;"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["amount"],"properties":{"amount":{"type":"number","example":500000},"currency":{"type":"string","enum":["toman","usdt"],"default":"toman"},"network":{"type":"string","enum":["trc20","erc20","bep20"],"description":"اختیاری — محدودکردن به یک شبکه"},"networks":{"type":"array","items":{"type":"string"},"description":"اختیاری — زیرمجموعهٔ شبکه‌های مجاز"},"order_id":{"type":"string","example":"ORDER-1024"},"description":{"type":"string"},"customer_email":{"type":"string","format":"email"},"success_url":{"type":"string","format":"uri"},"cancel_url":{"type":"string","format":"uri"},"metadata":{"type":"object","additionalProperties":true}}}}}},"responses":{"201":{"description":"ساخته شد","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Charge"}}}}}},"422":{"description":"خطای اعتبارسنجی","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"tags":["فاکتورها"],"summary":"فهرست فاکتورها","parameters":[{"name":"status","in":"query","schema":{"type":"string"}},{"name":"per_page","in":"query","schema":{"type":"integer","default":25}}],"responses":{"200":{"description":"موفق","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Charge"}}}}}}}}}},"/charges/{id}":{"get":{"tags":["فاکتورها"],"summary":"وضعیت فاکتور","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"موفق","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Charge"}}}}}},"404":{"description":"یافت نشد","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/charges/{id}/cancel":{"post":{"tags":["فاکتورها"],"summary":"لغو فاکتور","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"لغو شد","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Charge"}}}}}}}}},"/withdrawals":{"post":{"tags":["برداشت"],"summary":"درخواست تسویه","description":"برداشت از موجودی کیف پول به یک آدرسِ **از پیش‌تاییدشده** (whitelist). افزودن آدرس فقط از پنل کاربری ممکن است.","x-codeSamples":[{"lang":"cURL","source":"curl -X POST https://netarz.ir/api/v1/gateway/withdrawals \\\n  -H 'Authorization: Bearer sk_live_XXX' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"network\": \"trc20\", \"address\": \"TXYZ…\", \"amount_toman\": 5000000}'"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["network","address","amount_toman"],"properties":{"network":{"type":"string","enum":["trc20","erc20","bep20"]},"address":{"type":"string"},"amount_toman":{"type":"integer","example":5000000}}}}}},"responses":{"201":{"description":"ثبت شد","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Withdrawal"}}}}}},"422":{"description":"خطا (موجودی ناکافی / آدرس تاییدنشده)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"tags":["برداشت"],"summary":"فهرست برداشت‌ها","responses":{"200":{"description":"موفق","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Withdrawal"}}}}}}}}}},"/withdrawals/{id}":{"get":{"tags":["برداشت"],"summary":"وضعیت برداشت","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"موفق","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Withdrawal"}}}}}}}}},"/account":{"get":{"tags":["حساب"],"summary":"اطلاعات حساب و موجودی","responses":{"200":{"description":"موفق","content":{"application/json":{"example":{"data":{"id":"pk_live_XXX","name":"فروشگاه من","status":"active","balance_toman":12500000,"commission":{"payment_percent":1.5,"withdrawal_percent":1},"available_networks":[{"network":"trc20","label":"ترون (TRC20)"}]}}}}}}}},"/networks":{"get":{"tags":["حساب"],"summary":"شبکه‌های فعال","responses":{"200":{"description":"موفق","content":{"application/json":{"example":{"data":{"networks":[{"network":"trc20","label":"ترون (TRC20)","chain":"TRON","asset":"USDT","confirmations_required":20}],"asset":"USDT","min_charge_toman":50000,"charge_ttl_minutes":30}}}}}}}}},"webhooks":{"charge":{"post":{"summary":"رویدادهای فاکتور (charge.*) و تسویه (settlement.paid)","description":"به `webhook_url` شما ارسال می‌شود. امضا در هدر `X-NetArz-Signature` است.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"evt_a1b2c3d4-…"},"event":{"type":"string","example":"charge.confirmed"},"created":{"type":"integer","example":1700000000},"data":{"$ref":"#/components/schemas/Charge"}}}}}},"responses":{"200":{"description":"دریافت شد"}}}}}}