اتصال به درگاه پیاکسا، سادهتر از آنچه فکر میکنید
بیشتر کسبوکارها برای دریافت پرداخت به کدنویسی نیاز ندارند: لینک پرداخت، افزونهٔ ووکامرس، فروشگاه کانال و رباتهای آمادهٔ
پیاکسا بدون برنامهنویسی راهاندازی میشوند. اگر سایت، اپ یا ربات اختصاصی دارید، اتصال تنها با دو درخواست انجام میشود:
ایجاد پرداخت و تأیید آن. این صفحه هر دو راه را قدمبهقدم توضیح میدهد.
بدون کدنویسیلینک پرداخت، ووکامرس، فروشگاه کانال و ربات آماده
با کدنویسیدو درخواست: ایجاد پرداخت و تأیید آن
آزمایش رایگانمحیط آزمایشی، بدون ثبتنام و بدون پرداخت واقعی
۰۱انتخاب روش
روش مناسب کسبوکار خود را انتخاب کنید
همهٔ روشها از یک حساب و یک پنل استفاده میکنند و میتوانید همزمان از چند روش بهره ببرید.
روش
مناسب برای
کدنویسی
شروع
لینک پرداخت
فروش در اینستاگرام، واتساپ، تلگرام یا بهصورت حضوری. لینک را برای خریدار میفرستید و خریدار از همان صفحه پرداخت میکند.
پیش از دریافت پرداخت واقعی، این موارد را در پنل آماده کنید
این موارد برای همهٔ روشها لازم است. اگر یکی از آنها آماده نباشد، پرداخت ایجاد نمیشود و پیام خطا علت آن را اعلام میکند
(فهرست خطاها).
درخواست درگاه تأییدشده و قرارداد امضاشده
پس از تکمیل مشخصات و ثبت درخواست درگاه، کارشناسان پیاکسا درخواست را بررسی و تأیید میکنند. سپس قرارداد را در پنل بخوانید و با کد پیامکی امضا کنید؛ تا قرارداد امضا نشود، پرداختی پذیرفته نمیشود.
نشانی سایت یا ربات ثبتشده
نشانی سایت یا ربات خود را در پنل ثبت کنید تا تأیید شود. نشانی بازگشت خریدار و نشانی اعلان پرداخت (callback_url) تنها روی همین نشانیها پذیرفته میشود.
کارت بانکی فعال و گوشی دریافت پیامک
در نوع «کارت به کارت شخصی»، دستکم یک کارت بانکی به نام خودتان ثبت و تأیید شود و برنامهٔ Payexa Uploader روی گوشیای که پیامکهای بانک را دریافت میکند نصب و به حساب متصل باشد.
اگر گوشی بیش از ۳۰ دقیقه به سامانه متصل نشود، پرداخت تازه پذیرفته نمیشود. در نوع «کارت به کارت ادمین» این مورد لازم نیست.
موجودی کیف پول
کارمزد هر پرداخت موفق از کیف پول کسر میشود. موجودی کیف پول باید دستکم به اندازهٔ حداقل لازم باشد؛ این مقدار در بخش کیف پول پنل نمایش داده میشود.
کلید API
برای اتصال با API و افزونهٔ ووکامرس، کلید API را از بخش مدیریت درگاه در پنل بردارید. این کلید را تنها روی سرور خود نگه دارید و هرگز در کد سمت مرورگر یا اپلیکیشن قرار ندهید.
آزمایش، بدون نیاز به هیچکدام از این موارد. پیش از اتصال واقعی، اتصال خود را در محیط آزمایشی بسنجید: بهجای
pay.pexn.ir از sandbox.pexn.ir و بهجای کلید API از کلید آزمایشی
PAYEXA استفاده کنید. در این محیط پرداخت واقعی انجام نمیشود، ثبتنام لازم نیست و همهٔ مسیرهای هر دو نسخهٔ API در دسترس است.
در آزمایشگاه پیاکسا نیز میتوانید حالتهای مختلف یک پرداخت (موفق، منقضی و انصراف خریدار) و پاسخ سامانه به هر کدام را ببینید.
ایجاد پرداخت، هدایت خریدار به صفحهٔ پرداخت و تأیید پرداخت پس از بازگشت خریدار. نمونهکد کامل برای PHP، Python و Node.js
آماده است؛ بخشهای بعد از آن تنها برای مراجعهاند و برای راهاندازی لازم نیست همهٔ آنها را بخوانید.
اتصال تازه را با نسخهٔ ۲ پیادهسازی کنید. اتصالهای نسخهٔ ۱ (از جمله افزونهٔ ووکامرس) بدون تغییر به کار خود ادامه میدهند و کلید API برای هر دو نسخه یکسان است.
۰۱مراحل اتصال
اتصال به درگاه تنها به دو درخواست نیاز دارد: ایجاد پرداخت و تأیید پرداخت. روند کامل یک پرداخت به شرح زیر است:
۰۱
ایجاد پرداخت
هنگامی که خریدار دکمهٔ پرداخت را در سایت شما میزند، سرور شما مبلغ و شمارهٔ سفارش را به پیاکسا ارسال میکند و در پاسخ، شناسهٔ پرداخت (payment_id) و نشانی صفحهٔ پرداخت (payment_url) را دریافت میکند. شناسهٔ پرداخت را همراه سفارش ذخیره کنید.
۰۲
هدایت خریدار به صفحهٔ پرداخت
بلافاصله پس از ایجاد پرداخت، خریدار را به نشانی payment_url دریافتشده در پاسخ هدایت (redirect) کنید (بخش ۴). اگر فروش از طریق ربات تلگرام یا بله انجام میشود، بهجای آن نشانی telegram_url یا bale_url را بهصورت دکمهٔ «پرداخت» زیر پیام ربات قرار دهید (بخش ۶). خریدار در صفحهٔ پرداخت، مبلغ و شمارهٔ کارت مقصد را میبیند و مبلغ را کارت به کارت میکند. تشخیص واریز بهصورت خودکار توسط پیاکسا انجام میشود و اقدامی از سوی شما لازم نیست.
۰۳
تأیید پرداخت پس از بازگشت خریدار
پس از پرداخت، خریدار به نشانی کالبک (callback_url) سایت شما بازگردانده میشود و payment_id در این نشانی قرار دارد. با این شناسه درخواست تأیید پرداخت را ارسال کنید و در صورتی که پاسخ first_verification: true بود، سفارش را تحویل دهید.
کلید API را از پنل پذیرنده دریافت کنید و تنها روی سرور خود نگه دارید؛ این کلید نباید در کد سمت مرورگر (جاوااسکریپت) یا اپلیکیشن قرار گیرد.
اگر خریدار پس از پرداخت صفحه را ببندد، نتیجهٔ پرداخت از دست نمیرود؛ زیرا پیاکسا یک اعلان سرور به سرور نیز به همان نشانی کالبک ارسال میکند. هر دو حالت با یک کد واحد پردازش میشوند (بخش ۵).
درخواست تأیید را میتوان چند بار ارسال کرد؛ مقدار first_verification تنها در نخستین تأیید true است و بنابراین هیچ سفارشی دو بار تحویل نمیشود.
۰۲نمونهکد کامل
نمونهکدهای زیر کل فرایند اتصال را پوشش میدهند. کافی است کلید API و نشانی سایت خود را جایگزین کنید و دو تابع
save_payment_id (ذخیرهٔ شناسهٔ پرداخت همراه سفارش) و deliver_order (تحویل سفارش)
را مطابق سامانهٔ فروشگاه خود پیادهسازی کنید.
import requests
from flask import Flask, redirect, request
PAYEXA_API_KEY = "YOUR_API_KEY" # کلید API از پنل پذیرنده
PAYEXA_URL = "https://pay.pexn.ir/v2/payments"
app = Flask(__name__)
def payexa(path="", body=None):
return requests.post(PAYEXA_URL + path, json=body or {}, timeout=20,
headers={"Authorization": f"Bearer {PAYEXA_API_KEY}"}).json()
@app.route("/pay") # هنگام زدن دکمهٔ «پرداخت» توسط خریدار
def pay():
result = payexa(body={
"amount": 5000000, # ریال
"order_id": "INV-1024", # شمارهٔ سفارش شما
"callback_url": "https://your-shop.ir/payexa-back",
})
if not result["ok"]:
return result["error"]["message"]
save_payment_id("INV-1024", result["data"]["payment_id"])
return redirect(result["data"]["payment_url"]) # هدایت خریدار به صفحهٔ پرداخت
@app.route("/payexa-back", methods=["GET", "POST"]) # بازگشت خریدار و اعلان پیاکسا
def payexa_back():
payment_id = request.args.get("payment_id") or (request.get_json(silent=True) or {}).get("payment_id", "")
result = payexa(f"/{payment_id}/verify")
if result["ok"] and result["data"]["first_verification"]:
deliver_order(result["data"]["order_id"]) # تنها در نخستین تأیید
return "پرداخت با موفقیت انجام شد" if result["ok"] else result["error"]["message"]
import express from "express";
const PAYEXA_API_KEY = "YOUR_API_KEY"; // کلید API از پنل پذیرنده
const PAYEXA_URL = "https://pay.pexn.ir/v2/payments";
const app = express();
app.use(express.json());
async function payexa(path = "", body = {}) {
const res = await fetch(PAYEXA_URL + path, {
method: "POST",
headers: { Authorization: `Bearer ${PAYEXA_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify(body),
});
return res.json();
}
// هنگام زدن دکمهٔ «پرداخت» توسط خریدار
app.get("/pay", async (req, res) => {
const result = await payexa("", {
amount: 5000000, // ریال
order_id: "INV-1024", // شمارهٔ سفارش شما
callback_url: "https://your-shop.ir/payexa-back",
});
if (!result.ok) return res.send(result.error.message);
await savePaymentId("INV-1024", result.data.payment_id);
res.redirect(result.data.payment_url); // هدایت خریدار به صفحهٔ پرداخت
});
// بازگشت خریدار و اعلان پیاکسا
app.all("/payexa-back", async (req, res) => {
const paymentId = req.query.payment_id || req.body?.payment_id || "";
const result = await payexa(`/${encodeURIComponent(paymentId)}/verify`);
if (result.ok && result.data.first_verification) await deliverOrder(result.data.order_id); // تنها در نخستین تأیید
res.send(result.ok ? "پرداخت با موفقیت انجام شد" : result.error.message);
});
آزمایش: در محیط آزمایشی، بهجای pay.pexn.ir از sandbox.pexn.ir و بهجای کلید API خود از PAYEXA استفاده کنید. همین کد بدون هیچ تغییر دیگری کار میکند.
نشانی کالبک (callback_url) باید روی سایتی باشد که در پنل ثبت و تأیید شده است.
جزئیات هر قدم
اگر نمونهکد بالا را به کار بردهاید، اتصال شما کامل است. بخشهای زیر جزئیات هر درخواست را برای مراجعه شرح میدهند.
۰۳ایجاد پرداخت
POST
درخواست را از سرور خود و با هدر Authorization: Bearer کلید_API به نشانی زیر ارسال کنید:
https://pay.pexn.ir/v2/payments
پارامترهای درخواست
فیلد
الزامی
توضیح
amount
بله
مبلغ سفارش به ریال و بهصورت عدد صحیح؛ در حال حاضر بین ۵۰۰٬۰۰۰ و ۵۰۰٬۰۰۰٬۰۰۰ ریال. اگر مبلغ بیرون از بازهٔ مجاز باشد، بازهٔ مجاز در پیام خطا اعلام میشود.
order_id
بله
شمارهٔ سفارش در سامانهٔ شما؛ حداکثر ۱۰۰ نویسه، شامل حروف انگلیسی، ارقام و نویسههای - _ . : /. شمارهٔ سفارش عددی (مانند شمارهٔ سفارش ووکامرس) نیز پذیرفته میشود.
callback_url
بله
نشانی کالبک در سایت شما که با https آغاز شود و روی سایت یا ربات تأییدشده در پنل قرار داشته باشد. خریدار پس از پرداخت به این نشانی بازگردانده میشود و اعلان سرور به سرور نیز به همین نشانی ارسال میشود. نشانیهای شبکهٔ داخلی یا خصوصی پذیرفته نمیشوند. تنها در صورتی که return_url پیوند ربات باشد، ارسال آن الزامی نیست (بخش ۶).
description
خیر
شرح سفارش (حداکثر ۲۵۵ نویسه)؛ در صفحهٔ پرداخت با عنوان «بابت» نمایش داده میشود.
metadata
خیر
هر اطلاعات دلخواهی که باید همراه پرداخت نگه داشته شود، بهصورت یک شیء JSON (حداکثر ۲ کیلوبایت)؛ در پاسخ تأیید و در اعلان پرداخت عیناً بازگردانده میشود.
return_url
خیر
نشانی بازگشت خریدار، در صورتی که با نشانی کالبک متفاوت باشد؛ معمولاً پیوند ربات (مانند https://t.me/YourBot) برای فروش از طریق ربات (بخش ۶). در صورت ارسال نشدن، خریدار به نشانی کالبک بازگردانده میشود.
جز این شش فیلد، فیلد دیگری نفرستید؛ فیلد ناشناخته با خطای VALIDATION_ERROR رد میشود.
پاسخ
فیلد
کاربرد
payment_id
شناسهٔ پرداخت؛ تنها مقداری که باید ذخیره کنید.
payment_url
نشانی صفحهٔ پرداخت؛ خریدار را بلافاصله به این نشانی هدایت (redirect) کنید (بخش ۴).
telegram_url / bale_url
نشانی همین پرداخت در ربات پرداخت پیاکسا در تلگرام / بله. برای فروش از طریق ربات، بهجای payment_url از این نشانی بهعنوان دکمهٔ «پرداخت» استفاده کنید. اگر ربات مربوط در دسترس نباشد، مقدار آن null است و در این صورت payment_url را در اختیار خریدار قرار دهید.
payable_amount
مبلغ دقیقی که خریدار باید واریز کند؛ اندکی با مبلغ سفارش تفاوت دارد تا واریز بهصورت خودکار شناسایی شود. مقدار به تومان در payable_amount_toman آمده است.
expires_at
پایان مهلت پرداخت (۳۰ دقیقه پس از ایجاد آن) به وقت جهانی (UTC).
created
true اگر پرداخت تازه ایجاد شده باشد؛ false اگر همان پرداخت قبلی این سفارش بازگردانده شده باشد.
card
کارت مقصد واریز: شمارهٔ پوشانده، نام صاحب کارت و بانک.
اگر همان order_id با همان مبلغ دوباره ارسال شود (برای نمونه، وقتی خریدار دو بار دکمهٔ پرداخت را بزند) و پرداخت قبلی هنوز در انتظار یا پرداختشده باشد، همان پرداخت قبلی با created: false بازگردانده میشود و پرداخت تکراری ایجاد نمیشود.
اگر همان order_id با مبلغ دیگری ارسال شود، خطای ORDER_ID_CONFLICT بازگردانده میشود. پس از منقضی شدن پرداخت قبلی، برای همان سفارش میتوانید پرداخت تازه ایجاد کنید.
ایجاد پرداخت تنها زمانی پذیرفته میشود که موارد پیش از اتصال آماده باشد.
۰۴هدایت خریدار به صفحهٔ پرداخت یا ربات
پس از ایجاد موفق پرداخت، خریدار را با یکی از نشانیهای زیر به پرداخت هدایت کنید. این نشانیها در پاسخ ایجاد پرداخت (بخش ۳)
بهصورت آماده بازگردانده میشوند و نیازی به ساختن آنها نیست. نشانی مناسب به محل فروش شما بستگی دارد:
محل فروش
فیلد پاسخ
روش هدایت خریدار
وبسایت
payment_url
خریدار را بلافاصله به این نشانی هدایت (redirect) کنید؛ نمونهکد آن در ادامه آمده است.
ربات تلگرام
telegram_url
این نشانی را بهصورت دکمهٔ «پرداخت» زیر پیام ربات خود قرار دهید (بخش ۶). خریدار پرداخت را در ربات پرداخت پیاکسا انجام میدهد.
ربات بله
bale_url
همانند تلگرام، این نشانی را بهصورت دکمهٔ «پرداخت» زیر پیام ربات خود قرار دهید (بخش ۶).
نمونهکد هدایت خریدار در وبسایت
در نمونههای زیر، result پاسخ درخواست ایجاد پرداخت (بخش ۳) است:
مهلت هر پرداخت ۳۰ دقیقه است؛ بنابراین خریدار را بلافاصله پس از ایجاد پرداخت هدایت کنید.
این نشانیها تنها برای هدایت خریدار هستند و نباید از سمت سرور فراخوانی شوند.
اگر telegram_url یا bale_url برابر null باشد (ربات مربوط در دسترس نیست)، payment_url را در اختیار خریدار قرار دهید.
در صفحهٔ پرداخت، نام سایت یا ربات شما با عنوان «پرداخت به» نمایش داده میشود و خریدار مبلغ و شمارهٔ کارت مقصد را میبیند. تشخیص واریز بهصورت خودکار انجام میشود.
پس از پرداخت، خریدار به نشانی کالبک (یا return_url) بازگردانده میشود؛ مرحلهٔ بعد، تأیید پرداخت است (بخش ۵).
۰۵بازگشت خریدار و تأیید پرداخت
POST
اطلاعات ارسالی به نشانی کالبک
پس از پرداخت، خریدار با نشانی زیر به سایت شما بازگردانده میشود:
شناسهٔ پرداخت؛ همان مقداری که در پاسخ ایجاد پرداخت گرفتید.
order_id
همان شمارهٔ سفارش خودتان که هنگام ایجاد پرداخت فرستادید.
status
یکی از paid (پرداخت انجام شده)، expired (مهلت تمام شده) یا canceled (خریدار انصراف داده است).
مقصد این بازگشت، return_url است و اگر آن را نفرستاده باشید، callback_url.
اگر نشانی شما پارامترهای دیگری در query داشته باشد همه حفظ میشوند؛ فقط همین سه پارامتر تنظیم یا بازنویسی میشوند.
اگر return_url پیوند ربات باشد (بخش ۶)، تلگرام و بله فقط start=<payment_id> را به ربات میدهند و سه پارامتر بالا در آن حالت وجود ندارند؛ ربات با همان شناسه تأیید میکند.
اگر مسیر کالبک شما اعلان POST را نپذیرد (برای نمونه، مسیری که فقط GET را پاسخ میدهد)، همین سه پارامتر بهصورت GET به callback_url با status=paid فرستاده میشود؛ بهتر است مسیر کالبک شما هم POST و هم GET را بپذیرد.
همزمان، پیاکسا یک اعلان سرور به سرور (درخواست POST حاوی payment_id در بدنه) نیز به همین نشانی ارسال میکند تا
در صورت بسته شدن صفحه توسط خریدار، نتیجهٔ پرداخت از دست نرود. هر دو درخواست را به یک شیوه پردازش کنید:payment_id را بخوانید و پرداخت را تأیید کنید.
یک درخواست POST با همان هدر کلید API به نشانی بالا ارسال کنید؛ بدنهٔ درخواست الزامی نیست. پاسخ را به شرح جدول زیر تفسیر کنید:
پاسخ
مفهوم
اقدام لازم
ok و first_verification: true
پرداخت انجام شده و این نخستین تأیید است.
سفارش را تحویل دهید.
ok و first_verification: false
پرداخت پیشتر تأیید شده است.
تنها پیام «پرداخت موفق» را نمایش دهید و سفارش را دوباره تحویل ندهید.
PAYMENT_NOT_PAID
هنوز واریزی ثبت نشده است.
وضعیت «در انتظار پرداخت» را نمایش دهید.
PAYMENT_EXPIRED
مهلت پرداخت به پایان رسیده و واریزی ثبت نشده است.
سفارش را آزاد کنید؛ خریدار میتواند پرداخت جدیدی انجام دهد.
نمونهٔ پاسخهای خطا
هنوز پرداخت نشده (کد 409):
{
"ok": false,
"error": {
"code": "PAYMENT_NOT_PAID",
"message": "این پرداخت هنوز انجام نشده است."
}
}
مهلت تمامشده (کد 409):
{
"ok": false,
"error": {
"code": "PAYMENT_EXPIRED",
"message": "مهلت این پرداخت تمام شده و پرداختی ثبت نشده است."
}
}
اگر میخواهید وضعیت را بدون خطا و برای هر سه حالت با کد 200 بخوانید، از استعلام پرداخت (بخش ۹) استفاده کنید؛ تأیید پرداخت همچنان با همین درخواست انجام میشود.
curl -X POST "https://pay.pexn.ir/v2/payments/A7F3C9E1B5D2468A0C1E3F5B7D9A2C4E6/verify" \
-H "Authorization: Bearer YOUR_API_KEY"
مقدار status در نشانی بازگشت (paid، expired، یا canceled به معنای انصراف خریدار) صرفاً جنبهٔ راهنما دارد؛ ملاک قطعی، پاسخ درخواست تأیید است.
برای اطمینان بیشتر میتوانید مبلغ سفارش را نیز در بدنهٔ درخواست تأیید ارسال کنید: {"amount": 5000000}. در صورت مغایرت، خطای AMOUNT_MISMATCH بازگردانده میشود.
تا زمانی که سرور شما به اعلان پاسخ موفق (کد 2xx) ندهد یا پرداخت را تأیید نکنید، اعلان پرداخت حداکثر ۶ بار ارسال میشود: یک بار هنگام پرداخت و سپس ۱، ۵، ۱۵، ۳۰ و ۶۰ دقیقه پس از هر تلاش (رویهم حدود دو ساعت). برای پرداختی که در مهلت انجام نشود، اعلان payment.expired فقط یک بار ارسال میشود.
اگر خریدار در مهلت مقرر واریز کرده باشد اما پرداخت بهصورت خودکار تأیید نشده باشد، میتواند پس از پایان مهلت، رسید واریز را ارسال کند. در صورت تأیید این رسید در پنل توسط شما، همان پرداخت منقضیشده به وضعیت paid تغییر میکند و اعلان payment.paid طبق روال معمول برای شما ارسال میشود؛ نمونهکد بخش ۲ این حالت را نیز بدون تغییر بهدرستی پردازش میکند.
۰۶ربات تلگرام و بله
اگر فروش شما از طریق ربات تلگرام یا بله انجام میشود، مراحل ایجاد و تأیید پرداخت دقیقاً مانند فروش در سایت (بخشهای ۱ تا ۵) است
و تنها در دو مورد زیر تفاوت دارد:
۰۱
دکمهٔ پرداخت در ربات
بهجای هدایت خریدار به payment_url، نشانی telegram_url (در بله، bale_url) را از پاسخ ایجاد پرداخت بردارید و بهصورت دکمهٔ «پرداخت» زیر پیام ربات خود قرار دهید. خریدار پرداخت را در ربات پرداخت پیاکسا انجام میدهد و از تلگرام یا بله خارج نمیشود.
۰۲
بازگشت خریدار به ربات شما
پیوند ربات خود را در پارامتر return_url قرار دهید (مانند https://t.me/YourBot). پس از پرداخت، خریدار با یک دکمه به ربات شما بازمیگردد و ربات پیام /start <payment_id> را دریافت میکند. در این مرحله، با همان payment_id پرداخت را تأیید کنید (بخش ۵).
سپس نشانی telegram_url دریافتشده در پاسخ را بهصورت دکمهٔ پیام ربات ارسال کنید (در بله، bale_url را با همین ساختار در API بله به کار ببرید). در نمونهٔ زیر، CHAT_ID شناسهٔ گفتوگوی خریدار و TELEGRAM_URL مقدار telegram_url از پاسخ ایجاد پرداخت است:
POST https://api.telegram.org/bot<YOUR_BOT_TOKEN>/sendMessage
{
"chat_id": CHAT_ID,
"text": "برای پرداخت سفارش، دکمهٔ زیر را بزنید",
"reply_markup": { "inline_keyboard": [[ { "text": "💳 پرداخت", "url": TELEGRAM_URL } ]] }
}
اگر ربات شما وبسرور ندارد، میتوانید callback_url را ارسال نکنید و تنها return_url را بفرستید؛ در این حالت، تأیید پرداخت هنگام دریافت پیام /start انجام میشود.
ربات شما باید در پنل ثبت و تأیید شده باشد. پیوند ربات را در callback_url قرار ندهید؛ این پارامتر نشانی سرور شماست.
همهٔ خطاها ساختار {"ok": false, "error": {"code": "…", "message": "…"}} را دارند.
مقدار message به زبان فارسی است و میتوان آن را مستقیماً به کاربر نمایش داد. رایجترین خطاها:
code
مفهوم
اقدام لازم
UNAUTHORIZED
کلید API ارسال نشده یا نادرست است.
کلید را از پنل بردارید و در هدر Authorization: Bearer بفرستید.
VALIDATION_ERROR
یکی از فیلدها نامعتبر است.
نام فیلد و علت آن در error.fields آمده است.
CALLBACK_NOT_ALLOWED
نشانی کالبک یا بازگشت روی سایت یا ربات تأییدشدهٔ شما نیست.
نشانی سایت یا ربات را در پنل ثبت کنید تا تأیید شود.
ORDER_ID_CONFLICT
برای این شمارهٔ سفارش، پرداختی با مبلغ دیگر وجود دارد.
تا پایان مهلت پرداخت قبلی صبر کنید یا شمارهٔ سفارش تازه بفرستید.
MERCHANT_INACTIVE
درگاه فعال نیست (برای نمونه، هنوز تأیید نشده است).
وضعیت درخواست درگاه را در پنل ببینید.
CONTRACT_NOT_SIGNED
قرارداد درگاه هنوز امضا نشده است.
قرارداد را در پنل بخوانید و امضا کنید.
INSUFFICIENT_WALLET_BALANCE
موجودی کیف پول کمتر از حداقل لازم است.
کیف پول را از پنل شارژ کنید.
NO_ACTIVE_CARD
کارت فعالی برای دریافت وجه وجود ندارد.
کارت بانکی را در پنل ثبت یا فعال کنید.
MERCHANT_TEMPORARILY_INACTIVE
گوشی دریافت پیامک ثبت نشده یا بیش از ۳۰ دقیقه به سامانه متصل نبوده است.
برنامهٔ Payexa Uploader را روی گوشی باز کنید و از اتصال اینترنت آن مطمئن شوید.
PAYMENT_NOT_PAID / PAYMENT_EXPIRED
در تأیید پرداخت: هنوز واریزی ثبت نشده است / مهلت پرداخت به پایان رسیده است.
به بخش ۵ مراجعه کنید.
code
HTTP
مفهوم
UNAUTHORIZED
401
کلید API ارسال نشده یا نامعتبر است.
IP_NOT_ALLOWED
403
محدودیت نشانی IP برای حساب شما فعال است و درخواست از نشانیای آمده که در پنل، بخش «IP سرور»، ثبت نشده است.
MERCHANT_INACTIVE
403
درگاه فعال نیست؛ علت در merchant_status آمده است. تأیید پرداختهای پیشین همچنان امکانپذیر است.
CONTRACT_NOT_SIGNED
403
قرارداد درگاه هنوز امضا نشده است؛ تا امضای آن پرداخت تازه پذیرفته نمیشود.
VALIDATION_ERROR
422
ورودی نامعتبر است؛ جزئیات در error.fields آمده است.
CALLBACK_NOT_ALLOWED
422
نشانی کالبک یا بازگشت روی سایت یا رباتهای تأییدشده قرار ندارد، یا پیوند ربات در callback_url ارسال شده است.
ORDER_ID_CONFLICT
409
برای این order_id پرداختی با مبلغ متفاوت در انتظار پرداخت است یا انجام شده است.
PAYMENT_NOT_FOUND
404
پرداخت یافت نشد یا متعلق به این کلید API نیست.
PAYMENT_NOT_PAID
409
درخواست تأیید پیش از انجام پرداخت ارسال شده است.
PAYMENT_EXPIRED
409
مهلت پرداخت به پایان رسیده است.
AMOUNT_MISMATCH
409
مبلغ ارسالشده در درخواست تأیید با مبلغ پرداخت مطابقت ندارد.
INSUFFICIENT_WALLET_BALANCE
402
موجودی کیف پول برای کسر کارمزد کافی نیست.
NO_ACTIVE_CARD
503
در حال حاضر کارت فعالی برای دریافت وجه وجود ندارد.
MERCHANT_TEMPORARILY_INACTIVE
503
گوشی دریافت پیامکهای بانکی ثبت نشده یا بیش از ۳۰ دقیقه به سامانه متصل نبوده است.
RATE_LIMITED
429
تعداد درخواستها از حد مجاز بیشتر شده است؛ پس از retry_after ثانیه دوباره تلاش کنید.
API_KEY_NOT_ALLOWED
400
کلید API به مسیر سمت مرورگر (بخش ۱۱) ارسال شده است.
NOT_FOUND / METHOD_NOT_ALLOWED
404 / 405
نشانی یا متد HTTP نادرست است.
REQUEST_FAILED
400
درخواست به دلیلی جز موارد بالا انجام نشد؛ متن خطا را بررسی کنید.
INTERNAL_ERROR
500
خطای داخلی سامانه؛ پس از چند لحظه دوباره تلاش کنید.
تکمیلی (اختیاری)
این بخشها برای راهاندازی لازم نیستند؛ هر زمان به آنها نیاز داشتید سراغشان بیایید.
۰۸بررسی امضای اعلان و هدرهای وبهوک
این بررسی الزامی نیست؛ زیرا سفارش تنها پس از تأیید پرداخت با کلید API تحویل میشود و یک اعلان جعلی نمیتواند
به تحویل سفارش منجر شود. با این حال، اگر بخواهید درخواستهای جعلی را در همان ابتدا رد کنید، اعلان POST پیاکسا هدرهای زیر را دارد:
X-Payexa-Event: payment.paid (یا payment.expired)
X-Payexa-Signature: t=<زمان ارسال>,v1=<۶۴ نویسهٔ هگز>
v1 = HMAC-SHA256( key = کلید API شما , message = "{t}." + بدنهٔ خام درخواست )
در صورت عدم تطابق v1، یا اختلاف بیش از ۵ دقیقهٔ t با ساعت سرور شما، درخواست را رد کنید.
فقط همین دو هدر اضافه میآید؛ هدر جداگانهای برای زمان وجود ندارد و زمان داخل همان هدر امضا با t= میآید (ثانیهٔ یونیکس).
بدنهٔ اعلان JSON فشرده است: بدون فاصله بعد از : و , و کاراکترهای غیرانگلیسی به شکل \uXXXX نوشته میشوند (برای نمونه، متن فارسی در metadata). به همین دلیل امضا را روی بایتهای خام بدنه بگیرید، نه روی JSON بازسازیشده.
خروجی امضا هگز با حروف کوچک و ۶۴ نویسه است؛ آن را با مقایسهٔ امن (hash_equals در PHP، compare_digest در Python، timingSafeEqual در Node) با مقدار v1 بسنجید.
هر تلاش دوبارهٔ اعلان، t و امضای تازه دارد؛ برای تشخیص تکرار از payment_id و event استفاده کنید، نه از امضا.
پس از بررسی امضا، پرداخت را تأیید کنید و پاسخ موفق (۲xx) بدهید؛ نتیجهٔ نهایی همان پاسخ درخواست تأیید است.
نمونهٔ کامل دو اعلان (هدرها و بدنه)
برای آزمودن پیادهسازی: اگر همین بدنهها را با کلید نمونهٔ example_api_key_for_docs و t=1793371263 امضا کنید، باید دقیقاً همین v1 را بگیرید.
پاسخ شامل همان اطلاعات پرداخت بههمراه verified و paid_at است. مقدار status یکی از pending، paid یا expired است.
استعلام، پرداخت را تأیید نمیکند؛ برای تحویل سفارش همچنان تأیید پرداخت (بخش ۵) الزامی است.
۱۰استعلام کارمزد
GET
کارمزد هر پرداخت موفق از کیف پول شما در پنل کسر میشود و از مبلغ واریزی خریدار چیزی کم نمیشود. با این استعلام میتوانید پیش از ایجاد پرداخت، مبلغ این کارمزد را بدانید
و در صورت تمایل، آن را از خریدار دریافت کنید. درخواست را از سرور خود و با هدر Authorization: Bearer کلید_API به نشانی زیر ارسال کنید:
https://pay.pexn.ir/v2/fees?amount=1000000
پارامتر درخواست
پارامتر
الزامی
توضیح
amount
بله
مبلغ سفارش به ریال و بهصورت عدد صحیح؛ همان مبلغی که هنگام ایجاد پرداخت (بخش ۳) در فیلد amount ارسال میشود، با همان بازهٔ مجاز. نوع درگاه شما (کارت به کارت شخصی یا ادمین) از روی کلید API تشخیص داده میشود و ارسال آن لازم نیست.
جز amount پارامتر دیگری نفرستید؛ پارامتر ناشناخته با خطای VALIDATION_ERROR رد میشود.
پاسخ
فیلد
کاربرد
wallet_fee
کارمزدی که پس از موفق شدن پرداختی با این مبلغ از کیف پول شما کسر میشود، به ریال؛ همیشه مضربی از ۱۰ ریال (تومان کامل). مقدار به تومان در wallet_fee_toman آمده است.
amount_with_fee
کمترین مبلغی که اگر از خریدار دریافت شود، پس از کسر کارمزدِ همان مبلغ، دستکم مبلغ amount برای شما باقی میماند؛ مضربی از ۱۰ ریال. مقدار به تومان در amount_with_fee_toman آمده است.
fees
ریز کارمزد: عنوان (title)، درصد (rate_percent)، کمینه و بیشینه (min_fee، max_fee) و مبلغ (fee) هر عنوان، به ریال.
merchant_type
نوع درگاه شما: personal (کارت به کارت شخصی) یا admin (کارت به کارت ادمین).
testnet
برای حساب آزمایشی true است؛ در این حالت کارمزدی کسر نمیشود و wallet_fee صفر است.
limits
کمترین (min_amount) و بیشترین (max_amount) مبلغ مجاز برای ایجاد پرداخت، به ریال.
عنوانها، درصدها و بازهٔ مجاز این نمونه فرضی است؛ مقادیر واقعی را از پاسخ استعلام بخوانید.
دریافت کارمزد از خریدار
اگر میخواهید کارمزد را خریدار بپردازد، پیش از ایجاد پرداخت مبلغ سفارش را استعلام کنید و مقدار amount_with_fee را بهعنوان amount در درخواست ایجاد پرداخت (بخش ۳) ارسال کنید. خریدار همین مبلغ را میپردازد، کل آن به کارت شما واریز میشود و پس از کسر کارمزد از کیف پول، دستکم مبلغ اصلی سفارش برای شما باقی میماند. جمع سادهٔ «مبلغ سفارش + wallet_fee» کافی نیست، زیرا کارمزد روی مبلغ نهایی محاسبه میشود.
کارمزد بر اساس مبلغ سفارش (amount) محاسبه میشود، نه مبلغ واریزی خریدار (payable_amount).
تعرفهٔ کارمزد ممکن است تغییر کند؛ استعلام را نزدیک به زمان ایجاد پرداخت انجام دهید و نتیجه را بیش از چند دقیقه نگه ندارید.
دریافت کارمزد از خریدار، نحوهٔ کسر آن را تغییر نمیدهد: کارمزد همچنان از کیف پول کسر میشود و کیف پول باید حداقل موجودی لازم را داشته باشد (پیش از اتصال).
اگر amount_with_fee از limits.max_amount بیشتر باشد، ایجاد پرداخت با آن مبلغ پذیرفته نمیشود.
سقف درخواست برای هر کلید API، ۱۲۰ استعلام در دقیقه است؛ در صورت عبور از سقف، خطای RATE_LIMITED همراه با هدر Retry-After بازگردانده میشود.
در محیط آزمایشی (sandbox.pexn.ir با کلید PAYEXA)، پاسخ با تعرفهٔ جاری کارت به کارت شخصی محاسبه میشود.
۱۱صفحهٔ پرداخت اختصاصی
GET
اگر میخواهید اطلاعات کارت و مبلغ را در صفحهٔ سایت خود نمایش دهید، مقادیر card و payable_amount را از پاسخ ایجاد پرداخت بردارید
و وضعیت پرداخت را از سمت مرورگر و بدون کلید API از نشانی زیر استعلام کنید:
// در مرورگر خریدار، هر ۵ ثانیه یک بار
const timer = setInterval(async () => {
const { ok, data } = await (await fetch("https://pay.pexn.ir/v2/payments/" + paymentId + "/client")).json();
if (ok && data.status !== "pending") {
clearInterval(timer);
location.href = "/payexa-back?payment_id=" + paymentId; // تأیید پرداخت در سرور شما
}
}, 5000);
تنها سایتهای تأییدشدهٔ شما مجاز به خواندن این پاسخ از مرورگر هستند. اطلاعات کارت تنها تا زمانی که پرداخت باز است نمایش داده میشود.
تحویل سفارش همچنان تنها پس از تأیید پرداخت در سرور شما مجاز است.
۱۲امنیت و محدودیتها
تحویل تنها پس از تأیید
سفارش را نه بر اساس status در نشانی بازگشت و نه بر اساس اعلان POST تحویل دهید؛ تنها زمانی که پاسخ تأیید، first_verification: true باشد.
نگهداری کلید تنها روی سرور
در صورت افشای کلید API، بلافاصله آن را در پنل تغییر دهید. همچنین میتوانید در پنل، بخش «IP سرور»، تا ۵ نشانی IP یا بازهٔ سرور خود را ثبت کنید.
«پرداخت به: …»
صفحهٔ پرداخت نام سایت یا ربات شما را نمایش میدهد؛ به خریداران توصیه کنید پیش از پرداخت به آن توجه کنند.
سقف درخواست برای هر کلید API در دقیقه: ایجاد پرداخت ۶۰، تأیید ۶۰، استعلام پرداخت ۱۲۰ و استعلام کارمزد ۱۲۰ درخواست؛ و از هر نشانی IP رویهم ۶۰۰ درخواست در دقیقه. در صورت عبور از سقف، خطای RATE_LIMITED همراه با هدر Retry-After بازگردانده میشود.
مبالغ به ریال و بهصورت عدد صحیح هستند؛ زمانها به وقت جهانی (UTC) و در قالبی مانند 2026-10-01T09:30:00Z بیان میشوند.
هدر قدیمی X-API-KEY نیز بهجای Authorization: Bearer پذیرفته میشود.
۱۳مهاجرت از نسخهٔ ۱
نسخهٔ ۱ همچنان فعال است و مهاجرت الزامی نیست. کلید API برای هر دو نسخه یکسان است. معادل مفاهیم دو نسخه در جدول زیر آمده است:
نسخهٔ ۱
نسخهٔ ۲
POST /v1/payment/request
POST /v2/payments
meta.order_ref
order_id
authority + ساختن /startPay?authority=…
payment_id + payment_url آماده
بازگشت با status=OK&authority=…
بازگشت با payment_id&order_id&status=paid
تأیید (verify) با order_id و token (مبلغ یکتا)
تأیید با payment_id و بدون توکن
کد 200 در نخستین تأیید و 201 در دفعات بعد
همواره 200؛ مقدار first_verification برابر true یا false
هر پرداخت با همان نسخهای تأیید میشود که با آن ایجاد شده است.
پرسشها
۱۴مشکلات رایج و راهحل آنها
مشکل
علت و راهحل
خریدار پرداخت کرده اما سفارش در سایت ثبت نشده است.
سفارش تنها پس از تأیید پرداخت تحویل میشود. بررسی کنید که مسیر کالبک شما درخواست تأیید را ارسال میکند و هم GET و هم POST را میپذیرد. وضعیت پرداخت در پنل، بخش تراکنشها، دیده میشود و تأیید پرداخت را میتوان بعداً نیز انجام داد.
خریدار مبلغی متفاوت با مبلغ اعلامشده واریز کرده است.
واریز تنها با مبلغ دقیق payable_amount بهصورت خودکار شناسایی میشود. خریدار میتواند پس از پایان مهلت، رسید واریز را ارسال کند تا شما آن را در پنل بررسی و تأیید کنید.
خطای CALLBACK_NOT_ALLOWED
نشانی کالبک باید روی سایت یا ربات ثبتشده و تأییدشده در پنل باشد. نشانی را در پنل ثبت کنید و پس از تأیید آن دوباره تلاش کنید.
خطای MERCHANT_TEMPORARILY_INACTIVE
گوشی دریافت پیامک بیش از ۳۰ دقیقه به سامانه متصل نبوده است. برنامهٔ Payexa Uploader را روی گوشی باز کنید و اتصال اینترنت و تنظیمات باتری گوشی را بررسی کنید.
نشانی telegram_url یا bale_url برابر null است.
ربات پرداخت پیاکسا در آن پیامرسان در دسترس نیست؛ نشانی payment_url را به خریدار بدهید.
اتصال در محیط آزمایشی کار میکند اما در محیط واقعی نه.
کلید API واقعی را بهجای PAYEXA و نشانی pay.pexn.ir را بهجای sandbox.pexn.ir قرار دهید و موارد پیش از اتصال را بررسی کنید.
اگر مشکل شما در این فهرست نیست، از بخش پشتیبانی پنل تیکت ثبت کنید و شناسهٔ پرداخت (payment_id) را در آن بنویسید.
مستندات نسخهٔ ۱ (قدیمی). نسخهٔ ۱ همچنان فعال است و پشتیبانی میشود و اتصالهای موجود و افزونهها
بدون تغییر به کار خود ادامه میدهند. برای پیادهسازی اتصال جدید از نسخهٔ ۲ استفاده کنید که سادهتر است
(یک شناسهٔ واحد، تأیید پرداخت بدون توکن مبلغ و اعلان امضاشده).
۰۱روند کلی اتصال
برای راهاندازی اتصال، شش مرحلهٔ زیر را به همین ترتیب انجام دهید.
۰۱
ثبت سفارش در سامانهٔ خود
سفارش را ابتدا در سامانهٔ خود با وضعیت pending ذخیره کنید.
۰۲
تنظیم هدرهای الزامی
پیش از ارسال درخواست، هدرهای Content-Type و X-API-KEY را تنظیم کنید.
۰۳
ارسال درخواست به payment/request
مبلغ و callback_url را ارسال کنید و در پاسخ، authority و اطلاعات پرداخت را دریافت کنید.
۰۴
هدایت خریدار به صفحهٔ پرداخت
پس از دریافت authority در پاسخ مرحلهٔ ۳، خریدار را به نشانی https://pay.pexn.ir/startPay?authority={authority} هدایت کنید.
۰۵
دریافت callback
پس از پرداخت، callback را دریافت کنید؛ اما سفارش را در این مرحله نهایی نکنید.
۰۶
تأیید قطعی از سمت سرور (Verify)
پس از دریافت callback، درخواست verify را از سمت سرور ارسال کنید و در صورت موفقیت، سفارش را نهایی کنید.
برای ارسال داده با قالب JSON، مقدار این هدر باید application/json باشد.
X-API-KEY
بله
کلید پذیرنده برای احراز هویت؛ این مقدار را تنها در سمت سرور نگه دارید.
کلید API را در کد سمت مرورگر یا اپلیکیشن موبایل قرار ندهید.
در محیط عملیاتی، درخواستهای سمت سرور را با تعیین مهلت زمانی (timeout) و ثبت گزارش (logging) اجرا کنید.
۰۳ایجاد درخواست پرداخت
POST
برای آغاز پرداخت، این endpoint را فراخوانی کنید و پس از دریافت authority، خریدار را به صفحهٔ پرداخت هدایت کنید (بخش ۴).
https://pay.pexn.ir/v1/payment/request
فیلد
نوع
الزام
توضیح
amount
number
بله
مبلغ اصلی سفارش.
callback_url
string
بله
نشانیای که نتیجهٔ پرداخت پس از انجام آن به آن ارسال میشود. برای پذیرندههایی که از ۱۳ مهر ۱۴۰۵ ثبتنام کردهاند، این نشانی (و نشانی بازگشت در meta) باید روی سایت یا ربات تأییدشده در پنل باشد؛ در غیر این صورت درخواست با خطای 403 و کد callback_mismatch رد میشود.
meta.order_ref
string
پیشنهادی
شناسهٔ سفارش در سامانهٔ شما؛ توصیه میشود یکتا باشد.
پس از دریافت authority در پاسخ مرحلهٔ ۳، در صورت فروش از طریق وب، خریدار را به صفحهٔ پرداخت هدایت کنید و در صورت فروش از طریق ربات تلگرام، او را به پیوند ربات پیاکسا هدایت کنید.
مقدار {authority} باید از پاسخ موفق مرحلهٔ ۳ خوانده شود.
این نشانی تنها برای هدایت خریدار است و نباید از سمت سرور فراخوانی شود.
برای آغاز پرداخت در ربات تلگرام، از پیوند ربات پیاکسا با قالب https://t.me/payexa_bot?start=pay_{authority} استفاده کنید.
https://pay.pexn.ir/startPay?authority={authority دریافتشده در مرحلهٔ ۳}
https://t.me/payexa_bot?start=pay_{authority دریافتشده در مرحلهٔ ۳}
۰۵تأیید تراکنش (Verify)
POST
پس از دریافت callback، این endpoint را فراخوانی کنید و در صورت موفقیت، سفارش را نهایی کنید.
اگر خریدار در مهلت مقرر واریز کرده باشد اما پرداخت بهصورت خودکار تأیید نشده باشد، میتواند پس از پایان مهلت، رسید واریز را
ارسال کند. با تأیید این رسید در پنل توسط شما، همان تراکنش منقضیشده موفق میشود و callback موفق طبق روال معمول به سایت شما ارسال میشود.