همه چیز برای یکپارچهسازی احراز هویت بلینر در سایت یا اپ شما.
چکلیست اتصال بلینر به سایت یا اپ شما:
ثبتنام کسبوکار
به /dashboard/register بروید، حساب بسازید و وارد داشبورد شوید.
ساخت اپ و دریافت کلیدها
از بخش «اپها» یک اپ جدید بسازید. دامنهٔ مجاز (مثلاً belener.ir) و redirect URIهای روی همان دامنه را ثبت کنید و client_id و client_secret را یکبار کپی کنید (secret فقط همان لحظه نمایش داده میشود).
انتخاب روش یکپارچهسازی
API لینک احراز (سادهتر) یا OIDC استاندارد. هر دو در همین صفحه توضیح داده شدهاند.
تأیید نتیجه در سرور
پس از بازگشت کاربر result_token یا code را در سرور تأیید کنید. اگر کاربر مرورگر را بست، با session_id وضعیت را از POST /api/v1/verify-status پول کنید.
سادهترین روش: یک لینک شخصیسازیشده برای کاربر بسازید و او را به آنجا هدایت کنید. نیازی به پیادهسازی OIDC ندارید. نتیجه را هم از بازگشت مرورگر (result_token) و هم با پول session_id میتوانید بگیرید — حتی اگر کاربر مرورگر را بسته باشد.
| پارامتر | نوع | توضیح |
|---|---|---|
| client_id | string | شناسه اپ شما |
| client_secret | string | کلید محرمانه اپ (فقط server-side) |
| redirect_url | string (URL) | آدرس بازگشت پس از احراز |
| level | 1 | 2 | 3 | سطح احراز موردنیاز |
| mobile | string | شماره موبایل کاربر — در صفحهٔ بلینر با OTP پیامکی تأیید میشود (غیرقابل ویرایش توسط کاربر) |
{
"verify_url": "https://belener.ir/verify/uuid",
"session_id": "uuid",
"expires_at": "2024-01-01T12:30:00Z"
}لینک verify_url را به کاربر نمایش دهید یا مستقیماً redirect کنید. اعتبار لینک ۳۰ دقیقه است.
پس از احراز هویت موفق، کاربر به redirect_url با پارامتر ?result_token=... برمیگردد. اعتبار توکن ۳۰ دقیقه است.
result_token با کلید داخلی بلینر امضا میشود. شما به آن کلید دسترسی ندارید — حتماً از POST /api/v1/verify-result با client_id و client_secret خودتان تأیید کنید.| پارامتر | نوع | توضیح |
|---|---|---|
| client_id | string | شناسه اپ شما |
| client_secret | string | کلید محرمانه اپ |
| result_token | string | توکن برگشتی در query string |
پاسخ موفق (200) — در این لحظه هزینه از کیفپول شما کسر میشود (احراز اول / دسترسی مجدد؛ تکرار همان کاربر رایگان است):
{
"sub": "user-uuid",
"level": 2,
"session_id": "session-uuid",
"client_id": "cl_YOUR_CLIENT_ID",
"user": {
"phone_number": "09123456789",
"name": "علی رضایی",
"national_id": "0012345678",
"card_number": "6037990000000006",
"card_numbers": [
"6037990000000006",
"6219861012345678"
],
"verification_level": 2
},
"billing": {
"type": "verify",
"charged": 20000
}
}فیلد card_number کارت فعال/اولویتدار است؛card_numbers آرایهٔ کارتهایی است که کاربر در صفحهٔ احراز انتخاب کرده (میتواند یک کارت یا همهٔ کارتهای تأییدشده باشد).
session_id را هنگام ساخت لینک ذخیره کنید و از سرور خود وضعیت را بپرسید. اگر کاربر مرورگر را ببندد، پس از تأیید کارشناس همین API نتیجه را برمیگرداند — وابسته به ریدایرکت مرورگر نیستید.
completed یا failed متوقف شوید. این درخواست فقط server-side است.| پارامتر | نوع | توضیح |
|---|---|---|
| client_id | string | شناسه اپ شما |
| client_secret | string | کلید محرمانه اپ |
| session_id | string | همان مقدار برگشتی از POST /api/v1/verify |
مقدار status:
| status | معنی |
|---|---|
| pending | کاربر هنوز احراز را تمام نکرده |
| awaiting_review | مدارک در صف بررسی کارشناس است |
| needs_fix | نیاز به اصلاح مدرک — کاربر باید برگردد |
| completed | موفق — فیلد user مثل verify-result پر است |
| failed | رد نهایی — فیلد reason را ببینید |
اگر نشست منقضی یا ناشناخته باشد پاسخ 404 session_not_found است. در صف بررسی، نشست تا ۲۴ ساعت زنده میماند.
// ۱) ساخت لینک احراز هویت
const res = await fetch('https://belener.ir/api/v1/verify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
client_id: 'cl_YOUR_CLIENT_ID',
client_secret: 'YOUR_CLIENT_SECRET',
redirect_url: 'https://belener.ir/kyc-callback',
level: 2, // سطح احراز موردنیاز: 1، 2، یا 3
mobile: '09123456789', // شماره موبایل احرازشده توسط شما
}),
});
const { verify_url, session_id, expires_at } = await res.json();
// کاربر را به verify_url هدایت کنید
// پس از احراز، به redirect_url با ?result_token=... بازمیگردد
// session_id را در سرور خود ذخیره کنید — اگر کاربر مرورگر را بست، با آن وضعیت را پول کنید
// ۲الف) تأیید result_token در سرور (هرگز در مرورگر) — بعد از بازگشت کاربر
const verify = await fetch('https://belener.ir/api/v1/verify-result', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
client_id: 'cl_YOUR_CLIENT_ID',
client_secret: 'YOUR_CLIENT_SECRET',
result_token: req.query.result_token,
}),
});
const data = await verify.json();
// data: { sub, level, session_id, client_id, user: { phone_number, name, national_id, card_number, card_numbers, verification_level } }
// ۲ب) پول وضعیت با session_id (حتی اگر کاربر مرورگر را بسته باشد)
const poll = await fetch('https://belener.ir/api/v1/verify-status', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
client_id: 'cl_YOUR_CLIENT_ID',
client_secret: 'YOUR_CLIENT_SECRET',
session_id,
}),
});
const status = await poll.json();
// status.status: pending | awaiting_review | needs_fix | completed | failed
// اگر completed باشد همان فیلدهای user را دارد — دیگر به بازگشت مرورگر وابسته نیستیداگر سیستم شما از OpenID Connect پشتیبانی میکند (مثل WordPress، Laravel، Django)، از Discovery URL استفاده کنید:
https://belener.ir/.well-known/openid-configuration
/oidc/authorize با پارامترهای مناسب هدایت کنید.redirect_uri با پارامتر code./oidc/token (server-side)./oidc/userinfo.| Scope | Claims دریافتی |
|---|---|
| openid | sub (همیشه الزامی) |
| profile | name, given_name, family_name |
| mobile | phone_number, phone_number_verified |
| national_id | national_id (اگر احراز شده باشد) |
| card_number | card_number (کارت فعال) و card_numbers (آرایهٔ کارتهای تأییدشده) |
| verification_level | verification_level (سطح ۰ تا ۳) |
| Endpoint | Method | احراز هویت | توضیح |
|---|---|---|---|
| /.well-known/openid-configuration | GET | — | OIDC Discovery |
| /oidc/authorize | GET | — | شروع جریان OAuth |
| /oidc/token | POST | client_secret | دریافت access/id token |
| /oidc/userinfo | GET | Bearer token | اطلاعات کاربر |
| /oidc/jwks | GET | — | کلیدهای عمومی JWT |
| /api/v1/verify | POST | client_id + secret | ساخت لینک احراز مستقیم |
| /api/v1/verify-result | POST | client_id + secret | تأیید result_token |
| /api/v1/verify-status | POST | client_id + secret | پول وضعیت نشست با session_id |
| /api/v1/queue-status | GET | — | وضعیت صف احراز هویت |
پاسخهای خطا بهصورت JSON با فیلدهای error و error_description برمیگردند.
| error | HTTP | معنی |
|---|---|---|
| invalid_request | 400 | بدنه یا پارامترها نامعتبر (مثلاً redirect_url در لیست مجاز نیست یا دامنهٔ اپ مطابقت ندارد) |
| invalid_client | 401 | client_id یا client_secret اشتباه / غیرفعال |
| unauthorized_client | 403 | کلاینت سیستمی یا حساب تعلیقشده |
| invalid_token | 401 | result_token نامعتبر، منقضی، یا متعلق به این client نیست |
| session_not_found | 404 | session_id نامعتبر، منقضی، یا متعلق به این اپ نیست |
| insufficient_balance | 403 | موجودی کیفپول کسبوکار برای تحویل نتیجه کافی نیست |
| rate_limited | 429 | تعداد درخواست بیش از حد — کمی بعد دوباره تلاش کنید |
redirect_url باید دقیقاً با یکی از آدرسهای ثبتشده در تنظیمات اپ مطابقت داشته باشد (شامل پروتکل و path)، و hostname آن باید روی دامنهٔ مجاز همان اپ باشد (مثلاً belener.ir). سابدامین مجاز است.mobile وارد کند؛ بدون تأیید پیامک، مراحل KYC شروع نمیشود.هر سطح مشخص میکند چه scopeهایی باید درخواست شوند و چه claimsهایی در پاسخ برمیگردند. scope openid همیشه الزامی است و در همه سطوح وجود دارد.
احراز نشده
کاربر هنوز هیچ اطلاعاتی ارائه نداده است.
هویت و کارت بانکی
تطابق موبایل ↔ کد ملی (شاهکار) و تطابق کد ملی ↔ شماره کارت بانکی؛ تأیید خودکار
Scopes موردنیاز
Claims دریافتی
مدرک شناسایی
تطابق کد ملی، نام، نام خانوادگی و عکس کارت ملی / شناسنامه / مدرک شناسایی
Scopes موردنیاز
Claims دریافتی
ویدیویی (کامل)
همه مراحل سطح ۲ بهعلاوه ویدیو سلفی با جمله احراز هویت
Scopes موردنیاز
Claims دریافتی
verify-result یا verify-status برمیگردد. هر بار ارسال کد تأیید موبایل در صفحهٔ احراز از کیفپول صاحب API کسر میشود: پیامک (۱۶۴ تومان) یا تماس صوتی (۹۷۰ تومان). هر شماره در هر ساعت حداکثر دو بار میتواند کد بگیرد.نمونهکد کامل برای فریمورکها و زبانهای مختلف. همه از Discovery URL و استاندارد OIDC استفاده میکنند.
import { Issuer, generators } from 'openid-client';
const issuer = await Issuer.discover('https://belener.ir');
const client = new issuer.Client({
client_id: 'cl_YOUR_CLIENT_ID',
client_secret: 'YOUR_CLIENT_SECRET',
redirect_uris: ['https://belener.ir/callback'],
response_types: ['code'],
});
// ۱. هدایت کاربر به صفحه احراز
const code_verifier = generators.codeVerifier();
const code_challenge = generators.codeChallenge(code_verifier);
const url = client.authorizationUrl({
scope: 'openid profile mobile national_id card_number verification_level',
code_challenge,
code_challenge_method: 'S256',
});
res.redirect(url);
// ۲. در callback: دریافت توکن
const params = client.callbackParams(req);
const tokenSet = await client.oauthCallback(
'https://belener.ir/callback',
params,
{ code_verifier }
);
const user = tokenSet.claims(); // { sub, phone_number, name, verification_level }https://belener.ir/.well-known/openid-configuration