خطاها
یک قالب واحد برای هر خطا، و معنای هر کد PAY_ و MERCHANT_
هر پاسخ غیر ۲xx از کوینلند پی همین شکل را دارد:
{
"statusCode": 422,
"errors": {
"error": ["PAY_CURRENCY_NOT_ACCEPTED"]
}
}errors.error آرایهای از کدهای ماشینیِ پایدار با قالب UPPER_SNAKE است. هیچ پیام خوانا، در هیچ
زبانی، در هیچ جای پاسخ وجود ندارد — و این عامدانه است: مشتریان شما متن شما را میخوانند، نه متن ما. کد را
به جملهای که خودتان نوشتهاید نگاشت کنید، به زبانی که مشتری شما صحبت میکند.
کدها فقط افزوده میشوند. کدی که منتشر شود هرگز معنایش تغییر نمیکند و هرگز تغییر نام نمیدهد، چون ترجمهها و هشدارهای شما بر پایه آنها ساخته شدهاند. کدهای تازه میتوانند ظاهر شوند، پس برای کدهایی که مدیریت میکنید شاخه بگذارید و بقیه را به یک پیام عمومی بسپارید.
خواندن قالب خطا
const res = await fetch(url, init);
if (!res.ok) {
const body = await res.json().catch(() => null);
const code = body?.errors?.error?.[0] ?? "UNKNOWN";
throw new CoinlandPayError(code, res.status);
}دو نکته که ارزش دارد بر پایهشان بسازید:
- آرایه میتواند بیش از یک کد داشته باشد. خطاهای اعتبارسنجی ممکن است چند کد را یکجا گزارش کنند. اولی را برای شاخهبندی بگیرید و همه را ثبت کنید.
- تنها بر پایه کد وضعیت شاخه نگذارید. چند کد یک وضعیت مشترک دارند؛ کد قرارداد است و وضعیت جزئیات انتقال.
کدهای کوینلند پی
جلسههای پرداخت و پرداختها
| کد | HTTP | معنا | چه کاری کنید |
|---|---|---|---|
PAY_SESSION_NOT_FOUND | ۴۰۴ | جلسه یا پرداختی با آن شناسه زیر حساب شما نیست | شناسه را بررسی کنید. جلسهای که به کسبوکار دیگری تعلق دارد هم عامدانه همین پاسخ را میگیرد |
PAY_SESSION_EXPIRED | ۴۲۲ | مهلت جلسه پیش از تأیید مشتری گذشت | جلسه تازه بسازید؛ چیزی رزرو نشده بود |
PAY_SESSION_STATE | ۴۰۹ | این عمل در وضعیت فعلی جلسه مجاز نیست، مثلاً لغو یک جلسه تکمیلشده | جلسه را بخوانید و بر پایه status شاخه بگذارید |
PAY_DUPLICATE_REFERENCE | ۴۰۹ | همان reference_id با محتوای متفاوت فرستاده شد | شناسه تازه نسازید. یا همان محتوای اصلی را بفرستید، یا این را یک سفارش تازه بگیرید |
PAY_CURRENCY_NOT_ACCEPTED | ۴۲۲ | ارزی در amounts در مجموعه پذیرفتهشده شما نیست، در کل پلتفرم غیرفعال است، یا تومان است — این ریل فقط رمزارز است | accepted_currencies را در زمان راهاندازی از GET /me بخوانید و ارزها را در کد ثابت نکنید |
PAY_AMOUNT_INVALID | ۴۲۲ | غیرمثبت، ارقام اعشار بیش از حد آن ارز، یا بیرون از محدودههای پلتفرم — همچنین وقتی درخواست ساخت جلسه هم amounts و هم price_usd را بفرستد، یا هیچکدام را | مبالغ را بهصورت رشته اعشاری و با دقت خودِ آن ارز قالببندی کنید، و دقیقاً یکی از amounts یا price_usd را بفرستید |
PAY_RATE_UNAVAILABLE | ۵۰۳ | price_usd فرستاده شده اما همین حالا هیچ ارز پذیرفتهشدهای قابل قیمتگذاری نیست | دوباره تلاش کنید؛ خودِ درخواست مشکلی ندارد |
PAY_SELF_PAYMENT | ۴۲۲ | حسابی که میخواهد پرداخت کند همان کسبوکاری است که جلسه را ساخته | چیزی در کد شما برای اصلاح نیست؛ یک کسبوکار نمیتواند به خودش پرداخت کند |
PAY_RECEIPT_INVALID | ۴۲۲ | اعتبارسنجی رسید ناموفق بود: امضای نادرست، محتوای تغییریافته، یا پرداخت ناشناس | رسید را نامعتبر بگیرید. یک کد هر سه را پوشش میدهد تا تلاش جعل چیزی یاد نگیرد |
ارسال دوباره و عیناً یکسانِ POST /sessions خطا نیست: همان reference_id با همان محتوا، جلسه اصلی را
با وضعیت موفق برمیگرداند. تنها محتوای تغییریافته PAY_DUPLICATE_REFERENCE را ایجاد میکند.
جلسههای پرداخت را ببینید.
پرداخت به مشتری و بازپرداخت
اینها از جهت پرداخت به مشتری میآیند و به کلیدی از کلاس پرداخت به مشتری نیاز دارند.
| کد | HTTP | معنا | چه کاری کنید |
|---|---|---|---|
MERCHANT_PAYOUTS_DISABLED | ۴۰۳ | پرداخت به مشتری برای کسبوکار شما مسلح نیست، یا مسیر جستوجوی ایمیل برایتان فعال نشده | با کوینلند تماس بگیرید. یک کد، هم ریل غیرفعال و هم کسبوکار معلق و هم روشننبودن پرداخت و هم تنظیمنشدن سقفها را پوشش میدهد — راهحل یکی است |
PAY_WRONG_KEY_KIND | ۴۰۳ | کلید پرداختگیری روی مسیر پرداخت به مشتری به کار رفته، یا برعکس | از کلید کلاس دیگر استفاده کنید. خودِ کلید معتبر است و به همین دلیل این خطا UNAUTHORIZED نیست |
PAY_RECIPIENT_INVALID | ۴۲۲ | گیرنده قابل پرداخت نیست، یا درخواست هر دو مسیر گیرنده را فرستاده، یا هیچکدام | payer_id را بررسی کنید یا جستوجو را تکرار کنید. یک کد، نشانی ناشناس و حساب غیرواجد شرایط و توکن منقضی یا متعلق به کسبوکار دیگر و recipient_confirm ناهمخوان را پوشش میدهد تا نشود با این اندپوینت فهمید چه کسی حساب دارد |
PAY_PAYOUT_LIMIT | ۴۲۲ | عبور از بیشینه هر پرداخت یا سقف ۲۴ ساعت گذشته | پرداخت را در چند روز بشکنید، منتظر پایان بازه بمانید، یا از کوینلند افزایش سقف بخواهید |
PAY_REFUND_EXCEEDS_PAYMENT | ۴۲۲ | جمع بازپرداختها از charged_amount آن پرداخت عبور میکند | جمع بازپرداختهای خودتان از آن پرداخت را با charged_amount مقایسه کنید و فقط باقیمانده را بازپرداخت کنید |
PAY_LOOKUP_THROTTLED | ۴۲۹ | سهمیه جستوجوی گیرنده در آن دقیقه یا آن روز تمام شده است | روی جستوجو عقب بکشید. پرداخت با payer_id تأثیری نمیگیرد |
کدهای INSUFFICIENT_BALANCE (۴۲۲) و PAY_RATE_UNAVAILABLE (۵۰۳) هم روی این سطح دیده میشوند: اولی وقتی
کیفپول کسبوکارتان amount + fee را پوشش نمیدهد، و دومی وقتی ارز نرخ زنده دلاری ندارد و در نتیجه سقفها
قابل اعمال نیستند. پرداخت رد میشود، نه اینکه بدون سنجش برود.
اتصال هویت مشتری
اینها از اتصال هویت پرداختکننده میآیند: شیء الزامی customer روی هر جلسه، و پیوند
دائمی میان customer.id شما و حساب کوینلند پرداختکننده.
| کد | HTTP | معنا | چه کاری کنید |
|---|---|---|---|
PAY_CUSTOMER_REQUIRED | ۴۲۲ | POST /sessions بدون شیء customer فراخوانی شد | در هر فراخوانی ساخت، customer.id و customer.name و customer.email را بفرستید. این شیء برای هر کسبوکاری الزامی است و راهی برای انصراف ندارد |
PAY_BINDING_REQUIRED | ۴۰۳ | پرداختکننده پیش از آنکه فرایند اتصال او را متصل کند خواست پرداخت را تأیید کند | سمت ویجت است؛ پرداختکننده اول فرایند را کامل میکند. چیزی در کد شما برای اصلاح نیست |
PAY_BINDING_REVIEW | ۴۰۳ | اتصال در انتظار بررسی شماست، پس پرداخت رد میشود | در زبانه «مشتریان» کنسول یا با POST /customers/{id}/binding/review تأیید یا رد کنید |
PAY_BINDING_MISMATCH | ۴۰۳ | حساب کوینلندی که وارد شده همانی نیست که به این customer.id متصل است | مشتری با حساب متصلشده وارد شود — یا اگر پیوند واقعاً اشتباه است، شما اتصال را قطع کنید |
PAY_BINDING_CONFLICT | ۴۰۹ | این customer.id یا آن حساب کوینلند همین حالا یک اتصال زنده دارد | اتصال را بخوانید و تصمیم بگیرید؛ اگر پیوند موجود اشتباه است اول قطعش کنید |
PAY_BINDING_STATE | ۴۰۹ | این عمل در وضعیت فعلی اتصال مجاز نیست، مثلاً بررسی یک اتصال فعال | اتصال را بخوانید و بر پایه status شاخه بگذارید |
مرحله تأیید پرداخت ممکن است TOTP_REQUIRED، TOTP_NOT_ENROLLED یا TOTP_INVALID هم پاسخ بدهد —
همان گام دوعاملی که هر پرداختی دارد، همسطح امنیتی یک برداشت. اینها داخل ویجت به پرداختکننده نشان
داده میشوند و هرگز به یکپارچهسازی شما نمیرسند.
حساب کسبوکار شما
| کد | HTTP | معنا | چه کاری کنید |
|---|---|---|---|
MERCHANT_NOT_FOUND | ۴۰۴ | حسابی که این کلید به آن تعلق دارد یک کسبوکار نیست | از پشتیبانی کوینلند ارتقای حساب را بخواهید |
MERCHANT_DISABLED | ۴۰۳ | این کسبوکار در حال حاضر نمیتواند پرداخت بگیرد | با کوینلند تماس بگیرید. یک کد هم کسبوکار معلق و هم ریل غیرفعال در کل پلتفرم را پوشش میدهد؛ تفکیک آنها فقط برای اپراتور است، چون راهحل یکی است |
MERCHANT_KEY_LIMIT | ۴۲۲ | سقف کلیدهای API فعال پر شده است | پیش از ساخت کلید تازه، یکی را در کنسول کسبوکار باطل کنید |
MERCHANT_WEBHOOK_URL_INVALID | ۴۲۲ | https نیست، غیرقابلتحلیل است، یا به یک آدرس خصوصی اشاره میکند | از یک نشانی https قابل دسترسی از اینترنت عمومی استفاده کنید |
MERCHANT_LOGO_INVALID | ۴۲۲ | لوگوی بارگذاریشده بیرون از فهرست مجاز نوع یا اندازه است | محدودیتهای نمایشدادهشده در کنسول را ببینید |
MERCHANT_CONVERT_TARGET_INVALID | ۴۲۲ | ارز مقصد تبدیل خودکار در فهرست مقصدهای مجاز کوینلند نیست | یکی از مقصدهایی را که کنسول پیشنهاد میدهد انتخاب کنید |
MERCHANT_EXISTS | ۴۰۹ | ارتقا روی حسابی انجام شد که پیش از این کسبوکار بوده | کاری لازم نیست؛ حساب شما ارتقا یافته است |
پنج مورد آخر از کنسول کسبوکار میآیند، نه از API کسبوکار. اینجا فهرست شدهاند چون کنسول و API یک قالب خطا و یک فهرست کد مشترک دارند، پس کدی که در مرورگر میبینید همان معنایی را دارد که روی API داشت.
MERCHANT_DISABLED کدی نیست که با تلاش مجدد رد شود
یعنی کوینلند پرداختهای شما را خاموش کرده است، یا مخصوص کسبوکار شما یا در کل پلتفرم. تلاش مجدد آن را برطرف نمیکند. برای مشتریانتان یک حالت «موقتاً در دسترس نیست» نشان دهید و با ما تماس بگیرید.
کدهای عمومی
اینها در سطح پلتفرم هستند و هر اندپوینتی میتواند برگرداندشان.
| کد | HTTP | معنا |
|---|---|---|
UNAUTHORIZED | ۴۰۱ | کلید API غایب، بدشکل، باطلشده یا ناشناس. یک کد برای هر رد شدن در لایه احراز هویت، تا فراخواننده نتواند بفهمد کدام بخش اشتباه بوده |
FORBIDDEN | ۴۰۳ | احراز هویت شده، اما مجاز نیست |
VALIDATION_FAILED | ۴۲۲ | بدنه درخواست از اعتبارسنجی طرحواره رد شد: فیلد الزامی جاافتاده، نوع نادرست، رشته بیش از حد بلند |
RATE_LIMITED | ۴۲۹ | درخواست بیش از حد. پیش از تلاش مجدد با تأخیر تصادفی عقب بکشید |
NOT_FOUND | ۴۰۴ | چنین مسیری وجود ندارد |
CONFLICT | ۴۰۹ | تضاد وضعیت عمومی، جایی که کد مشخصتری کاربرد ندارد |
INTERNAL_SERVER_ERROR | ۵۰۰ | چیزی در سمت ما شکست خورد |
SERVICE_UNAVAILABLE | ۵۰۳ | موقتاً قادر به پاسخدهی نیست. با عقبنشینی تلاش کنید |
MAINTENANCE_MODE | ۵۰۳ | کوینلند در حالت تعمیرات است. خواندن و نوشتن هر دو خاموشاند |
کدام خطاها را دوباره تلاش کنیم
| وضعیت | تلاش مجدد؟ |
|---|---|
| وقفه زمانی یا قطع اتصال | بله، با همان reference_id. ایدمپوتنسی برای همین است |
429 RATE_LIMITED | بله، پس از عقبنشینی با تأخیر تصادفی |
500، 502، 503 | بله، با عقبنشینی نمایی |
| هر ۴xx دیگر | نه. درخواست نادرست است؛ تلاش مجدد بدون تغییر همان پاسخ را میدهد |
وقفه زمانی یک شکست نیست
به شما نمیگوید جلسه ساخته شده یا نه. همان درخواست را عیناً و با همان reference_id دوباره بفرستید: اگر
انجام شده بود جلسه اصلی را میگیرید و اگر نشده بود یک جلسه تازه. ساختن یک شناسه تازه بهجای آن، همان
کاری است که یک سفارش را به دو جلسه پرداخت میرساند.
نگاشت کدها به متن خودتان
نگاشت را در یک جا و بر پایه کد نگه دارید، با یک حالت پیشفرض:
const MESSAGES = {
PAY_SESSION_EXPIRED: "این پرداخت منقضی شده است. برای گرفتن یک پرداخت تازه دوباره شروع کنید.",
PAY_CURRENCY_NOT_ACCEPTED: "در حال حاضر نمیتوانیم این ارز را بپذیریم.",
PAY_AMOUNT_INVALID: "مبلغ سفارش مشکلی دارد.",
MERCHANT_DISABLED: "پرداخت با کوینلند در حال حاضر در دسترس نیست.",
RATE_LIMITED: "تلاشهای بیش از حد. یک دقیقه دیگر امتحان کنید.",
};
// کدی که هرگز ندیدهاید هم باید یک جمله تولید کند، چون کدهای تازه بدون تغییر
// نسخه منتشر میشوند.
export const messageFor = (code) => MESSAGES[code] ?? "پرداخت انجام نشد.";هر چیزی که به مشتری نشان میدهید، کد خام را در کنار شناسه درخواست خودتان ثبت کنید. وقتی با پشتیبانی کوینلند تماس میگیرید، کد بههمراه شناسه جلسه یا پرداخت برای پیدا کردن دقیق آن رویداد کافی است.