نشانی پایه (Base URL)
همه مسیرها نسبت به این آدرس هستند:
https://YOUR-SITE.com/wp-json/darban/v1
تا API را در پنل فعال نکنید، این مسیرها در دسترس نیستند.
۱) فعالسازی API در پنل
- ورود به بخش API از منوی دربان وارد بخش «API توسعهدهنده» شوید.
- فعالسازی تیک «فعالسازی API» را بزنید و ذخیره کنید.
- تولید کلیدها برای کلید API و کلید مخفی روی «تولید» کلیک کنید. کلید مخفی فقط سمت سرور بماند و داخل اپ موبایل قرار نگیرد.
-
امنیت پیشنهادی برای سایت واقعی
- الزام کلید API با هدر X-Darban-Key
- در صورت نیاز، امضای HMAC
- محدودیت تعداد درخواست در دقیقه
- در صورت نیاز، فهرست IP مجاز یا مسدود
| تنظیم | پیشفرض | توضیح |
|---|---|---|
| فعالسازی API | خاموش | ثبت مسیرهای REST |
| کلید API | — | برای هدر X-Darban-Key |
| کلید مخفی | — | امضای JWT و HMAC (فقط سرور) |
| عمر توکن دسترسی | ۳۶۰۰ ثانیه | تقریباً ۱ ساعت |
| عمر توکن تازهسازی | ~۱۴ روز | برای گرفتن توکن جدید بدون ورود دوباره |
| محدودیت نرخ | ۶۰ | درخواست در دقیقه برای هر IP (۰ = بدون سقف) |
۲) مدل احراز هویت
- عمومی: ارسال OTP، تأیید OTP، ثبتنام، ورود با رمز، تازهسازی توکن
- با توکن: خروج، پروفایل و بهروزرسانی پروفایل — با هدر Authorization: Bearer <access_token>
- جایگزین هدر: X-Darban-Authorization: Bearer …
امضای HMAC (اختیاری)
اگر در پنل الزام امضا را روشن کنید:
HMAC-SHA256("{timestamp}.{raw_body}", api_secret)
و هدرهای X-Darban-Timestamp و X-Darban-Signature را بفرستید. اختلاف ساعت بیش از ۵ دقیقه رد میشود.
۳) شکل پاسخ موفق ورود
در ورود موفق معمولاً کاربر و اطلاعات نشست برمیگردد:
{
"success": true,
"code": "login_success",
"message": "…",
"user": {
"id": 12,
"display_name": "علی رضایی",
"email": "ali@example.com",
"username": "09121234567",
"roles": ["customer"],
"phone": "989121234567",
"verified": true
},
"session_data": {
"jwt_token": "<access JWT>",
"refresh_token": "<refresh JWT>",
"wordpress_cookie": false,
"expires_at": 1710000000,
"token_type": "Bearer"
}
}
۴) فهرست اندپوینتها
| روش | مسیر | احراز | بدنه |
|---|---|---|---|
| POST | otp/send | عمومی | phone, dial_code |
| POST | otp/resend | عمومی | phone, dial_code |
| POST | otp/verify | عمومی | phone, dial_code, code |
| POST | otp/register | عمومی | ticket, fields{…} |
| POST | login | عمومی | identifier, password, dial_code |
| POST | token/refresh | عمومی | refresh_token |
| POST | logout | توکن | — |
| GET | profile | توکن | — |
| POST | profile/update | توکن | fields{…} |
| POST | profile/complete | توکن | ticket, fields{…} |
| POST | profile/verify-mobile | توکن | ticket, phone, dial_code, code |
نکته
otp/resend همان کار ارسال کد را انجام میدهد. قبل از ارسال دوباره، مقدار تأخیر پیشنهادی در پاسخ (معمولاً حدود ۶۰ ثانیه) را رعایت کنید.
۵) سناریو: ورود با OTP (کاربر موجود)
- ارسال کد با POST /otp/send
- تأیید کد با POST /otp/verify و ذخیره توکنها
- درخواستهای محافظتشده با Bearer
- تازهسازی توکن وقتی access منقضی شد
POST /otp/send
curl -X POST "https://YOUR-SITE.com/wp-json/darban/v1/otp/send" \
-H "Content-Type: application/json" \
-H "X-Darban-Key: YOUR_API_KEY" \
-H "User-Agent: MyApp/1.0" \
-d "{\"phone\":\"09121234567\",\"dial_code\":\"98\"}"
const base = 'https://YOUR-SITE.com/wp-json/darban/v1';
const res = await fetch(`${base}/otp/send`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Darban-Key': 'YOUR_API_KEY',
'User-Agent': 'MyApp/1.0',
},
body: JSON.stringify({
phone: '09121234567',
dial_code: '98',
}),
});
const data = await res.json();
console.log(data.code, data.user_exists, data.security_data);
<?php
$base = 'https://YOUR-SITE.com/wp-json/darban/v1';
$body = json_encode([
'phone' => '09121234567',
'dial_code' => '98',
]);
$ch = curl_init($base . '/otp/send');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'X-Darban-Key: YOUR_API_KEY',
'User-Agent: MyApp/1.0',
],
CURLOPT_POSTFIELDS => $body,
CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
import requests
base = "https://YOUR-SITE.com/wp-json/darban/v1"
r = requests.post(
f"{base}/otp/send",
headers={
"Content-Type": "application/json",
"X-Darban-Key": "YOUR_API_KEY",
"User-Agent": "MyApp/1.0",
},
json={"phone": "09121234567", "dial_code": "98"},
timeout=30,
)
print(r.json())
import 'dart:convert';
import 'package:http/http.dart' as http;
final uri = Uri.parse('https://YOUR-SITE.com/wp-json/darban/v1/otp/send');
final res = await http.post(
uri,
headers: {
'Content-Type': 'application/json',
'X-Darban-Key': 'YOUR_API_KEY',
'User-Agent': 'MyApp/1.0',
},
body: jsonEncode({'phone': '09121234567', 'dial_code': '98'}),
);
print(jsonDecode(res.body));
POST /otp/verify
curl -X POST "https://YOUR-SITE.com/wp-json/darban/v1/otp/verify" \
-H "Content-Type: application/json" \
-H "X-Darban-Key: YOUR_API_KEY" \
-d "{\"phone\":\"09121234567\",\"dial_code\":\"98\",\"code\":\"12345\"}"
const res = await fetch(`${base}/otp/verify`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Darban-Key': 'YOUR_API_KEY',
},
body: JSON.stringify({
phone: '09121234567',
dial_code: '98',
code: '12345',
}),
});
const data = await res.json();
if (data.code === 'login_success') {
localStorage.setItem('access', data.session_data.jwt_token);
localStorage.setItem('refresh', data.session_data.refresh_token);
}
<?php
$body = json_encode([
'phone' => '09121234567',
'dial_code' => '98',
'code' => '12345',
]);
$ch = curl_init($base . '/otp/verify');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'X-Darban-Key: YOUR_API_KEY',
],
CURLOPT_POSTFIELDS => $body,
CURLOPT_RETURNTRANSFER => true,
]);
$data = json_decode(curl_exec($ch), true);
r = requests.post(
f"{base}/otp/verify",
headers={
"Content-Type": "application/json",
"X-Darban-Key": "YOUR_API_KEY",
},
json={
"phone": "09121234567",
"dial_code": "98",
"code": "12345",
},
)
data = r.json()
access = data.get("session_data", {}).get("jwt_token")
final res = await http.post(
Uri.parse('$base/otp/verify'),
headers: {
'Content-Type': 'application/json',
'X-Darban-Key': 'YOUR_API_KEY',
},
body: jsonEncode({
'phone': '09121234567',
'dial_code': '98',
'code': '12345',
}),
);
final data = jsonDecode(res.body) as Map<String, dynamic>;
۶) سناریو: ثبتنام با OTP (شماره جدید)
- ارسال کد — معمولاً کاربر از قبل وجود ندارد
- تأیید کد — پاسخ تکمیل پروفایل بههمراه ticket و فیلدهای لازم
- ثبتنام با POST /otp/register
POST /otp/register
curl -X POST "https://YOUR-SITE.com/wp-json/darban/v1/otp/register" \
-H "Content-Type: application/json" \
-H "X-Darban-Key: YOUR_API_KEY" \
-d "{\"ticket\":\"TICKET_FROM_VERIFY\",\"fields\":{\"first_name\":\"Ali\",\"last_name\":\"Rezaei\",\"email\":\"ali@example.com\"}}"
const res = await fetch(`${base}/otp/register`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Darban-Key': 'YOUR_API_KEY',
},
body: JSON.stringify({
ticket: ticketFromVerify,
fields: {
first_name: 'Ali',
last_name: 'Rezaei',
email: 'ali@example.com',
},
device_id: 'android-pixel-8',
set_cookie: false,
}),
});
const data = await res.json(); // code: register_success
<?php
$body = json_encode([
'ticket' => $ticket,
'fields' => [
'first_name' => 'Ali',
'last_name' => 'Rezaei',
'email' => 'ali@example.com',
],
]);
// POST {$base}/otp/register with header X-Darban-Key
r = requests.post(
f"{base}/otp/register",
headers={
"Content-Type": "application/json",
"X-Darban-Key": "YOUR_API_KEY",
},
json={
"ticket": ticket,
"fields": {
"first_name": "Ali",
"last_name": "Rezaei",
"email": "ali@example.com",
},
},
)
print(r.json())
final res = await http.post(
Uri.parse('$base/otp/register'),
headers: {
'Content-Type': 'application/json',
'X-Darban-Key': 'YOUR_API_KEY',
},
body: jsonEncode({
'ticket': ticket,
'fields': {
'first_name': 'Ali',
'last_name': 'Rezaei',
'email': 'ali@example.com',
},
}),
);
فرمساز و API
فیلدهای داخل fields باید با فیلدهای بخش «فرمساز» منوی دربان یکی باشند. اگر فرم خالی باشد، عضویت فقط با موبایل انجام میشود.
۷) سناریو: ورود با رمز عبور
ورود با رمز باید در تنظیمات دربان فعال باشد. شناسه میتواند موبایل، ایمیل یا نام کاربری باشد.
POST /login
curl -X POST "https://YOUR-SITE.com/wp-json/darban/v1/login" \
-H "Content-Type: application/json" \
-H "X-Darban-Key: YOUR_API_KEY" \
-d "{\"identifier\":\"09121234567\",\"password\":\"SecretPass123\",\"dial_code\":\"98\"}"
const res = await fetch(`${base}/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Darban-Key': 'YOUR_API_KEY',
},
body: JSON.stringify({
identifier: '09121234567',
password: 'SecretPass123',
dial_code: '98',
}),
});
const data = await res.json();
if (data.code === 'requires_mobile') {
// حساب رمز دارد ولی موبایل تأیید نشده
// ticket را نگه دارید و مسیر تأیید موبایل را ادامه دهید
}
<?php
$body = json_encode([
'identifier' => '09121234567',
'password' => 'SecretPass123',
'dial_code' => '98',
]);
// POST {$base}/login
r = requests.post(
f"{base}/login",
headers={
"Content-Type": "application/json",
"X-Darban-Key": "YOUR_API_KEY",
},
json={
"identifier": "09121234567",
"password": "SecretPass123",
"dial_code": "98",
},
)
print(r.json())
final res = await http.post(
Uri.parse('$base/login'),
headers: {
'Content-Type': 'application/json',
'X-Darban-Key': 'YOUR_API_KEY',
},
body: jsonEncode({
'identifier': '09121234567',
'password': 'SecretPass123',
'dial_code': '98',
}),
);
۸) تازهسازی و خروج
POST /token/refresh
curl -X POST "https://YOUR-SITE.com/wp-json/darban/v1/token/refresh" \
-H "Content-Type: application/json" \
-H "X-Darban-Key: YOUR_API_KEY" \
-d "{\"refresh_token\":\"REFRESH_JWT\"}"
const res = await fetch(`${base}/token/refresh`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Darban-Key': 'YOUR_API_KEY',
},
body: JSON.stringify({
refresh_token: localStorage.getItem('refresh'),
}),
});
const data = await res.json(); // code: token_refreshed
localStorage.setItem('access', data.session_data.jwt_token);
localStorage.setItem('refresh', data.session_data.refresh_token);
<?php
$body = json_encode(['refresh_token' => $refreshJwt]);
// POST {$base}/token/refresh
r = requests.post(
f"{base}/token/refresh",
headers={
"Content-Type": "application/json",
"X-Darban-Key": "YOUR_API_KEY",
},
json={"refresh_token": refresh_jwt},
)
print(r.json())
final res = await http.post(
Uri.parse('$base/token/refresh'),
headers: {
'Content-Type': 'application/json',
'X-Darban-Key': 'YOUR_API_KEY',
},
body: jsonEncode({'refresh_token': refreshJwt}),
);
POST /logout
curl -X POST "https://YOUR-SITE.com/wp-json/darban/v1/logout" \
-H "Authorization: Bearer ACCESS_JWT" \
-H "X-Darban-Key: YOUR_API_KEY"
await fetch(`${base}/logout`, {
method: 'POST',
headers: {
Authorization: `Bearer ${localStorage.getItem('access')}`,
'X-Darban-Key': 'YOUR_API_KEY',
},
});
localStorage.removeItem('access');
localStorage.removeItem('refresh');
<?php
$ch = curl_init($base . '/logout');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $accessJwt,
'X-Darban-Key: YOUR_API_KEY',
],
CURLOPT_RETURNTRANSFER => true,
]);
curl_exec($ch);
requests.post(
f"{base}/logout",
headers={
"Authorization": f"Bearer {access_jwt}",
"X-Darban-Key": "YOUR_API_KEY",
},
)
await http.post(
Uri.parse('$base/logout'),
headers: {
'Authorization': 'Bearer $accessJwt',
'X-Darban-Key': 'YOUR_API_KEY',
},
);
۹) پروفایل
GET /profile
curl -X GET "https://YOUR-SITE.com/wp-json/darban/v1/profile" \
-H "Authorization: Bearer ACCESS_JWT" \
-H "X-Darban-Key: YOUR_API_KEY"
const res = await fetch(`${base}/profile`, {
headers: {
Authorization: `Bearer ${access}`,
'X-Darban-Key': 'YOUR_API_KEY',
},
});
const data = await res.json(); // code: profile
<?php
$ch = curl_init($base . '/profile');
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $accessJwt,
'X-Darban-Key: YOUR_API_KEY',
],
CURLOPT_RETURNTRANSFER => true,
]);
echo curl_exec($ch);
r = requests.get(
f"{base}/profile",
headers={
"Authorization": f"Bearer {access_jwt}",
"X-Darban-Key": "YOUR_API_KEY",
},
)
print(r.json())
final res = await http.get(
Uri.parse('$base/profile'),
headers: {
'Authorization': 'Bearer $accessJwt',
'X-Darban-Key': 'YOUR_API_KEY',
},
);
print(res.body);
POST /profile/update
curl -X POST "https://YOUR-SITE.com/wp-json/darban/v1/profile/update" \
-H "Authorization: Bearer ACCESS_JWT" \
-H "Content-Type: application/json" \
-H "X-Darban-Key: YOUR_API_KEY" \
-d "{\"fields\":{\"first_name\":\"Ali\",\"last_name\":\"Rezaei\",\"display_name\":\"Ali R\",\"user_email\":\"ali@example.com\"}}"
await fetch(`${base}/profile/update`, {
method: 'POST',
headers: {
Authorization: `Bearer ${access}`,
'Content-Type': 'application/json',
'X-Darban-Key': 'YOUR_API_KEY',
},
body: JSON.stringify({
fields: {
first_name: 'Ali',
last_name: 'Rezaei',
display_name: 'Ali R',
user_email: 'ali@example.com',
},
}),
});
<?php
$body = json_encode([
'fields' => [
'first_name' => 'Ali',
'last_name' => 'Rezaei',
'display_name' => 'Ali R',
'user_email' => 'ali@example.com',
],
]);
// POST {$base}/profile/update + Bearer
requests.post(
f"{base}/profile/update",
headers={
"Authorization": f"Bearer {access_jwt}",
"Content-Type": "application/json",
"X-Darban-Key": "YOUR_API_KEY",
},
json={
"fields": {
"first_name": "Ali",
"last_name": "Rezaei",
"display_name": "Ali R",
"user_email": "ali@example.com",
}
},
)
await http.post(
Uri.parse('$base/profile/update'),
headers: {
'Authorization': 'Bearer $accessJwt',
'Content-Type': 'application/json',
'X-Darban-Key': 'YOUR_API_KEY',
},
body: jsonEncode({
'fields': {
'first_name': 'Ali',
'last_name': 'Rezaei',
'display_name': 'Ali R',
'user_email': 'ali@example.com',
},
}),
);
۱۰) نمونه ساخت امضای HMAC
import crypto from 'crypto'; // Node.js
const secret = process.env.DARBAN_API_SECRET;
const body = JSON.stringify({ phone: '09121234567', dial_code: '98' });
const timestamp = Math.floor(Date.now() / 1000).toString();
const signature = crypto
.createHmac('sha256', secret)
.update(`${timestamp}.${body}`)
.digest('hex');
// headers:
// X-Darban-Timestamp: timestamp
// X-Darban-Signature: signature
// X-Darban-Key: YOUR_API_KEY
<?php
$secret = getenv('DARBAN_API_SECRET');
$body = json_encode(['phone' => '09121234567', 'dial_code' => '98']);
$timestamp = (string) time();
$signature = hash_hmac('sha256', $timestamp . '.' . $body, $secret);
import hmac, hashlib, json, time, os
secret = os.environ["DARBAN_API_SECRET"].encode()
body = json.dumps({"phone": "09121234567", "dial_code": "98"}, separators=(",", ":"))
timestamp = str(int(time.time()))
signature = hmac.new(secret, f"{timestamp}.{body}".encode(), hashlib.sha256).hexdigest()
import 'dart:convert';
import 'package:crypto/crypto.dart';
final secret = utf8.encode(apiSecret);
final body = jsonEncode({'phone': '09121234567', 'dial_code': '98'});
final timestamp = (DateTime.now().millisecondsSinceEpoch ~/ 1000).toString();
final signature = Hmac(sha256, secret)
.convert(utf8.encode('$timestamp.$body'))
.toString();
۱۱) کدهای خطای رایج
| code | معنی |
|---|---|
phone_required | شماره ارسال نشده |
invalid_phone / blocked | شماره نامعتبر یا مسدود |
mismatch / expired / too_many | خطای تأیید کد |
ticket_invalid | تیکت منقضی یا استفادهشده |
key_invalid / signature_invalid | کلید یا امضا اشتباه |
rate_limited | سقف درخواست در دقیقه پر شده |
refresh_invalid / refresh_revoked | توکن تازهسازی نامعتبر |
forbidden_role | نقش کاربر مجاز نیست |
phone_in_use | شماره متعلق به کاربر دیگر است |
توجه درباره IP
تشخیص IP از آدرس مستقیم سرور است. اگر پشت CDN هستید، فهرست IP را با دقت تنظیم کنید.
۱۲) چکلیست اتصال اپ
- API در پنل فعال است و Base URL درست است
- درگاه پیامک تست شده و کد واقعی میرسد
- فرمساز با فیلدهای اپ هماهنگ است
- کلید API و کلید مخفی فقط در جای امن نگهداری میشوند
- توکن دسترسی و تازهسازی جدا ذخیره میشوند و روی خطای احراز، refresh اجرا میشود
- بعد از logout، توکنها سمت اپ پاک میشوند