الانتقال إلى المحتوى الرئيسي
كل المقالات
تقني10 دقائق قراءة

الدفع داخل التطبيق في المغرب: البنية الآمنة لتطبيقات iOS وAndroid

الدفع داخل التطبيق في المغرب: خادمكم ينشئ الجلسة، والتطبيق يفتح صفحة الدفع المستضافة، والويب هوك الموقَّع يؤكد الأداء، ولا مفتاح API داخل التطبيق.

الدفع داخل التطبيق في المغرب، على iOS أو Android، يقوم على قاعدة واحدة: التطبيق لا يتحدث أبدًا مباشرة إلى API الدفع. يرسل الطلبية إلى خادمكم؛ وينشئ خادمكم جلسة دفع بمفتاح API الخاص به ولا يعيد إلى التطبيق إلا عنوان صفحة الدفع المستضافة؛ ويدفع الزبون فيها بالبطاقة مع ‎3-D Secure؛ ثم يؤكد ويب هوك موقَّع الأداء لخادمكم، الذي يسأله التطبيق ليعرض النتيجة. لا مفتاح داخل التطبيق، ولا رقم بطاقة بين أيديكم. يشرح هذا الدليل هذا المسار خطوة بخطوة، مع الشفرة من جهة الخادم، والعودة، والتأكيد، والاختبار.

الدفع داخل التطبيق في المغرب: عمّ نتحدث؟

عبارة «تطبيق الدفع» تغطي أمرين مختلفين تمامًا. هناك التطبيقات التي يثبّتها الأفراد ليدفعوا؛ وهناك البنية التي يستعملها تطبيق — للتوصيل أو الحجز أو التكوين أو الخدمات — ليستخلص من مستخدميه. وChariPay من النوع الثاني: ChariPay منصة دفع مغربية، مزوّد خدمات دفع (PSP) تشغّله Chari Money، مؤسسة أداء مرخَّصة من بنك المغرب. لا يثبّت مستخدموكم أي شيء إضافي: يدفعون ضمن مسار تطبيقكم، في صفحة تستضيفها ChariPay.

لا يتطلب الإدماج الموثَّق أي SDK للهاتف. فهو يمر عبر ثلاث لبنات تعرفونها إن كان لديكم خادم: خادمكم، وREST API الخاصة بـChariPay، وصفحة الدفع المستضافة. فلا شيء يُدمج إذن في الملف التنفيذي للتطبيق، والخادم نفسه يخدم تطبيق iOS وتطبيق Android وموقعكم.

نقطة الانطلاق التقنية هي فضاء المطورين؛ أما مجموعة Postman ومواصفة OpenAPI فتُنزَّلان من توثيق API، ويعرض دليل API الدفع في المغرب الإدماج في جهة الخادم.

المسار في سبع مراحل، من التطبيق إلى الويب هوك

هذه البنية الكاملة للأداء داخل تطبيق، دون اختصار:

  1. 1يرسل التطبيق الطلبية إلى خادمكم: السلة ومعرّف المستخدم، لا أكثر. لا مفتاح ولا بيانات بطاقة.
  2. 2ينشئ خادمكم الجلسة لدى ChariPay، بالترويسة X-CHARI-PAY-API-KEY: المفتاح لا يغادر الخادم أبدًا.
  3. 3يعيد الخادم إلى التطبيق `checkoutUrl` وحده، أي عنوان صفحة الدفع الخاصة بهذه الجلسة.
  4. 4يفتح التطبيق الصفحة المستضافة على هذا العنوان.
  5. 5يدفع الزبون: بالبطاقة مع ‎3-D Secure، في الصفحة المستضافة، مؤكدًا العملية لدى بنكه.
  6. 6يُعاد الزبون إلى عنوان accept أو decline الخاص بكم، حسب النتيجة.
  7. 7يصل الويب هوك الموقَّع إلى خادمكم، فيعلّم الطلبية مدفوعة؛ ويسأل التطبيق خادمكم ثم يعرض النتيجة.
المرحلةالفاعلما يمر
1التطبيق ← خادمكمالطلبية والمستخدم، دون مفتاح ولا بطاقة
2خادمكم ← API ChariPayالمبلغ، وorderId، والزبون، وعناوين العودة، وmetadata
3خادمكم ← التطبيقcheckoutUrl، لا شيء غيره
4–5الزبون ↔ الصفحة المستضافة وبنكهالبطاقة ومصادقة ‎3-D Secure
6الصفحة المستضافة ← عنوان العودةعودة المستخدم، لا دليل الأداء
7ChariPay ← خادمكم؛ التطبيق ← خادمكمالويب هوك الموقَّع؛ ثم حالة الطلبية

لكل سهم سبب وجوده. البطاقة تتلقاها الصفحة المستضافة، لا نموذج في تطبيقكم، ولا يرى خادمكم رقمها أبدًا. والمفتاح لا يمر إلا بين خادمكم وChariPay. وحقيقة الأداء تصل عبر القناة الموقَّعة الوحيدة: الويب هوك.

يمكنكم تركيب هذا المسار من أوله إلى آخره دون مال حقيقي: ابدؤوا في وضع الاختبار. ثلاثة حقول (الاسم، والبريد الإلكتروني المهني، والمؤسسة)، ورابط تفعيل يصلكم بالبريد لاختيار كلمة المرور، ثم بوابة التاجر حيث تنشئون بأنفسكم مفتاح الاختبار بعد إعادة مصادقة؛ ولا يُعرض المفتاح كاملًا إلا مرة واحدة. تضعونه في خادم التطوير وتدفعون ببطاقة الاختبار. الأمر مجاني، بلا حد زمني ودون موافقة تنتظرونها: والتحقق من مؤسستكم (KYB) لا يشترطه إلا الانتقال إلى الإنتاج.

لماذا لا يجوز أن يدخل مفتاح API إلى التطبيق أبدًا

مفتاح واحد لكل شركة ولكل بيئة، بصلاحيات (scopes) لكل وحدة؛ تنشئونه بأنفسكم من بوابة التاجر بعد إعادة مصادقة؛ ولا يُعرض المفتاح كاملًا إلا مرة واحدة ولا يُرسل أبدًا بالبريد الإلكتروني؛ ويمكن أن يتعايش مفتاحان مدة التدوير دون انقطاع. والمفتاح سرّ: لا يوضع أبدًا في المتصفح، ولا في تطبيق محمول، ولا في مستودع git، ولا في لقطة شاشة.

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

والمفتاح هو أيضًا من يختار البيئة: عنوان أساسي واحد، https://api-psp.charipay.ma، يخدم السندبوكس والإنتاج معًا، والمفتاح هو الذي يحسم، chari_sk_test_… للسندبوكس وchari_sk_live_… للإنتاج. مفتاح اختبار في غير مكانه أقل خطورة إذن من مفتاح إنتاج، لكن القاعدة واحدة للاثنين. وإن احتمل تسرّب مفتاح، فأنشئوا مفتاحًا جديدًا، وانقلوا خادمكم إليه، ثم اسحبوا القديم. والتفاصيل في حماية مفاتيح API.

من جهة الخادم: إنشاء الجلسة وإعادة checkoutUrl وحده

حين يرسل التطبيق طلبية، ينشئ خادمكم الجلسة. الطلب بـcurl:

bash
curl -X POST 'https://api-psp.charipay.ma/v1/payment-sessions' \
  -H 'X-CHARI-PAY-API-KEY: chari_sk_test_...' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: order-2026-0421-session' \
  -d '{
    "amount": 250.00,
    "orderId": "ORD-2026-0421",
    "externalId": "order-2026-0421",
    "config": {
      "customer": {
        "email": "amine.bennani@example.com",
        "firstName": "Amine",
        "lastName": "Bennani",
        "phone": "+212600000000"
      },
      "urls": {
        "accept": "https://votre-boutique.ma/paiement/succes",
        "decline": "https://votre-boutique.ma/paiement/echec",
        "notification": "https://votre-boutique.ma/webhooks/charipay"
      }
    },
    "metadata": { "cartId": "c_987", "source": "web" }
  }'

ويتضمن الرد (201، أو 200 عند الإعادة) هذه الحقول الخمسة، ولا شيء غيرها:

json
{
  "sessionId": "ps_5Kd0Rn",
  "sessionToken": "st_…",
  "verifyKey": "vk_5Kd0Rn",
  "expiresAt": "2026-10-05T10:15:00Z",
  "checkoutUrl": "https://…/checkout/ps_5Kd0Rn"
}

يحتفظ خادمكم بـsessionId إلى جانب الطلبية، ولا يرسل إلى التطبيق إلا checkoutUrl. وتُقرأ حالة الجلسة ومبلغها بعد ذلك عبر GET /v1/payment-sessions/{sessionId}. وفي تطبيق، ضعوا في metadata ما يربط الجلسة بمستخدمكم، كمعرّف السلة والمنصة ("source": "ios" أو "android" بدل "web"): إنه كائن مسطّح لا يتجاوز 4 كيلوبايت، يعود كما هو في الويب هوك.

ثلاثة أعراف ينبغي احترامها: المبالغ بالدرهم وبالوحدات الرئيسية (250.00)؛ وكل عنوان مصرَّح به عنوان https:// عمومي، وإلا كان الرد 400؛ والحقل الاختياري الذي لا تستعملونه يُحذف، ولا يكون null أبدًا. والمرجع الكامل للحقول في وحدة «جلسات الدفع» في توثيق API.

العودة إلى التطبيق: عناوين https عمومية، لا أكثر

بعد الأداء، تعيد الصفحة المستضافة المستخدم إلى عنوان accept أو decline الخاص بالجلسة. وهذه العناوين عناوين https:// عمومية؛ وإن لم تحددوها، تُطبَّق القيم الافتراضية المضبوطة في حسابكم، ثم قيم المنصة. عمليًا، وجّهوها نحو صفحات في نطاقكم مخصصة للتطبيق: «جارٍ التحقق من الأداء» و«الأداء لم يكتمل».

النقطة الجوهرية: هذه العناوين تعيد المستخدم، ولا تثبت الأداء. أكّدوا الطلبية عند استلام الويب هوك، لا عند إعادة التوجيه وحدها: فإعادة التوجيه تعني أن المشتري عاد، لا أن الأداء قد تمّ. والتطبيق الذي يعرض «مدفوع» لأنه رأى عنوان accept سيعرض يومًا «مدفوع» لأداء لم يتم.

أما كيف يفتح التطبيق الصفحة ويستعيد الزمام، فذلك يتوقف على اختياراتكم التقنية والأنظمة المستهدفة، ولا نصف إعداداته هنا. التزموا بالمبدأ: صفحة مستضافة تُفتح على العنوان المتلقى، لا داخل iframe مخفي أبدًا، وعودة عبر عنوان https؛ واختبروا العودة على أجهزتكم المستهدفة. تعيش الجلسة 72 ساعة افتراضيًا (وexpiresAt لتقصيرها) ولا تُستهلك إلا مرة واحدة؛ وما يحدث إن أغلق المستخدم الصفحة مشروح في انتهاء جلسة الدفع والعودة منها.

التأكيد من جهة الخادم: التطبيق يسأل خادمكم

لا ينادي التطبيق API ChariPay أبدًا، ولا حتى للسؤال عن حالة. بل يسأل خادمكم عن حالة الطلبية، والخادم يعرفها من الويب هوك الموقَّع:

  1. 1عند العودة من الصفحة المستضافة، يعرض التطبيق «جارٍ التحقق من الأداء».
  2. 2يسأل خادمكم عن الطلبية، على فترات قصيرة ولمدة محدودة.
  3. 3يجيب خادمكم «مدفوع» بمجرد أن يتلقى ويتحقق ويسجّل الويب هوك payment.succeeded لهذه الطلبية، التي يجدها عبر metadata الخاص بكم؛ وبالنسبة إلى الجلسة، يحمل الحدث أيضًا orderId الخاص بكم.
  4. 4وإن لم يصل شيء، يمكن لخادمكم أن يقرأ بنفسه GET /v1/payment-sessions/{sessionId}.

الاستعلام من الخادم حل احتياطي، لا مصدر الحقيقة. وبعد أي انقطاع، طابِقوا عبر GET /v1/transactions. أما المستقبِل نفسه، من التوقيع على المحتوى الخام إلى نافذة منع الإعادة وحذف المكرَّر حسب Chari-Event-Id، فمشروح في إنجاح دمج الويب هوك.

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

وماذا لو عرض التطبيق نموذج بطاقة خاصًا به؟

هذا ممكن، عبر الدفع المباشر. يتيح لكم الدفع المباشر بناء نموذج البطاقة الخاص بكم: التحقق من الجلسة، وإرسال بيانات البطاقة، وعودة ‎3-D Secure، وحالة الأداء. ولا تُوثَّق هذه النداءات بمفتاح API الخاص بكم بل بالجلسة ومفتاح التحقق لمرة واحدة (vk) — فلا ترسلوا مفتاح API إليها أبدًا — وهي تُدخلكم في نطاق الامتثال الخاص ببيانات البطاقات.

وفي تطبيق، ليس التطبيق هو من ينفّذ هذه النداءات. في الدفع المباشر، خادمكم هو الذي ينفّذ نداءات /checkout/*، من خادم إلى خادم؛ وفي صفحة الدفع المستضافة، تنفّذها صفحة الدفع الخاصة بـChariPay نفسها. وفي الحالتين تُوثَّق بالجلسة ومفتاحها vk، لا بمفتاح API الخاص بكم أبدًا. فنموذج تطبيقكم يرسل البطاقة إذن إلى خادمكم، الذي يُرسل طلب الأداء: وبيانات البطاقة تمر عبر تطبيقكم وعبر خادمكم.

قارنوا بالصفحة المستضافة: يُدخل زبونكم بطاقته في صفحة الدفع المستضافة، داخل نطاق حاصل على شهادة PCI DSS المستوى 1: لا ترون أبدًا رقم بطاقة، ويُختصر استبيان التقييم الذاتي الخاص بكم تبعًا لذلك — وهو ما يُؤكَّد مع مستشاركم أو جهة الاقتناء لديكم.

وفي تطبيق، لا معنى للدفع المباشر إلا إذا كان لديكم سبب محدد لعدم استعمال الصفحة المستضافة. والنداءات الأربعة، والتوثيق بـvk، وشبكة القرار، كلها في مقال الدفع المباشر.

اختبار المسار على الهاتف في وضع الاختبار

قبل تقديم أي إصدار، مرّوا على هذه القائمة بهاتف حقيقي:

  • المفتاح: chari_sk_test_… على الخادم فقط؛ ابحثوا عنه في الملف التنفيذي وفي مستودع التطبيق، ويجب ألا يوجد في أي منهما.
  • عناوين العودة: accept وdecline عناوين https:// عمومية تعيد المستخدم فعلًا على أجهزتكم المستهدفة.
  • أداء ناجح: بطاقة الاختبار ‎4918 9141 0719 5005، CVV 123، وأي تاريخ انتهاء مستقبلي، ورمز ‎3-D Secure 555؛ هذه البطاقة هي الوحيدة المقبولة، ولا يتحرك أي مال حقيقي.
  • التأكيد: لا يعرض التطبيق «مدفوع» إلا بعد أن يتلقى خادمكم الويب هوك؛ وفي السندبوكس تُرسل الويب هوكس بشكل عادي.
  • التخلي: أغلقوا الصفحة في منتصف الأداء وتحققوا من أن الطلبية تبقى «في الانتظار».
  • النقر المزدوج: مستخدم ينقر مرتين على «ادفع» يجب ألا ينشئ جلستين؛ أرسلوا Idempotency-Key ثابتًا لكل طلبية، أو externalId فريدًا: فالإنشاء بـexternalId موجود يعيد الجلسة الموجودة بـ200 OK بدل 201 Created.

أسئلة شائعة

هل أحتاج إلى SDK لقبول الدفع داخل تطبيق الهاتف؟

لا. لا يتطلب الإدماج الموثَّق أي SDK للهاتف: فهو يمر عبر خادمكم، الذي ينادي REST API، وعبر صفحة الدفع المستضافة التي يفتحها التطبيق على العنوان المتلقى. لا شيء يُدمج في الملف التنفيذي، والخادم نفسه يخدم تطبيقي iOS وAndroid وموقعكم. ويقترح توثيق API أيضًا مجموعة Postman لتجاربكم.

هل يمكن للتطبيق مناداة API الدفع مباشرة؟

لا. نداءات API موثَّقة بمفتاحكم، والمفتاح سرّ: لا يوضع أبدًا في المتصفح، ولا في تطبيق محمول، ولا في مستودع git، ولا في لقطة شاشة. ويمكن تفكيك أي تطبيق منشور. التطبيق يتحدث إلى خادمكم، وخادمكم وحده يتحدث إلى API ChariPay، ولا يعيد إلى التطبيق إلا checkoutUrl الخاص بالجلسة.

هل أحتاج إلى خادم للاستخلاص داخل تطبيق الهاتف؟

بالنسبة إلى إدماج عبر API، نعم: فالخادم هو من يحتفظ بالمفتاح، وينشئ الجلسات، ويتلقى الويب هوكس الموقَّعة. وبدون خادم، لا إدماج: تستطيعون إرسال رابط دفع منشأ في بوابة التاجر إلى زبون، وهو رابط لاستعمال واحد، رابط لكل بيع، ومتابعة الأداء في بوابة التاجر. إنه حل مؤقت للانطلاق، لا إدماج مرتبط بطلبياتكم.

كيف يعرف التطبيق أن الأداء نجح؟

يسأل خادمكم. والخادم يعرف ذلك من الويب هوك الموقَّع payment.succeeded، وهو المرجع؛ أما إعادة التوجيه إلى عنوان accept فتعني فقط أن المستخدم عاد. وكحل احتياطي، يستطيع خادمكم قراءة الجلسة عبر GET /v1/payment-sessions/{sessionId}. ويعرض التطبيق «جارٍ التحقق» ما دام الخادم لم يؤكد.

أين أضع مفتاح الاختبار خلال التطوير؟

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

هل يمكن للتطبيق عرض نموذج بطاقة خاص به؟

نعم، عبر الدفع المباشر: يرسل نموذج التطبيق البطاقة إلى خادمكم، وخادمكم هو الذي ينفّذ نداءات /checkout/*، من خادم إلى خادم، موثَّقة بالجلسة ومفتاحها vk، لا بمفتاح API الخاص بكم أبدًا. لكنه يُدخلكم في نطاق الامتثال الخاص ببيانات البطاقات. ولا معنى له إلا إذا كان لديكم سبب محدد لعدم استعمال الصفحة المستضافة، ومقال الدفع المباشر يفصّل الموازنة.

هل يمر رقم البطاقة عبر تطبيقي؟

مع الصفحة المستضافة، لا يتلقى البطاقةَ أيُّ نموذج في تطبيقكم: يُدخلها زبونكم في صفحة الدفع المستضافة، داخل نطاق حاصل على شهادة PCI DSS المستوى 1، ولا ترون أبدًا رقم بطاقة، لا في التطبيق ولا في خادمكم. أما مع الدفع المباشر، فتمر بيانات البطاقة عبر تطبيقكم وعبر خادمكم، مع ما يرافق ذلك من التزامات الامتثال.

الخطوة التالية

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

بقلم فريق ChariPay.

اقرؤوا بعده

الامتثال4 دقائق قراءة

حماية مفاتيح الواجهة

حماية مفاتيح API الخاصة بالدفع: خمس قواعد بسيطة، والتدوير المخطَّط، وما يجب فعله بالترتيب حين يتسرّب مفتاح فعلًا إلى مستودع أو سجل.

مستعدون للتجربة بأنفسكم؟

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

  • مجاني ودون التزام
  • وضع الاختبار منذ التسجيل
  • لا موافقة تنتظرونها