Files
customerTicket/docs/PHONE_CONTACTS_API.md
2026-09-30 11:09:12 +03:30

14 KiB

راهنمای API جست‌وجوی مخاطبان برای Phone

این API مخاطبان ثبت‌شده در پروژهٔ تیکتینگ را به شکل قابل استفاده برای «منابع بیرونی» Phone ارائه می‌کند. قرارداد پاسخ آن با نمونهٔ ابتدایی EXTERNAL_CONTACT_APIS.md سازگار است. این endpoint فقط اطلاعات را می‌خواند؛ ایجاد یا ویرایش مخاطب از طریق آن انجام نمی‌شود.

نشانی و روش درخواست

مورد مقدار
روش GET
مسیر /api/phone-contacts، بدون / پایانی
نوع پاسخ موفق application/json با کد 200
احراز هویت هدر Authorization: Bearer <API_KEY>
بدنهٔ درخواست ندارد؛ پارامترها در URL ارسال می‌شوند

نشانی کامل را با دامنهٔ همین پروژه بسازید؛ برای نمونه https://crm.example.com/api/phone-contacts. مقدار <API_KEY> کلیدی است که مدیر در دیتابیس این پروژه ثبت کرده است. نشست کاربر یا کوکی برای این API لازم نیست.

پارامترهای query string

پارامتر ضروری رفتار
search برای دریافت نتیجه، بله متن جست‌وجو؛ فاصله‌های ابتدا و انتها حذف می‌شوند و حداکثر ۸۰ نویسهٔ اول بررسی می‌شود. مقدار خالی، غایب یا کوتاه‌تر از دو نویسه، نتیجهٔ خالی می‌دهد.
limit خیر بیشترین تعداد مخاطب در پاسخ. پیش‌فرض 50 است. مقدار عددی کمتر از 1 به 1 و بیشتر از 50 به 50 محدود می‌شود؛ مقدار غیرعددی خطای 400 می‌دهد.

نمونهٔ درخواست HTTP:

GET /api/phone-contacts?search=%D8%B9%D9%84%DB%8C&limit=50 HTTP/1.1
Host: crm.example.com
Authorization: Bearer <API_KEY>
Accept: application/json

نمونه با curl، با فرض اینکه کلید از قبل در متغیر محیطی همان shell موجود است:

curl --fail-with-body --get 'https://crm.example.com/api/phone-contacts' \
  --data-urlencode 'search=علی رضایی' \
  --data-urlencode 'limit=50' \
  -H "Authorization: Bearer ${PHONE_CONTACTS_API_KEY}" \
  -H 'Accept: application/json'

--data-urlencode متن فارسی و فاصله‌ها را برای URL کدگذاری می‌کند. کلید را در URL قرار ندهید.

پاسخ موفق

ریشهٔ پاسخ همیشه یک شیء JSON با کلید contacts است. هر عضو این آرایه نام، شمارهٔ همراه و آرایهٔ شماره‌ها را دارد:

{
  "contacts": [
    {
      "name": "علی رضایی",
      "mobile": "09123456789",
      "phones": [
        {"type": "همراه", "number": "09123456789"}
      ]
    }
  ]
}
فیلد نوع توضیح
contacts آرایه حداکثر ۵۰ مخاطب، یا آرایهٔ خالی.
contacts[].name رشته نام نمایشی غیرخالی؛ فاصلهٔ دو سر حذف شده و حداکثر ۱۲۰ نویسه است.
contacts[].mobile رشته همان مقدار phones[].number، برای مصرف‌کننده‌ای که فیلد مستقیم شماره را می‌خواهد. نام این فیلد برای سازگاری حفظ شده و ممکن است مقدار آن تلفن ثابت باشد.
contacts[].phones آرایه در ساختار کنونی پروژه، یک شمارهٔ ثبت‌شدهٔ معتبر برای هر مخاطب.
contacts[].phones[].type رشته برای همراه ایرانی همراه و برای شمارهٔ دیگر تلفن.
contacts[].phones[].number رشته شمارهٔ قابل شماره‌گیری؛ شمارهٔ ایرانی با 0 محلی برگردانده می‌شود، مانند 0913... یا 021....

شماره پیش از ارسال به متن تبدیل می‌شود؛ فاصله، پرانتز، نقطه و خط تیره حذف می‌شوند و رقم‌های فارسی و عربی به رقم لاتین تبدیل می‌شوند. شمارهٔ نهایی باید حداکثر ۶۴ نویسه و فقط شامل رقم، +، * یا # باشد. مخاطب بدون نام یا شمارهٔ معتبر در پاسخ نمی‌آید. چون دیتابیس فعلی فیلد مستقل برای تلفن ثابت ندارد، هیچ شمارهٔ فرضی تولید نمی‌شود. شناسهٔ داخلی مخاطب نیز در پاسخ فرستاده نمی‌شود.

محدودیت ۵۰ مخاطب، نام ۱۲۰ نویسه‌ای و یک شمارهٔ حداکثر ۶۴ نویسه‌ای برای هر مخاطب، پاسخ را بسیار پایین‌تر از سقف پردازش ۱ MiB در Phone نگه می‌دارد.

اگر مخاطبی پیدا نشود، درخواست همچنان موفق است:

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store

{"contacts":[]}

برای پاسخ‌های JSON موفق و خطاهای JSON این view، هدر Cache-Control: no-store تنظیم می‌شود.

چه مخاطبانی نمایش داده می‌شوند؟

فقط رکوردهایی بررسی می‌شوند که پروفایل CustomerProfile داشته باشند، حساب مرتبط با آن‌ها از نوع CUSTOMER و فعال باشد، شمارهٔ همراه داشته باشد و دست‌کم یکی از فیلدهای نام، نام خانوادگی یا نام سازمان در پروفایل یا حساب آن‌ها پر باشد. سپس نام و شمارهٔ نهایی نیز اعتبارسنجی می‌شود.

نام نمایشی به این ترتیب انتخاب می‌شود: نام و نام خانوادگی پروفایل، سپس نام و نام خانوادگی حساب، سپس نام سازمان پروفایل. خروجی نام به ۱۲۰ نویسه محدود می‌شود.

اگر search شماره باشد، شکل‌های محلی با 0، بین‌المللی با +98 یا 0098، و شکل ۱۰ رقمی بدون پیشوند برای شماره‌های ایرانی به یک قالب مقایسه تبدیل می‌شوند. این قاعده به 912 یا هیچ پیش‌شمارهٔ موبایلی محدود نیست؛ برای نمونه 02112345678، +982112345678 و 00982112345678 نیز معادل‌اند. رقم‌های فارسی/عربی و جداکننده‌هایی مانند فاصله و خط تیره پذیرفته می‌شوند. تطبیق با مقدار ذخیره‌شده دقیق است و شمارهٔ ایرانی در پاسخ با 0 محلی برمی‌گردد.

این API فقط شماره‌ای را می‌تواند پیدا کند که در دادهٔ موجود حساب مخاطب ذخیره شده باشد. مدل فعلی User.mobile هنگام ثبت معمول، شمارهٔ همراه ایرانی را می‌پذیرد و فیلد جداگانه‌ای برای خط ثابت ندارد؛ بنابراین جست‌وجوی 021... فقط برای داده‌ای نتیجه می‌دهد که چنین شماره‌ای از قبل در آن موجود باشد. مدل مخاطب و فرم ثبت آن برای این قابلیت تغییر نکرده‌اند.

برای جست‌وجوی متنی، نام، نام خانوادگی و نام سازمان پروفایل و نام و نام خانوادگی حساب بررسی می‌شوند. برای جست‌وجوی چندواژه‌ای، هر واژه باید دست‌کم در یکی از این فیلدها پیدا شود. جست‌وجو نسبت به بزرگی حروف لاتین حساس نیست؛ شکل عربی «ي/ك» در متن ورودی به «ی/ک» تبدیل می‌شود. نتیجه‌هایی که یک فیلدشان دقیقاً با کل متن جست‌وجو برابر است، اول می‌آیند؛ سپس نتیجه‌هایی که فیلدی با آن متن شروع می‌شود و بعد سایر تطبیق‌ها. در هر گروه، شناسهٔ داخلی ترتیب را تعیین می‌کند.

limit سقف تعداد رکوردهای بررسی‌شده برای خروجی را تعیین می‌کند. اگر در میان آن‌ها رکوردی هنگام ساخت پاسخ به علت نام یا شمارهٔ نامعتبر کنار گذاشته شود، ممکن است تعداد نهایی کمتر از limit باشد. API صفحه‌بندی یا پارامتر page ندارد؛ Phone باید نتایج مورد نیاز را از همین پاسخ اول دریافت کند.

کدهای پاسخ و خطاها

وضعیت علت بدنهٔ معمول
200 درخواست معتبر؛ با نتیجه یا بدون نتیجه {"contacts":[...]} یا {"contacts":[]}
400 مقدار limit عدد صحیح نیست، مانند limit=abc {"error":"invalid limit"}
401 هدر Bearer غایب/نامعتبر است، کلید اشتباه است یا کلید در پنل غیرفعال شده است {"error":"unauthorized"}
405 روشی غیر از GET، مانند POST پاسخ استاندارد Django برای روش نامجاز

احراز هویت پیش از بررسی پارامترهای جست‌وجو انجام می‌شود؛ بنابراین درخواست بدون کلید حتی برای جست‌وجوی کوتاه نیز 401 می‌گیرد. خطاهای غیرمنتظرهٔ سرور ممکن است 5xx باشند.

ایجاد و تغییر کلید API در دیتابیس

  1. Migration برنامه را با محیط مجازی همین مخزن اجرا کنید: .venv/Scripts/python.exe manage.py migrate phone_contacts_api --noinput. در محیط توسعهٔ محلی این migration قبلاً اعمال شده است؛ در هر محیط استقرار باید جداگانه اجرا شود.
  2. با حساب دارای مجوز مدیریت وارد /x5admin/ شوید و بخش «دسترسی API مخاطبان Phone» ← «کلید API مخاطبان Phone» را باز کنید.
  3. هنگام ایجاد، یک کلید تصادفی با طول ۳۲ تا ۲۵۶ نویسه در فیلد «کلید جدید» وارد و گزینهٔ «فعال» را روشن کنید. در هر زمان فقط یک رکورد کلید قابل تعریف است.
  4. برای تعویض کلید، همان رکورد را ویرایش و مقدار جدید وارد کنید. کلید قدیمی پس از ذخیره دیگر پذیرفته نمی‌شود. اگر فیلد را خالی بگذارید، کلید فعلی حفظ می‌شود. خاموش کردن «فعال» دسترسی را بلافاصله قطع می‌کند.

مقدار خام کلید پس از ذخیره در پنل قابل بازیابی نیست و فقط هش آن در دیتابیس می‌ماند. کلیدی را که ثبت می‌کنید از مسیر امن به مسئول تنظیم Phone منتقل کنید. کلید در متغیر محیطی Phone نگهداری می‌شود، اما منبع اعتبارسنجی این API دیتابیس همین پروژه است؛ تغییر کلید در پنل پروژه باید با تغییر مقدار نزد Phone همراه باشد.

تنظیم منبع در Phone

در پنل «منابع بیرونی» Phone، یک منبع با این مقادیر تعریف کنید:

فیلد پنل Phone مقدار
آدرس ثابت API https://<دامنه-این-پروژه>/api/phone-contacts
روش درخواست GET
پارامترهای URL {"search":"{{query}}","limit":50}
هدرها {"Authorization":"Bearer {{env:PHONE_EXTERNAL_CRM_TOKEN}}","Accept":"application/json"}
بدنهٔ POST {}
مسیر فهرست contacts
مسیر نام مخاطب name
نگاشت شماره‌ها [{"path":"phones[]","value_path":"number","label_path":"type"}]

مقدار PHONE_EXTERNAL_CRM_TOKEN در محیط اجرای Phone باید با کلید خامی که در پنل همین پروژه ثبت شده برابر باشد. Phone از سرور خود به این API درخواست می‌فرستد؛ بنابراین DNS، TLS و دسترسی شبکه از میزبان Phone به دامنهٔ این پروژه باید برقرار باشد. دستور curl بالا را نیز ترجیحاً از همان میزبان اجرا کنید.

دامنهٔ دسترسی و محدودیت‌ها

این API با یک کلید مشترک کار می‌کند و هویت کاربران Phone را دریافت نمی‌کند. در نتیجه هر دارندهٔ کلید می‌تواند مخاطبان واجد شرایط را جست‌وجو کند؛ مجوزهای دیدن شماره در رابط Phone، محدودسازی داده‌های خروجی این API نیستند. کلید را فقط در سامانهٔ مورد اعتماد قرار دهید و در صورت افشا فوراً آن را در پنل تغییر دهید.

این endpoint فقط GET و احراز هویت Bearer را پیاده‌سازی می‌کند. شمارهٔ دفتر، چند شماره برای یک مخاطب، صفحه‌بندی، جست‌وجوی اختصاصی بر اساس واحد سازمانی و ایجاد/ویرایش مخاطب در این API وجود ندارد. برای قالب‌های دیگر پاسخ یا داده‌های بیشتر باید منبع دادهٔ متناظر در پروژه وجود داشته باشد.