API عمومی واریزت،
بدون ثبتنام و بدون پلن پولی.
یک درخواست برای ساخت سفارش، یک وبهوک امضاشده برای تایید. با کلید تست، همه سناریوها را در Sandbox و بدون پول واقعی امتحان کنید.
# create an order with a unique amount
curl -X POST https://api.varizet.ir/v1/orders \
-H "Authorization: Bearer vz_test_4eC39HqLyjWDarjt" \
-H "Idempotency-Key: ketabnama-order-12345" \
-H "Content-Type: application/json" \
-d '{
"amount": 8500000,
"merchant_order_id": "INV-12345",
"unique_mode": "increase",
"customer": { "phone": "09121234567" },
"return_url": "https://ketabnama.ir/checkout/thanks?o=12345"
}'
# 201 Created
{
"id": "ord_01JBX4Q8M6",
"code": "VZ-8K2Q",
"status": "awaiting_payment",
"unique_amount": 8500430,
"expires_at": "2026-10-28T11:02:00Z",
"payment_url": "https://pay.varizet.ir/p/kJ8s2QaX7mZr4TnB"
}شروع سریع
اولین سفارش را در پنج دقیقه بسازید. همه نمونهها با کلید تست اجرا میشوند و هیچ پول واقعی جابهجا نمیشود.
- ۱
کلید تست بگیرید
رایگان ثبتنام کنید؛ کلیدvz_test_…بلافاصله در پنل، بخش کلیدهای API آماده است. کلید را فقط سمت سرور نگه دارید. - ۲
سفارش با مبلغ یکتا بسازید
مبلغ را به ریال و یک
Idempotency-Keyیکتا بفرستید. پاسخ شاملunique_amountوpayment_urlاست.curl https://api.varizet.ir/v1/orders \ -H "Authorization: Bearer vz_test_4eC39HqLyjWDarjt" \ -H "Idempotency-Key: 5c1f0d7e-order-12345" \ -H "Content-Type: application/json" \ -d '{"amount": 8500000, "merchant_order_id": "INV-12345"}'// Node.js 18+ (built-in fetch); or: npm i @varizet/node const res = await fetch('https://api.varizet.ir/v1/orders', { method: 'POST', headers: { Authorization: `Bearer ${process.env.VARIZET_SECRET_KEY}`, 'Idempotency-Key': `order-${order.id}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ amount: 8500000, // integer rial merchant_order_id: order.id, return_url: 'https://ketabnama.ir/checkout/thanks', }), }); const payment = await res.json(); // send the customer to payment.payment_url<?php // PHP 8.1+ with ext-curl; or: composer require varizet/varizet-php $ch = curl_init('https://api.varizet.ir/v1/orders'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . getenv('VARIZET_SECRET_KEY'), 'Idempotency-Key: order-' . $order->id, 'Content-Type: application/json', ], CURLOPT_POSTFIELDS => json_encode([ 'amount' => 8500000, // integer rial 'merchant_order_id' => (string) $order->id, 'return_url' => 'https://ketabnama.ir/checkout/thanks', ]), ]); $payment = json_decode(curl_exec($ch), true); // redirect the customer to $payment['payment_url'] - ۳
مشتری را به صفحه پرداخت بفرستید
مشتری را بهpayment_urlهدایت کنید یا مبلغ یکتا و کارت مقصد را در صفحه خودتان نمایش دهید. پس از تایید، مشتری بهreturn_urlبرمیگردد. - ۴
وبهوک order.paid را تایید کنید
امضایVarizet-Signatureرا بررسی کنید و سفارش را پرداختشده علامت بزنید. جزئیات در بخش تایید امضا.
اصول API
API به سبک APIهای پرداخت شناختهشده طراحی شده است؛ اگر با یکی کار کرده باشید، این یکی هم آشناست.
- آدرس پایه
https://api.varizet.ir/v1- احراز هویت
Authorization: Bearer <key>با کلیدهایvz_live_…وvz_test_…- قالب
- JSON و UTF-8؛ زمانها ISO-8601 به UTC؛ مبالغ عدد صحیح ریال
- Idempotency
- هدر
Idempotency-Keyبرای همه POSTها، نگهداری ۲۴ ساعت؛ تکرار با بدنه متفاوت ←409 idempotency_mismatch - صفحهبندی
- Cursor:
?limit=50&starting_after=ord_…←{ data, has_more, next_cursor } - نسخه
- در مسیر (
/v1)؛ تغییرات جزئی با هدرVarizet-Version: 2026-10-01 - سقف درخواست
- رایگان ۶۰، رشد ۳۰۰، حرفهای ۱٬۲۰۰ در دقیقه؛ هدرهای
RateLimit-* - شناسهها
- پیشوندی:
ord_،plink_،cus_،dep_،ref_،whe_،evt_
وبهوکها
چند endpoint با رویدادهای دلخواه بسازید. هر تحویل امضا میشود، لاگ کامل دارد و از پنل یا API دوباره فرستاده میشود.
| رویداد | زمان ارسال |
|---|---|
order.created | ساخت سفارش |
order.paid | تایید پرداخت، خودکار یا دستی |
order.needs_review | ورود سفارش به صندوق بررسی |
order.underpaid | کمواریز؛ مابهالتفاوت با مبلغ یکتای جدید درخواست میشود |
order.expired | پایان مهلت تکمیلی بدون پرداخت |
order.canceled | لغو سفارش توسط فروشنده یا API |
refund.created | ثبت بازپرداخت |
deposit.unmatched | واریزی که به هیچ سفارشی نرسید |
device.offline | قطع شدن دستگاه یا کانال تشخیص |
device.online | برگشت دستگاه به حالت آنلاین |
card.cap_reached | رسیدن کارت مقصد به سقف روزانه |
# POST https://ketabnama.ir/webhooks/varizet
Varizet-Signature: t=1761647652,v1=5257a869e7ec…8bd
Content-Type: application/json
{
"id": "evt_01JBX5R2T9",
"type": "order.paid",
"created_at": "2026-10-28T10:34:12Z",
"livemode": true,
"data": {
"object": {
"id": "ord_01JBX4Q8M6",
"code": "VZ-8K2Q",
"status": "paid",
"unique_amount": 8500430,
"paid_amount": 8500430,
"merchant_order_id": "INV-12345",
"match": { "score": 98, "channel": "android_sms" }
}
}
}- پاسخ
2xxدر کمتر از ۱۰ ثانیه یعنی تحویل موفق. - تلاش مجدد نمایی، ۸ بار: ۱۰ ثانیه، ۱ دقیقه، ۵ دقیقه، ۳۰ دقیقه، ۲ ساعت، ۶ ساعت، ۱۲ ساعت، ۲۴ ساعت.
- اگر همه تحویلهای یک endpoint سه روز پیاپی شکست بخورد، غیرفعال و به شما اعلان میشود.
- ترتیب تضمین نمیشود؛ از
created_atوGET /v1/orders/{id}استفاده کنید.
تایید امضای وبهوک
هر درخواست هدر Varizet-Signature دارد: زمان ارسال و HMAC-SHA256 روی «زمان + نقطه + بدنه خام» با secret همان endpoint. امضا زماندار است تا درخواست قدیمی دوباره پخش نشود.
Varizet-Signature: t=1761647652,v1=5257a869e7…
signed_payload = t + "." + raw_body
expected = HMAC_SHA256(endpoint_secret, signed_payload) # hex
accept if constant_time_equal(expected, v1) and |now - t| <= 300simport crypto from 'node:crypto';
// rawBody: the exact request body string, before JSON.parse
export function verifyVarizetSignature(rawBody, header, secret) {
const parts = header.split(',').map((p) => p.trim().split('='));
const t = Number(parts.find(([k]) => k === 't')?.[1]);
// during secret rotation the header carries two v1 values
const signatures = parts.filter(([k]) => k === 'v1').map(([, v]) => v);
const expected = crypto
.createHmac('sha256', secret)
.update(`${t}.${rawBody}`)
.digest('hex');
const fresh = Math.abs(Date.now() / 1000 - t) <= 300;
return fresh && signatures.some((v1) =>
v1.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(expected)));
}<?php
// $payload = file_get_contents('php://input');
function varizet_verify(string $payload, string $header, string $secret): bool
{
$t = null;
$signatures = [];
foreach (explode(',', $header) as $part) {
[$k, $v] = array_map('trim', explode('=', $part, 2)) + [null, null];
if ($k === 't') { $t = (int) $v; }
if ($k === 'v1') { $signatures[] = $v; }
}
if ($t === null || abs(time() - $t) > 300) { return false; }
$expected = hash_hmac('sha256', $t . '.' . $payload, $secret);
foreach ($signatures as $v1) {
if (hash_equals($expected, $v1)) { return true; }
}
return false;
}امضا را روی بدنه دقیقاً همانطور که رسیده بسازید، پیش از parse کردن JSON.
درخواستی که t آن بیش از ۳۰۰ ثانیه با زمان سرور شما فاصله دارد رد شود.
تا ۲۴ ساعت پس از چرخش، هدر دو مقدار v1 دارد؛ پذیرش هر کدام کافی است.
Sandbox و تست
هر درخواستی با کلید vz_test_ در محیطی کاملاً جدا اجرا میشود: سفارش، لینک و وبهوک واقعی، با واریز شبیهسازیشده که از همان موتور تطبیق عبور میکند.
# test keys only: simulate a deposit for an awaiting order
curl -X POST https://api.varizet.ir/v1/test/deposits \
-H "Authorization: Bearer vz_test_4eC39HqLyjWDarjt" \
-H "Idempotency-Key: sim-12345-1" \
-H "Content-Type: application/json" \
-d '{"amount": 8500430, "payer_last4": "7890", "bank": "mellat"}'
# → matched to VZ-8K2Q, and order.paid is delivered to your endpointPOST /v1/test/depositsواریز را با مبلغ، بانک و ۴ رقم کارت دلخواه شبیهسازی میکند.POST /v1/test/orders/{id}/expireسفارش را فوراً منقضی میکند تا مسیر انقضا را تست کنید.- پاسخها
"livemode": falseدارند و در سقف تراکنش ماهانه حساب نمیشوند.
- ملت6104 3378 9012 4520
- سامان6219 8610 3452 9015
- ملی6037 9910 1234 5678
خطاها
همه خطاها یک قالب دارند؛ type برای دستهبندی، code برای منطق برنامه و message فارسی برای نمایش به کاربر.
{
"error": {
"type": "invalid_request",
"code": "amount_too_small",
"message": "حداقل مبلغ سفارش ۱۰٬۰۰۰ ریال است.",
"param": "amount",
"request_id": "req_01JBX4Q8M6"
}
}| HTTP | type | نمونه code |
|---|---|---|
| 400 | invalid_request | amount_too_small, invalid_phone, invalid_callback_url |
| 401 | authentication_error | invalid_api_key, key_revoked |
| 403 | permission_error | scope_missing, ip_not_allowed, plan_limit_reached |
| 404 | not_found | order_not_found |
| 409 | conflict | unique_amount_exhausted, idempotency_mismatch, order_not_cancelable |
| 422 | validation_error | merchant_order_id_duplicate |
| 429 | rate_limited | too_many_requests |
| 5xx | api_error | internal_error (با request_id به پشتیبانی بدهید) |
SDK و ابزارها
کلاینتهای رسمی تایید امضا و مدلهای تایپشده را آماده دارند. برای هر زبان دیگری، از مرجع OpenAPI کلاینت بسازید.
- موجود
Node.js SDK
TypeScript با تایپ کامل تولیدشده از OpenAPI و کمککننده وبهوک برای Express، Fastify و Next.js.
npm i @varizet/nodeشروع سریع - موجود
OpenAPI و Postman
مرجع ماشینی کامل API عمومی برای تولید کلاینت در هر زبان و مجموعه Postman آماده.
دریافت openapi.json - موجود
PHP SDK
کلاینت API، تایید امضای وبهوک و مدلهای تایپشده؛ هسته مشترک همه افزونههای PHP.
composer require varizet/varizet-phpنمونه کد PHP - موجود
لاراول
Facade، کانفیگ، مسیر وبهوک با Middleware امضا و رویدادهای لاراول مثل
OrderPaid.composer require varizet/laravelشروع سریع - موجود
Python SDK
کلاینت sync و async با کمککنندههای Django و FastAPI.
pip install varizetSDKها و ابزارها - موجود
Varizet CLI
وبهوکها را به لوکالهاست بیاورید، رویداد آزمایشی بسازید و واریز شبیهسازی کنید.
varizet listen --forward-to localhost:3000/webhooksSandbox و تست
varizet login
varizet listen --forward-to localhost:3000/webhooks
varizet trigger order.paid
varizet simulate deposit 8500430کلید تست را بگیرید و اولین سفارش را بسازید.
بدون پلن پولی و بدون کارت بانکی؛ Sandbox در پلن رایگان هم کامل است و API Live از پلن رشد فعال میشود.