6.9 KiB
Subscription API
مدیریت پنلهای اشتراکی (Free / Basic / Professional).
GET /api/v1/subscription/plans
لیست پنلها با دورههای فعال (عمومی — بدون auth).
پلن
free: همه امکانات (patient_records,services,sms_panel,insurance) فعالاند؛ تنها محدودیت آن تعداد منشی (max_secretaries) است.
Response 200:
{
"success": true,
"data": [
{
"uuid": "...",
"name": "free",
"level": 0,
"max_secretaries": 1,
"features": { "patient_records": true, "services": true, "sms_panel": true, "insurance": true },
"active": true,
"periods": []
},
{
"uuid": "...",
"name": "basic",
"level": 1,
"max_secretaries": 3,
"features": { "patient_records": true, "services": true, "sms_panel": false },
"active": true,
"periods": [
{
"uuid": "...",
"plan_uuid": "...",
"label": "یک ماهه",
"duration_months": 1,
"price_rials": 290000,
"is_trial": false,
"active": true,
"sort_order": 1
}
]
}
]
}
GET /api/v1/subscription/my
اشتراک فعال کاربر جاری.
Permission: IS_AUTHENTICATED_FULLY
نکته: از نسخه فعلی، این endpoint برای ROLE_SECRETARY نیز کار میکند. منشی از طریق UserActiveContextRepository به db_uuid entity مربوطه (doctor یا clinic) دسترسی پیدا میکند و اشتراک همان entity برگردانده میشود.
Response 200:
{
"success": true,
"data": {
"subscription": {
"uuid": "...",
"plan": { "name": "basic", "level": 1, "max_secretaries": 3, "features": {...} },
"period": { "label": "یک ماهه", "duration_months": 1, "price_rials": 290000 },
"is_trial": false,
"starts_at": 1718000000,
"expires_at": 1720678400,
"days_remaining": 30,
"is_active": true
},
"used_trial": false,
"effective_plan": { "name": "basic", "level": 1, "max_secretaries": 3, "features": {...} }
}
}
اگر اشتراک فعالی نداشت subscription برابر null است، اما effective_plan همیشه مقدار دارد: پلن اشتراک فعال، یا در نبود اشتراک، پلن پیشفرض free. فرانتاند برای تعیین دسترسی به امکانات (hasFeature) باید از effective_plan استفاده کند (نه subscription) تا کاربرانِ بدون اشتراک هم امکانات پلن free را داشته باشند. subscription/hasPlan صرفاً برای نمایش وضعیت اشتراک پولی است.
POST /api/v1/subscription/trial
فعالسازی تریال رایگان (یکبار برای هر entity).
Permission: IS_AUTHENTICATED_FULLY
Response 201: همان ساختار ClinicSubscription
Errors:
| Code | HTTP | توضیح |
|---|---|---|
| ERR_TRIAL_ALREADY_USED | 422 | قبلاً از تریال استفاده شده |
| ERR_TRIAL_DISABLED | 422 | تریال غیرفعال است — یا SiteConfig: trial_enabled=0، یا پلن basic هیچ دورهٔ تریالِ active ندارد |
| ERR_FORBIDDEN_001 | 403 | پروفایل doctor/clinic یافت نشد |
| ERR_NOT_FOUND_001 | 500 | پلن basic وجود ندارد یا غیرفعال است (نصب ناقص) |
POST /api/v1/subscription-payment
شروع پرداخت اشتراک.
Permission: IS_AUTHENTICATED_FULLY
Request Body:
{
"gateway": "mellat",
"amount_rials": 290000,
"period_uuid": "uuid-of-subscription-period",
"frontend_address": "https://example.com/payment-result"
}
| فیلد | نوع | الزامی |
|---|---|---|
| gateway | string (mellat|sep) | ✅ |
| amount_rials | integer | ✅ |
| period_uuid | string (UUID) | ✅ |
| frontend_address | string (URL) | ❌ |
Response 200:
{
"success": true,
"data": {
"payment_uuid": "...",
"redirect_url": "https://gateway.shaparak.ir/...",
"order_id": "ORD-XXXXXXXXXXXXXXXX"
}
}
GET /api/v1/subscription-payment/callback/{gateway}
callback درگاه پرداخت — پس از پرداخت موفق، ClinicSubscription به صورت خودکار ایجاد میشود (بر اساس period_uuid ذخیرهشده در metadata پرداخت).
Admin Endpoints
GET /api/v1/admin/subscription/plans
Permission: ROLE_ADMIN — لیست همه پلنها شامل غیرفعالها (بر خلاف endpoint عمومی که فقط فعالها را برمیگرداند). هر پلن فیلد active دارد و periods همیشه یک آرایه است (فقط دورههای فعال).
POST /api/v1/admin/subscription/plan
Permission: ROLE_ADMIN
{
"name": "enterprise",
"level": 3,
"max_secretaries": 20,
"features": { "patient_records": true, "services": true, "sms_panel": true }
}
خطاها:
| کد | HTTP | شرح |
|---|---|---|
| ERR_VALIDATION_001 | 422 | name یا level ارسال نشده |
| ERR_VALIDATION_001 | 422 | پلنی با این نام از قبل وجود دارد (نام یکتاست) |
PATCH /api/v1/admin/subscription/plan/{uuid}
Permission: ROLE_ADMIN — ویرایش پنل (همه فیلدها اختیاری)
خطاها:
| کد | HTTP | شرح |
|---|---|---|
| ERR_SUBSCRIPTION_NOT_FOUND | 404 | پلن یافت نشد |
| ERR_VALIDATION_001 | 422 | نام جدید متعلق به پلن دیگری است |
POST /api/v1/admin/subscription/period
Permission: ROLE_ADMIN
{
"plan_uuid": "...",
"label": "شش ماهه",
"duration_months": 6,
"price_rials": 1500000,
"is_trial": false,
"sort_order": 2
}
PATCH /api/v1/admin/subscription/period/{uuid}
Permission: ROLE_ADMIN — ویرایش دوره
DELETE /api/v1/admin/subscription/period/{uuid}
Permission: ROLE_ADMIN — غیرفعال کردن دوره (soft delete: active=false)
GET /api/v1/admin/subscription/report
Permission: ROLE_ADMIN
Query params: page, limit
{
"success": true,
"data": [
{
"uuid": "...",
"entity_type": "clinic",
"entity_id": 5,
"is_trial": false,
"starts_at": 1718000000,
"expires_at": 1720678400,
"plan_name": "basic",
"plan_level": 1
}
],
"meta": { "totalRecords": 50, "totalPages": 3, "currentPage": 1 }
}
Error Codes
| Code | HTTP | توضیح |
|---|---|---|
| ERR_SUBSCRIPTION_REQUIRED | 403 | قابلیت نیاز به پنل Basic+ دارد |
| ERR_TRIAL_ALREADY_USED | 422 | تریال قبلاً استفاده شده |
| ERR_TRIAL_DISABLED | 422 | تریال غیرفعال است |
| ERR_SUBSCRIPTION_NOT_FOUND | 404 | پنل یافت نشد |