ترحيل المستخدمين
تنقل Locate مستخدميها ونقاطهم من نظام Shukah القديم إلى خدماتها الخاصة. توثّق هذه الوحدة، لفريق تطبيق الجوال، ما الذي حلّ محل كل واجهة Shukah يستدعيها التطبيق في مجالي المستخدمين والنقاط، حقلًا بحقل، وما الذي ما زال ناقصًا.
الخلفية
ملاحظات مؤرَّخة عن كيفية وصول الترحيل إلى ما هو عليه. قُرئت الحقائق المتعلقة بالخدمات في 2026-10-01 وأُعيد فحصها في parity audit بتاريخ 2026-10-02؛ أما قائمة ما يستدعيه التطبيق فمن نسخة التطبيق اللحظية (snapshot) بتاريخ 2026-02-26.
- من 2026-06-25 إلى 2026-08-04، بناء المصادقة. نسخ جماعي للمستخدمين والعناوين والـ tokens من Shukah
إلى خدمة المصادقة (auth service)، ثم routes للعميل على نمط Shukah تحت
/api/v1/clients/*(نُقلت من/maeda/api/*في 2026-07-10)، ثم مزامنة حية (live sync) في الاتجاهين. - 2026-07-06، الخطة. نقل جميع المستخدمين ونقاطهم من Shukah إلى منصة Locate (Merchant)، مع تشغيل النظامين بالتوازي ليكون الانتقال تدريجيًا وقابلًا للتراجع عنه. قدّرت الخطة المدة بين 3 و4 أسابيع.
- من 2026-07-15 إلى 2026-09-22، بناء النقاط. نسخ السجل (ledger) والمزامنة الحية (2026-07-15)، ثم واجهات القراءة (2026-07-16)، ثم مسار كتابة طلبات النقاط على شرائح (من 2026-09-17 إلى 2026-09-22).
- 2026-10-01، ما يستدعيه التطبيق. تستدعي النسخة اللحظية للتطبيق واجهات Shukah المدرجة في
تقدّم الترحيل. لأغلبها route في Locate، ولبعضها لا، ومنها
حذف الحساب (
GET /maeda/client/delete) الذي يبقى على Shukah. يرجى تأكيد القائمة على التطبيق الحالي. - 2026-10-01، نافذة التحديث المنبثقة. يعرض التطبيق نافذة «حدّث التطبيق» اعتمادًا على أربعة headers
في الاستجابة (
new_versionوold_versionوhas_new_versionوis_required_update). لا تُرسلها أي خدمة في Locate، فتتوقف النافذة عن العمل بعد التحويل، إن كانت Shukah ترسلها اليوم (غير موثّق بعد). راجع التحقق من الـ token. - 2026-10-01، الـ flags الاثنان الخاصان بطلبات النقاط مفعّلان على dev. دفع طلب النقاط بالنقاط وبالبطاقة
يُفعَّل كلٌّ منهما بـ flag على الخادم. أجاب كلاهما بأنه مفعّل على dev؛ أما production فغير
مؤكَّد، والـ flag المعطَّل يُجيب بـ
403. راجع طلبات النقاط. - 2026-10-01، الـ tokens. لا يستدعي التطبيق exchange-token أبدًا. المستخدم الذي يحمل token من Shukah
ويستدعي verify-token في Locate يحصل على
401، فيحذف التطبيق الـ token المخزَّن ويُسجِّل خروج المستخدم. راجع الـ Tokens. - 2026-10-01، dev فقط هو الموثَّق. الـ hosts والعينات الملتقطة (captures) والفحوص كلها لـ dev. أما هل كل route في Locate منشور في production فسؤال منفصل؛ وأغلب الصفحات تنص على ذلك.
- 2026-10-02، يجري نقل Shukah إلى Laravel. تجيب Shukah على dev بأجسام أخطاء من Laravel
(قيم
typeمثلIlluminate\…وSymfony\…). ويتتبع عمود "Implemented in Laravel" في جدول حركة الإنتاج (production traffic sheet) الخاص بالفريق ذلك النقل، على الـ URLs نفسها. ولا يتتبع الانتقال إلى Locate. - 2026-10-02، الـ parity audit. أُرسل المُدخل نفسه إلى Shukah وإلى Locate على dev لكل
route يمكن استدعاؤه بأمان. أهم النتائج: لا يوجد token واحد يعمل على الخدمتين (routes العميل في
خدمة المصادقة،
/api/v1/clients/*، لا تقبل إلا JWT من Locate، وroutes النقاط في order-v2 لا تقبل إلا token من Shukah، راجع الـ Tokens)؛ ونسخ العناوين بين Locate وShukah معطوب في الاتجاهين (راجع دفتر العناوين)؛ وإنشاء طلب النقاط في Locate يجيب دون معرّف الطلب الذي يحتفظ به التطبيق (أكّده استدعاء حي في اليوم نفسه)، فلا تستطيع استدعاءات الدفع إيجاد الطلب (راجع طلبات النقاط). ووجد استدعاء متابعة في اليوم نفسه أن النقاط المصروفة على جانب لا تُخصم من الآخر (خلال ثواني التشغيل؛ ولم يُفحص هل يصل لاحقًا)، لذا يجب أن يقرأ التطبيق الرصيد من الجانب الذي يُنشئ فيه الطلبات. الأرصدة على dev: في 2026-10-01 كان للعميل نفسه"514405.6788"نقطة في Locate و"128712.41"في Shukah؛ وفي 2026-10-02 كان لدى Shukah"514853.64": فقد تغيرت بيانات Shukah على dev بينهما. وكانت Locate حينها أقل بـ 447.96 نقطة، وهذا يلائم تأخر تغذية Locate من Shukah بنحو يومين (استنتاج؛ راجع محفظة النقاط). وتحمل الصفحات الآن هذه النتائج، كلٌّ بتاريخه.
من يستدعي ماذا
Mobile app ──► Auth service ◄──────────► Shukah (legacy, /maeda/...)
│ login, token, profile, ▲ still serves delete-account,
│ address book │ restaurant orders, payments
│ │
└──────► order-v2 (/api/v2/client) ─────┤ order-v2 also calls Shukah
│ passes the point routes │ for some point calls
▼ │
Point service ◄────────────────┘ ledger sync (designed both ways; see Point orders)
(not exposed to the app)
وتستدعي الخدمات بعضها بعضًا أيضًا: يسأل order-v2 وخدمة النقاط خدمة المصادقة
GET /api/v1/users عن هوية المستدعي، فلا يرسل التطبيق header لذلك. وتفاصيل
عمليات المزامنة في الصفحات تحت «التفاصيل (للـ backend)».
| المجال | ما يستدعيه التطبيق | الخدمة التي تخدمه | Shukah سابقًا |
|---|---|---|---|
| تسجيل الدخول والتسجيل | reset-otp، verify-otp | Auth service | GET /maeda/api/reset-otp، GET /maeda/api/verify-otp |
| الجلسة والملف الشخصي | verify-token، client lookup، update profile، push setting، add device | Auth service | /maeda/api/verify-token، /maeda/client، PUT /maeda/client/{id}، /maeda/client/add-device-id |
| دفتر العناوين | list، get، create، update، delete | Auth service | /maeda/address-book و/maeda/address-book/{id} |
| استبدال الـ token | exchange-token (لا يستدعيه التطبيق بعد) | Auth service | لا شيء: endpoint موجود في Locate فقط |
| النقاط | الرصيد، السجل، الأسئلة الشائعة، العروض، المناسبات | order-v2، الذي يمرّرها إلى خدمة النقاط | /maeda/client/points، /maeda/client/point-history، /maeda/points-faq، /maeda/point-offer، /maeda/point-occasion |
| طلبات النقاط | إنشاء، قراءة، وصف، دفع بالبطاقة أو بالجلسة | order-v2 وخدمة النقاط | /maeda/point-order وroutes checkout-payment |
| معدلات الكسب، كود بطاقة الهدية | معدلات النقاط، كود بطاقة الهدية | order-v2 نفسه | /maeda/point-rate، /maeda/giftcard-code/use |
| حذف الحساب | لم يُستبدل | يبقى على Shukah | GET /maeda/client/delete |
تضم صفحة تقدّم الترحيل القائمة الكاملة بحالة كل route، وتقابل صفحة Shukah مقابل Locate كل واجهة من Shukah ببديلها.
عناوين URL الأساسية
يبني التطبيق عنوان URL من عنوان أساسي (base URL) ثم / ثم الـ endpoint. وتكتب صفحات Locate أمثلة curl
باستخدام $AUTH_BASE_URL و$ORDER_BASE_URL و$SHUKAH_BASE_URL، وهي الـ host فقط.
أما البادئة (prefix) فتوضع في المسار: /api/v1 على host المصادقة، و/api/v2/client على host الـ order-v2،
و/maeda على Shukah.
Dev
| الخدمة | Host | البادئة |
|---|---|---|
| Auth service | https://dev.authentication.locate.sa | /api/v1 |
| order-v2 | https://dev.v2.api.order.locate.sa | /api/v2/client |
| Point service | https://dev-point-api.locate.sa (لا يستدعيه التطبيق) | /api/client |
| Shukah | https://dev-api.shukah.com | /maeda |
UAT
| الخدمة | Host | البادئة |
|---|---|---|
| Auth service | غير موثّق بعد — اسأل فريق الـ backend | غير موثّق بعد — اسأل فريق الـ backend |
| order-v2 | https://dev.v2.api.order.locate.sa (مماثل لـ dev في إعدادات UAT بالتطبيق) | /api/v2/client |
| Point service | غير موثّق بعد — اسأل فريق الـ backend | غير موثّق بعد — اسأل فريق الـ backend |
| Shukah | https://dev-api.shukah.com (مماثل لـ dev في إعدادات UAT بالتطبيق) | /maeda |
Production
| الخدمة | Host | البادئة |
|---|---|---|
| Auth service | غير موثّق بعد — اسأل فريق الـ backend | غير موثّق بعد — اسأل فريق الـ backend |
| order-v2 | https://v2.api.order.locate.sa | /api/v2/client |
| Point service | غير موثّق بعد — اسأل فريق الـ backend | غير موثّق بعد — اسأل فريق الـ backend |
| Shukah | https://api.shukah.com | /maeda |
ليس للتطبيق اليوم base URL لخدمة المصادقة في أي من إعدادات بيئاته، لذا يحتاج إلى واحد. الـ hosts أعلاه مصدرها إعدادات التطبيق نفسه ووثائق الخدمات؛ أما hosts خدمة المصادقة في UAT وproduction فموجودة في إعدادات النشر (deployment) التي لم يطّلع عليها البحث.
الـ Tokens
- Token من Shukah. سلسلة معتمة (opaque). تُصدرها Shukah عند تسجيل الدخول.
- Token من Locate. هو JWT تصدره خدمة المصادقة. لا تاريخ انتهاء له ولا شيء يُبطله.
يوضع كلاهما في Authorization: Bearer <token>. وهذه الصفحات وما تقبله:
| الصفحات | الـ token |
|---|---|
| تسجيل الدخول برمز OTP، استبدال الـ token، واستدعاء add-device-id في الملف الشخصي والإعدادات | لا حاجة إلى token. |
| التحقق من الـ token، البحث عن عميل، دفتر العناوين، وتحديث الملف الشخصي وتحديث الإعداد في الملف الشخصي والإعدادات | JWT من Locate فقط. وtoken من Shukah يحصل على 401. |
| صفحات النقاط (محفظة النقاط، سجل النقاط، عروض النقاط، طلبات النقاط، الأسئلة الشائعة عن النقاط) | token من Shukah فقط، على dev اليوم. أما JWT من Locate فيحصل على 401 Invalid or expired token (التُقط على dev، 2026-10-02؛ وفي 2026-10-01 كان لا يزال يحصل على 200). وroute معدل الكسب (earn-rate) عام. وتنص الصفحة على الحالات التي لا يحتاج فيها route إلى token. |
| تفاصيل المستخدم | مع x-auth-from: SHUKAH يمرّر dev الـ token إلى Shukah، فيعمل token من Shukah ويُتوقَّع أن يحصل JWT من Locate على 401 (استنتاج، 2026-10-02: رفضت routes النقاط التي تستدعيه الـ JWT؛ ولم يُستدعَ هذا الـ route مع x-auth-from في ذلك اليوم). وroutes النقاط تعتمد على هذا الاستدعاء، ولهذا يفشل JWT من Locate هناك. |
فيحتاج التطبيق اليوم إلى الـ token كليهما: JWT من Locate لخدمة المصادقة وtoken من Shukah لـ order-v2. وتوضح Shukah مقابل Locate السبب، وأهمية ذلك عند تحوّل التطبيق.
الحصول على token تجريبي
يحتاج قسم «جرّبه» في صفحات المصادقة إلى JWT من Locate في $TOKEN، إلا تفاصيل المستخدم
التي تحتاج إلى token من Shukah. ويحتاج قسم «جرّبه» في صفحات نقاط order-v2 إلى token من Shukah في $SHUKAH_TOKEN
اليوم، لأن JWT من Locate يحصل على 401 هناك (dev، 2026-10-02). استخدم dev فقط. وهناك طريقتان للحصول على
JWT من Locate (أ وب أدناه)، وطريقة واحدة للحصول على token من Shukah منه (ج).
أ. تسجيل الدخول برمز OTP
استدعاءان: reset-otp يطلب الرمز، وverify-otp يستبدل الرمز بـ token.
export AUTH_BASE_URL=https://dev.authentication.locate.sa
export PHONE='<test-mode-phone>' # placeholder: replace it with a test-mode number
curl -s -G "$AUTH_BASE_URL/api/v1/clients/reset-otp" --data-urlencode "contact_phone=$PHONE"
curl -s -G "$AUTH_BASE_URL/api/v1/clients/verify-otp" --data-urlencode "contact_phone=$PHONE" --data-urlencode "code=2022"
تحتوي الاستجابة الثانية على الـ token في access_token. احتفظ به في $TOKEN.
reset-otp يرسل رسالة SMS حقيقية ما لم يكن الحساب في وضع الاختبار (account_mode: TEST).
يحصل حساب وضع الاختبار على الرمز الثابت 2022 دون رسالة SMS. وليس للخدمة API لجعل الحساب
في وضع الاختبار: يضبطه فريق الـ backend في قاعدة البيانات. اطلب من الـ backend رقمًا في وضع الاختبار؛ أما هل
يوجد واحد على dev: غير موثّق بعد.
الرقم المضمَّن في الشيفرة +966500000000 يقبل 2022 أيضًا، لكن الخدمة ما زالت تحاول إرسال
SMS إليه، فلا تستخدمه. ولا تضع أبدًا رقم شخص حقيقي في اختبار.
ملاحظات: صلاحية الرمز 3 دقائق، وما دام رمز ساريًا لا يرسل reset-otp رمزًا جديدًا (ويظل
يجيب {"status":true}). ويستطيع فريق الـ backend قراءة آخر OTP عبر route تصحيح (debug) إداري
محميّ بمفتاح API؛ وهو للـ backend فقط، فاسأل الـ backend. راجع
تسجيل الدخول برمز OTP للقواعد الكاملة.
ب. استبدال token موجود من Shukah
إذا كان لديك بالفعل token من Shukah لعميل على dev، فاستبدله بـ JWT من Locate. ويأتي token Shukah من تسجيل الدخول الحالي في Shukah؛ أما كيفية الحصول على واحد دون التطبيق: غير موثّق بعد.
export AUTH_BASE_URL=https://dev.authentication.locate.sa
export SHUKAH_TOKEN='<shukah-token>'
curl -s -X POST "$AUTH_BASE_URL/api/v1/clients/exchange-token" -H "Content-Type: application/json" -d "{\"token\":\"$SHUKAH_TOKEN\",\"target_platform\":\"locate\"}"
يوجد الـ JWT من Locate في data.token. احتفظ به في $TOKEN.
هذا الاستدعاء يكتب: ففي كل مرة يخزّن token جديدًا للعميل ويدفعه إلى Shukah. لا ترسل استدعاءين للعميل نفسه في الثانية نفسها. راجع استبدال الـ token.
ج. الحصول على token من Shukah انطلاقًا من JWT من Locate
استدعاء exchange-token نفسه مع JWT من Locate الخاص بك وtarget_platform مضبوطًا على shukah يُرجع
الـ token الخاص بـ Shukah المخزَّن لذلك العميل:
curl -s -X POST "$AUTH_BASE_URL/api/v1/clients/exchange-token" -H "Content-Type: application/json" -d "{\"token\":\"$TOKEN\",\"target_platform\":\"shukah\"}".
يوجد الـ token الخاص بـ Shukah في data.token. احتفظ به في $SHUKAH_TOKEN. ويُفحص الـ JWT أولًا. وقد
تكون الإجابة {"status":200,"data":{}} عندما لا تكون للـ token المخزَّن لـ Shukah نسخة خام؛ وحينئذٍ لا تنجح
هذه الطريقة لذلك العميل (راجع استبدال الـ token).
المتغيرات التي تستخدمها الصفحات
export AUTH_BASE_URL=https://dev.authentication.locate.sa
export ORDER_BASE_URL=https://dev.v2.api.order.locate.sa
export SHUKAH_BASE_URL=https://dev-api.shukah.com
export TOKEN='<locate-jwt>'
export SHUKAH_TOKEN='<shukah-token>'
استبدل عنصرَي الـ token النائبين (placeholders) بما يخصّك. ولا تودِع token حقيقيًا في ملف، ولا تلصقه في تذكرة (ticket) أو محادثة.
كيف تقرأ هذه الصفحات
لصفحة الـ endpoint الشكل التالي:
- الخلفية والميزة: ما يفعله التطبيق اليوم على Shukah، وما هي الميزة، بكلمات بسيطة.
- كتلة واحدة لكل endpoint، بهذا الترتيب:
- مربع TL;DR (عنوانه "Replaces Shukah"): واجهة Shukah التي يستبدلها وحالتها؛ والتقييم (verdict) مع عدد الفروق الكاسرة (breaking) والفروق التي تستحق المراقبة؛ وسطر لكل فرق، 🔴 للكاسر و🟡 لما يستحق المراقبة؛ والخدمة التي تخدمه، وأي الـ tokens نجحت، وكيف ومتى جرى التحقق، ورابط إلى جانب Shukah. ويشرح دليل الحالات في تقدّم الترحيل التقييمات والعلامات؛
- الطلب (Request) والاستجابة (Response): جداول بكل حقل؛
- الأخطاء: الـ bodies الحقيقية؛
- جرّبه: أمر
curlيستخدم المتغيرات أعلاه؛ - الفروق عن Shukah: الفروق الحقيقية فقط، ولكل منها أثره على التطبيق. وإذا لم يكن لـ route أي
فرق قال
Drop-in — no differences foundمع التاريخ.
- تنبيه: ثلاثة تحذيرات من سطر واحد على الأكثر.
- سطر فاصل، ثم التفاصيل (للـ backend): قواعد العمل والمخاطر والمصادر (Sources) التي تسمّي المستودع والـ commit والملف لكل حقيقة.
يستخدم مربع TL;DR وجدول التقدّم هذه الحالات:
| العلامة | المعنى |
|---|---|
| ✅ تم الاستبدال | يوجد route في Locate. |
| ❌ لم يُستبدل | لا يوجد route في Locate بعد. |
| ➖ لن يُرحَّل | تبقى الواجهة على Shukah عن قصد. |
| 🚩 flag | مُنفَّذ، لكن استخدامه يتوقف على مفتاح (flag على الخادم أو إعداد في التطبيق). |
تضيف تقدّم الترحيل الفحص على dev: طلب واحد إلى الـ route في Locate على dev دون token، في التاريخ المبيّن. وهو يبيّن أن الـ route منشور ويستجيب، لا أنه يعمل لعميل مسجّل الدخول.
غير موثّق بعد يعني أنه لا شيفرة ولا وثيقة ولا عيّنة ملتقطة أظهرت الجواب. وليس تخمينًا ولا «لا». تعامل معه على أنه سؤال لفريق الـ backend أو فريق الجوال.
تذكر العينات مصدرها: ملتقطة على dev في تاريخ معيّن (مع استبدال البيانات الشخصية بقيم
توضيحية)، أو مأخوذة من وثيقة خدمة، مع مسارها وتاريخها. وتشير أسماء ملفات الالتقاط (capture) تحت Sources إلى مجموعة التقاط dev بتاريخ 2026-10-01 غير المودَعة (uncommitted) وإلى مجموعة التقاط parity-audit بتاريخ 2026-10-02 (بأسماء مثل points--shukah)، ويحتفظ بهما كاتب الوثائق؛ وهما ليستا في هذا المستودع.
استثناء من الوحدات الأخرى. أغلب الوحدات لا تعيد ذكر أسماء الحقول أو أشكال الاستجابات، لأن OpenAPI المعروضة للخدمة هي مصدر الحقيقة. أما الخدمات هنا فلا تنشر أي OpenAPI، لذا توثّق هذه الصفحات الحقول بنفسها، من الشيفرة. ولذلك قد تتقادم جداول الحقول: افحص الـ commit المذكور تحت Sources، وعند اختلاف الصفحة عن الخدمة، فالقول للخدمة.
الوسوم
تحمل الصفحات وسومًا (tags). يرتبط كل وسم بكل صفحة تحمله.
| الوسم | المعنى |
|---|---|
auth-service | تخدمه خدمة المصادقة. يستدعيه التطبيق مباشرة. |
order-v2 | يُوصَل إليه عبر client API الخاصة بـ order-v2. |
point-service | تخدمه خدمة النقاط، خلف order-v2. |
authentication | تسجيل الدخول والـ tokens والجلسات. |
profile | الملف الشخصي للعميل وإعداداته وأجهزته. |
address-book | عناوين التوصيل المحفوظة للعميل. |
points | الرصيد والسجل والعروض والمناسبات والأسئلة الشائعة. |
point-orders | شراء النقاط أو إهداؤها، ودفع ثمنها. |
shukah-replacement | endpoint في Locate يحل محل واجهة Shukah. |
new-endpoint | endpoint في Locate لا يقابله شيء في Shukah. |
overview | صفحات على مستوى الوحدة: الخلفية والتقدّم والمقارنة. |
mobile | مكتوب لفريق تطبيق الجوال. |
backend | تستدعيه خدمات الـ backend، أو مكتوب لمهندسي الـ backend. |
client | يستدعيه تطبيق العميل باستخدام الـ token الخاص بالعميل نفسه. |
admin | يُستدعى من أداة إدارية، وليس من تطبيق العميل. ولا توجد صفحة تحمل هذا الوسم بعد. |
server-to-server | تستدعيه خدمة backend أخرى، وليس تطبيقًا. |
الحالة ليست وسمًا، بل توجد في تقدّم الترحيل.
الصفحات
ابدأ من هنا إذا كنت تحوّل التطبيق: قائمة التحويل.
- قائمة التحويل: كل تغيير يجب على التطبيق إجراؤه للانتقال من Shukah إلى Locate.
- تقدّم الترحيل: كل واجهة Shukah يستدعيها التطبيق، مع حالتها وفحص dev.
- Shukah مقابل Locate: جانب Shukah من كل واجهة، مقابل بديلها.
Auth service
- تسجيل الدخول برمز OTP: تسجيل الدخول أو التسجيل برقم هاتف ورمز من 4 أرقام.
- التحقق من الـ token: التحقق من الـ token والحصول على الملف الشخصي للعميل المسجّل الدخول.
- استبدال الـ token: استبدال token من Shukah بـ token من Locate، أو العكس.
- تفاصيل المستخدم: تحويل token إلى ملف شخصي؛ وهو الـ route الذي يستدعيه order-v2 وخدمة النقاط.
- البحث عن عميل: إيجاد عميل برقم الهاتف.
- دفتر العناوين: عرض العناوين المحفوظة وقراءتها وإنشاؤها وتعديلها وحذفها.
- الملف الشخصي والإعدادات: تحديث الملف الشخصي، وتشغيل الإشعارات (push) أو إيقافها، وتسجيل جهاز.
النقاط
- محفظة النقاط: الرصيد وانتهاء الصلاحية ومعدلات الكسب وكود بطاقة الهدية.
- سجل النقاط: معاملات النقاط الخاصة بالعميل.
- عروض النقاط: الباقات التي يستطيع العميل شراءها أو إهداءها، ومناسبات الإهداء.
- طلبات النقاط: إنشاء طلب إهداء نقاط وقراءته ودفعه.
- الأسئلة الشائعة عن النقاط: الأسئلة والأجوبة بالإنجليزية والعربية.