NAV
cURL PHP Node.js Go Python C#

مقدمه

به API درگاه پرداخت ایران‌درگاه خوش آمدید! این API با استاندارد snake_case برای تمامی فیلدهای ورودی و خروجی، امکان ایجاد تراکنش‌های پرداخت آنلاین و تأیید آن‌ها را فراهم می‌کند.

شما می‌توانید از نمونه کدهای موجود در سمت چپ صفحه استفاده کنید. کدهای نمونه در زبان‌های مختلف برنامه‌نویسی ارائه شده‌اند!

ویژگی‌های جدید

احراز هویت

ایران درگاه برای احراز هویت از یک توکن واحد استفاده می‌کند که برای ترمینال شما صادر و در اختیار شما قرار می‌گیرد.

فرمت توکن

توکن‌ها با پیشوندِ بامعنی صادر می‌شوند تا محیط عملیاتی و آزمایشی از روی نگاه قابل تشخیص باشند:

پیشوند محیط
idg_live_... محیط عملیاتی (Production)
idg_test_... محیط آزمایشی (Sandbox)

پس از صدور، توکن شکل کلی idg_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx دارد (حدود ۵۰ کاراکتر).

ارسال توکن

توکن را به‌صورت مستقیم در هدر Authorization با پیشوند Bearer بفرستید:

curl "https://ipg.irandargah.com/v2/payments" \
  -H "Authorization: Bearer idg_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
<?php
$headers = [
    'Authorization: Bearer idg_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx',
    'Content-Type: application/json',
];
const headers = {
  Authorization: "Bearer idg_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "Content-Type": "application/json",
};
req.Header.Set("Authorization", "Bearer idg_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx")
req.Header.Set("Content-Type", "application/json")
headers = {
    'Authorization': 'Bearer idg_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx',
    'Content-Type':  'application/json',
}
client.DefaultRequestHeaders.Add("Authorization", "Bearer idg_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx");

دریافت توکن

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

  1. وارد پنل کاربری شوید
  2. به بخش «درگاه‌ها» بروید
  3. در صورت نیاز به توکن جدید، با پشتیبانی تماس بگیرید — توکن یک‌بار در پیام پاسخ ارسال می‌شود

چرخش توکن (Rotation)

زمانی که توکن چرخش پیدا می‌کند (rotation)، توکن قبلی به‌صورت خودکار به‌ مدت ۲۴ ساعت همچنان معتبر می‌ماند. این پنجره برای انتقال آرام بدون قطعی طراحی شده است:

لحظه حالت
T + 0 توکن جدید صادر می‌شود؛ توکن قدیمی هنوز معتبر است
T + [0, 24h) هر دو توکن کار می‌کنند؛ زمان مناسب برای انتقال تدریجی
T + 24h توکن قدیمی به‌طور کامل باطل می‌شود — فقط توکن جدید کار می‌کند

در طول این ۲۴ ساعت، هر درخواستی که با توکن قدیمی ارسال شود، در پاسخ خود این هدرهای هشدار را دریافت می‌کند:

هدر توضیح
X-Token-Deprecated مقدار true — یعنی این توکن در حال انقضاست
X-Token-Deprecated-Expires-At زمان دقیق انقضای توکن قدیمی (ISO 8601)

اگر در سرور خود این هدرها را رصد کنید، می‌توانید پیش از انقضا متوجه شوید کدام instance هنوز به توکن قدیمی متصل است.

ابطال اضطراری (Emergency Revoke)

اگر مشکوک شدید توکن لو رفته (مثلاً در GitHub commit کرده‌اید یا در گفتگوی Telegram دیده شده):

  1. وارد پنل کاربری شوید
  2. ترمینال موردنظر را باز کنید ← دکمه‌ی «مدیریت کلید امضا»
  3. در پایین صفحه، بخش قرمز «ناحیه‌ی خطر» ← دکمه‌ی «باطل کن — توکن لو رفته» را بزنید

پس از ابطال، با پشتیبانی تماس بگیرید تا توکن جدید برایتان صادر شود.

کلید Idempotency

دریافت کلید Idempotency

curl -X GET "https://ipg.irandargah.com/v2/idempotency-key"
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://ipg.irandargah.com/v2/idempotency-key");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);
$idempotencyKey = $result['idempotency_key'];
?>
fetch("https://ipg.irandargah.com/v2/idempotency-key")
  .then((response) => response.json())
  .then((data) => {
    const idempotencyKey = data.idempotency_key;
    console.log("Idempotency Key:", idempotencyKey);
  });
resp, err := http.Get("https://ipg.irandargah.com/v2/idempotency-key")
if err != nil {
    log.Fatal(err)
}
defer resp.Body.Close()

var result map[string]interface{}
json.NewDecoder(resp.Body).Decode(&result)
idempotencyKey := result["idempotency_key"].(string)
import requests

response = requests.get('https://ipg.irandargah.com/v2/idempotency-key')
data = response.json()
idempotency_key = data['idempotency_key']
using var client = new HttpClient();
var response = await client.GetAsync("https://ipg.irandargah.com/v2/idempotency-key");
var json = await response.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<dynamic>(json);
string idempotencyKey = result.idempotency_key;

پاسخ موفق:

{
  "success": true,
  "idempotency_key": "txn_1a2b3c4d5e6f7g8h9i0j",
  "expires_in": 86400,
  "usage": "Include this key in the Idempotency-Key header for your payment request"
}

این آدرس برای دریافت یک کلید منحصر به فرد Idempotency استفاده می‌شود که برای جلوگیری از تراکنش‌های تکراری ضروری است.

آدرس درخواست

GET
https://ipg.irandargah.com/v2/idempotency-key

پارامترهای پاسخ

پارامتر نوع توضیح
success boolean وضعیت موفقیت درخواست
idempotency_key string کلید منحصر به فرد با پیشوند txn_
expires_in integer مدت زمان اعتبار کلید به ثانیه (۸۶۴۰۰ = ۲۴ ساعت)
usage string راهنمای استفاده از کلید

فرآیند پرداخت

فرآیند پرداخت در ایران‌درگاه شامل مراحل زیر است:

  1. ایجاد تراکنش: درخواست پرداخت به آدرس /v2/payments ارسال می‌شود
  2. هدایت کاربر: کاربر با استفاده از authority دریافتی به صفحه پرداخت هدایت می‌شود
  3. پرداخت: کاربر عملیات پرداخت را در صفحه بانک انجام می‌دهد
  4. بازگشت: کاربر به callback_url شما برگردانده می‌شود
  5. تأیید: درخواست تأیید به آدرس /v2/verifications ارسال می‌شود

پرداخت

ایجاد تراکنش پرداخت

curl -X POST "https://ipg.irandargah.com/v2/payments" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: unique-key-123" \
  -d '{
    "amount": 100000,
    "order_id": "ORDER-12345",
    "callback_url": "https://merchant.com/callback",
    "description": "خرید محصول آزمایشی",
    "mobile": "09123456789"
  }'
<?php
$data = [
    'amount' => 100000,
    'order_id' => 'ORDER-12345',
    'callback_url' => 'https://merchant.com/callback',
    'description' => 'خرید محصول آزمایشی',
    'mobile' => '09123456789'
];

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://ipg.irandargah.com/v2/payments");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "Authorization: Bearer YOUR_API_TOKEN",
    "Content-Type: application/json",
    "Idempotency-Key: unique-key-123"
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

$result = json_decode($response, true);
?>
const payment = {
  amount: 100000,
  order_id: "ORDER-12345",
  callback_url: "https://merchant.com/callback",
  description: "خرید محصول آزمایشی",
  mobile: "09123456789",
};

const response = await fetch("https://ipg.irandargah.com/v2/payments", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_API_TOKEN",
    "Content-Type": "application/json",
    "Idempotency-Key": "unique-key-123",
  },
  body: JSON.stringify(payment),
});

const data = await response.json();
console.log(data);
package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "net/http"
)

type PaymentRequest struct {
    Amount      int    `json:"amount"`
    OrderID     string `json:"order_id"`
    CallbackURL string `json:"callback_url"`
    Description string `json:"description"`
    Mobile      string `json:"mobile"`
}

func main() {
    payment := PaymentRequest{
        Amount:      100000,
        OrderID:     "ORDER-12345",
        CallbackURL: "https://merchant.com/callback",
        Description: "خرید محصول آزمایشی",
        Mobile:      "09123456789",
    }

    jsonData, _ := json.Marshal(payment)

    req, _ := http.NewRequest("POST", "https://ipg.irandargah.com/v2/payments", bytes.NewBuffer(jsonData))
    req.Header.Set("Authorization", "Bearer YOUR_API_TOKEN")
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("Idempotency-Key", "unique-key-123")

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    defer resp.Body.Close()
}
import requests
import json

payment_data = {
    'amount': 100000,
    'order_id': 'ORDER-12345',
    'callback_url': 'https://merchant.com/callback',
    'description': 'خرید محصول آزمایشی',
    'mobile': '09123456789'
}

headers = {
    'Authorization': 'Bearer YOUR_API_TOKEN',
    'Content-Type': 'application/json',
    'Idempotency-Key': 'unique-key-123'
}

response = requests.post(
    'https://ipg.irandargah.com/v2/payments',
    headers=headers,
    json=payment_data
)

result = response.json()
print(result)
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

public class PaymentRequest
{
    [JsonProperty("amount")]
    public int Amount { get; set; }

    [JsonProperty("order_id")]
    public string OrderId { get; set; }

    [JsonProperty("callback_url")]
    public string CallbackUrl { get; set; }

    [JsonProperty("description")]
    public string Description { get; set; }

    [JsonProperty("mobile")]
    public string Mobile { get; set; }
}

public async Task<string> CreatePaymentAsync()
{
    var payment = new PaymentRequest
    {
        Amount = 100000,
        OrderId = "ORDER-12345",
        CallbackUrl = "https://merchant.com/callback",
        Description = "خرید محصول آزمایشی",
        Mobile = "09123456789"
    };

    using var client = new HttpClient();
    client.DefaultRequestHeaders.Add("Authorization", "Bearer YOUR_API_TOKEN");
    client.DefaultRequestHeaders.Add("Idempotency-Key", "unique-key-123");

    var json = JsonConvert.SerializeObject(payment);
    var content = new StringContent(json, Encoding.UTF8, "application/json");

    var response = await client.PostAsync("https://ipg.irandargah.com/v2/payments", content);
    return await response.Content.ReadAsStringAsync();
}

پاسخ موفق:

{
  "success": true,
  "data": {
    "transaction": {
      "authority": "2025100121424146HC",
      "gateway_url": "https://ipg.irandargah.com/startpay/2025100121424146HC",
      "expires_at": "1404-06-28 10:50:00"
    },
    "meta": {
      "idempotency_key": "unique-key-123",
      "request_id": "65a4c7e8f1234",
      "processing_time_ms": 45
    }
  },
  "message": "تراکنش با موفقیت ایجاد شد",
  "status_code": 100,
  "timestamp": "1404-06-28 10:30:00"
}

این آدرس برای ایجاد یک تراکنش پرداخت جدید استفاده می‌شود.

آدرس درخواست

POST
https://ipg.irandargah.com/v2/payments

هدرهای ارسالی

هدر مقدار توضیحات
Authorization Bearer YOUR_API_TOKEN توکن شما (اجباری)
Content-Type application/json نوع محتوای درخواست (اجباری)
Idempotency-Key unique-string کلید منحصر به فرد برای جلوگیری از درخواست‌های تکراری (اجباری)

پارامترهای ارسالی (snake_case)

پارامتر نوع اجباری توضیح
amount integer مبلغ تراکنش به ریال — حداقل ۱۰۰٬۰۰۰ (۱۰٬۰۰۰ تومان) و حداکثر ۴٬۰۰۰٬۰۰۰٬۰۰۰ (۴۰۰ میلیون تومان)
order_id string شناسه سفارش در سیستم شما — حداکثر ۵۰ کاراکتر، فقط A-Z, a-z, 0-9, -, _ (بدون فاصله یا فارسی)
callback_url string آدرس بازگشت پس از پرداخت — حداکثر ۵۰۰ کاراکتر، باید با http:// یا https:// شروع شود
mobile string شماره موبایل خریدار — فرمت‌های پذیرفته‌شده: 09xxxxxxxxx, 989xxxxxxxxx, +989xxxxxxxxx, 00989xxxxxxxxx, 9xxxxxxxxx
description string توضیحات تراکنش — حداکثر ۲۵۵ کاراکتر، بدون کاراکترهای < و > (جلوگیری از HTML)
card_number string شماره کارت پیش‌فرض — فرمت‌ها: کامل (۱۶ رقم) یا ماسک‌شده (۶ رقم + ****** + ۴ رقم). در صورت ارسال، خریدار فقط با این کارت می‌تواند پرداخت کند
action string متد HTTP برای فراخوانی callback — POST یا GET (پیش‌فرض: POST)
affiliate_code string کد معرف — ۴ تا ۶ کاراکتر، فقط حروف انگلیسی و اعداد
direct_verify boolean تأیید خودکار تراکنش بدون فراخوانی API تأیید (پیش‌فرض: false). در حالت true، callback با status_code=100 به‌جای 201 ارسال می‌شود

دریافت اطلاعات پرداخت

curl "https://ipg.irandargah.com/v2/payments/2025100121424146HC" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
<?php
$authority = '2025100121424146HC';

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://ipg.irandargah.com/v2/payments/{$authority}");
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer YOUR_API_TOKEN"]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
curl_close($ch);
?>
const authority = "2025100121424146HC";

const response = await fetch(
  `https://ipg.irandargah.com/v2/payments/${authority}`,
  {
    headers: {
      Authorization: "Bearer YOUR_API_TOKEN",
    },
  }
);

const data = await response.json();
authority := "2025100121424146HC"
url := fmt.Sprintf("https://ipg.irandargah.com/v2/payments/%s", authority)

req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("Authorization", "Bearer YOUR_API_TOKEN")

client := &http.Client{}
resp, err := client.Do(req)
authority = '2025100121424146HC'

response = requests.get(
    f'https://ipg.irandargah.com/v2/payments/{authority}',
    headers={'Authorization': 'Bearer YOUR_API_TOKEN'}
)

result = response.json()
string authority = "2025100121424146HC";

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer YOUR_API_TOKEN");

var response = await client.GetAsync($"https://ipg.irandargah.com/v2/payments/{authority}");
var content = await response.Content.ReadAsStringAsync();

پاسخ موفق:

{
  "success": true,
  "data": {
    "transaction": {
      "authority": "2025100121424146HC",
      "ref_id": "2025100121424146HC",
      "amount": 100000,
      "status": "completed",
      "created_at": "1404-06-28 10:30:00",
      "updated_at": "1404-06-28 10:35:00"
    },
    "meta": {
      "request_id": "65a4c7e8f1234",
      "cached": false
    }
  },
  "message": "اطلاعات تراکنش با موفقیت دریافت شد",
  "status_code": 200,
  "timestamp": "1404-06-28 10:35:00"
}

این آدرس برای دریافت اطلاعات یک تراکنش پرداخت استفاده می‌شود.

آدرس درخواست

GET
https://ipg.irandargah.com/v2/payments/{authority}

پارامترهای ارسالی

پارامتر توضیح
authority شناسه یکتای تراکنش

فیلدهای پاسخ

فیلد نوع توضیح
authority string شناسه یکتای تراکنش
ref_id string شماره مرجع بانکی (در صورت تأیید موفق)
amount integer مبلغ تراکنش به ریال
status string وضعیت متنی — یکی از: pending, completed, failed, timeout, cancelled, unknown
created_at string زمان ایجاد به خورشیدی
updated_at string آخرین زمان به‌روزرسانی به خورشیدی

لغو پرداخت

curl -X POST "https://ipg.irandargah.com/v2/payments/2025100121424146HC/cancel" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
<?php
$authority = '2025100121424146HC';

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://ipg.irandargah.com/v2/payments/{$authority}/cancel");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer YOUR_API_TOKEN"]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
curl_close($ch);
?>
const authority = "2025100121424146HC";

const response = await fetch(
  `https://ipg.irandargah.com/v2/payments/${authority}/cancel`,
  {
    method: "POST",
    headers: {
      Authorization: "Bearer YOUR_API_TOKEN",
    },
  }
);
authority := "2025100121424146HC"
url := fmt.Sprintf("https://ipg.irandargah.com/v2/payments/%s/cancel", authority)

req, _ := http.NewRequest("POST", url, nil)
req.Header.Set("Authorization", "Bearer YOUR_API_TOKEN")

client := &http.Client{}
resp, err := client.Do(req)
authority = '2025100121424146HC'

response = requests.post(
    f'https://ipg.irandargah.com/v2/payments/{authority}/cancel',
    headers={'Authorization': 'Bearer YOUR_API_TOKEN'}
)
string authority = "2025100121424146HC";

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer YOUR_API_TOKEN");

var response = await client.PostAsync($"https://ipg.irandargah.com/v2/payments/{authority}/cancel", null);

پاسخ موفق:

{
  "success": true,
  "data": {
    "transaction": {
      "authority": "2025100121424146HC",
      "ref_id": null,
      "amount": 100000,
      "status": "completed",
      "created_at": "1404-06-28 10:30:00",
      "updated_at": "1404-06-28 10:35:00"
    },
    "meta": {
      "request_id": "65a4c7e8f1234",
      "cached": false
    }
  },
  "message": "پرداخت با موفقیت لغو شد",
  "status_code": 200,
  "timestamp": "1404-06-28 10:35:00"
}

این آدرس برای لغو یک تراکنش پرداخت استفاده می‌شود.

آدرس درخواست

POST
https://ipg.irandargah.com/v2/payments/{authority}/cancel

پارامترهای ارسالی

پارامتر توضیح
authority شناسه یکتای تراکنش

بازگشت از درگاه (Callback)

پارامترهای Callback

پس از انجام پرداخت توسط کاربر در درگاه بانکی، بانک کاربر را به آدرس callback_url شما با پارامترهای زیر هدایت می‌کند:

پارامترهای بازگشتی (snake_case)

پارامتر نوع توضیح
authority string شناسه یکتای تراکنش
status_code integer کد وضعیت پرداخت (201 یا 100 = موفق، مقادیر منفی = ناموفق)
message string پیام توضیحی وضعیت
amount integer مبلغ پرداخت شده به ریال
order_id string شناسه سفارش شما
ref_id string شماره مرجع بانکی (در صورت موفقیت با direct_verify=true)
card_pan string شماره کارت ماسک شده (در صورت موفقیت با direct_verify=true)

نمونه آدرس Callback

فرمت بازگشت اطلاعات

https://yoursite.com/callback?
  authority=2025100121424146HC&
  status_code=201&
  message=پرداخت+در+انتظار+تایید+است&
  amount=100000&
  order_id=ORDER-12345&
  ref_id=123456789&
  card_pan=603799******1234

مثال پردازش Callback

<?php
// Laravel - V2 Callback Handler (snake_case)
Route::any('/callback', function (Request $request) {
    // دریافت پارامترهای callback - تمام فیلدها snake_case هستند
    $callbackData = [
        'authority'   => $request->input('authority'),
        'status_code' => (int) $request->input('status_code'),
        'message'     => $request->input('message'),
        'amount'      => (int) $request->input('amount'),
        'order_id'    => $request->input('order_id'),
        'ref_id'      => $request->input('ref_id'),
        'card_pan'    => $request->input('card_pan'),
    ];

    // بررسی وضعیت پرداخت
    // کد 201 = پرداخت موفق، منتظر تأیید (حالت معمول)
    // کد 100 = پرداخت و تأیید موفق (حالت direct_verify=true)
    if (in_array($callbackData['status_code'], [201, 100])) {
        // پرداخت موفق - تأیید با API (در حالت direct_verify=false)
        $response = Http::withToken(env('API_TOKEN'))
            ->post('https://ipg.irandargah.com/v2/verifications', [
                'authority' => $callbackData['authority'],
                'amount'    => $callbackData['amount'],
            ]);

        $result = $response->json();

        if ($result['success']) {
            $ref_id = $result['data']['verification']['ref_id'];

            // به‌روزرسانی وضعیت سفارش
            Order::where('order_id', $callbackData['order_id'])
                ->update([
                    'status'    => 'paid',
                    'ref_id'    => $ref_id,
                    'card_pan'  => $callbackData['card_pan'],
                ]);

            return view('payment.success', ['ref_id' => $ref_id]);
        }
    }

    // پرداخت ناموفق
    return view('payment.failed', [
        'status_code' => $callbackData['status_code']
    ]);
});
?>
// Node.js/Express - V2 Callback Handler (snake_case)
app.all("/callback", async (req, res) => {
  // پارامترها از body یا query string دریافت می‌شوند (بسته به action)
  const params = { ...req.query, ...req.body };
  const { authority, status_code, message, amount, order_id, ref_id, card_pan } = params;

  // کد 201 = موفق (منتظر تأیید)، کد 100 = موفق (تأیید شده)
  if (parseInt(status_code) === 201 || parseInt(status_code) === 100) {
    // Verify payment with API
    const response = await fetch(
      "https://ipg.irandargah.com/v2/verifications",
      {
        method: "POST",
        headers: {
          Authorization: "Bearer YOUR_API_TOKEN",
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          authority,
          amount: parseInt(amount),
        }),
      }
    );

    const result = await response.json();

    if (result.success) {
      // Update order status in database
      await Order.update(
        {
          status:   "paid",
          ref_id:   result.data.verification.ref_id,
          card_pan: card_pan,
        },
        { where: { order_id } }
      );

      return res.render("success", {
        ref_id: result.data.verification.ref_id,
      });
    }
  }

  res.render("failed", { status_code });
});
# Python/Django - V2 Callback Handler (snake_case)
from django.shortcuts import render
import requests

def payment_callback(request):
    # دریافت پارامترهای callback (GET یا POST بسته به action)
    params = request.POST if request.method == 'POST' else request.GET
    callback_data = {
        'authority':   params.get('authority'),
        'status_code': int(params.get('status_code', -1)),
        'message':     params.get('message'),
        'amount':      int(params.get('amount', 0)),
        'order_id':    params.get('order_id'),
        'ref_id':      params.get('ref_id'),
        'card_pan':    params.get('card_pan'),
    }

    # کد 201 = موفق (منتظر تأیید)، کد 100 = موفق (تأیید شده)
    if callback_data['status_code'] in [201, 100]:
        # تأیید پرداخت با API
        response = requests.post(
            'https://ipg.irandargah.com/v2/verifications',
            headers={'Authorization': 'Bearer YOUR_API_TOKEN'},
            json={
                'authority': callback_data['authority'],
                'amount':    callback_data['amount']
            }
        )

        result = response.json()

        if result['success']:
            # به‌روزرسانی سفارش
            Order.objects.filter(order_id=callback_data['order_id']).update(
                status='paid',
                ref_id=result['data']['verification']['ref_id'],
                card_pan=callback_data['card_pan']
            )

            return render(request, 'payment/success.html', {
                'ref_id': result['data']['verification']['ref_id']
            })

    return render(request, 'payment/failed.html', {
        'status_code': callback_data['status_code']
    })

کدهای وضعیت Callback

status_code معنی اقدام
201 پرداخت موفق، منتظر تأیید API فراخوانی API تأیید (/verifications)
100 پرداخت و تأیید موفق (direct_verify) ذخیره ref_id و نمایش موفقیت
-1 پرداخت ناموفق یا لغو توسط کاربر نمایش خطا به کاربر

تأیید پرداخت

تأیید تراکنش

curl -X POST "https://ipg.irandargah.com/v2/verifications" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: verification-key-123" \
  -d '{
    "authority": "2025100121424146HC",
    "amount": 100000
  }'
<?php
$data = [
    'authority' => '2025100121424146HC',
    'amount' => 100000
];

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://ipg.irandargah.com/v2/verifications");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "Authorization: Bearer YOUR_API_TOKEN",
    "Content-Type: application/json",
    "Idempotency-Key: verification-key-123"
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
curl_close($ch);

$result = json_decode($response, true);
?>
const verification = {
  authority: "2025100121424146HC",
  amount: 100000,
};

const response = await fetch("https://ipg.irandargah.com/v2/verifications", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_API_TOKEN",
    "Content-Type": "application/json",
    "Idempotency-Key": "verification-key-123",
  },
  body: JSON.stringify(verification),
});

const data = await response.json();
type VerificationRequest struct {
    Authority string `json:"authority"`
    Amount    int    `json:"amount"`
}

func verifyPayment() {
    verification := VerificationRequest{
        Authority: "2025100121424146HC",
        Amount:    100000,
    }

    jsonData, _ := json.Marshal(verification)

    req, _ := http.NewRequest("POST", "https://ipg.irandargah.com/v2/verifications", bytes.NewBuffer(jsonData))
    req.Header.Set("Authorization", "Bearer YOUR_API_TOKEN")
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("Idempotency-Key", "verification-key-123")

    client := &http.Client{}
    resp, err := client.Do(req)
}
verification_data = {
    'authority': '2025100121424146HC',
    'amount': 100000
}

headers = {
    'Authorization': 'Bearer YOUR_API_TOKEN',
    'Content-Type': 'application/json',
    'Idempotency-Key': 'verification-key-123'
}

response = requests.post(
    'https://ipg.irandargah.com/v2/verifications',
    headers=headers,
    json=verification_data
)

result = response.json()
public class VerificationRequest
{
    [JsonProperty("authority")]
    public string Authority { get; set; }

    [JsonProperty("amount")]
    public int Amount { get; set; }
}

var verification = new VerificationRequest
{
    Authority = "2025100121424146HC",
    Amount = 100000
};

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer YOUR_API_TOKEN");
client.DefaultRequestHeaders.Add("Idempotency-Key", "verification-key-123");

var json = JsonConvert.SerializeObject(verification);
var content = new StringContent(json, Encoding.UTF8, "application/json");

var response = await client.PostAsync("https://ipg.irandargah.com/v2/verifications", content);

پاسخ موفق:

{
  "success": true,
  "data": {
    "verification": {
      "ref_id": "123456789",
      "authority": "2025100121424146HC",
      "amount": 100000,
      "verified_at": "1404-06-28 10:35:00"
    },
    "meta": {
      "request_id": "req_verify_001",
      "processing_time_ms": 85
    }
  },
  "message": "تراکنش با موفقیت تأیید شد",
  "status_code": 200,
  "timestamp": "1404-06-28 10:35:00"
}

این آدرس پس از بازگشت کاربر از صفحه پرداخت برای تأیید نهایی تراکنش استفاده می‌شود.

آدرس درخواست

POST
https://ipg.irandargah.com/v2/verifications

پارامترهای ارسالی (snake_case)

پارامتر نوع الزامی توضیح
authority string شناسه یکتای تراکنش
amount integer مبلغ تراکنش به ریال (برای اعتبارسنجی)
order_id string شناسه سفارش (اختیاری)

وضعیت تأیید

curl "https://ipg.irandargah.com/v2/verifications/2025100121424146HC" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
<?php
$authority = '2025100121424146HC';

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://ipg.irandargah.com/v2/verifications/{$authority}");
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer YOUR_API_TOKEN"]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
curl_close($ch);
?>
const authority = "2025100121424146HC";

const response = await fetch(
  `https://ipg.irandargah.com/v2/verifications/${authority}`,
  {
    headers: {
      Authorization: "Bearer YOUR_API_TOKEN",
    },
  }
);

const data = await response.json();
authority := "2025100121424146HC"
url := fmt.Sprintf("https://ipg.irandargah.com/v2/verifications/%s", authority)

req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("Authorization", "Bearer YOUR_API_TOKEN")

client := &http.Client{}
resp, err := client.Do(req)
authority = '2025100121424146HC'

response = requests.get(
    f'https://ipg.irandargah.com/v2/verifications/{authority}',
    headers={'Authorization': 'Bearer YOUR_API_TOKEN'}
)

result = response.json()
string authority = "2025100121424146HC";

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer YOUR_API_TOKEN");

var response = await client.GetAsync($"https://ipg.irandargah.com/v2/verifications/{authority}");
var content = await response.Content.ReadAsStringAsync();

پاسخ موفق:

{
  "success": true,
  "data": {
    "verification": {
      "ref_id": "123456789",
      "authority": "2025100121424146HC",
      "amount": 100000,
      "verified_at": "1404-06-28 10:35:00"
    },
    "meta": {
      "request_id": "req_status_001"
    }
  },
  "message": "اطلاعات تراکنش با موفقیت دریافت شد",
  "status_code": 200,
  "timestamp": "1404-06-28 10:40:00"
}

این آدرس برای بررسی وضعیت تأیید یک تراکنش استفاده می‌شود.

آدرس درخواست

GET
https://ipg.irandargah.com/v2/verifications/{authority}

پارامترهای ارسالی

پارامتر توضیح
authority شناسه یکتای تراکنش

تلاش مجدد تأیید

curl -X POST "https://ipg.irandargah.com/v2/verifications/2025100121424146HC/retry" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
<?php
$authority = '2025100121424146HC';

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://ipg.irandargah.com/v2/verifications/{$authority}/retry");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer YOUR_API_TOKEN"]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
curl_close($ch);
?>
const authority = "2025100121424146HC";

const response = await fetch(
  `https://ipg.irandargah.com/v2/verifications/${authority}/retry`,
  {
    method: "POST",
    headers: {
      Authorization: "Bearer YOUR_API_TOKEN",
    },
  }
);
authority := "2025100121424146HC"
url := fmt.Sprintf("https://ipg.irandargah.com/v2/verifications/%s/retry", authority)

req, _ := http.NewRequest("POST", url, nil)
req.Header.Set("Authorization", "Bearer YOUR_API_TOKEN")

client := &http.Client{}
resp, err := client.Do(req)
authority = '2025100121424146HC'

response = requests.post(
    f'https://ipg.irandargah.com/v2/verifications/{authority}/retry',
    headers={'Authorization': 'Bearer YOUR_API_TOKEN'}
)
string authority = "2025100121424146HC";

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer YOUR_API_TOKEN");

var response = await client.PostAsync($"https://ipg.irandargah.com/v2/verifications/{authority}/retry", null);

پاسخ موفق:

{
  "success": true,
  "data": {
    "verification": {
      "ref_id": "123456789",
      "authority": "2025100121424146HC",
      "amount": 100000,
      "verified_at": "1404-06-28 10:45:00"
    },
    "meta": {
      "request_id": "req_retry_001",
      "processing_time_ms": 120
    }
  },
  "message": "تأیید مجدد با موفقیت انجام شد",
  "status_code": 200,
  "timestamp": "1404-06-28 10:45:00"
}

این آدرس برای تلاش مجدد تأیید یک تراکنش ناموفق استفاده می‌شود.

آدرس درخواست

POST
https://ipg.irandargah.com/v2/verifications/{authority}/retry

پارامترهای ارسالی

پارامتر توضیح
authority شناسه یکتای تراکنش

تراکنش‌ها

فهرست تراکنش‌ها

curl "https://ipg.irandargah.com/v2/transactions?page=1&per_page=10&status=completed&from_date=1404-06-01&to_date=1404-06-31" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
<?php
$query = http_build_query([
    'page'      => 1,
    'per_page'  => 10,
    'status'    => 'completed',
    'from_date' => '1404-06-01',
    'to_date'   => '1404-06-31',
]);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://ipg.irandargah.com/v2/transactions?{$query}");
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer YOUR_API_TOKEN"]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
curl_close($ch);
?>
const params = new URLSearchParams({
  page:      1,
  per_page:  10,
  status:    "completed",
  from_date: "1404-06-01",
  to_date:   "1404-06-31",
});

const response = await fetch(
  `https://ipg.irandargah.com/v2/transactions?${params}`,
  {
    headers: {
      Authorization: "Bearer YOUR_API_TOKEN",
    },
  }
);
params := url.Values{}
params.Add("page", "1")
params.Add("per_page", "10")
params.Add("status", "completed")
params.Add("from_date", "1404-06-01")
params.Add("to_date", "1404-06-31")

url := fmt.Sprintf("https://ipg.irandargah.com/v2/transactions?%s", params.Encode())

req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("Authorization", "Bearer YOUR_API_TOKEN")
params = {
    'page':      1,
    'per_page':  10,
    'status':    'completed',
    'from_date': '1404-06-01',
    'to_date':   '1404-06-31',
}

response = requests.get(
    'https://ipg.irandargah.com/v2/transactions',
    headers={'Authorization': 'Bearer YOUR_API_TOKEN'},
    params=params
)
var query = "?page=1&per_page=10&status=completed&from_date=1404-06-01&to_date=1404-06-31";

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer YOUR_API_TOKEN");

var response = await client.GetAsync($"https://ipg.irandargah.com/v2/transactions{query}");

پاسخ موفق:

{
  "success": true,
  "data": {
    "transactions": [
      {
        "authority": "2025100121424146HC",
        "amount": 100000,
        "status": "completed",
        "order_id": "ORDER-12345",
        "ref_code": "2025100121424146HC",
        "created_at": "1404-06-28 10:30:00",
        "verified_at": "1404-06-28 10:45:00"
      }
    ],
    "pagination": {
      "current_page": 1,
      "per_page": 10,
      "total": 1,
      "last_page": 1
    }
  },
  "timestamp": "1404-06-28 10:45:00"
}

این آدرس برای دریافت فهرست تراکنش‌ها استفاده می‌شود.

آدرس درخواست

GET
https://ipg.irandargah.com/v2/transactions

پارامترهای ارسالی

پارامتر اجباری پیش‌فرض توضیح
from_date تاریخ شروع به خورشیدی (YYYY-MM-DD) — نمی‌تواند تاریخ آینده باشد
to_date تاریخ پایان به خورشیدی (YYYY-MM-DD) — باید بزرگ‌تر یا مساوی from_date باشد
page 1 شماره صفحه
per_page 10 تعداد آیتم در هر صفحه (حداکثر 100)
status فیلتر بر اساس وضعیت — یکی از: pending, completed, failed, cancelled

جزئیات تراکنش

curl "https://ipg.irandargah.com/v2/transactions/2025100121424146HC" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
<?php
$authority = '2025100121424146HC';

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://ipg.irandargah.com/v2/transactions/{$authority}");
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer YOUR_API_TOKEN"]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
curl_close($ch);
?>
const authority = "2025100121424146HC";

const response = await fetch(
  `https://ipg.irandargah.com/v2/transactions/${authority}`,
  {
    headers: {
      Authorization: "Bearer YOUR_API_TOKEN",
    },
  }
);
authority := "2025100121424146HC"
url := fmt.Sprintf("https://ipg.irandargah.com/v2/transactions/%s", authority)

req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("Authorization", "Bearer YOUR_API_TOKEN")
authority = '2025100121424146HC'

response = requests.get(
    f'https://ipg.irandargah.com/v2/transactions/{authority}',
    headers={'Authorization': 'Bearer YOUR_API_TOKEN'}
)
string authority = "2025100121424146HC";

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer YOUR_API_TOKEN");

var response = await client.GetAsync($"https://ipg.irandargah.com/v2/transactions/{authority}");

پاسخ موفق:

{
  "success": true,
  "data": {
    "transaction": {
      "authority": "2025100121424146HC",
      "order_id": "ORDER-12345",
      "amount": 100000,
      "status": "completed",
      "workflow_state": "COMPLETED",
      "description": "خرید محصول آزمایشی",
      "ref_code": "2025100121424146HC",
      "callback_url": "https://merchant.com/callback",
      "created_at": "1404-06-28 10:30:00",
      "updated_at": "1404-06-28 10:35:00",
      "expires_at": "1404-06-28 10:50:00",
      "is_expired": false,
      "can_be_verified": false,
      "verification_status": 200
    }
  },
  "timestamp": "1404-06-28 11:00:00"
}

این آدرس برای دریافت جزئیات کامل یک تراکنش استفاده می‌شود.

آدرس درخواست

GET
https://ipg.irandargah.com/v2/transactions/{authority}

پارامترهای ارسالی

پارامتر توضیح
authority شناسه یکتای تراکنش

فیلدهای پاسخ

فیلد نوع توضیح
authority string شناسه یکتای تراکنش
order_id string شناسه سفارش در سیستم شما
amount integer مبلغ تراکنش به ریال
status string وضعیت متنی — یکی از: pending, completed, failed, timeout, cancelled, unknown
workflow_state string وضعیت دقیق در ماشین حالت داخلی (برای دیباگ)
description string توضیحات تراکنش
ref_code string شماره مرجع بانکی (پس از تأیید موفق)
callback_url string آدرس callback ثبت‌شده برای این تراکنش
created_at string زمان ایجاد به خورشیدی
updated_at string آخرین زمان به‌روزرسانی به خورشیدی
expires_at string زمان انقضای تراکنش به خورشیدی
is_expired boolean آیا تراکنش منقضی شده است
can_be_verified boolean آیا تراکنش قابل تأیید است
verification_status integer کد وضعیت تأیید (۲۰۰ = تأییدشده)

وضعیت سیستم

بررسی سلامت

curl "https://ipg.irandargah.com/health"
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://ipg.irandargah.com/health");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
curl_close($ch);
?>
const response = await fetch("https://ipg.irandargah.com/health");
const data = await response.json();
resp, err := http.Get("https://ipg.irandargah.com/health")
if err != nil {
    log.Fatal(err)
}
defer resp.Body.Close()
response = requests.get('https://ipg.irandargah.com/health')
result = response.json()
using var client = new HttpClient();
var response = await client.GetAsync("https://ipg.irandargah.com/health");
var content = await response.Content.ReadAsStringAsync();

پاسخ موفق:

{
  "status": "ok",
  "timestamp": "1404-06-29 10:30:00",
  "version": "2.0.0"
}

این آدرس برای بررسی وضعیت سلامت API استفاده می‌شود.

آدرس درخواست

GET
https://ipg.irandargah.com/health

وب‌هوک‌ها

وب‌هوک‌ها به شما اجازه می‌دهند به‌جای polling، رویدادهای مهم (پرداخت موفق، استرداد، تسویه و …) را به‌صورت real-time روی URL خودتان دریافت کنید. ایران‌درگاه پس از وقوع هر رویداد، یک درخواست POST به آدرس ثبت‌شده‌ی شما ارسال می‌کند.

ثبت وب‌هوک

curl -X POST "https://ipg.irandargah.com/v2/webhooks/subscribe" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://merchant.com/webhook",
    "events": ["payment.completed", "payment.failed"],
    "secret": "your_optional_secret_min_8_chars",
    "description": "وب‌هوک اصلی فروشگاه"
  }'
<?php
$data = [
    'url'         => 'https://merchant.com/webhook',
    'events'      => ['payment.completed', 'payment.failed'],
    'secret'      => 'your_optional_secret_min_8_chars', // اختیاری
    'description' => 'وب‌هوک اصلی فروشگاه',              // اختیاری
];

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://ipg.irandargah.com/v2/webhooks/subscribe");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "Authorization: Bearer YOUR_API_TOKEN",
    "Content-Type: application/json",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data, JSON_UNESCAPED_UNICODE));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
curl_close($ch);
?>
const webhook = {
  url: "https://merchant.com/webhook",
  events: ["payment.completed", "payment.failed"],
  secret: "your_optional_secret_min_8_chars", // اختیاری
  description: "وب‌هوک اصلی فروشگاه", // اختیاری
};

const response = await fetch(
  "https://ipg.irandargah.com/v2/webhooks/subscribe",
  {
    method: "POST",
    headers: {
      Authorization: "Bearer YOUR_API_TOKEN",
      "Content-Type": "application/json",
    },
    body: JSON.stringify(webhook),
  },
);
type WebhookSubscription struct {
    URL         string   `json:"url"`
    Events      []string `json:"events"`
    Secret      string   `json:"secret,omitempty"`
    Description string   `json:"description,omitempty"`
}

webhook := WebhookSubscription{
    URL:         "https://merchant.com/webhook",
    Events:      []string{"payment.completed", "payment.failed"},
    Secret:      "your_optional_secret_min_8_chars",
    Description: "وب‌هوک اصلی فروشگاه",
}

jsonData, _ := json.Marshal(webhook)

req, _ := http.NewRequest("POST", "https://ipg.irandargah.com/v2/webhooks/subscribe", bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer YOUR_API_TOKEN")
req.Header.Set("Content-Type", "application/json")
webhook_data = {
    'url':         'https://merchant.com/webhook',
    'events':      ['payment.completed', 'payment.failed'],
    'secret':      'your_optional_secret_min_8_chars',  # اختیاری
    'description': 'وب‌هوک اصلی فروشگاه',                # اختیاری
}

response = requests.post(
    'https://ipg.irandargah.com/v2/webhooks/subscribe',
    headers={
        'Authorization': 'Bearer YOUR_API_TOKEN',
        'Content-Type':  'application/json',
    },
    json=webhook_data
)
public class WebhookSubscription
{
    public string Url { get; set; }
    public List<string> Events { get; set; }
    public string Secret { get; set; }       // اختیاری
    public string Description { get; set; }  // اختیاری
}

var webhook = new WebhookSubscription
{
    Url         = "https://merchant.com/webhook",
    Events      = new List<string> { "payment.completed", "payment.failed" },
    Secret      = "your_optional_secret_min_8_chars",
    Description = "وب‌هوک اصلی فروشگاه",
};

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer YOUR_API_TOKEN");

var json    = JsonConvert.SerializeObject(webhook);
var content = new StringContent(json, Encoding.UTF8, "application/json");

var response = await client.PostAsync("https://ipg.irandargah.com/v2/webhooks/subscribe", content);

پاسخ موفق (HTTP 201):

{
  "success": true,
  "data": {
    "webhook": {
      "id": "65a4c7e8f1234",
      "url": "https://merchant.com/webhook",
      "events": ["payment.completed", "payment.failed"],
      "secret": "***masked***",
      "is_active": true,
      "created_at": "1404-06-29 10:30:00"
    }
  },
  "message": "Webhook subscription created successfully",
  "timestamp": "1404-06-29 10:30:00"
}

آدرس درخواست

POST
https://ipg.irandargah.com/v2/webhooks/subscribe

پارامترهای ارسالی

پارامتر نوع اجباری توضیح
url string آدرس HTTPS endpoint شما (باید URL معتبر باشد)
events array حداقل یک رویداد از فهرست انواع رویدادها
secret string کلید مخفی برای امضای HMAC — بین ۸ تا ۶۴ کاراکتر. اگر ندهید، سرور یک کلید ۶۴ کاراکتری Hex تولید می‌کند
description string توضیح کوتاه برای شناسایی این وب‌هوک — حداکثر ۲۵۵ کاراکتر

انواع رویدادها

رویداد توضیح
payment.created تراکنش پرداخت جدید ایجاد شد
payment.completed پرداخت با موفقیت تکمیل شد
payment.failed پرداخت ناموفق بود
payment.cancelled پرداخت لغو شد
payment.reversed پرداخت معکوس/استرداد شد
verification.completed تأیید پرداخت با موفقیت انجام شد
verification.failed تأیید پرداخت ناموفق بود
refund.created درخواست برگشت وجه ثبت شد
refund.completed برگشت وجه با موفقیت تکمیل شد
settlement.created دسته تسویه‌حساب ایجاد شد
settlement.completed تسویه‌حساب با موفقیت انجام شد
settlement.failed تسویه‌حساب ناموفق بود

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

curl "https://ipg.irandargah.com/v2/webhooks/events" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://ipg.irandargah.com/v2/webhooks/events");
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer YOUR_API_TOKEN"]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
curl_close($ch);

$events = json_decode($response, true)['data']['events'];
?>
const response = await fetch("https://ipg.irandargah.com/v2/webhooks/events", {
  headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});

const { data } = await response.json();
console.log(data.events);
req, _ := http.NewRequest("GET", "https://ipg.irandargah.com/v2/webhooks/events", nil)
req.Header.Set("Authorization", "Bearer YOUR_API_TOKEN")

client := &http.Client{}
resp, err := client.Do(req)
if err != nil { log.Fatal(err) }
defer resp.Body.Close()

var result map[string]interface{}
json.NewDecoder(resp.Body).Decode(&result)
response = requests.get(
    'https://ipg.irandargah.com/v2/webhooks/events',
    headers={'Authorization': 'Bearer YOUR_API_TOKEN'}
)

events = response.json()['data']['events']
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer YOUR_API_TOKEN");

var response = await client.GetAsync("https://ipg.irandargah.com/v2/webhooks/events");
var content  = await response.Content.ReadAsStringAsync();

پاسخ موفق:

{
  "success": true,
  "data": {
    "events": {
      "payment.created": "Triggered when a new payment is initiated",
      "payment.completed": "Triggered when a payment is successfully completed",
      "...": "..."
    },
    "webhook_requirements": {
      "url": "Must be a valid HTTPS URL",
      "response_timeout": "10 seconds",
      "retry_attempts": "3 times with exponential backoff",
      "expected_response": "HTTP 200-299 status code",
      "signature_header": "X-Webhook-Signature (HMAC-SHA256)"
    }
  },
  "timestamp": "1404-06-29 10:30:00"
}
GET
https://ipg.irandargah.com/v2/webhooks/events

این آدرس برای دریافت فهرست به‌روز رویدادهای پشتیبانی‌شده استفاده می‌شود.

لغو اشتراک

curl -X POST "https://ipg.irandargah.com/v2/webhooks/unsubscribe" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"webhook_id": "65a4c7e8f1234"}'
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://ipg.irandargah.com/v2/webhooks/unsubscribe");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "Authorization: Bearer YOUR_API_TOKEN",
    "Content-Type: application/json",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['webhook_id' => '65a4c7e8f1234']));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
curl_close($ch);
?>
const response = await fetch(
  "https://ipg.irandargah.com/v2/webhooks/unsubscribe",
  {
    method: "POST",
    headers: {
      Authorization: "Bearer YOUR_API_TOKEN",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ webhook_id: "65a4c7e8f1234" }),
  },
);
data := map[string]string{"webhook_id": "65a4c7e8f1234"}
jsonData, _ := json.Marshal(data)

req, _ := http.NewRequest("POST", "https://ipg.irandargah.com/v2/webhooks/unsubscribe", bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer YOUR_API_TOKEN")
req.Header.Set("Content-Type", "application/json")
response = requests.post(
    'https://ipg.irandargah.com/v2/webhooks/unsubscribe',
    headers={
        'Authorization': 'Bearer YOUR_API_TOKEN',
        'Content-Type':  'application/json',
    },
    json={'webhook_id': '65a4c7e8f1234'}
)
var data = new { webhook_id = "65a4c7e8f1234" };

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer YOUR_API_TOKEN");

var json    = JsonConvert.SerializeObject(data);
var content = new StringContent(json, Encoding.UTF8, "application/json");

var response = await client.PostAsync("https://ipg.irandargah.com/v2/webhooks/unsubscribe", content);

پاسخ موفق:

{
  "success": true,
  "data": {
    "webhook_id": "65a4c7e8f1234",
    "status": "unsubscribed"
  },
  "message": "Webhook unsubscribed successfully",
  "timestamp": "1404-06-29 10:30:00"
}

این آدرس وب‌هوک را غیرفعال می‌کند (is_active = false) — رکورد در دیتابیس باقی می‌ماند ولی دیگر رویدادی به این endpoint ارسال نمی‌شود.

POST
https://ipg.irandargah.com/v2/webhooks/unsubscribe

پارامترهای ارسالی

پارامتر نوع اجباری توضیح
webhook_id string شناسه‌ی وب‌هوک که در زمان ثبت دریافت کرده‌اید

تست وب‌هوک

curl -X POST "https://ipg.irandargah.com/v2/webhooks/test" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "webhook_id": "65a4c7e8f1234",
    "event_type": "payment.completed"
  }'
<?php
$data = [
    'webhook_id' => '65a4c7e8f1234',
    'event_type' => 'payment.completed',
];

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://ipg.irandargah.com/v2/webhooks/test");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "Authorization: Bearer YOUR_API_TOKEN",
    "Content-Type: application/json",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
curl_close($ch);
?>
const response = await fetch("https://ipg.irandargah.com/v2/webhooks/test", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_API_TOKEN",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    webhook_id: "65a4c7e8f1234",
    event_type: "payment.completed",
  }),
});
data := map[string]string{
    "webhook_id": "65a4c7e8f1234",
    "event_type": "payment.completed",
}
jsonData, _ := json.Marshal(data)

req, _ := http.NewRequest("POST", "https://ipg.irandargah.com/v2/webhooks/test", bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer YOUR_API_TOKEN")
req.Header.Set("Content-Type", "application/json")
response = requests.post(
    'https://ipg.irandargah.com/v2/webhooks/test',
    headers={
        'Authorization': 'Bearer YOUR_API_TOKEN',
        'Content-Type':  'application/json',
    },
    json={
        'webhook_id': '65a4c7e8f1234',
        'event_type': 'payment.completed',
    }
)
var data = new {
    webhook_id = "65a4c7e8f1234",
    event_type = "payment.completed",
};

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer YOUR_API_TOKEN");

var json    = JsonConvert.SerializeObject(data);
var content = new StringContent(json, Encoding.UTF8, "application/json");

var response = await client.PostAsync("https://ipg.irandargah.com/v2/webhooks/test", content);

پاسخ موفق:

{
  "success": true,
  "data": {
    "webhook_id": "65a4c7e8f1234",
    "event_type": "payment.completed",
    "test_result": {
      "status": "success",
      "response_code": 200,
      "response_time": null,
      "error": null
    }
  },
  "message": "Webhook test completed",
  "timestamp": "1404-06-29 10:30:00"
}

این آدرس یک بدنه درخواست نمونه برای رویداد مشخص‌شده تولید کرده و فوراً به endpoint شما ارسال می‌کند تا بتوانید پیاده‌سازی خود را پیش از رفتن به محیط عملیاتی تست کنید.

POST
https://ipg.irandargah.com/v2/webhooks/test

پارامترهای ارسالی

پارامتر نوع اجباری توضیح
webhook_id string شناسه‌ی وب‌هوک
event_type string یکی از: payment.created, payment.completed, payment.failed, payment.cancelled, refund.created, refund.completed, verification.completed

ساختار پیام وب‌هوک

پیامی که به endpoint شما ارسال می‌شود ساختار زیر را دارد:

{
  "event": "payment.completed",
  "timestamp": "2025-10-01T10:35:00+03:30",
  "merchant_code": "MERCHANT001",
  "data": {
    "authority": "2025100121424146HC",
    "amount": 100000,
    "order_id": "ORDER-12345",
    "ref_code": "2025100121424146HC",
    "pan": "603799******1234",
    "verified_at": "1404-06-29 10:35:00"
  },
  "signature": "a1b2c3d4e5f6..."
}

فیلدهای ثابت بدنه درخواست

فیلد نوع توضیح
event string نوع رویداد (همان مقداری که در زمان اشتراک انتخاب کرده‌اید)
timestamp string زمان وقوع رویداد در فرمت ISO 8601 با منطقه زمانی تهران
merchant_code string کد پذیرنده‌ی شما
data object محتوای رویداد (فیلدها بسته به نوع رویداد متفاوت است — جدول زیر)
signature string امضای HMAC-SHA256 روی data (فقط اگر secret ست شده باشد)

فیلدهای data بر اساس نوع رویداد

رویداد فیلدهای داخل data
payment.created authority, amount, status, created_at
payment.completed / verification.completed authority, amount, order_id, ref_code, pan, verified_at
payment.failed / payment.cancelled / verification.failed authority, amount, status, message
refund.created refund_code, authority, amount, status, reason, created_at
refund.completed refund_code, authority, amount, status, completed_at
settlement.created / settlement.completed / settlement.failed settlement_code, amount, status, period

هدرهای وب‌هوک

هر درخواست وب‌هوک با هدرهای زیر ارسال می‌شود:

هدر توضیح
Content-Type همیشه application/json
User-Agent IranDargah-Webhook/1.0
X-Webhook-Event نوع رویداد (مثال: payment.completed)
X-Webhook-Timestamp زمان ارسال (Unix timestamp بر حسب ثانیه)
X-Webhook-ID شناسه یکتای این رویداد (برای deduplication و idempotency)
X-Webhook-Signature امضای HMAC-SHA256 — فقط اگر secret در زمان اشتراک ست شده باشد

راستی‌آزمایی امضا

<?php
function verifyWebhookSignature(string $rawBody, string $signature, string $secret): bool {
    // فقط فیلد data امضا می‌شود
    $payload  = json_decode($rawBody, true);
    $dataJson = json_encode($payload['data'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);

    $expected = hash_hmac('sha256', $dataJson, $secret);
    return hash_equals($expected, $signature);
}

// استفاده
$body      = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';

if (! verifyWebhookSignature($body, $signature, 'YOUR_WEBHOOK_SECRET')) {
    http_response_code(401);
    exit('Invalid signature');
}
?>
const crypto = require("crypto");

function verifyWebhookSignature(rawBody, signature, secret) {
  // فقط فیلد data امضا می‌شود
  const payload = JSON.parse(rawBody);
  const dataJson = JSON.stringify(payload.data);

  const expected = crypto
    .createHmac("sha256", secret)
    .update(dataJson)
    .digest("hex");
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
}

// در Express
app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
  const signature = req.headers["x-webhook-signature"];
  if (!verifyWebhookSignature(req.body, signature, "YOUR_WEBHOOK_SECRET")) {
    return res.status(401).send("Invalid signature");
  }
  // ... پردازش webhook
  res.sendStatus(200);
});
import hmac, hashlib, json

def verify_webhook_signature(raw_body: bytes, signature: str, secret: str) -> bool:
    # فقط فیلد data امضا می‌شود
    payload   = json.loads(raw_body)
    data_json = json.dumps(payload['data'], ensure_ascii=False, separators=(',', ':'))

    expected = hmac.new(secret.encode(), data_json.encode(), hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature)

Retry و Timeout

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

پارامتر مقدار
Timeout ۱۰ ثانیه (اگر endpoint شما در این بازه پاسخ ندهد، خطا تلقی می‌شود)
Retries حداکثر ۳ تلاش
Backoff exponential — ۲ دقیقه، ۴ دقیقه، ۸ دقیقه (سقف ۶۰ دقیقه)
موفقیت پاسخ HTTP با کد 2xx
شکست پاسخ غیر-2xx، timeout، یا عدم پاسخ‌دهی

پس از ۳ تلاش ناموفق، رویداد به DLQ (Dead Letter Queue) منتقل می‌شود و می‌توانید آن را از پنل مدیریتی مشاهده و در صورت نیاز دوباره retry کنید.

گزارش‌ها

گزارش روزانه

curl "https://ipg.irandargah.com/v2/reports/daily?date=1404-06-28" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
<?php
$date = '1404-06-28';

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://ipg.irandargah.com/v2/reports/daily?date={$date}");
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer YOUR_API_TOKEN"]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
curl_close($ch);
?>
const date = "1404-06-28";

const response = await fetch(
  `https://ipg.irandargah.com/v2/reports/daily?date=${date}`,
  {
    headers: {
      Authorization: "Bearer YOUR_API_TOKEN",
    },
  }
);
date := "1404-06-28"
url := fmt.Sprintf("https://ipg.irandargah.com/v2/reports/daily?date=%s", date)

req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("Authorization", "Bearer YOUR_API_TOKEN")
date = '1404-06-28'

response = requests.get(
    f'https://ipg.irandargah.com/v2/reports/daily?date={date}',
    headers={'Authorization': 'Bearer YOUR_API_TOKEN'}
)
string date = "1404-06-28";

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer YOUR_API_TOKEN");

var response = await client.GetAsync($"https://ipg.irandargah.com/v2/reports/daily?date={date}");

پاسخ موفق:

{
  "success": true,
  "data": {
    "report_date": "1404-06-28",
    "summary": {
      "total_transactions": 150,
      "successful_transactions": 135,
      "failed_transactions": 15,
      "total_amount": 15000000,
      "successful_amount": 13500000,
      "success_rate": 90.0,
      "total_fees": 270000
    },
    "hourly_breakdown": [
      { "hour": 10, "transactions": 25, "amount": 2500000 }
    ],
    "payment_methods": [
      { "method": "card", "transactions": 140, "amount": 14000000 }
    ],
    "status_breakdown": [
      { "status": "completed", "count": 135 },
      { "status": "failed",    "count": 15  }
    ]
  },
  "timestamp": "1404-06-28 23:59:59"
}

این آدرس برای دریافت گزارش روزانه تراکنش‌ها استفاده می‌شود.

آدرس درخواست

GET
https://ipg.irandargah.com/v2/reports/daily

پارامترهای ارسالی

پارامتر الزامی توضیح
date تاریخ مورد نظر به خورشیدی (YYYY-MM-DD). در صورت ارسال نشدن، امروز درنظر گرفته می‌شود. نمی‌تواند تاریخ آینده باشد

فیلدهای پاسخ

فیلد نوع توضیح
report_date string تاریخ گزارش به خورشیدی
summary.total_transactions int تعداد کل تراکنش‌ها
summary.successful_transactions int تعداد تراکنش‌های موفق
summary.failed_transactions int تعداد تراکنش‌های ناموفق
summary.total_amount int جمع کل مبلغ تراکنش‌ها (ریال)
summary.successful_amount int جمع مبلغ تراکنش‌های موفق (ریال)
summary.success_rate float درصد موفقیت
summary.total_fees int جمع کارمزد (ریال)
hourly_breakdown array تفکیک ساعتی
payment_methods array تفکیک روش پرداخت
status_breakdown array تفکیک وضعیت

گزارش ماهانه

curl "https://ipg.irandargah.com/v2/reports/monthly?month=1404-06" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
<?php
$month = '1404-06';

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://ipg.irandargah.com/v2/reports/monthly?month={$month}");
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer YOUR_API_TOKEN"]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
curl_close($ch);
?>
const month = "1404-06";

const response = await fetch(
  `https://ipg.irandargah.com/v2/reports/monthly?month=${month}`,
  {
    headers: {
      Authorization: "Bearer YOUR_API_TOKEN",
    },
  }
);
month := "1404-06"
url := fmt.Sprintf("https://ipg.irandargah.com/v2/reports/monthly?month=%s", month)

req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("Authorization", "Bearer YOUR_API_TOKEN")
month = '1404-06'

response = requests.get(
    f'https://ipg.irandargah.com/v2/reports/monthly?month={month}',
    headers={'Authorization': 'Bearer YOUR_API_TOKEN'}
)
string month = "1404-06";

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer YOUR_API_TOKEN");

var response = await client.GetAsync($"https://ipg.irandargah.com/v2/reports/monthly?month={month}");

پاسخ موفق:

{
  "success": true,
  "data": {
    "report_month": "1404-06",
    "period": {
      "from": "1404-06-01",
      "to":   "1404-06-31"
    },
    "summary": {
      "total_transactions": 4500,
      "successful_transactions": 4050,
      "failed_transactions": 450,
      "total_amount": 450000000,
      "success_rate": 90.0
    },
    "daily_breakdown": [
      { "date": "1404-06-28", "transactions": 150, "amount": 15000000 }
    ],
    "payment_methods": [
      { "method": "card", "transactions": 4200, "amount": 420000000 }
    ],
    "psp_breakdown": [
      { "psp": "mellat",  "transactions": 2500, "amount": 250000000 },
      { "psp": "saderat", "transactions": 1550, "amount": 200000000 }
    ]
  },
  "timestamp": "1404-07-01 00:00:00"
}

آدرس درخواست

GET
https://ipg.irandargah.com/v2/reports/monthly

پارامترهای ارسالی

پارامتر الزامی توضیح
month ماه مورد نظر به خورشیدی (YYYY-MM). در صورت ارسال نشدن، ماه جاری درنظر گرفته می‌شود. نمی‌تواند ماه آینده باشد

فیلدهای پاسخ

فیلد نوع توضیح
report_month string ماه گزارش به خورشیدی
period.from / period.to string بازه‌ی تاریخی گزارش به خورشیدی
summary.* object خلاصه‌ی آماری (مشابه گزارش روزانه)
daily_breakdown array تفکیک روزانه
payment_methods array تفکیک روش پرداخت
psp_breakdown array تفکیک به‌ازای ارائه‌دهنده‌ی خدمات پرداخت (PSP)

محیط آزمایشی (Sandbox)

آدرس پایه محیط آزمایشی

https://sandbox.irandargah.com

محیط آزمایشی برای تست API اختیار شماست. این محیط دقیقاً مشابه محیط عملیاتی است با تفاوت‌های زیر:

تفاوت‌ها با محیط عملیاتی

ویژگی محیط عملیاتی محیط آزمایشی
آدرس پایه ipg.irandargah.com sandbox.irandargah.com
توکن احراز هویت توکن واقعی توکن تست (از پنل sandbox)
تراکنش‌ها تراکنش واقعی با بانک تراکنش شبیه‌سازی شده
کارت‌های بانکی کارت‌های واقعی کارت‌های تستی (جدول زیر)
هزینه تراکنش کارمزد واقعی محاسبه می‌شود بدون هزینه

ساختار آدرس‌ها

محیط آزمایشی در زیردامنه جداگانه قرار دارد و ساختار کاملاً مشابه محیط عملیاتی دارد:

آدرس محیط عملیاتی محیط آزمایشی
آدرس پایه https://ipg.irandargah.com https://sandbox.irandargah.com
ایجاد تراکنش https://ipg.irandargah.com/v2/payments https://sandbox.irandargah.com/v2/payments
تائید تراکنش https://ipg.irandargah.com/v2/verifications https://sandbox.irandargah.com/v2/verifications

کارت‌های تستی

برای تست در محیط آزمایشی، از کارت‌های زیر استفاده کنید:

شماره کارت نتیجه CVV2 تاریخ انقضا توضیحات نوع خطا
6037997123456789 123 05/12 تراکنش موفق
6219861012345678 456 05/12 پرداخت ناموفق failed
5041721098765432 789 05/12 موجودی ناکافی insufficient
6273811122334455 321 05/12 انقضای زمان تراکنش timeout

نحوه استفاده

تمام آدرس‌های API بدون تغییر در محیط آزمایشی قابل استفاده هستند، فقط:

  1. آدرس پایه را تغییر دهید
  2. از توکن تست استفاده کنید
  3. از کارت‌های تستی استفاده کنید

مثال: ایجاد پرداخت با سندباکس

تنها تفاوت محیط آزمایشی با محیط عملیاتی در آدرس پایه و توکن است — همان درخواست و همان پاسخ. کافی است این دو را در زمان بیلد روی هر محیطی که می‌خواهید ست کنید:

# Production
BASE_URL="https://ipg.irandargah.com";       TOKEN="YOUR_PRODUCTION_TOKEN"
# یا Sandbox
BASE_URL="https://sandbox.irandargah.com";   TOKEN="YOUR_SANDBOX_TOKEN"

curl -X POST "$BASE_URL/v2/payments" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 100000,
    "order_id": "ORDER-12345",
    "callback_url": "https://yoursite.com/callback"
  }'
<?php
$environment = 'sandbox'; // 'production' یا 'sandbox'
$config = [
    'production' => [
        'base_url' => 'https://ipg.irandargah.com',
        'token'    => 'YOUR_PRODUCTION_TOKEN',
    ],
    'sandbox' => [
        'base_url' => 'https://sandbox.irandargah.com',
        'token'    => 'YOUR_SANDBOX_TOKEN',
    ],
];
$baseUrl = $config[$environment]['base_url'];
$token   = $config[$environment]['token'];

$paymentData = [
    'amount'       => 100000,
    'order_id'     => 'ORDER-' . time(),
    'callback_url' => 'https://yoursite.com/callback',
    'description'  => 'خرید تستی',
];

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "{$baseUrl}/v2/payments");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "Authorization: Bearer {$token}",
    "Content-Type: application/json",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($paymentData, JSON_UNESCAPED_UNICODE));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
curl_close($ch);

$result = json_decode($response, true);
if ($result['success']) {
    $gatewayUrl = $result['data']['transaction']['gateway_url'];
    header('Location: ' . $gatewayUrl);
}
?>
const environment = "sandbox"; // یا "production"
const config = {
  production: {
    base_url: "https://ipg.irandargah.com",
    token: "YOUR_PRODUCTION_TOKEN",
  },
  sandbox: {
    base_url: "https://sandbox.irandargah.com",
    token: "YOUR_SANDBOX_TOKEN",
  },
};
const { base_url, token } = config[environment];

const response = await fetch(`${base_url}/v2/payments`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${token}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    amount: 100000,
    order_id: `ORDER-${Date.now()}`,
    callback_url: "https://yoursite.com/callback",
    description: "خرید تستی",
  }),
});

const result = await response.json();
if (result.success) {
  window.location.href = result.data.transaction.gateway_url;
}
type EnvConfig struct{ BaseURL, Token string }

config := map[string]EnvConfig{
    "production": {"https://ipg.irandargah.com",     "YOUR_PRODUCTION_TOKEN"},
    "sandbox":    {"https://sandbox.irandargah.com", "YOUR_SANDBOX_TOKEN"},
}
env := config["sandbox"] // یا "production"

payload, _ := json.Marshal(map[string]interface{}{
    "amount":       100000,
    "order_id":     fmt.Sprintf("ORDER-%d", time.Now().Unix()),
    "callback_url": "https://yoursite.com/callback",
})

req, _ := http.NewRequest("POST", env.BaseURL + "/v2/payments", bytes.NewBuffer(payload))
req.Header.Set("Authorization", "Bearer " + env.Token)
req.Header.Set("Content-Type", "application/json")

client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
import requests, time

config = {
    'production': {'base_url': 'https://ipg.irandargah.com',     'token': 'YOUR_PRODUCTION_TOKEN'},
    'sandbox':    {'base_url': 'https://sandbox.irandargah.com', 'token': 'YOUR_SANDBOX_TOKEN'},
}
env = config['sandbox']  # یا 'production'

response = requests.post(
    f"{env['base_url']}/v2/payments",
    headers={
        'Authorization': f"Bearer {env['token']}",
        'Content-Type':  'application/json',
    },
    json={
        'amount':       100000,
        'order_id':     f"ORDER-{int(time.time())}",
        'callback_url': 'https://yoursite.com/callback',
        'description':  'خرید تستی',
    }
)

result = response.json()
if result['success']:
    gateway_url = result['data']['transaction']['gateway_url']
var config = new Dictionary<string, (string BaseUrl, string Token)> {
    ["production"] = ("https://ipg.irandargah.com",     "YOUR_PRODUCTION_TOKEN"),
    ["sandbox"]    = ("https://sandbox.irandargah.com", "YOUR_SANDBOX_TOKEN"),
};
var env = config["sandbox"]; // یا "production"

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {env.Token}");

var body = new {
    amount       = 100000,
    order_id     = $"ORDER-{DateTimeOffset.Now.ToUnixTimeSeconds()}",
    callback_url = "https://yoursite.com/callback",
    description  = "خرید تستی",
};
var content  = new StringContent(JsonConvert.SerializeObject(body), Encoding.UTF8, "application/json");
var response = await client.PostAsync($"{env.BaseUrl}/v2/payments", content);

مثال: تأیید پرداخت با Sandbox

BASE_URL="https://sandbox.irandargah.com"
TOKEN="YOUR_SANDBOX_TOKEN"

curl -X POST "$BASE_URL/v2/verifications" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "authority": "2025100121424146HC",
    "amount": 100000
  }'
<?php
$baseUrl = 'https://sandbox.irandargah.com';
$token   = 'YOUR_SANDBOX_TOKEN';

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "{$baseUrl}/v2/verifications");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "Authorization: Bearer {$token}",
    "Content-Type: application/json",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
    'authority' => '2025100121424146HC',
    'amount'    => 100000,
]));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
curl_close($ch);
?>
const baseUrl = "https://sandbox.irandargah.com";
const token = "YOUR_SANDBOX_TOKEN";

const response = await fetch(`${baseUrl}/v2/verifications`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${token}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    authority: "2025100121424146HC",
    amount: 100000,
  }),
});
baseURL := "https://sandbox.irandargah.com"
token   := "YOUR_SANDBOX_TOKEN"

payload, _ := json.Marshal(map[string]interface{}{
    "authority": "2025100121424146HC",
    "amount":    100000,
})

req, _ := http.NewRequest("POST", baseURL + "/v2/verifications", bytes.NewBuffer(payload))
req.Header.Set("Authorization", "Bearer " + token)
req.Header.Set("Content-Type", "application/json")

client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
base_url = 'https://sandbox.irandargah.com'
token    = 'YOUR_SANDBOX_TOKEN'

response = requests.post(
    f'{base_url}/v2/verifications',
    headers={
        'Authorization': f'Bearer {token}',
        'Content-Type':  'application/json',
    },
    json={
        'authority': '2025100121424146HC',
        'amount':    100000,
    }
)
var baseUrl = "https://sandbox.irandargah.com";
var token   = "YOUR_SANDBOX_TOKEN";

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token}");

var body    = new { authority = "2025100121424146HC", amount = 100000 };
var content = new StringContent(JsonConvert.SerializeObject(body), Encoding.UTF8, "application/json");
var response = await client.PostAsync($"{baseUrl}/v2/verifications", content);

دریافت توکن تست

برای دریافت توکن تست:

  1. به پنل مدیریت محیط آزمایشی مراجعه کنید: https://sandbox.irandargah.com/dashboard
  2. از بخش API Tokens یک توکن جدید ایجاد کنید
  3. توکن را در کدهای تست خود استفاده کنید

تست فرآیند کامل

1. ایجاد تراکنش

curl -X POST "https://sandbox.irandargah.com/v2/payments" \
  -H "Authorization: Bearer YOUR_SANDBOX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 100000,
    "order_id": "TEST-001",
    "callback_url": "https://yoursite.com/callback"
  }'

پاسخ موفق:

{
  "success": true,
  "data": {
    "transaction": {
      "authority": "20250107145623ABCDEF",
      "gateway_url": "https://sandbox.irandargah.com/startpay/20250107145623ABCDEF",
      "expires_at": "1404-10-17 15:11:23"
    },
    "meta": {
      "request_id": "sandbox_678abc123",
      "processing_time_ms": 45,
      "environment": "sandbox",
      "test_mode": true
    }
  },
  "message": "تراکنش با موفقیت ایجاد شد",
  "status_code": 100,
  "timestamp": "1404-10-17 14:56:23"
}

2. هدایت به درگاه

از gateway_url دریافتی در پاسخ استفاده کنید.

3. پرداخت با کارت تستی

4. دریافت Callback

پارامترهای بازگشتی:

https://yoursite.com/callback?
  authority=2025100121424146HC&
  status_code=201&
  message=پرداخت+در+انتظار+تایید+است&
  amount=100000&
  order_id=TEST-001&
  ref_id=123456789&
  card_pan=603799******6789

5. تأیید تراکنش

curl -X POST "https://sandbox.irandargah.com/v2/verifications" \
  -H "Authorization: Bearer YOUR_SANDBOX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "authority": "2025100121424146HC",
    "amount": 100000
  }'

محدودیت‌های محیط آزمایشی

محدودیت مقدار
تعداد تراکنش روزانه نامحدود
مبلغ حداکثر 10,000,000 ریال
نرخ درخواست 10 درخواست در ثانیه
زمان انقضای توکن 30 روز

کدهای خطا

ایران‌درگاه از کدهای وضعیت HTTP استاندارد و همچنین کدهای خطای سفارشی استفاده می‌کند.

کدهای وضعیت HTTP

کد معنی
200 OK -- درخواست موفق
201 Created -- منبع جدید ایجاد شد
400 Bad Request -- درخواست نامعتبر
401 Unauthorized -- توکن نامعتبر
403 Forbidden -- دسترسی مجاز نیست
404 Not Found -- منبع یافت نشد
422 Validation Error -- خطا در اعتبارسنجی
429 Too Many Requests -- بیش از حد درخواست
500 Internal Server Error -- خطای داخلی سرور

کدهای خطای سفارشی

کد پیام توضیحات
100 تراکنش با موفقیت ایجاد شد موفقیت در ایجاد تراکنش
200 عملیات با موفقیت انجام شد موفقیت در تأیید تراکنش
-2 خطا در اعتبارسنجی ورودی خطا در پارامترهای ورودی (مقدار، فرمت، الزامی بودن، ...)
-21 تراکنش قبلاً تأیید شده است تلاش مجدد برای تأیید تراکنشی که قبلاً تأیید شده
-31 خطای داخلی سرور خطای سیستمی غیرمنتظره
-33 تراکنش یافت نشد تراکنش با این authority وجود ندارد
-50 اطلاعات احراز هویت یافت نشد هدر Authorization یا X-API-Key/X-Merchant-ID ارسال نشده
-51 اطلاعات احراز هویت نامعتبر است merchant_id یا api_key اشتباه است
-52 آدرس IP در لیست مجاز نیست آدرس IP فرستنده در IP whitelist ترمینال نیست
-53 ترمینال غیرفعال یا تحت بررسی است ترمینال در وضعیت غیرفعال، معلق، یا تحت بررسی است
-54 تعداد درخواست‌ها بیش از حد مجاز است از rate limit ترمینال عبور کرده‌اید
-101 هدرهای امضا ارسال نشده برای ترمینال‌های با require_signature=true، هدر X-Signature یا X-Timestamp نیست
-102 timestamp درخواست نامعتبر یا منقضی است اختلاف بیش از ۵ دقیقه با زمان سرور
-103 امضای درخواست نامعتبر است امضای X-Signature با محتوای درخواست همخوانی ندارد
-500 خطای غیرمنتظره در سرور خطای داخلی پیش‌بینی‌نشده
996 سرویس در دسترس نیست عدم دسترسی موقت به سرویس بانکی

انواع خطا (Error Types)

خطاها با type دسته‌بندی می‌شوند:

نوع توضیح
validation_error خطا در اعتبارسنجی ورودی
authentication_error خطا در احراز هویت
authorization_error خطا در مجوز دسترسی
business_logic_error نقض قوانین تجاری
rate_limit_error تعداد درخواست بیش از حد
server_error خطای داخلی سرور
gateway_error خطا در ارتباط با درگاه بانکی

ساختار پاسخ خطا

{
  "success": false,
  "error": {
    "message": "خطا در اعتبارسنجی ورودی",
    "code": -2,
    "type": "validation_error",
    "details": {
      "validation": {
        "amount": ["مبلغ باید حداقل 100000 ریال باشد"],
        "order_id": ["فیلد order_id الزامی است"]
      }
    }
  },
  "status_code": -2,
  "timestamp": "1404-06-28 10:30:00",
  "meta": {
    "request_id": "req_error_001"
  }
}

محدودیت‌های API

محدودیت نرخ درخواست

محدودیت‌ها بر اساس توکن Bearer (یا IP در نبود توکن) به‌ازای هر دقیقه اعمال می‌شوند. در صورت فراتر رفتن، پاسخ HTTP 429 Too Many Requests دریافت خواهید کرد.

آدرس بدون امضا با امضای معتبر (X-Signature)
POST /v2/payments (ایجاد پرداخت) ۱۰۰ درخواست/دقیقه نامحدود
POST /v2/verifications (تأیید پرداخت) ۱۰۰ درخواست/دقیقه نامحدود
POST /v2/refunds (استرداد) ۳۰ درخواست/دقیقه نامحدود
GET /v2/reports/* (گزارش‌ها) ۶۰ درخواست/دقیقه نامحدود
GET /v2/transactions/* (تراکنش‌ها) ۶۰ درخواست/دقیقه نامحدود
POST /v2/webhooks/{subscribe,unsubscribe,test} ۱۰ درخواست/دقیقه (مستقل از امضا)
POST /v2/webhooks/test ۳ درخواست/دقیقه (مستقل از امضا)

محدودیت endpoint تولید امضا

POST /api/prepare-request سه محدودیت هم‌زمان دارد — اگر هر کدام پر شوند، پاسخ ۴۲۹ می‌گیرید:

محدودیت مقدار identifier
محدودیت per-IP ۱۰۰ درخواست/دقیقه آدرس IP
محدودیت per-token ۲۰۰ درخواست/دقیقه هدر X-API-Token (یا IP در نبودش)
محدودیت روزانه ۱۰٬۰۰۰ درخواست/روز هدر X-API-Token (یا IP در نبودش)

نمایش محدودیت در هدر بازگشتی

HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1642248000
Retry-After: 60

پاسخ JSON خطا:

{
  "success": false,
  "error": {
    "message": "تعداد درخواست‌ها بیش از حد مجاز است",
    "code": -54,
    "type": "rate_limit_error"
  },
  "status_code": -54,
  "timestamp": "1404-06-29 10:30:00"
}

امنیت

HTTPS

تمام ارتباطات باید از طریق HTTPS انجام شود. درخواست‌های HTTP به طور خودکار به HTTPS تغییر مسیر می‌یابند.

API Token

توکن idg_live_… خود را در مکان امن (Vault، Secret Manager، یا متغیر محیطی سرور) نگهداری کنید. هرگز آن را در کد سمت کلاینت (مرورگر، اپ موبایل) قرار ندهید و در مخازن عمومی Git قرار نگذارید. در صورت نشت، فوراً از پنل کاربری ابطال اضطراری را بزنید (به بخش احراز هویت مراجعه کنید).

Idempotency

برای جلوگیری از تراکنش‌های تکراری، از هدر Idempotency-Key استفاده کنید.

IP Whitelist

می‌توانید دسترسی API خود را به IP های مشخص محدود کنید از طریق پنل کاربری.

امضای درخواست (Request Signing)

برای ترمینال‌هایی که قابلیت امضای درخواست (require_signature) فعال است، هر درخواست ارسالی باید با secret_key ترمینال امضا شده و دو هدر زیر ارسال شود:

هدر توضیح
X-Signature امضای HMAC-SHA256 محاسبه‌شده
X-Timestamp زمان Unix درخواست (ثانیه)

فرمول محاسبه امضا

payload    = "METHOD:endpoint:json_body:timestamp"
signature  = HMAC-SHA256(payload, secret_key)
بخش توضیح مثال
METHOD متد HTTP به حروف بزرگ POST
endpoint نام endpoint بدون /v2/ payments
json_body بدنه درخواست به فرمت JSON (بدون فاصله، UTF-8) {"amount":100000,...}
timestamp زمان Unix (ثانیه) — همان مقدار هدر X-Timestamp 1727800000

مثال عملی

<?php
$secretKey = 'your_secret_key';
$timestamp = time();

$method   = 'POST';
$endpoint = 'payments';
$body     = json_encode([
    'amount'       => 100000,
    'callback_url' => 'https://yoursite.com/callback',
    'order_id'     => 'ORDER-123',
], JSON_UNESCAPED_UNICODE);

$payload   = "{$method}:{$endpoint}:{$body}:{$timestamp}";
$signature = hash_hmac('sha256', $payload, $secretKey);

// ارسال هدرها
$headers = [
    'Authorization: Bearer YOUR_API_TOKEN',
    'X-Signature: ' . $signature,
    'X-Timestamp: ' . $timestamp,
    'Content-Type: application/json',
];
const crypto = require('crypto');

const secretKey = 'your_secret_key';
const timestamp = Math.floor(Date.now() / 1000);

const method   = 'POST';
const endpoint = 'payments';
const body     = JSON.stringify({
  amount:       100000,
  callback_url: 'https://yoursite.com/callback',
  order_id:     'ORDER-123',
});

const payload   = `${method}:${endpoint}:${body}:${timestamp}`;
const signature = crypto.createHmac('sha256', secretKey).update(payload).digest('hex');

const headers = {
  Authorization: 'Bearer YOUR_API_TOKEN',
  'X-Signature': signature,
  'X-Timestamp': String(timestamp),
  'Content-Type': 'application/json',
};
import hmac, hashlib, time, json

secret_key = 'your_secret_key'
timestamp  = str(int(time.time()))

method   = 'POST'
endpoint = 'payments'
body     = json.dumps({
    'amount':       100000,
    'callback_url': 'https://yoursite.com/callback',
    'order_id':     'ORDER-123',
}, ensure_ascii=False)

payload   = f"{method}:{endpoint}:{body}:{timestamp}"
signature = hmac.new(secret_key.encode(), payload.encode(), hashlib.sha256).hexdigest()

headers = {
    'Authorization': 'Bearer YOUR_API_TOKEN',
    'X-Signature':   signature,
    'X-Timestamp':   timestamp,
    'Content-Type':  'application/json',
}

تولید امضا از طریق API

اگر نمی‌خواهید امضا را سمت کلاینت محاسبه کنید، می‌توانید از endpoint کمکی زیر استفاده کنید.

curl -X POST "https://ipg.irandargah.com/api/prepare-request" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "method":   "POST",
    "endpoint": "payments",
    "data": {
      "amount":       100000,
      "callback_url": "https://yoursite.com/callback",
      "order_id":     "ORDER-123"
    }
  }'
<?php
$body = [
    'method'   => 'POST',
    'endpoint' => 'payments',
    'data'     => [
        'amount'       => 100000,
        'callback_url' => 'https://yoursite.com/callback',
        'order_id'     => 'ORDER-123',
    ],
];

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://ipg.irandargah.com/api/prepare-request');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Authorization: Bearer YOUR_API_TOKEN',
    'Content-Type: application/json',
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body, JSON_UNESCAPED_UNICODE));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
curl_close($ch);

$prepared = json_decode($response, true);
// $prepared['signature'], $prepared['timestamp'], $prepared['idempotency_key']
?>
const body = {
  method:   "POST",
  endpoint: "payments",
  data: {
    amount:       100000,
    callback_url: "https://yoursite.com/callback",
    order_id:     "ORDER-123",
  },
};

const response = await fetch(
  "https://ipg.irandargah.com/api/prepare-request",
  {
    method: "POST",
    headers: {
      Authorization:  "Bearer YOUR_API_TOKEN",
      "Content-Type": "application/json",
    },
    body: JSON.stringify(body),
  }
);

const prepared = await response.json();
// prepared.signature, prepared.timestamp, prepared.idempotency_key
body := map[string]interface{}{
    "method":   "POST",
    "endpoint": "payments",
    "data": map[string]interface{}{
        "amount":       100000,
        "callback_url": "https://yoursite.com/callback",
        "order_id":     "ORDER-123",
    },
}
jsonData, _ := json.Marshal(body)

req, _ := http.NewRequest("POST", "https://ipg.irandargah.com/api/prepare-request", bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer YOUR_API_TOKEN")
req.Header.Set("Content-Type", "application/json")

client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()

var prepared map[string]interface{}
json.NewDecoder(resp.Body).Decode(&prepared)
body = {
    'method':   'POST',
    'endpoint': 'payments',
    'data': {
        'amount':       100000,
        'callback_url': 'https://yoursite.com/callback',
        'order_id':     'ORDER-123',
    },
}

response = requests.post(
    'https://ipg.irandargah.com/api/prepare-request',
    headers={
        'Authorization': 'Bearer YOUR_API_TOKEN',
        'Content-Type':  'application/json',
    },
    json=body
)

prepared = response.json()
# prepared['signature'], prepared['timestamp'], prepared['idempotency_key']
var body = new {
    method   = "POST",
    endpoint = "payments",
    data = new {
        amount       = 100000,
        callback_url = "https://yoursite.com/callback",
        order_id     = "ORDER-123",
    },
};

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer YOUR_API_TOKEN");

var json    = JsonConvert.SerializeObject(body);
var content = new StringContent(json, Encoding.UTF8, "application/json");

var response = await client.PostAsync("https://ipg.irandargah.com/api/prepare-request", content);
var result   = await response.Content.ReadAsStringAsync();

پاسخ:

{
  "success":            true,
  "idempotency_key":    "idem_1727800000_abc123xyz",
  "signature_required": true,
  "signature":          "a1b2c3d4e5f6...",
  "timestamp":          "1727800000",
  "algorithm":          "HMAC-SHA256",
  "headers": {
    "X-Idempotency-Key": "idem_1727800000_abc123xyz",
    "X-Signature":       "a1b2c3d4e5f6...",
    "X-Timestamp":       "1727800000",
    "Content-Type":      "application/json"
  },
  "expires_at": "2025-10-01T10:35:00.000Z"
}

امضای دریافت‌شده ۵ دقیقه اعتبار دارد.

تأیید امضای پاسخ (Response Signature Verification)

سرور ایران‌درگاه پاسخ تمام endpointهای v2 را برای ترمینال‌هایی که secret_key دارند امضا می‌کند. دو هدر زیر به پاسخ اضافه می‌شوند:

هدر توضیح
X-Response-Signature امضای HMAC-SHA256 بدنه پاسخ
X-Response-Timestamp زمان Unix تولید پاسخ (ثانیه)

فرمول تأیید

payload          = response_body + ":" + X-Response-Timestamp
expected         = HMAC-SHA256(payload, secret_key)
is_valid         = timing_safe_compare(expected, X-Response-Signature)

بازه زمانی قابل قبول: ۵ دقیقه از زمان درج شده در X-Response-Timestamp.

مثال تأیید پاسخ

<?php
function verifyResponse(string $body, string $signature, string $timestamp, string $secretKey): bool
{
    if (abs(time() - (int)$timestamp) > 300) {
        return false; // timestamp منقضی شده
    }

    $payload  = "{$body}:{$timestamp}";
    $expected = hash_hmac('sha256', $payload, $secretKey);

    return hash_equals($expected, $signature);
}

// استفاده
$isValid = verifyResponse(
    $responseBody,
    $response->getHeader('X-Response-Signature'),
    $response->getHeader('X-Response-Timestamp'),
    'your_secret_key'
);
const crypto = require('crypto');

function verifyResponse(body, signature, timestamp, secretKey) {
  if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) {
    return false; // timestamp منقضی شده
  }

  const payload  = `${body}:${timestamp}`;
  const expected = crypto.createHmac('sha256', secretKey).update(payload).digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signature)
  );
}
import hmac, hashlib, time

def verify_response(body: str, signature: str, timestamp: str, secret_key: str) -> bool:
    if abs(time.time() - int(timestamp)) > 300:
        return False  # timestamp منقضی شده

    payload  = f"{body}:{timestamp}"
    expected = hmac.new(secret_key.encode(), payload.encode(), hashlib.sha256).hexdigest()

    return hmac.compare_digest(expected, signature)

پشتیبانی

برای دریافت پشتیبانی فنی: