پرداختها
مدل انتقال داخلی، کارمزدی که amount را از net_amount جدا میکند، و شماره رسید برای چیست
پرداخت آن چیزی است که یک جلسه پرداخت تکمیلشده بهجا میگذارد: یک رکورد تغییرناپذیر از ارزشی که از یک حساب کوینلند به حساب دیگر منتقل شده است. این شیء معتبرِ این API است و همان چیزی است که هر وبهوک به شما میگوید بیایید و بخوانید.
مدل انتقال داخلی
هر دو طرف یک پرداخت کوینلند پی حسابهای کوینلند هستند — حساب مشتری و حساب شما. پس پرداخت یک بدهکار و یک بستانکار در دفتر حساب خودِ کوینلند است که با هم ثبت میشوند:
┌──▶ fee_amount (Coinland)
payer ── amount ──────┤
└──▶ net_amount (merchant)هیچ چیزی به بلاکچین نمیرسد. این چهار پیامد را دارد که ارزش دارد بر پایهشان طراحی کنید:
- در یک مرحله تسویه میشود. نه وضعیت در انتظار وجود دارد، نه شمارش تأییدیه، نه mempool. تا زمانی که
ویجت به مشتری بگوید پرداخت انجام شد، پول در موجودی شماست و
GET /payments/{id}پاسخ میدهد. - در هیچ اندازهای کارمزد شبکه ندارد. انتقال ۴ تتر همانقدر هزینه دارد که ۴٬۰۰۰ تتر، و همین پرداختهای خرد را به شکلی ممکن میکند که یک ریل روی زنجیره نمیتواند.
- قابل بازگشت نیست. نه چارجبک وجود دارد و نه فراخوانی بازگشت در این API. بازپرداخت یک انتقال است که خودتان و به تشخیص خودتان از موجودی خودتان میفرستید.
- فقط پرداختهای تکمیلشده اینجا وجود دارند. شیء «پرداخت در انتظار» برای استعلام وجود ندارد. جلسهای
که پرداخت نشده،
payment: nullدارد، و انتقال یا بهصورت اتمیک انجام میشود یا هرگز انجام نمیشود.
پرداختها به یک کیفپول کسبوکارِ اختصاصی واریز میشوند که از موجودی اسپات و معاملاتی شخصی شما جدا نگه داشته میشود، تا درآمد یک کسبوکار با پول شخصی قاطی نشود. برای بررسی رسیدن یک پرداخت، همین کیفپول جایی است که باید نگاه کنید.
بیرون بردن درآمدتان
کیفپول کسبوکار آنچه دریافت کردهاید را نگه میدارد؛ خودش مقصد برداشت نیست. بیرون بردن پول دو مرحله دارد و مرحله دوم همان کاری است که همیشه میکردید:
از کسبوکار به کیفپول اصلی انتقال دهید، در کنسول کسبوکار. این جابهجایی بین دو دفتر حساب خودِ ماست، پس فوری و بدون کارمزد است — نه کارمزد شبکهای، نه صرافی بیرونی، نه انتظار.
از کیفپول اصلی معامله یا برداشت کنید، دقیقاً مثل قبل. هیچ چیزی در آن مسیر تغییر نکرده است.
برداشت مستقیم از کیفپول کسبوکار وجود ندارد، و این عامدانه است
نمیتوانید مستقیماً از کیفپول کسبوکار برداشت کنید، و این نبودن طراحی است نه کمبود: به این ترتیب یک مسیر برداشت باقی میماند، همان که میشناسید، بهجای اینکه یک مقصد برداشت دوم با قواعد خودش اضافه شود. اول انتقال دهید، بعد برداشت کنید.
مبلغ، کارمزد و مبلغ خالص
`amount` ارزش سفارش است، نه آنچه از پرداختکننده کسر شد
اگر تا امروز بر پایه amount مغایرتگیری میکردهاید، این را بخوانید. amount عددی است که شما
قیمت گذاشتهاید. آنچه واقعاً از مشتری کسر شده charged_amount است، و وقتی
fee_bearer برابر "customer" باشد بزرگتر است. برای دفتر حساب خودتان همیشه net_amount فیلد
درست بوده و هست؛ برای «مشتری من چقدر پرداخت کرد» به charged_amount سوئیچ کنید.
چهار عدد بههمراه پرچمی که آنها را به هم پیوند میدهد، و اشتباه گرفتنشان رایجترین باگ مغایرتگیری در هر ریل پرداختی است:
نام
نوع
کارمزد را چه کسی میپردازد
برای هر کسبوکار خودتان انتخاب میکنید که کارمزد کوینلند را جذب کنید یا به مبلغ مشتری اضافه شود. یک اتحاد در هر دو حالت برقرار است و کل مدل حسابداری همین است:
charged_amount - net_amount == fee_amountfee_bearer | از مشتری کسر میشود | شما دریافت میکنید |
|---|---|---|
merchant | charged_amount == amount | net_amount == amount - fee_amount |
customer | charged_amount == amount + fee_amount | net_amount == amount |
پس مبالغ سفارش را با amount، دفتر حساب خودتان را با net_amount، و هر پرسشی از جنس «مشتری
چقدر پرداخت کرد» را با charged_amount مغایرتگیری کنید. استفاده از یک فیلد برای هر سه، همان
چیزی است که دفتر حساب را دچار انحراف میکند.
نرخ کارمزد شما از کجا میآید
نرخ شما عدد ثابتی نیست و خودتان نمیتوانید تعیینش کنید. از یک نردبان پلکانی میآید که بر پایه حجم و تعداد پرداختهای ۳۰ روز اخیر شما بهصورت خودکار جابهجا میشود — هرچه بیشتر معامله کنید، خودبهخود پله پایینتر میروید. پله فعلی و پیشرفت شما تا پله بعدی در کنسول کسبوکار نمایش داده میشود.
نرخ شما در لحظه ساخت جلسه تثبیت میشود
نرخ مؤثر و اینکه کارمزد را چه کسی میپردازد، در لحظه ساخت جلسه پرداخت روی همان جلسه تثبیت میشوند و تأیید نهایی بر همان تصویر ثبتشده تسویه میکند. نتیجهای که باید بر پایهاش طراحی کنید:
تغییر نرخ روی جلسه بعدی شما اثر میگذارد، نه روی جلسهای که از قبل باز است.
این مهم است چون نردبان خودش و در یک بازبینی شبانه جابهجا میشود، در حالی که یک جلسه میتواند تا ۲۴ ساعت زنده بماند. بدون این تثبیت، مبلغی که در ویجت نمایش داده شده و مبلغی که در نهایت کسر میشود میتوانستند با هم نخوانند. با آن، مشتریای که به یک پرداخت باز نگاه میکند دقیقاً همان شرایطی را میپردازد که به او اعلام شده بود.
این همان تضمینی است که قیمتهای ارزی در یک جلسه دلاری از قبل دارند، در همان
بازه — مهلت خودِ جلسه (expires_at). یک مهلت، نه دو تا.
چون شرایط پیش از جابهجا شدن پول تثبیت شدهاند، تغییر نرخ گذشته را هم بازنویسی نمیکند: fee_amount
یک پرداخت قدیمی برای همیشه قطعی است و گزارشی که ماه پیش گرفتهاید امروز هم همان پاسخ را میدهد.
هر چهار مبلغ رشته اعشاریاند و باید تا رسیدن به پایگاه داده شما رشته بمانند. آنها را با یک نوع اعشاری دقیق پارس کنید، هرگز با عدد شناور — بخش مدیریت مبالغ در آماده انتشار را ببینید.
نگه داشتن فقط استیبلکوین
میتوانید برای هر کسبوکار انتخاب کنید که هر ارزی دریافت میکنید بهصورت خودکار به تتر (USDT) فروخته شود، تا موجودیتان در یک دارایی بماند و هر ارزی که مشتریانتان پرداخت کردهاند روی هم انباشته نشود. این قابلیت بهصورت پیشفرض خاموش است و خودتان در کنسول کسبوکار روشنش میکنید. در حال حاضر تتر تنها مقصد مجاز است — این فهرست را اپراتور تعیین میکند، نه شما.
پس از تسویه هر پرداخت چه اتفاقی میافتد:
- کوینلند
net_amountهمان پرداخت را از کیفپول کسبوکار به کیفپول اسپات شما منتقل میکند، آنجا یک سفارش فروش بازار (اسپات) معمولی از طرف شما ثبت میکند، و حاصل را به کیفپول کسبوکار برمیگرداند. - این کار در یک بازبینی دورهای و کمی بعد از تسویه انجام میشود و فروش بهصورت غیرهمگام تسویه میشود — پس پیش از نشستن تتر در کیفپول کسبوکار یک حالت «در جریان» وجود دارد. نه بلافاصله است و نه در بازهای تضمینشده.
تبدیل یک معامله است، نه یک انتقال
با قیمت لحظهای بازار اجرا میشود و کارمزد معمول معاملات اسپات را میپردازد. نه رایگان است و نه نرخش قفل شده: قیمتهای یک جلسه دلاری و شرایط کارمزد شما هر دو در لحظه ساخت جلسه تثبیت میشوند، اما این فروش بعد از آن و با نرخ همان لحظه بازار انجام میشود. هیچ بخشی از تبدیل از پیش اعلام نمیشود.
سه حالت اصلاً تبدیل نمیشوند و در هر سه، ارز بهسادگی در موجودی شما میماند:
| حالت | چه میشود |
|---|---|
| پرداخت از ابتدا با همان ارز مقصد شما رسیده | چیزی برای فروش نیست |
| مبلغ کمتر از حداقل بازار است | بیدرنگ بهعنوان خردهمانده میماند — انتظار کمکی نمیکند |
| بازار در دسترس نیست یا فروش شکست میخورد | هر ۱۵ دقیقه، تا ۵ بار تلاش میشود و بعد برای همیشه رها میشود — و ارز به کیفپول کسبوکار شما برگردانده میشود |
تبدیل روی یک پرداختِ تسویهشده سوار میشود، هرگز شرط آن نیست
این همان نکتهای است که باید با خود ببرید. پرداخت در همان لحظه تسویه قطعی است و درستی یک پرداخت
هرگز به باز بودن بازار وابسته نیست. تبدیلی که رد شود، شکست بخورد یا اصلاً اجرا نشود، پرداخت را
completed و پول را مال شما باقی میگذارد — فقط همان ارز اولیه را نگه میدارید. نه بازگشتی وجود
دارد و نه کسر بعدی.
هیچ اعلانی هم در هیچ حالتی برایتان فرستاده نمیشود: نه ایمیلی هست و نه وبهوکی برای تبدیل. نتیجه و
دلیل آن (already-stable، below-min، market-unavailable، target-invalid،
attempts-exhausted) در کنسول کسبوکار ثبت میشود، و اگر ارزی که انتظار داشتید تبدیل شود هنوز در
موجودیتان مانده، همانجا را نگاه کنید.
آستانه خردهمانده همان حداقل بازارِ آن جفتارز است و در هیچ سطح رو به کسبوکاری منتشر نمیشود — از
پیش نمیتوانید حساب کنید که یک پرداخت مشخص تبدیل خواهد شد یا نه. آنچه به دست میآورید نتیجه است، که با
below-min ثبت میشود.
چون این فروش یک سفارش معمولی در حساب خودتان است، در تاریخچه معاملات عادی شما و کنار هر معامله دیگری
دیده میشود، و کارمزدش هم همانجا قابل مغایرتگیری است. هر رکورد تبدیل، order_id معاملهای را هم که
به آن تبدیل شده همراه دارد، پس میتوانید یک پرداخت مشخص را به یک معامله مشخص وصل کنید. توجه کنید که
این کارمزد، کارمزد معامله است و کاملاً از fee_amount جداست، که کارمزد کوینلند روی خودِ پرداخت
است.
این تنظیم در کنسول کسبوکار انجام و خوانده میشود و عامداً بخشی از API کسبوکار نیست: نه
GET /me و نه شیء پرداخت آن را گزارش میکنند، چون تبدیل چیزی است که بعداً برای موجودی شما رخ میدهد،
نه خاصیتی از خودِ پرداخت.
شماره رسید
هر پرداخت در کنار شناسه یکتای خود یک شماره رسید خوانا هم میگیرد:
CLP-8F3K2M9Qاین شماره برای گفتن با صدای بلند و تایپ دستی طراحی شده است: چیزی است که مشتری در ایمیل پشتیبانی نقل میکند و کارشناس شما در کادر جستوجو میچسباند. برخلاف شناسه یکتا، کوتاه است و از این مسیر سالم بیرون میآید.
همچنین یک شناسه جستوجو است. GET /api/pay/v1/payments/{id} هر دو را میپذیرد:
# با شناسه یکتا
curl .../api/pay/v1/payments/b92e4d17-6c38-4a05-9f2b-1e7d3c8a5049 \
-H "Authorization: Bearer $COINLAND_PAY_KEY"
# با شماره رسید — همان رکورد
curl .../api/pay/v1/payments/CLP-8F3K2M9Q \
-H "Authorization: Bearer $COINLAND_PAY_KEY"شماره رسید محرمانه نیست و اطلاعات محرمانه هم نیست. دانستن آن بهتنهایی چیزی را اثبات نمیکند، و توکن رسید امضاشده برای همین کار وجود دارد.
فهرست کردن پرداختها
GET /api/pay/v1/payments پرداختهای شما را از جدید به قدیم و با صفحهبندی مکاننما برمیگرداند:
curl "https://my.coinlandexchange.com/api/pay/v1/payments?limit=100¤cy=usdt&from=2026-08-01T00:00:00Z" \
-H "Authorization: Bearer $COINLAND_PAY_KEY"{
"data": [
{
"id": "b92e4d17-6c38-4a05-9f2b-1e7d3c8a5049",
"receipt_no": "CLP-8F3K2M9Q",
"session_id": "3a7f21e8-9c04-4d6b-8e15-7b2a9f3c1d60",
"reference_id": "order-10492",
"status": "completed",
"currency": "usdt",
"amount": "24.90",
"charged_amount": "24.90",
"fee_amount": "0.12",
"fee_bearer": "merchant",
"net_amount": "24.78",
"metadata": { "cart_id": "c_88213" },
"receipt": "v1.eyJwYXltZW50X2lkIjoi...",
"paid_at": "2026-08-11T12:04:31Z"
}
],
"next_cursor": "eyJwYWlkX2F0IjoiMjAyNi0wOC0xMVQxMjowNDozMVoifQ"
}با دنبال کردن next_cursor صفحهها را بخوانید تا وقتی که null برگردد. صفحهها را نشمارید و اندازه صفحه
را فرض نگیرید: همان مکاننمایی را که به شما داده شده بفرستید، و وقتی مکاننمایی نبود متوقف شوید.
from و to بازه paid_at را محدود میکنند و currency به یک ارز فیلتر میکند. با هم همان چیزی هستند
که با آن گزارش تسویه روزانه میسازید:
const API = "https://my.coinlandexchange.com";
export async function* allPayments(params: Record<string, string>) {
let cursor: string | null = null;
do {
const query = new URLSearchParams({ ...params, limit: "100" });
if (cursor) query.set("cursor", cursor);
const page = await fetch(`${API}/api/pay/v1/payments?${query}`, {
headers: { Authorization: `Bearer ${process.env.COINLAND_PAY_KEY}` },
}).then((r) => r.json());
yield* page.data;
cursor = page.next_cursor; // stop when it comes back null
} while (cursor);
}مغایرتگیری
پرداختها reference_id شما را همراه دارند، پس مغایرتگیری به هیچ شناسهای که خودتان انتخاب نکردهاید نیاز
ندارد:
- پرداختهای یک روز را با
fromوtoبخوانید. - هر
reference_idرا به یک سفارش در سیستم خودتان وصل کنید. - بررسی کنید
amountبا آنچه برای آن سفارش در آن ارز مطالبه کردهاید یکی است. net_amountرا به تفکیک ارز جمع بزنید و با بستانکاریهای کیفپول کسبوکار خود مقایسه کنید.
سفارشی که پرداختی ندارد هرگز پرداخت نشده است. پرداختی که سفارشی ندارد همان موردی است که باید بررسی شود، و
تقریباً همیشه یعنی یک reference_id دوباره استفاده شده یا جایی تولید شده که انتظارش را نداشتهاید.