Command Palette

Search for a command to run...

المدوّنة

إطلاق التطبيقات في الجزائر

نُشر في
مدة القراءة
6 د قراءة
الأشكال
4 أشكال
Tabaga Team

الدفع بلا بطاقة دولية، أرقام هاتف على ثلاثة متعاملين، واجهات بالعربية أولًا، مراجعة المتاجر، ولماذا تركنا Firebase.

كل الدروس تبدأ بالطريقة نفسها: أضف Stripe، أرسل رابطًا سحريًا إلى بريد إلكتروني، ورتّب الشاشة من اليسار. مستخدمونا يدفعون ببطاقة الذهبية في مكتب البريد، ويسجّلون برقم يبدأ بـ +213 عند أحد المتعاملين الثلاثة، ويقرؤون من اليمين. لا ينطبق أيٌّ من الإعدادات الثلاثة الافتراضية، وكلٌّ منها يلوي البنية أكثر مما يبدو. هذا ما تعلمناه عبر اثني عشر منتجًا، مكتوبًا كما تمنّينا لو كتبه لنا أحد.

3
متعاملين نختبر عليهم وصول رمز التحقق، في الأسبوع الأول
5 د
مدة صلاحية رمز التحقق، تُفحص على الخادم، خمس محاولات
468
اختبارًا في منتج واحد، كثير منها للاتجاه والتباين
~78
ملفًا لمسناها لمغادرة Firebase، من تطبيق كامل

المال أولًا، ثم كل شيء آخر

customerEdahabiaCIBBaridiMobCCPVisa · MCChargily Paycalled from a functionwebhooksubscriptionsno Stripe · no recurring chargerenew per periodSeppaidOctpaidNovreminder sentDecpaidJanlapsedFebpaida lapse is a state, not a failed charge; the app degrades, it never locks
الشكل 1.المال في الجزائر: بطاقات وتحويلات محلية عبر Chargily، واشتراك هو شراء بتاريخ تجدّده بنفسك، لأن قنوات الدفع لا تتكرر تلقائيًا.

لا وجود لـ Stripe هنا. البطاقات هي الذهبية وCIB، والتحويلات تمر عبر بريدي موب وCCP، ومعالجات الدفع العالمية لا تصل إلى هذه القنوات. منصّتنا لوظائف الطلبة تمرّر الدفع عبر Chargily Pay من دالة بلا خادم، مع webhook يكتب سطر الاشتراك، وما تزال خارطة طريقها تحمل بندًا مفتوحًا لم نحلّه بالكامل: الاشتراكات على قنوات دفع غير متكررة. الحل الذي يعمل هو التجديد كل فترة: الباقة شراء بتاريخ، وتذكير يدفعك لتكراره، والانقضاء حالة يتراجع إليها التطبيق، لا اقتطاعًا فاشلًا يغلق الباب.

في تطبيق طلب الطعام للمطاعم تجاوزنا الدفع كليًا. الطعام سلعة مادية، فالشراء داخل التطبيق عند Apple ممنوع، والتطبيق لا يحصّل شيئًا: الدفع عند الطاولة أو عند التوصيل. ملاحظات مراجع App Store تقول ذلك بوضوح، وتدقيق الجاهزية يتأكد أن لا واجهة شراء موجودة في أي مكان من الكود.

القيد يمتد أبعد من الدفع. خادم سحابي فقط يفرض بطاقة دولية على كل عميل لمجرد دفع الاستضافة. لهذا طبقة المزامنة في Batipro قابلة للاستضافة الذاتية، ولهذا يشغّلها بعض العملاء على VPS في الجزائر يُفوتر بالدينار وبفاتورة محلية.

ثلاثة متعاملين، شريحة لكل واحد

+213 numberphone-otp function6 digits · hash · 5 min · 5 triesphone_otpsserver key only, no table permissionsSMS_SEND_URLaggregatorany Algerian one, or TwilioDjezzyOoredooMobilistest all three in week oneplan a WhatsApp fallback{ ok }
الشكل 2.تسجيل الدخول بالهاتف: الرمز يولد ويُهشّر ويُفحص على الخادم؛ التطبيق لا يرى سوى ok، ومزوّد الرسائل قيمة في الإعدادات.

كل منتج للعموم هنا يسجّل برقم هاتف. أكثر عائق رأيناه هو وصول الرسائل النصية، لذلك تقول ملاحظاتنا لمنصة المعدات بصراحة: تحقق من الوصول عند جازي وأوريدو وموبيليس بأرقام حقيقية على الثلاثة خلال الأسبوع الأول، وخطّط لرمز تحقق عبر واتساب كبديل إن لم يكن موثوقًا.

كيف ننجز رمز التحقق نفسه: الرمز المكوّن من ستة أرقام يولد ويُهشّر ويُفحص كليًا على الخادم، في جدول لا يستطيع العميل قراءته أبدًا، بصلاحية خمس دقائق وخمس محاولات كحد أقصى. التطبيق لا يرى سوى { ok }. مزوّد الرسائل غير مربوط عمدًا، أي مجمّع جزائري أو Twilio، وحين يُترك رابط الإرسال فارغًا تكتب الدالة الرمز في سجل تنفيذها كي لا يحرق التطوير الرصيد.

أحيانًا الجواب الصحيح ليس الرسائل النصية أصلًا. الرسائل تكلف مالًا، لذا يستعمل منتج الروضات رموز دعوة تصدرها المديرة مع جلسة مرتبطة بالجهاز، والتسجيل الذاتي غير مدعوم عمدًا. قاعدة من ذلك الكود نطبقها الآن في كل مكان: المصادقة هي الشيء الوحيد الذي لا يمكن وضعه في طابور. التشغيل بلا شبكة ينتظر بدل أن يخرج أحدًا من حسابه؛ وحده 401 حقيقي يفعل ذلك.

من اليمين إلى اليسار منذ أول commit

ConnexionDemandesOffresMessagesContinuerFR · Directionality ltrتسجيل الدخولالطلباتالعروضالرسائلمتابعةAR · Directionality rtlEdgeInsetsDirectionalAlignmentDirectionalstart / endnever left / rightfonts bundledtested in both locales
الشكل 3.الشاشة نفسها بالفرنسية والعربية: هوامش اتجاهية، محاذاة start/end وأسهم معكوسة، مع عربية مكتوبة لا مترجمة.

تعديل تطبيق لاحقًا ليدعم اليمين-إلى-اليسار مؤلم، فتوقفنا عن التعديل اللاحق. القواعد التي يفرضها الآن إعداد المحلّل والاختبارات في مشاريعنا الأحدث:

  • استعمل EdgeInsetsDirectional وAlignmentDirectional وstart / end. أبدًا left / right.
  • اختبر كل شاشة باللغتين منذ الأسبوع الأول. منصة المعدات تُشحن مع 468 اختبارًا عبر نحو ثلاثين ملفًا، وحصة جيدة منها فحوص تدويل واتجاه وتباين.
  • ضمّن الخطوط. Tajawal للعربية، مشحونة داخل التطبيق، لأن التطبيق يُستعمل حيث لا Wi-Fi، والخط الذي يُحمَّل عند التشغيل خط لا يُحمَّل أحيانًا.
  • أبقِ العلامة هندسةً متجهية، لا حرفًا من خط، حتى تُرسم بالشكل نفسه في كل لغة.
  • اكتب العربية ولا تترجمها. تعليقا commit في موقع Batipro يقولانها أفضل: «عربية بسيطة لا عربية أدبية» و«العربية تُرجمت ولم تُكتب».

عربية بسيطة لا عربية أدبية. العربية تُرجمت ولم تُكتب.

رسالتا commit، في ظهيرة واحدة

سجل commits في تطبيق قطر السيارات يُظهر شكل التعديل اللاحق حين تضطر إليه: هوامش اتجاهية، أسهم معكوسة، مساعد نموذج آمن للغة، وتغيير منفصل لتثبيت سهم التنقل في نهاية الصف. ثلاثة أسابيع كانت ستكون ثلاثة أيام لو بدأنا بها.

ما يراه المراجع

تدقيق الجاهزية لـ App Store الذي كتبناه لتطبيق المطعم مرتّب حسب أسباب الرفض التي يصطدم بها المطورون أكثر. تلك التي غيّرت إعداداتنا الافتراضية:

  • لا نافذة طلب تتبّع إن كنت لا تتبّع. Apple ترفض التطبيقات التي تعرض الطلب دون استعمال المعرّف.
  • أيقونة حقيقية بحجم 1024 في 1024. تصغير شعار نصي تلقائيًا إلى مربع سبب رفض شائع، وهو قبيح على أي حال.
  • اقفل iPhone على الوضع العمودي ما لم تكن كل شاشة تتعامل فعلًا مع الأفقي. إعلان دعم لا تملكه سبب رفض.
  • ارفع رقم البناء في كل رفع. إعادة رفع الرقم نفسه مرفوضة.
  • حاجز عدم اتصال صارم يستبدل الشاشة كلها عدواني جدًا في نظر المراجعين، الذين يختبرون على شبكات ضعيفة ويحبون رؤية المحتوى المخزن يظهر. اعرض شريطًا بدلًا منه.
  • اكتب ملاحظات المراجع مسبقًا. ملاحظاتنا تشرح لماذا يعمل «إرسال الطلب» بلا خطوة دفع، وأن طلبات الاختبار ستظهر في لوحتنا باسم المراجع وستُحذف.

على جانب Play، الأجزاء المملة هي التي تستحق الأتمتة: تصريح أمان البيانات يولده سكربت، وخطوات الكونسول التي لا واجهة برمجية لها موثّقة خطوة بخطوة، وملاحظات الإصدار تُكتب بالإنجليزية والفرنسية والعربية في سجل التغييرات نفسه حتى لا تتأخر صفحة المتجر أبدًا.

اكتشاف محرج من مراجعتنا لكودنا: تطبيق قطر السيارات كان التحديث عبر الهواء مضبوطًا فيه بشكل صحيح، وكان مسار الإصدار يتجاوزه بتشغيل بناء عادي. لشهور، لم يكن أي إصدار على Play يستطيع تلقي ترقيع. الإعداد كان صحيحًا؛ خط الأنابيب لم يكن.

الهجرة التي لم تكن تبديل إعدادات

FIREBASE → APPWRITE, COUNTED IN THE CODEBASErunTransaction~55 uses.batch()~60 usescollectionGroup~59 usesFieldValue.*~209 usesRealtime snapshots~35 usesPhone OTP~37 usesStorage✗ rebuilt by hand · ✓ mapped one to onepresentationdomaindata layer · ~78 filescloud functions · 18only the hatched layers changed~398 unit tests + integration against a real Appwrite before cutover
الشكل 4.مغادرة Firebase: ما انتقل مباشرة وما لم ينتقل، ولماذا حصرت البنية النظيفة الأثر في طبقة البيانات والدوال.

منصتنا لقطع غيار السيارات بدأت على Firebase وانتقلت إلى Appwrite. الأسباب هي المعتادة: استضافة ذاتية، إقامة البيانات، تكلفة متوقعة بدل الفوترة لكل قراءة، مع التحفظ الصادق في وثيقتنا نفسها بأن حجة التكلفة يجب أن توزن مقابل تكلفة الهجرة والتشغيل.

الحكم الذي كتبناه من البداية: هذا تغيير منصة كبير. عدّ الاستعمالات في الكود جعله ملموسًا. نحو 55 معاملة، و60 كتابة مجمّعة، و59 استعلام مجموعة تجميعات، و209 عمليات على قيم الحقول لم يكن لها مقابل واحد لواحد، والمستندات بلا مخطط صارت خصائص محددة مسبقًا. الاشتراكات اللحظية ورمز التحقق بالهاتف والتخزين انتقلت بسلاسة.

شيئان جعلا الأمر قابلًا للنجاة. البنية النظيفة حصرت العمل في طبقة البيانات، نحو 78 ملف Dart، وفي 18 دالة سحابية، بدل إعادة كتابة كاملة. ونحو 398 اختبار وحدة إضافة إلى اختبارات تكامل ضد نسخة Appwrite حقيقية جرت قبل أن يثق أحد بالانتقال. ومع ذلك كشفت أخطاء حقيقية: استعلامات تستعمل أسماء حقول Firebase قديمة لم تعد موجودة، وتدقيق مخطط وجد عشر خصائص ناقصة في المشروع الحي، وحفنة من مؤشرات التحميل العالقة.

ميزتان اختفتا بهدوء في الانتقال واضطررنا لإعادة بنائهما بعد ستة أسابيع، وهذا درس بحد ذاته.

إن كنت تطلق هنا

  1. اختر قناة الدفع أولًا، ثم الخادم.
  2. اشترِ شريحة من كل متعامل. اختبر وصول رموز التحقق قبل أن تكتب شاشة التسجيل.
  3. اسأل إن كنت تحتاج الرسائل النصية أصلًا.
  4. اعتمد اليمين-إلى-اليسار من اليوم الأول، ضمّن الخطوط، واكتب العربية.
  5. اكتب ملاحظات المراجع قبل أن يطلبها.
  6. عُدّ مساحة الواجهة البرمجية قبل الهجرة، واحتفظ بقائمة الميزات القديمة حتى يُطفأ الخادم القديم.
Command Palette

Search for a command to run...