مقدمه
به API درگاه پرداخت ایراندرگاه خوش آمدید! این API با استاندارد snake_case برای تمامی فیلدهای ورودی و خروجی، امکان ایجاد تراکنشهای پرداخت آنلاین و تأیید آنها را فراهم میکند.
شما میتوانید از نمونه کدهای موجود در سمت چپ صفحه استفاده کنید. کدهای نمونه در زبانهای مختلف برنامهنویسی ارائه شدهاند!
ویژگیهای جدید
- ✅ توکن واحد: احراز هویت با یک Bearer Token (با پیشوند
idg_live_/idg_test_) - ✅ چرخش امن توکن: ۲۴ ساعت پنجرهی grace خودکار پس از هر rotation تا عملیات بدون قطعی انجام شود
- ✅ ابطال اضطراری: امکان باطل کردن فوری توکن از پنل کاربری در صورت نشت
- ✅ استاندارد نامگذاری: تمامی فیلدها با نامگذاری
snake_case(مانندorder_id,callback_url,ref_id) - ✅ ساختار پاسخ یکسان: همه پاسخها شامل
success,data,message,status_codeوtimestamp - ✅ Idempotency-Key: جلوگیری از تراکنشهای تکراری با هدر
- ✅ مدیریت خطای پیشرفته: ساختار خطا با جزئیات و دستهبندی شده
- ✅ جلوگیری از Race Condition: قفل یکتا بودن
order_idدر سطح دیتابیس
احراز هویت
ایران درگاه برای احراز هویت از یک توکن واحد استفاده میکند که برای ترمینال شما صادر و در اختیار شما قرار میگیرد.
فرمت توکن
توکنها با پیشوندِ بامعنی صادر میشوند تا محیط عملیاتی و آزمایشی از روی نگاه قابل تشخیص باشند:
| پیشوند | محیط |
|---|---|
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");
دریافت توکن
صدور و چرخش توکن فقط پس از فعال شدن درگاه انجام میشود. برای دریافت توکن جدید:
- وارد پنل کاربری شوید
- به بخش «درگاهها» بروید
- در صورت نیاز به توکن جدید، با پشتیبانی تماس بگیرید — توکن یکبار در پیام پاسخ ارسال میشود
چرخش توکن (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 دیده شده):
- وارد پنل کاربری شوید
- ترمینال موردنظر را باز کنید ← دکمهی «مدیریت کلید امضا»
- در پایین صفحه، بخش قرمز «ناحیهی خطر» ← دکمهی «باطل کن — توکن لو رفته» را بزنید
پس از ابطال، با پشتیبانی تماس بگیرید تا توکن جدید برایتان صادر شود.
کلید 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 استفاده میشود که برای جلوگیری از تراکنشهای تکراری ضروری است.
آدرس درخواست
https://ipg.irandargah.com/v2/idempotency-key
پارامترهای پاسخ
| پارامتر | نوع | توضیح |
|---|---|---|
success |
boolean | وضعیت موفقیت درخواست |
idempotency_key |
string | کلید منحصر به فرد با پیشوند txn_ |
expires_in |
integer | مدت زمان اعتبار کلید به ثانیه (۸۶۴۰۰ = ۲۴ ساعت) |
usage |
string | راهنمای استفاده از کلید |
فرآیند پرداخت
فرآیند پرداخت در ایراندرگاه شامل مراحل زیر است:
- ایجاد تراکنش: درخواست پرداخت به آدرس
/v2/paymentsارسال میشود - هدایت کاربر: کاربر با استفاده از
authorityدریافتی به صفحه پرداخت هدایت میشود - پرداخت: کاربر عملیات پرداخت را در صفحه بانک انجام میدهد
- بازگشت: کاربر به
callback_urlشما برگردانده میشود - تأیید: درخواست تأیید به آدرس
/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"
}
این آدرس برای ایجاد یک تراکنش پرداخت جدید استفاده میشود.
آدرس درخواست
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"
}
این آدرس برای دریافت اطلاعات یک تراکنش پرداخت استفاده میشود.
آدرس درخواست
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"
}
این آدرس برای لغو یک تراکنش پرداخت استفاده میشود.
آدرس درخواست
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"
}
این آدرس پس از بازگشت کاربر از صفحه پرداخت برای تأیید نهایی تراکنش استفاده میشود.
آدرس درخواست
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"
}
این آدرس برای بررسی وضعیت تأیید یک تراکنش استفاده میشود.
آدرس درخواست
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"
}
این آدرس برای تلاش مجدد تأیید یک تراکنش ناموفق استفاده میشود.
آدرس درخواست
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"
}
این آدرس برای دریافت فهرست تراکنشها استفاده میشود.
آدرس درخواست
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"
}
این آدرس برای دریافت جزئیات کامل یک تراکنش استفاده میشود.
آدرس درخواست
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 استفاده میشود.
آدرس درخواست
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"
}
آدرس درخواست
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"
}
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 ارسال نمیشود.
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 شما ارسال میکند تا بتوانید پیادهسازی خود را پیش از رفتن به محیط عملیاتی تست کنید.
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"
}
این آدرس برای دریافت گزارش روزانه تراکنشها استفاده میشود.
آدرس درخواست
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"
}
آدرس درخواست
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 بدون تغییر در محیط آزمایشی قابل استفاده هستند، فقط:
- آدرس پایه را تغییر دهید
- از توکن تست استفاده کنید
- از کارتهای تستی استفاده کنید
مثال: ایجاد پرداخت با سندباکس
تنها تفاوت محیط آزمایشی با محیط عملیاتی در آدرس پایه و توکن است — همان درخواست و همان پاسخ. کافی است این دو را در زمان بیلد روی هر محیطی که میخواهید ست کنید:
# 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);
دریافت توکن تست
برای دریافت توکن تست:
- به پنل مدیریت محیط آزمایشی مراجعه کنید:
https://sandbox.irandargah.com/dashboard - از بخش
API Tokensیک توکن جدید ایجاد کنید - توکن را در کدهای تست خود استفاده کنید
تست فرآیند کامل
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. پرداخت با کارت تستی
- شماره کارت:
6037997123456789 - CVV2:
123 - تاریخ انقضا:
05/12 - رمز دوم (
OTP): هر عددی (در محیط آزمایشی قبول میشود)
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)
پشتیبانی
برای دریافت پشتیبانی فنی:
- ایمیل: contact@irandargah.com
- تلفن: ۰۳۱-۳۶۷۶۰۰۰۰
- پنل کاربری: https://panel.irandargah.com
- بخش پشتیبانی: https://irandargah.com/contact
- مستندات: https://docs.irandargah.com