تصميم واجهة برمجية للدفع
التعليمات
الهدف
صمم واجهة برمجية RESTful كاملة لمعالجة المدفوعات. ستحدد نقاط النهاية ومخططات الطلب/الاستجابة والمصادقة وقابلية التكرار ومعالجة الأخطاء وإشعارات webhook. هذا التمرين يعكس ما ستُسأل عنه في مقابلة تصميم أنظمة خلفية حقيقية في شركات مثل Stripe وSquare وAdyen.
المتطلبات
1. نقاط نهاية الدفع الأساسية
صمم نقاط النهاية RESTful التالية:
- إنشاء دفعة — بدء خصم مقابل طريقة دفع
- استرجاع دفعة — الحصول على تفاصيل الدفعة بالمعرف
- سرد المدفوعات — قائمة مُصفّحة مع تصفية حسب الحالة ونطاق التاريخ والمبلغ
- إنشاء استرداد — استرداد كامل أو جزئي مقابل دفعة مكتملة
- استرجاع استرداد — الحصول على تفاصيل الاسترداد بالمعرف
- سرد الاستردادات لدفعة — جميع الاستردادات المرتبطة بدفعة
لكل نقطة نهاية، حدد:
- طريقة HTTP والمسار (باتباع اصطلاحات REST)
- جسم الطلب (إن وجد) مع واجهات TypeScript
- جسم الاستجابة مع واجهات TypeScript
- رموز حالة HTTP المناسبة لحالات النجاح والخطأ
2. واجهات TypeScript لمخططات الطلب/الاستجابة
عرّف واجهات TypeScript كاملة لـ:
CreatePaymentRequest— المبلغ، العملة، طريقة الدفع، معرف العميل، البيانات الوصفية، الوصفPaymentResponse— جميع حقول الدفعة بما في ذلك الحالة والطوابع الزمنية وملخص الاستردادCreateRefundRequest— معرف الدفعة، المبلغ (اختياري للاسترداد الكامل)، السببRefundResponse— تفاصيل الاسترداد مع الحالةWebhookEvent— نوع الحدث، الحمولة، الطابع الزمني، التوقيعApiError— رمز الخطأ، الرسالة، مصفوفة التفاصيل، معرف الطلب
استخدم أنواعًا صحيحة: amount يجب أن يكون عددًا صحيحًا بأصغر وحدة عملة (سنتات)، currency يجب أن تستخدم رموز ISO 4217، الطوابع الزمنية يجب أن تكون سلاسل ISO 8601.
3. تصميم المصادقة
صمم نظام مصادقة من طبقتين:
- مصادقة مفتاح الواجهة البرمجية — لجميع طلبات الواجهة البرمجية. حدد صيغة الترويسة، بنية المفتاح (مفاتيح الاختبار مقابل الحية:
sk_test_*وsk_live_*)، وكيف يتحقق الخادم منها. - التحقق من توقيع webhook — لتسليم webhook. حدد كيف توقع حمولات webhook (HMAC-SHA256)، ما الترويسات المضمنة (
Webhook-Signature،Webhook-Timestamp)، وكيف يتحقق المستقبل من الأصالة. ضمّن الحماية ضد هجمات إعادة التشغيل.
4. تنفيذ مفتاح قابلية التكرار
صمم آلية قابلية التكرار لنقطة النهاية POST /payments:
- حدد صيغة ترويسة
Idempotency-Key(UUID v4) - اشرح منطق إزالة التكرار من جهة الخادم
- حدد ما يحدث عند: الطلب الأول، الطلب المكرر (نفس المفتاح)، المفتاح المنتهي
- حدد مدة صلاحية سجلات قابلية التكرار (مثلاً 24 ساعة)
- تعامل مع ظروف السباق (طلبات متزامنة بنفس المفتاح)
5. تصميم تحديد المعدل
حدد حدود المعدل لفئات نقاط النهاية المختلفة:
- إنشاء المدفوعات: حدود أكثر صرامة
- عمليات القراءة (GET): أكثر تساهلاً
- إعادة محاولات webhook: حدود منفصلة
حدد ترويسات الاستجابة (X-RateLimit-Limit، X-RateLimit-Remaining، X-RateLimit-Reset) واستجابة الخطأ عند تجاوز المعدل (429).
6. تصنيف رموز الأخطاء
صمم نظام أخطاء منظم يتضمن:
- فئات الأخطاء:
authentication_error،invalid_request_error،payment_error،rate_limit_error،api_error - رموز أخطاء محددة ضمن كل فئة (مثلاً
card_declined،insufficient_funds،invalid_currency) - رسائل مقروءة للبشر
- رموز أخطاء مقروءة للآلة
- معرف طلب لتصحيح الأخطاء
7. تصميم Webhook
صمم نظام إشعارات webhook لتحديثات حالة الدفع غير المتزامنة:
- حدد أنواع أحداث webhook:
payment.created،payment.succeeded،payment.failed،refund.created،refund.succeeded - حدد بنية حمولة webhook
- صف استراتيجية إعادة المحاولة مع التراجع الأسي (1 دقيقة، 5 دقائق، 30 دقيقة، ساعتان، 24 ساعة)
- صف كيفية التعامل مع فشل تسليم webhook وطابور الرسائل الميتة
المُخرَج
قدم ملف TypeScript واحد يحتوي على:
- جميع واجهات وأنواع TypeScript
- توثيق نقاط النهاية كتعليقات (الطريقة، المسار، الوصف، رموز الحالة)
- أمثلة JSON للطلب/الاستجابة لكل نقطة نهاية (كثوابت محددة النوع)
- توقيعات دوال المصادقة المساعدة
- توقيع الوسيط البرمجي لقابلية التكرار
- دوال توليد والتحقق من توقيع webhook
- دوال مصنع الأخطاء
تلميحات
- ادرس كيف تنظم Stripe واجهتها البرمجية — إنها المعيار الذهبي لتصميم واجهات الدفع البرمجية
- استخدم السنتات (أعداد صحيحة) للمبالغ المالية لتجنب مشاكل دقة النقطة العائمة
- ضمّن حقول
metadata(أزواج مفتاح-قيمة) للتوسعية - حالات الدفع يجب أن تشكل آلة حالة:
pending->processing->succeeded|failed - اجعل جميع الاستجابات تتضمن
request_idلقابلية التتبع - استخدم التصفح بالمؤشر لنقاط نهاية القوائم
- توقيع webhook يجب أن يتضمن الطابع الزمني لمنع هجمات إعادة التشغيل
ما يجب تقديمه
يجب أن يحتوي تقديمك على قسم ملف واحد في المحرر أدناه: ملف TypeScript كامل يحتوي على جميع الأقسام التسعة.