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

رموز أخطاء API الدفع: معنى كل رمز ومتى تصحّحون أو تعيدون المحاولة أو تنتظرون

رموز أخطاء API الدفع من 400 إلى 502: غلاف الخطأ، وcorrelationId، وسبب كل رمز وطريقة تصحيحه، ومتى تُعاد المحاولة بمفتاح Idempotency نفسه.

تتبع رموز أخطاء API الدفع لدى ChariPay قاعدة بسيطة: حالة HTTP تقول من عليه أن يتصرف، والحقل code يقول ماذا يفعل. فخطأ من فئة 4xx يُصحَّح من جهتكم قبل أي محاولة جديدة — إلا 429، حيث يكفي انتظار المدة التي تحدّدها Retry-After؛ وخطأ من فئة 5xx مصدره جهتنا ويُعاد بمفتاح Idempotency نفسه. يفصّل هذا الدليل غلاف الخطأ وcorrelationId الخاص به، وكل رمز منشور مع سببه وطريقة تصحيحه والسلوك الواجب، ثم قاعدة قرار، وطريقة تسجيل لا تُغرق تنبيهاتكم.

غلاف الخطأ وcorrelationId

ChariPay منصة دفع مغربية، مزوّد خدمات دفع (PSP) تشغّله Chari Money، مؤسسة أداء مرخَّصة من بنك المغرب. وكل أخطاء API التاجر لديها — المسارات /v1 — تشترك في الغلاف نفسه:

json
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "amount: must be greater than 0"
  },
  "correlationId": "b0c1e2d3-4f56-7890-abcd-ef0123456789"
}

ثلاثة حقول وثلاثة استعمالات. الحقل code ثابت: فهو جزء من العقد، وهو ما يختبره برنامجكم. والحقل message موجَّه إلى إنسان: يساعد على الفهم، لا على القرار. اختبروا code، لا message أبدًا. أما correlationId فيحدّد الطلب في سجلاتنا؛ ويعود أيضًا في الردود الناجحة، وإن أرسلتم ترويسة X-Request-Id خاصة بكم فإنها تُعاد في الرد وتصير هي correlationId. ولّدوا إذن معرّفًا لكل طلب من جهتكم، وأرسلوه في X-Request-Id، فيرتبط كل سطر في سجلاتكم بسطر في سجلاتنا دون عناء.

واستثناء ينبغي معرفته: نقاط التسجيل وبوابة التاجر لها صيغة أخطاء خاصة بها، برموز من نوع ERR-XXXX. أما الغلاف أعلاه فيخص مسارات /v1 التي يناديها مفتاحكم، كما يخص نداءات /checkout/* في الدفع المباشر، وهو موضوع بقية الدليل.

400 و401: الطلب أو المفتاح

الرمزالحالةالسببالتصحيح
VALIDATION_ERROR400حقل لا يجتاز التحقققراءة message وتصحيح الحقل
MISSING_PARAMETER400معامل مطلوب غائبإضافته
INVALID_IDEMPOTENCY_KEY400Idempotency-Key غائب أو أطول من اللازم حيث يكون مطلوبًا، مثلًا في POST /checkout/submit لجلسة قابلة لإعادة الاستعمالإرسال مفتاح صالح
UNAUTHORIZED401مفتاح API غائب أو غير صالحالتحقق من الترويسة X-CHARI-PAY-API-KEY ومن المفتاح الذي تحمّله إعداداتكم
INVALID_TOKEN401الدفع المباشر: مفتاح التحقق vk غير صالح أو مستهلَك، أو الجلسة لم يُتحقَّق منها أولًااحترام ترتيب النداءات (verify قبل submit) وعدم إعادة استعمال vk أبدًا

والرد 400 يعني أن API ترفض الطلب كما هو. وقبل مراجعة منطقكم، تحققوا من أن الطلب يحترم أعراف API:

  • حقول بصيغة camelCase: orderId، لا order_id؛
  • مبلغ بالدرهم، بالوحدات الرئيسية، بخانتين عشريتين على الأكثر: 149.90؛
  • كل عنوان مصرَّح به — العودة، والإشعار، والشعار — بصيغة https:// عمومية، وإلا كان الرد 400؛
  • expiresAt في المستقبل، بصيغة ISO-8601 بتوقيت UTC: 2026-07-31T10:15:00Z؛
  • metadata مسطّحة — نصوص وأرقام وقيم منطقية —، دون كائن متداخل ولا مصفوفة، و4 كيلوبايت على الأكثر.

واحذفوا كذلك أي حقل اختياري بدل إرساله بقيمة null: فـAPI تتعامل مع الحقول الغائبة. ولا يُعاد طلب 400 كما هو أبدًا، أيًّا كان code الخاص به، لأن الطلب نفسه سينتج الخطأ نفسه. صحّحوا ثم أرسلوا الطلب المصحَّح. وإن ظهر خطأ 401 UNAUTHORIZED مباشرة بعد نشر جديد، فتحققوا أولًا من متغير البيئة الذي يحمل المفتاح: فقد يكون فارغًا أو خاطئ الاسم أو مبتورًا.

ولبناء معالجة الأخطاء لديكم، استحثّوا هذه الأخطاء بمفتاح اختبار — حقل محذوف، وعنوان بـhttp://، ومفتاح خاطئ عمدًا — ثم اقرؤوا الحالة وcode اللذين تحصلون عليهما. ابدؤوا في وضع الاختبار: ثلاثة حقول — الاسم، والبريد الإلكتروني المهني، والمؤسسة —، ثم رابط تفعيل يصلكم بالبريد لاختيار كلمة المرور، ثم بوابة التاجر حيث تنشئون بأنفسكم مفتاح الاختبار بعد إعادة مصادقة. وهو مجاني، بلا حد زمني، والتحقق من مؤسستكم لا يشترطه إلا الإنتاج.

403 PRODUCTION_ACCESS_NOT_ENABLED وFORBIDDEN

الرمز 403 PRODUCTION_ACCESS_NOT_ENABLED معناه هو ما يقوله تمامًا: تنادون API بمفتاح chari_sk_live_… بينما الإنتاج لم يُفعَّل بعد على حسابكم. ليس خللًا في الإدماج، بل خطوة إدارية. ولها تصحيحان: العودة إلى مفتاح chari_sk_test_… ما دمتم في التطوير، أو إتمام الانتقال إلى الإنتاج — التحقق من المؤسسة، ودراسة الملف، ورسوم التفعيل 6 000 درهم شاملة الضريبة تُؤدّى مرة واحدة —، وقائمة الانتقال في الانتقال من السندبوكس إلى الإنتاج. ويجب أن يختبر برنامجكم هذا الرمز بعينه، PRODUCTION_ACCESS_NOT_ENABLED، وأن يُظهره بوضوح لفريقكم بدل إغراقه وسط الأخطاء العامة.

أما 403 FORBIDDEN فمن طبيعة أخرى: المفتاح موثَّق، لكنه لا يملك الصلاحية المطلوبة لهذا النداء. فلكل مفتاح صلاحيات حسب الوحدة؛ والمثال المنشور هو تصدير CSV للمعاملات، الذي يشترط الصلاحية transaction:export. والتصحيح أن تتحققوا، في بوابة التاجر، من صلاحيات المفتاح الذي يستعمله إدماجكم، وأن تنادوا بمفتاح يحمل الصلاحية التي يشترطها النداء. ولا توسّعوا الصلاحيات تلقائيًا: امنحوا المفتاح ما يناديه إدماجكم فعلًا، ولا شيء غيره.

404 و409 و410 و422: المورد، والتعارض، وانتهاء الصلاحية، والحالة

الحالةالرمزمعناهماذا تفعلون
404OPERATION_NOT_FOUNDلا عملية تطابق المعرّف المرسَلالتحقق من المعرّف ومن بيئة المفتاح
404ORDER_NOT_FOUNDلا أداء يطابق المرجعالتحقق من المرجع المرسَل
404SESSION_NOT_FOUNDجلسة غير معروفةالتحقق من sessionId المرسَل
409IDEMPOTENCY_CONFLICTIdempotency-Key نفسه بجسم مختلفإصلاح طريقة توليد المفاتيح؛ وعدم الإعادة كما هي
409SESSION_ALREADY_CONSUMEDالجلسة أُدّيت من قبلعدم إرسالها مجددًا؛ ولأداء جديد إنشاء جلسة جديدة، ولإرجاع المال الاسترداد
409SESSION_NOT_ACTIVEالجلسة أُلغيتإنشاء جلسة جديدة إذا كانت الطلبية ما تزال واجبة الأداء
410SESSION_EXPIREDالجلسة تجاوزت expiresAtإنشاء جلسة جديدة
422WALLET_NOT_ACTIVEطلب صالح، لكن المحفظة المعنية غير نشطةعدم الإعادة في حلقة؛ التواصل مع الفريق مع إرفاق correlationId

وفي معاملة أو استرداد، قد يأتي OPERATION_NOT_FOUND أيضًا من operationId أُنشئ في البيئة الأخرى: فالمفتاح هو الذي يختار البيئة، والسندبوكس والإنتاج معزولان.

ويشير 409 IDEMPOTENCY_CONFLICT إلى خلل من جهتكم، لا إلى عطل: المفتاح نفسه استُعمل لجسمين مختلفين. فمفتاح Idempotency يُشتق من النية — الطلبية والعملية —، لا من سحب عشوائي أبدًا؛ والآلية كاملة في Idempotency في المدفوعات.

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

429 RATE_LIMITED: اقرؤوا Retry-After

تعلن النقاط المعروضة للعموم عن حصتها في ثلاث ترويسات للرد. وبعد تجاوزها، تجيب API بـ429 مع الرمز RATE_LIMITED وترويسة Retry-After.

الترويسةما تخبركم به
X-RateLimit-Limitالحد الذي يسري على النداء
X-RateLimit-Remainingما تبقّى لكم قبل بلوغه
X-RateLimit-Resetلحظة إعادة ضبط العدّاد
Retry-Afterفي رد 429، المدة التي تنتظرونها قبل الإعادة

والسلوك الواجب على مرحلتين: انتظار المدة التي تعلنها Retry-After، ثم إعادة الطلب نفسه بمفتاح Idempotency نفسه. وفي المعالجات المجمّعة — مزامنة كتالوج، أو إعادة قراءة حالات، أو تصدير —، وزّعوا النداءات وراقبوا X-RateLimit-Remaining بدل انتظار 429. فتتابع ردود 429 على نقطة قراءة قد يكشف استطلاعًا مفرطًا: نتيجة الأداء تُعرف بالويب هوك، والاستطلاع ليس إلا حلًا احتياطيًا. ولا يُنشر أي حد رقمي: فلا تكتبوا حدًا ثابتًا في الشفرة، واقرؤوا الترويسات.

5xx و502 BAAS_CHARI_ERROR: الإعادة بالمفتاح نفسه

أخطاء 5xx من جهتنا: أعيدوا المحاولة بمفتاح Idempotency الخاص بكم بدل إنشاء مورد جديد. وهذه بالضبط الحالة التي وُجدت لها أدوات Idempotency الثلاث:

  • `Idempotency-Key` في عمليات الإنشاء: إعادة القيمة نفسها تُرجع النتيجة الأولى إن كانت المحاولة الأولى قد مرّت، دون تكرار.
  • `externalId` في الروابط والجلسات والاشتراكات والمنتجات: الإنشاء بـexternalId موجود يُرجع المورد الموجود بالرد 200 بدل 201.
  • `refundReference` في الاستردادات: 202 عند الإنشاء، و200 عند الإعادة، ولا استرداد ثانٍ أبدًا.

أعيدوا المحاولة بمهلة متزايدة بين المحاولات، وتوقفوا بعد بضع محاولات لتنبيه إنسان بدل الدوران في حلقة. فالإنشاء دون مفتاح Idempotency، إذا أُعيد بعد 5xx، قد يُنشئ نسخة مكررة: ولهذا يجب أن يحمل كل إنشاء ترسلونه مفتاحًا، منذ السندبوكس.

وحالة تشبه العطل وليست عطلًا: في السندبوكس، يرد 502 BAAS_CHARI_ERROR على بطاقة غير بطاقة الاختبار. لا فائدة من الإعادة: غيّروا البطاقة. فالبطاقة الوحيدة المقبولة في السندبوكس هي ‎4918 9141 0719 5005، مع CVV 123، وأي تاريخ انتهاء مستقبلي، ورمز ‎3-D Secure 555؛ وبقية مسار الاختبار في اختبار الدفع في وضع الاختبار.

رموز أخطاء API الدفع: قاعدة القرار

الحالةماذا تفعلونهل تعيدون؟
400تصحيح الحقلبعد التصحيح
401تصحيح الترويسة أو المفتاحبعد التصحيح
403استعمال المفتاح الصحيح أو الصلاحيات الصحيحة، أو تفعيل الإنتاجبعد التصحيح
404التحقق من المعرّف المرسَل، ومن بيئة المفتاح بالنسبة إلى عمليةبعد التصحيح
409تعارض Idempotency: إصلاح توليد المفاتيح؛ جلسة أُدّيت أو أُلغيت: جلسة جديدة إن بقي أداء مستحقليس كما هو أبدًا
410إنشاء جلسة جديدةلا
422رفع الحالة التي تمنعليس قبل ذلك
429انتظار Retry-Afterنعم، كما هو
5xxالانتظار بمهلة متزايدةنعم، بمفتاح Idempotency نفسه
502 BAAS_CHARI_ERROR في السندبوكستغيير البطاقةلا

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

التسجيل والتنبيه دون ضجيج

لكل نداء فاشل، سجّلوا الطريقة والمسار المنادى، وحالة HTTP، وcode، وcorrelationId — الذي يحمل X-Request-Id الخاص بكم إن أرسلتموه. ولا تسجّلوا مفتاح API أبدًا: فالمفتاح سرّ، والسجلات تتداولها الأيدي. ثم اضبطوا تنبيهاتكم حسب ما تعنيه كل إشارة:

الإشارةما تعنيهردّ الفعل
401 أو 403 في الإنتاجمفتاح غائب أو غير صالح، أو صلاحية ناقصة، أو إنتاج غير مفعَّلتنبيه فوري: نداءاتكم لم تعد تمرّ
تتابع ردود 429استطلاع مفرط أو مجموعة نداءات سيئة التوزيعتنبيه، ثم تنعيم النداءات
5xx متكررةعطل من جهتناتنبيه بعد عدة إخفاقات متتالية، وإعادة بمفاتيح Idempotency
409 IDEMPOTENCY_CONFLICTخلل في توليد المفاتيحتذكرة ذات أولوية
400 معزولةمعطيات طلبية بعينهاتذكرة، دون إيقاظ أحد

وحين تراسلون الفريق — تواصلوا مع الفريق —، أرفقوا correlationId والتوقيت بـUTC والمسار المنادى: فهذا ما يسمح بإيجاد طلبكم في سجلاتنا. ويعيد دليل API الدفع في المغرب معالجة الأخطاء إلى سياق الإدماج الكامل، ويسرد توثيق API الردود الممكنة لكل نقطة.

أسئلة شائعة

ماذا يعني الخطأ 403 PRODUCTION_ACCESS_NOT_ENABLED؟

يعني أنكم تنادون API بمفتاح chari_sk_live_… بينما الإنتاج لم يُفعَّل بعد على حسابكم. ليس خللًا في الإدماج: واصلوا العمل بمفتاح الاختبار، أو أتمّوا الانتقال إلى الإنتاج — التحقق من المؤسسة، ودراسة الملف، ورسوم التفعيل 6 000 درهم شاملة الضريبة تُؤدّى مرة واحدة.

ما فائدة correlationId في رد الخطأ؟

يحدّد طلبكم في سجلاتنا. ويعود في كل الردود، بما فيها الناجحة، ويحمل ترويستكم X-Request-Id إن أرسلتموها. سجّلوه دائمًا وأرفقوه بكل طلب مساعدة، مع التوقيت بـUTC والمسار المنادى: فهذا ما يسمح بإيجاد طلبكم في سجلاتنا. وولّدوا X-Request-Id فريدًا لكل طلب لتربطوا سجلاتكم بسجلاتنا.

هل أعيد الطلب بعد خطأ 500؟

نعم. أخطاء 5xx من جهتنا: أعيدوا المحاولة بمفتاح Idempotency الخاص بكم بدل إنشاء مورد جديد. فـIdempotency-Key نفسه أو externalId نفسه أو refundReference نفسه يضمن ألا تُنشأ أي نسخة مكررة إن كانت المحاولة الأولى قد مرّت. باعدوا بين المحاولات بمهلة متزايدة ونبّهوا إنسانًا بعد بضعة إخفاقات.

ماذا أفعل بعد خطأ 429 RATE_LIMITED؟

انتظروا المدة التي تحدّدها الترويسة Retry-After، ثم أعيدوا الطلب نفسه بمفتاح Idempotency نفسه. ولتفادي الخطأ التالي، راقبوا X-RateLimit-Remaining، ووزّعوا معالجاتكم المجمّعة، واستبدلوا الاستطلاع بالويب هوك: فنتيجة الأداء تُعرف بحدث موقَّع، لا بمناداة API في حلقة. ولا يُنشر أي حد رقمي، فاقرؤوا الترويسات دائمًا.

لماذا يُرجع السندبوكس 502 BAAS_CHARI_ERROR؟

لأن البطاقة المُدخلة ليست بطاقة الاختبار. في السندبوكس، لا تُقبل إلا البطاقة ‎4918 9141 0719 5005، مع CVV 123، وأي تاريخ انتهاء مستقبلي، ورمز ‎3-D Secure 555. وأي بطاقة أخرى تتلقى 502 BAAS_CHARI_ERROR: الإعادة لا تغيّر شيئًا، فغيّروا البطاقة. والمسار الكامل للاختبار مشروح في دليل اختبار الدفع في وضع الاختبار.

ماذا يعني الخطأ 409 IDEMPOTENCY_CONFLICT؟

يعني أن Idempotency-Key نفسه أُرسل بجسم مختلف عن الطلب الأول. إنه خلل من جهتكم، لا عطل في الشبكة: فمفتاح Idempotency يُشتق من النية — الطلبية والعملية —، والطلب المختلف يستدعي مفتاحًا مختلفًا. أصلحوا طريقة توليد المفاتيح في شفرتكم بدل إعادة الطلب كما هو.

ما حدّ الطلبات في API؟

لا يُنشر أي حد رقمي. فالنقاط المعروضة للعموم تعلن حصتها في الترويسات X-RateLimit-Limit وX-RateLimit-Remaining وX-RateLimit-Reset، وتجيب بـ429 RATE_LIMITED مع Retry-After عند تجاوزها. اقرؤوا هذه الترويسات بدل كتابة حد ثابت في الشفرة: وسيتكيّف إدماجكم من تلقاء نفسه. وفي المعالجات المجمّعة، وزّعوا النداءات على الوقت.

هل يعني خطأ API أن البنك رفض الأداء؟

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

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

استحثّوا هذه الأخطاء في السندبوكس — حقل غائب، وعنوان بـhttp://، ومفتاح خاطئ، وجلسة منتهية الصلاحية، ومفتاح Idempotency نفسه بجسم آخر، بما فيه externalId — وتحققوا من أن شفرتكم تتصرف كما تنص قاعدة القرار: ابدؤوا في وضع الاختبار. ثم اربطوا تسجيل correlationId، وحضّروا الانتقال مع الانتقال من السندبوكس إلى الإنتاج.

بقلم فريق ChariPay.

اقرؤوا بعده

تقني4 دقائق قراءة

لا تحصّلوا مرتين أبدًا — شرح Idempotency

شرح Idempotency في المدفوعات: كيف تمنع ترويسة Idempotency-Key وحقل externalId خصم المبلغ من الزبون مرتين حين تنقطع الشبكة في منتصف النداء.

تقني20 دقيقة قراءة

دمج API للدفع في المغرب: مفاتيح الاختبار والإنتاج، الروابط، الجلسات، الويب هوك الموقّع، والانتقال إلى الإنتاج

دمج API للدفع في المغرب: مفاتيح الاختبار والإنتاج على عنوان واحد، روابط وجلسات الدفع، ويب هوك موقّع بـ HMAC، Idempotency، بطاقة الاختبار، والانتقال إلى الإنتاج.

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

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

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