Coinland Payمستندات

اتصال هویت مشتری

چرا هر جلسه پرداخت مشتری شما را نام می‌برد، فرایند اتصال، صف بررسی، و سه اندپوینتی که یک اتصال را مدیریت می‌کنند

هر جلسه پرداخت متعلق به یکی از مشتریان خود شماست، و کوین‌لند پی این رابطه را صریح و دائمی می‌کند: اولین باری که یکی از مشتریان شما پرداخت کند، حساب کوین‌لندی که با آن می‌پردازد به customer.id شما متصل می‌شود. از آن پس فقط همان حساب کوین‌لند می‌تواند جلسه‌های آن مشتری را بپردازد، فقط شما می‌توانید این پیوند را قطع کنید، و خود مشتری نمی‌تواند آن را تغییر دهد.

این یک الزام مبارزه با پول‌شویی (AML) است، نه یک بهینه‌سازی. هر پرداخت روی این ریل همیشه به یک مشتری مشخص از یک کسب‌وکار مشخص قابل ردیابی است، و اتصال همان چیزی است که «همان شخص بودن» را از یک حدس به یک واقعیت تبدیل می‌کند.

شیء customer

POST /sessions در هر فراخوانی یک شیء customer می‌خواهد. نه راهی برای انصراف وجود دارد و نه استثنایی برای هیچ کسب‌وکاری: فراخوانی ساخت بدون آن با PAY_CUSTOMER_REQUIRED (۴۲۲) رد می‌شود.

"customer": {
  "id": "user-1042",
  "name": "Hamid Khosravi",
  "native_name": "حمید خسروی",
  "email": "hamid@example.com"
}
فیلدالزامیمحدودیت‌هاچیست
idبله[A-Za-z0-9_.:-]، ۱ تا ۱۲۸شناسه داخلی خود شما برای این مشتری. اتصال برای همیشه بر پایه آن کلید می‌خورد، پس باید در سیستم شما پایدار باشد
nameبله۱ تا ۲۵۵نام کامل مشتری، به خط لاتین
native_nameنه، اما به‌شدت توصیه‌شده۱ تا ۲۵۵نام کامل به خط مادری مشتری. پایه قوی تطبیق نام است، پس هر جا آن را دارید بفرستید
emailبلهیک ایمیل معتبرایمیل مشتری نزد شما. می‌تواند با ایمیل کوین‌لند او فرق داشته باشد

از اینکه این شیء بخشی از قرارداد است، دو قاعده نتیجه می‌شود:

  • هرگز مقدار جایگزین نفرستید. هویتی که می‌فرستید همان هویتی است که متصل می‌شود. یک مقدار مثل "guest" یا "test" یک حساب کوین‌لند واقعی را برای همیشه به هویت اشتباه گره می‌زند — آماده انتشار را ببینید.
  • هویت بخشی از اثر انگشت ایدمپوتنسی است. ارسال دوباره همان reference_id با customer متفاوت PAY_DUPLICATE_REFERENCE (۴۰۹) می‌گیرد، دقیقاً همان‌طور که تغییر مبلغ می‌گرفت.

فرایند اتصال

اولین باری که یک customer.id مشخص به شما پرداخت کند، ویجت میزبانی‌شده پیش از آنکه پرداخت جلو برود یک فرایند اتصال اجرا می‌کند:

پرداخت‌کننده پیوند را دو بار تأیید می‌کند. دو تأیید صریح، هر کدام با یک گزینه «خواندم و متوجه شدم»: اینکه حساب کوین‌لندی که با آن وارد شده متعلق به خود اوست، و اینکه این حساب به‌صورت دائمی به این هویت مشتری نزد کسب‌وکار شما متصل خواهد شد. رضایتِ بی‌سروصدا وجود ندارد — پرداخت‌کننده نمی‌تواند حسابی را متصل کند بی‌آنکه خوانده باشد این کار یعنی چه.

کوین‌لند نام را بررسی می‌کند. یک مقایسه فازی میان name و native_nameای که شما فرستاده‌اید و نام احرازشده (KYC) روی حساب کوین‌لند. پایه قوی این بررسی native_name است، و همین است که فرستادنش ارزش یک ستون اضافه در پایگاه داده شما را دارد.

نتیجه بررسی تعیین می‌کند بعد چه می‌شود.

  • تطبیق — اتصال active می‌شود و پرداخت جلو می‌رود.
  • عدم تطبیق — اتصال pending_review می‌شود: پرداخت رد می‌شود و اتصال در صف بررسی شما می‌ماند. تأیید شما آن را بدون تکرار فرایند از سوی مشتری فعال می‌کند؛ رد شما آن را کنار می‌گذارد.

تکمیل هر پرداخت — چه اولین و چه صدمین — کد دوعاملی (TOTP) پرداخت‌کننده را هم می‌خواهد، همان سطح امنیتی یک برداشت. این مرحله کاملاً سمت ویجت است: ویجت ممکن است TOTP_REQUIRED، TOTP_NOT_ENROLLED یا TOTP_INVALID را به پرداخت‌کننده نشان دهد، و هیچ‌کدام به یکپارچه‌سازی شما نمی‌رسند.

پس از اتصال

وقتی یک اتصال active شد:

  • فقط حساب کوین‌لند متصل‌شده می‌تواند جلسه‌های ساخته‌شده برای آن customer.id را بپردازد. هر حساب دیگری با PAY_BINDING_MISMATCH (۴۰۳) رد می‌شود.
  • مشتری هرگز نمی‌تواند اتصال را تغییر دهد. هیچ گسستن، اتصال دوباره یا انتقالی از سمت مشتری وجود ندارد. فقط شما می‌توانید آن را قطع کنید.
  • از هر طرف فقط یک اتصال زنده. یک customer.id که اتصال زنده دارد نمی‌تواند حساب دومی را متصل کند، و حساب کوین‌لندی که به یکی از مشتریان شما متصل است نمی‌تواند به مشتری دیگری متصل شود — هر دو تلاش PAY_BINDING_CONFLICT (۴۰۹) می‌گیرند.

هر چه در ادامه می‌آید زیر کلید پرداخت‌گیری شما اجرا می‌شود (Authorization: Bearer clpay_live_…)، همان کلیدی که جلسه می‌سازد.

خواندن یک اتصال

curl https://my.coinlandexchange.com/api/pay/v1/customers/user-1042/binding \
  -H "Authorization: Bearer $COINLAND_PAY_KEY"
۲۰۰ موفق
{
  "customer_id": "user-1042",
  "state": "active",
  "binding": {
    "binding_id": "5b8e2f40-7a13-4c96-8d2e-1f6a9c3b70e4",
    "customer_id": "user-1042",
    "payer_id": "7c1e5b90-3f42-4a86-9d05-2b8e4c1f6a37",
    "masked_name": "H**** K****",
    "supplied_name": "Hamid Khosravi",
    "supplied_name_native": "حمید خسروی",
    "supplied_email": "hamid@example.com",
    "status": "active",
    "match_score": "0.94",
    "match_passed": true,
    "bound_at": "2026-08-12T10:15:22.000Z",
    "reviewed_at": null,
    "created_at": "2026-08-12T10:14:03.000Z"
  }
}

state یکی از سه مقدار است:

stateمعناbinding
noneاین customer.id هرگز حسابی متصل نکرده استnull
activeمتصل؛ حساب پیوندخورده می‌تواند پرداخت کندشیء اتصال
pending_reviewتطبیق نام ناموفق بود؛ مشتری تا وقتی شما تعیین تکلیف نکنید نمی‌تواند پرداخت کندشیء اتصال

دو فیلد خواندن دقیقی می‌خواهند:

  • masked_name نام احرازشده حساب کوین‌لند است، ماسک‌شده ("H**** K****"). API هرگز نام کامل حساب یا ایمیل کوین‌لند آن را فاش نمی‌کند — ماسک آن‌قدر هست که شخصی را که قصدش را داشتید بازبشناسید، و آن‌قدر نیست که یک غریبه را شناسایی کند.
  • payer_id همان دستگیره مبهمی است که API پرداخت به مشتری به کار می‌برد، پس یک اتصال بدون هیچ جست‌وجویی آرگومان گیرنده یک پرداخت را به دست شما می‌دهد.

فیلدهای supplied_name، supplied_name_native و supplied_email همان چیزی را بازتاب می‌دهند که شما روی جلسه‌ای که اتصال را ساخت فرستادید — طرفِ شما در مقایسه، در کنار match_score و match_passed که ثبت می‌کنند بررسی چطور گذشت.

بررسی یک اتصال در انتظار

اتصال pending_review یعنی یک آدم واقعی خواست پرداخت کند و نتوانست. این اتصال در دو جا در صف بررسی شما می‌نشیند: زبانه «مشتریان» کنسول کسب‌وکار و API زیر — از هر کدام که با کار شما جور است تعیین تکلیف کنید، نتیجه یکی است.

تأیید
curl -X POST https://my.coinlandexchange.com/api/pay/v1/customers/user-1042/binding/review \
  -H "Authorization: Bearer $COINLAND_PAY_KEY" \
  -H "Content-Type: application/json" \
  -d '{"action": "approve"}'
رد
curl -X POST https://my.coinlandexchange.com/api/pay/v1/customers/user-1042/binding/review \
  -H "Authorization: Bearer $COINLAND_PAY_KEY" \
  -H "Content-Type: application/json" \
  -d '{"action": "reject", "reason": "Name does not match our records"}'

فیلد reason برای reject الزامی است و روی اتصال ثبت می‌شود. پاسخ، اتصالِ به‌روزشده است:

۲۰۰ موفق
{
  "binding": {
    "binding_id": "5b8e2f40-7a13-4c96-8d2e-1f6a9c3b70e4",
    "customer_id": "user-1042",
    "status": "active",
    "reviewed_at": "2026-08-12T11:02:47.000Z"
  }
}
  • تأیید اتصال را فعال می‌کند. مشتری فرایند را دوباره اجرا نمی‌کند — رضایتش را قبلاً داده بود؛ آنچه کم بود تأیید شما بود که ناهم‌خوانی نام مشکلی ندارد. تلاش بعدی او برای پرداخت انجام می‌شود.
  • رد اتصال را کنار می‌گذارد. تلاش بعدی آن مشتری برای پرداخت، با هر حسابی که آن موقع وارد شود، یک فرایند تازه را آغاز می‌کند.

بررسی اتصالی که pending_review نیست PAY_BINDING_STATE (۴۰۹) می‌گیرد: این عمل فقط در همان یک وضعیت مجاز است.

بررسی معوق یعنی یک مشتری مسدود، نه یک کار پس‌زمینه

تا وقتی یک اتصال در pending_review مانده، آن مشتری اصلاً نمی‌تواند به شما پرداخت کند. وب‌هوک binding.review را یک فراخوان به یک انسان بگیرید، نه یک سطر در یک گزارش — پول وقتی می‌رسد که کسی تصمیم بگیرد.

قطع یک اتصال

قطع اتصال یعنی این جمله: «این حساب کوین‌لند دیگر متعلق به این مشتری نیست.»

curl -X DELETE https://my.coinlandexchange.com/api/pay/v1/customers/user-1042/binding \
  -H "Authorization: Bearer $COINLAND_PAY_KEY" \
  -H "Content-Type: application/json" \
  -d '{"reason": "Customer reports the account is no longer theirs"}'
۲۰۰ موفق
{
  "customer_id": "user-1042",
  "state": "revoked"
}

فیلد reason الزامی است: گسستن یک پیوند هویتی یک عمل قابل حسابرسی است، و ثبتِ چرایی کنار ثبتِ چیستی جا دارد.

عمداً هیچ راهی برای نام بردن یک حساب جانشین در همان فراخوانی وجود ندارد. قطع فقط پیوند را می‌گسلد و نه بیشتر؛ دفعه بعدی که آن مشتری پرداخت کند یک فرایند تازه اجرا می‌شود و شخص جدید خودش را همان‌طور اثبات می‌کند که نفر اول کرد — رضایت، تطبیق نام، و اگر بررسی ناموفق بود صف بررسی. APIای که اجازه دهد شما مستقیم یک حساب دلخواه را متصل کنید، به یک کلید لورفته اجازه می‌داد پرداخت‌های یک مشتری را منحرف کند — دقیقاً همان چیزی که فرایند اتصال برای جلوگیری از آن وجود دارد.

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

سه رویداد، با همان سازوکار ارسال و امضای بقیه رویدادها، و با همان هشدار: محتوا یک سرنخ است. پیش از عمل کردن، وضعیت معتبر را از GET /customers/{customer_id}/binding بخوانید.

نوعچه زمانیچه کاری کنید
binding.completedمشتری متصل شد — فرایند با موفقیت گذشت، یا شما یک بررسی را تأیید کردیدمشتری را در سمت خودتان قابل‌پرداخت علامت بزنید
binding.reviewتطبیق نام ناموفق بود؛ مشتری تا تأیید یا رد شما نمی‌تواند پرداخت کندبه یک انسان خبر دهید؛ از کنسول یا اندپوینت بررسی تعیین تکلیف کنید
binding.revokedپیوند گسسته شد — یک قطع یا یک ردمنتظر یک فرایند تازه در پرداخت بعدی مشتری باشید
binding.review
{
  "event_id": "f83a2c16-4d95-4b70-8e21-6c0d9f3a5b48",
  "type": "binding.review",
  "binding_id": "5b8e2f40-7a13-4c96-8d2e-1f6a9c3b70e4",
  "customer_id": "user-1042",
  "status": "pending_review"
}

هر سه رویداد همین شکل را دارند؛ status روی binding.completed برابر active، روی binding.review برابر pending_review، و روی binding.revoked برابر revoked است.

خطاها

کدHTTPمعناچه کاری کنید
PAY_CUSTOMER_REQUIRED۴۲۲POST /sessions بدون شیء customer فراخوانی شددر هر فراخوانی ساخت، id و name و email را بفرستید. راهی برای انصراف وجود ندارد
PAY_BINDING_REQUIRED۴۰۳پرداخت‌کننده پیش از آنکه فرایند او را متصل کند خواست تأیید کندسمت ویجت است؛ پرداخت‌کننده اول فرایند را کامل می‌کند. چیزی در کد شما برای اصلاح نیست
PAY_BINDING_REVIEW۴۰۳اتصال در انتظار بررسی شماست، پس پرداخت رد می‌شودتأیید یا رد کنید — زبانه «مشتریان» کنسول یا اندپوینت بررسی
PAY_BINDING_MISMATCH۴۰۳حساب کوین‌لندی که وارد شده همانی نیست که به این customer.id متصل استمشتری با حساب متصل‌شده وارد شود — یا اگر پیوند واقعاً اشتباه است، شما آن را قطع کنید
PAY_BINDING_CONFLICT۴۰۹این customer.id یا آن حساب کوین‌لند همین حالا یک اتصال زنده دارداتصال را بخوانید و تصمیم بگیرید؛ اگر پیوند موجود اشتباه است اول قطعش کنید
PAY_BINDING_STATE۴۰۹این عمل در وضعیت فعلی اتصال مجاز نیست، مثلاً بررسی یک اتصال فعالاتصال را بخوانید و بر پایه status شاخه بگذارید

مرحله تأیید پرداخت ممکن است TOTP_REQUIRED، TOTP_NOT_ENROLLED یا TOTP_INVALID هم پاسخ بدهد — همان گام دوعاملی که هر پرداختی دارد. این‌ها داخل ویجت به پرداخت‌کننده نشان داده می‌شوند و هرگز به یکپارچه‌سازی شما نمی‌رسند.

«مشتری من حساب کوین‌لندش را عوض کرده»

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

سعی نکنید با ویرایش رکورد مشتری در سمت خودتان اتصال را «منتقل» کنید: یک customer.id تازه برای همان شخص، تاریخچه او را در دفترهای شما دوپاره می‌کند و اتصالِ شناسه قدیمی را زنده باقی می‌گذارد.

فهرست بررسی

  • customer در هر فراخوانی ساخت فرستاده شود، از پایگاه داده مشتریان خودتان، هرگز مقدار جایگزین.
  • هر جا native_name را دارید بفرستید — تطبیق نام به آن تکیه می‌کند.
  • customer.id در تمام عمر مشتری در سیستم شما پایدار بماند.
  • رویداد binding.review به یک انسان خبر بدهد؛ کسی مالک صف بررسی باشد.
  • برای تغییر حساب، تنها ابزار شما قطع اتصال است — قطع کنید و بگذارید فرایند بقیه‌اش را انجام دهد.

در این صفحه