دليل واجهة برمجة تطبيقات نظام الدفع OmniCRM
نظرة عامة
يوفر نظام الدفع OmniCRM بنية تحتية شاملة لمعالجة المدفوعات غير مرتبطة بالبائع. يدعم اليوم كل من Stripe وPayPal، ولكن الهيكلية المودولارية تسمح بالتكامل مع أي مزود دفع (Square، Adyen، Braintree، إلخ) دون الحاجة لتغيير كود التطبيق.
يغطي هذا المستند جميع واجهات برمجة التطبيقات الخاصة بالمدفوعات وسير العمل المتاحة في النظام.
🔧 تكامل Playbook Ansible: لتنفيذ واجهات برمجة التطبيقات هذه في Playbooks التزويد، راجع التحصيل والمدفوعات من Playbooks
جدول المحتويات
- الهيكلية المودولارية
- المفاهيم الأساسية
- المستندات المالية
- واجهات برمجة تطبيقات طرق الدفع
- واجهات برمجة تطبيقات تدفق الدفع
- واجهات برمجة تطبيقات المحفظة
- ملخص مرجع واجهة برمجة التطبيقات
- حالات الاستخدام الشائعة
الهيكلية المودولارية
لماذا غير مرتبطة بالبائع؟
يستخدم النظام طبقات التجريد لفصل منطق الأعمال عن تفاصيل مزود الدفع. وهذا يعني:
- ✅ إضافة مزودي دفع جدد دون الحاجة لتعديل كود التطبيق
- ✅ تبديل البائعين دون الحاجة لترحيل قاعدة البيانات
- ✅ دعم عدة بائعين في نفس الوقت
- ✅ واجهة برمجة تطبيقات متسقة بغض النظر عن مزود الخلفية
طبقات الهيكلية
إضافة بائع دفع جديد
لإضافة مزود جديد (على سبيل المثال، Square، Adyen، Braintree)، اتصل بفريق OmniCRM الفني الخاص بك.
للحصول على تفاصيل التكوين حول البائعين الحاليين (Stripe، PayPal)، راجع تكوين البائع.
نظرة عامة على العملية:
الخطوات:
- تنفيذ فئة المعالج مع
PaymentVendorInterfaceالقياسية (تفويض، التقاط، شحن، استرداد، إفراج) - تسجيل المعالج في VendorFactory مع اسم البائع
- اختبار التكامل مع بيئة اختبار البائع
- نشر - تدعم جميع واجهات برمجة التطبيقات الحالية البائع الجديد تلقائيًا
النتيجة: بمجرد النشر، يعمل البائع الجديد بسلاسة:
# إضافة طريقة دفع Square
curl -X POST /api/payments/methods \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"customer_id": 123,
"vendor": "square",
"payment_token": "sq_xxxxx"
}'
تدعم جميع واجهات برمجة التطبيقات الخاصة بالدفع البائع الجديد تلقائيًا دون الحاجة لتغييرات في كود التطبيق.
وقت التكامل: عادةً ما يستغرق من 1 إلى 2 يومًا لمعالج بائع جدي��.
تكوين البائع
تكوين Stripe
تعتبر Stripe هي البائع الرئيسي للدفع، حيث توفر معالجة بطاقات مع دعم 3D Secure.
1. الحصول على مفاتيح واجهة برمجة تطبيقات Stripe
- قم بالتسجيل في https://stripe.com
- انتقل إلى المطورين → مفاتيح واجهة برمجة التطبيقات
- انسخ المفتاح القابل للنشر الخاص بك (pk_live_... أو pk_test_...)
- انسخ المفتاح السري الخاص بك (sk_live_... أو sk_test_...)
مهم:
- استخدم مفاتيح الاختبار (pk_test_/sk_test_) للتطوير
- استخدم المفاتيح الحية (pk_live_/sk_live_) للإنتاج فقط
- لا تقم أبدًا بإيداع مفاتيح واجهة برمجة التطبيقات في التحكم في الإصدارات
2. تكوين الخلفية
أضف إلى crm_config.yaml:
payment_vendors:
stripe:
api_key: "sk_live_YOUR_SECRET_KEY_HERE"
publishable_key: "pk_live_YOUR_PUBLISHABLE_KEY_HERE"
أو عبر متغيرات البيئة:
export STRIPE_SECRET_KEY="sk_live_YOUR_SECRET_KEY_HERE"
export STRIPE_PUBLISHABLE_KEY="pk_live_YOUR_PUBLISHABLE_KEY_HERE"
3. تكوين الواجهة الأمامية
أضف إلى .env:
REACT_APP_STRIPE_PUBLISHABLE_KEY=pk_live_YOUR_PUBLISHABLE_KEY_HERE
ملاحظة أمنية: يجب أن يذهب المفتاح القابل للنشر فقط في الواجهة الأمامية. يجب ألا يتم الكشف عن المفتاح السري للمتصفح.
تكوين PayPal
يوفر PayPal تخزين بطاقات ومدفوعات حساب PayPal.
التكوين
أضف إلى crm_config.yaml:
payment_vendors:
paypal:
client_id: "AXx_YOUR_CLIENT_ID_HERE"
client_secret: "ELx_YOUR_CLIENT_SECRET_HERE"
mode: "live" # أو "sandbox" للاختبار
الامتثال لمعايير PCI
كيف يحافظ OmniCRM على الامتثال لمعايير PCI:
- يتم إدخال بيانات البطاقة مباشرة في iframes مستضافة من قبل البائع (Stripe Elements، PayPal Card Fields)
- OmniCRM لا ترى أو تخزن أرقام البطاقة الكاملة
- يتم تخزين طرق الدفع المرمزة فقط في قاعدة البيانات
- تم تقليل نطاق الامتثال لمعايير PCI لعملك
مقاييس معالجة الدفع
يوفر OmniCRM مقاييس شاملة لمراقبة عمل��ات معالجة الدفع. للحصول على تفاصيل كاملة حول مقاييس الدفع الخاصة بـ Stripe بما في ذلك تتبع استدعاءات واجهة برمجة التطبيقات، وأحجام الدفع، ومعدلات الفشل، وأوقات الاستجابة، راجع المراقبة والمقاييس.
مخطط قاعدة البيانات غير مرتبط بالبائع
يدعم مخطط قاعدة البيانات أي بائع دفع دون الحاجة لترحيل:
مثال - حفظ بطاقة Square:
{
"vendor": "square",
"vendor_payment_method_id": "sq_card_abc123",
"payment_type": "card"
}
لا تغييرات في الكود. لا ترحيل. يعمل ببساطة.
المفاهيم الأساسية
نماذج البيانات
PaymentMethod
تخزين غير مرتبط بالبائع لطرق دفع العملاء.
{
"payment_method_id": 789,
"customer_id": 123,
"vendor": "stripe", // 'stripe', 'paypal', or any added vendor
"vendor_payment_method_id": "pm_xxx", // Vendor's internal ID
"payment_type": "card", // 'card', 'paypal', 'ach', etc.
"is_default": true,
"card_brand": "visa",
"card_last4": "4242",
"card_exp_month": 12,
"card_exp_year": 2025,
"card_nickname": "My Visa Card",
"status": "active"
}
PaymentAuthorization
سجلات تفويض الالتزام ذو المرحلتين (تجميد الأموال).
{
"authorization_id": 301,
"customer_id": 123,
"payment_method_id": 789,
"vendor": "stripe", // Which vendor authorized
"vendor_authorization_id": "auth_xxx", // Vendor's authorization ID
"amount": 200.00,
"currency": "USD",
"status": "authorized", // 'authorized', 'captured', 'released'
"authorized_at": "2025-12-27T10:00:00Z",
"expires_at": "2026-01-03T10:00:00Z",
"meta": {}
}
PaymentCapture
المدفوعات الملتقطة/المكتملة.
{
"capture_id": 103,
"authorization_id": 301,
"customer_id": 123,
"payment_method_id": 789,
"vendor": "stripe",
"vendor_transaction_id": "ch_xxx", // Vendor's transaction ID
"amount": 200.00,
"currency": "USD",
"status": "succeeded", // 'succeeded', 'failed', 'refunded'
"captured_at": "2025-12-27T10:30:00Z",
"vendor_response": {}, // Full vendor response
"meta": {}
}
WalletAccount
محفظة العميل مع تتبع الرصيد (1 إلى 1 مع العميل).
{
"wallet_account_id": 456,
"customer_id": 123,
"balance": 150.50,
"currency": "USD",
"auto_recharge_enabled": true,
"auto_recharge_amount": 100.00,
"auto_recharge_threshold": 10.00,
"low_balance_warning_threshold": 10.00
}
WalletLedger
سجل تدقيق كامل لجميع معاملات المحفظة.
{
"ledger_id": 501,
"customer_id": 123,
"wallet_account_id": 456,
"transaction_type": "credit", // 'credit', 'debit', 'refund', 'adjustment'
"amount": 100.00,
"balance_before": 150.50,
"balance_after": 250.50,
"currency": "USD",
"description": "Card top-up",
"reference_type": "payment_capture", // Links to related object
"reference_id": 103,
"meta": {},
"created_at": "2025-12-27T10:35:00Z"
}
المستندات المالية
لإنشاء قوالب الفواتير والتخصيص، راجع فواتير العملاء.
الفواتير
التعريف: الفاتورة هي مستند يحتوي على قائمة من معاملات الخصم (الرسوم). عند استدعاء واجهة برمجة التطبيقات لإنشاء فاتورة، يجب تقديم مصفوفة من معرفات معاملات الخصم. يتم "ربط" تلك المعاملات بالفاتورة عن طريق تعيين حقل invoice_id الخاص بها.
للحصول على تفاصيل إدارة المعاملات، راجع المعاملات.
الحقول الرئيسية:
{
"invoice_id": 12345,
"invoice_number": "INV-2025-000001", // تم إنشاؤه تلقائيًا: INV-YYYY-NNNNNN
"customer_id": 123,
"title": "فاتورة خدمات شهرية",
"paid": true, // حالة الدفع
"void": false, // حالة الإلغاء
"payment_reference": "ch_xxxxx", // آخر/معرف الدفع الرئيسي
"payment_type": "stripe_capture", // آخر نوع دفع
"payment_time": "2025-12-27T10:30:00",
"start_date": "2025-12-01",
"end_date": "2025-12-31",
"due_date": "2026-01-15",
"retail_cost": 500.00, // إجمالي مبلغ الفاتورة
"wholesale_cost": 250.00
}
إنشاء الفاتورة: يتم إنشاء أرقام الفواتير تلقائيًا بتنسيق INV-YYYY-NNNNNN، بالتتابع ضمن السنة التقويمية، وإعادة تعيينها في 1 يناير من كل عام.
المدفوعات على الفواتير
كيف تعمل المدفوعات: بمجرد إنشاء فاتورة من معاملات الخصم، يمكن تطبيق الدفع عن طريق إنشاء معاملة ائتمانية (تكلفة التجزئة السلبية) مرتبطة بالفاتورة.
يجب أن:
- يتم إدراجها في الفاتورة مع وضع علامة واضحة كـ "مدفوعات"
- تظهر تاريخ الدفع ذي الصلة (والذي يمكن أن يختلف عن تاريخ إنشاء الفاتورة)
- تدعم عدة مدفوعات لكل فاتورة
- يتم صافيها ضد الخصومات لحساب رصيد الفاتورة
حالة الفاتورة:
- مدفوعة: تساوي المدفوعات الإجمالية (الائتمانات) أو تتجاوز الخصومات الإجمالية
- مدفوعة جزئيًا: تم تطبيق بعض المدفوعات ولكن لا يزال هناك رصيد
- مدفوعة زائدة: لا يتم التعامل معها حاليًا - تتطلب تقسيم الائتمان (ميزة مستقبلية)
المحاسبة ذات القيد المزدوج: ينفذ النظام محاسبة صحيحة حيث كل رسوم لها دفعة معاكسة:
// 1. معاملة خصم (رسوم)
{
"transaction_id": 7001,
"invoice_id": 12345,
"retail_cost": 100.00, // إيجابي = العميل مدين
"title": "رسوم الخدمة"
}
// 2. معاملة ائتمانية (دفع)
{
"transaction_id": 7002,
"invoice_id": 12345,
"retail_cost": -100.00, // سلبية = تم استلام الدفع
"title": "دفع للفاتورة: رسوم الخدمة (12345)",
"payment_type": "stripe_capture",
"payment_reference": "ch_xxxxx"
}
// النتيجة الصافية: $0 رصيد → تم وض�� علامة على الفاتورة كمدفوعة
بيانات الفاتورة التكميلية: بالإضافة إلى المعاملات الائتمانية، تخزن الفاتورة أيضًا حقول ملخص (payment_reference، payment_type، payment_time) لعمليات البحث السريعة. ومع ذلك:
- الطريقة الأساسية: المعاملات الائتمانية مرتبطة عبر
invoice_id(مواصفات هايدن) - البيانات الوصفية الثانوية: تخزن حقول الفاتورة ملخصًا لآخر/أهم دفعة
- لعدة مدفوعات: استعلام عن المعاملات الائتمانية للحصول على السجل الكامل
البيانات المالية
التعريف: تُظهر البيانات المالية جميع الخصومات والائتمانات من معاملات العميل خلال فترة محددة. هذا هو النوع الوحيد من المستندات حيث يتم عرض كل من الخصومات والائتمانات كعناصر قائمة معًا، مثل بيان البنك.
ملاحظات الائتمان
الغرض: تطبق فقط على الفواتير التي تم تطبيق المدفوعات عليها بالفعل. يجب أن يتم ذلك كجزء من عملية إلغاء الفاتورة.
العملية:
- يتم إلغاء الفاتورة (مع معاملات الخصم المرتبطة بها)
- يتم ربط أي مدفوعات تم تطبيقها بالفعل بملاحظة الائتمان التي تم إنشاؤها
- يدخل رصيد العميل في الائتمان بمقدار المبلغ المعادل
- يمكن بعد ذلك أن يكون رصيد ملاحظة الائتمان:
- مطبق على فاتورة أخرى كدفع، أو
- مسترد للعميل
منطق الاسترداد: إذا تم اختيار الاسترداد، يتم استدعاؤه بناءً على المعاملات الائتمانية المرتبطة وكيف تم دفعها في الأصل (على سبيل المثال، استرداد Stripe إذا كان نوع المعاملة الائتمانية هو Stripe).
واجهات برمجة تطبيقات طرق الدفع
تستخدم جميع نقاط النهاية عنوان URL الأساسي: /api/payments/
لإدارة طرق الدفع بالتفصيل والتعامل مع البطاقات، راجع طرق الدفع.
إضافة طريقة دفع
احفظ طريقة دفع جديدة لعميل.
نقطة النهاية: POST /api/payments/methods
الطلب:
curl -X POST https://your-domain.com/api/payments/methods \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"customer_id": 123,
"vendor": "stripe",
"payment_token": "pm_xxxxx",
"is_default": false,
"card_nickname": "My Visa Card"
}'
جسم الطلب:
{
"customer_id": 123,
"vendor": "stripe", // 'stripe', 'paypal', or any added vendor
"payment_token": "pm_xxxxx", // One-time token from frontend SDK
"is_default": false, // Set as default payment method?
"card_nickname": "My Visa Card" // Optional friendly name
}
الاستجابة (201 تم الإنشاء):
{
"success": true,
"message": "تمت إضافة طريقة الدفع بنجاح",
"data": {
"payment_method_id": 789,
"customer_id": 123,
"vendor": "stripe",
"payment_type": "card",
"card_brand": "visa",
"card_last4": "4242",
"card_exp_month": 12,
"card_exp_year": 2025,
"card_nickname": "My Visa Card",
"is_default": false,
"status": "active"
}
}
الحصول على طرق الدفع
استرجع جميع ��رق الدفع لعميل.
نقطة النهاية: GET /api/payments/methods?customer_id={id}
الطلب:
curl -X GET "https://your-domain.com/api/payments/methods?customer_id=123" \
-H "Authorization: Bearer YOUR_API_KEY"
الاستجابة (200 OK):
{
"success": true,
"data": [
{
"payment_method_id": 789,
"customer_id": 123,
"vendor": "stripe",
"payment_type": "card",
"card_brand": "visa",
"card_last4": "4242",
"is_default": true
},
{
"payment_method_id": 790,
"customer_id": 123,
"vendor": "paypal",
"payment_type": "paypal",
"paypal_email": "user@example.com",
"is_default": false
}
]
}
الحصول على طريقة الدفع الافتراضية
احصل على طريقة الدفع الافتراضية لعميل.
نقطة النهاية: GET /api/payments/methods/default?customer_id={id}
الطلب:
curl -X GET "https://your-domain.com/api/payments/methods/default?customer_id=123" \
-H "Authorization: Bearer YOUR_API_KEY"
الاستجابة (200 OK):
{
"success": true,
"data": {
"payment_method_id": 789,
"vendor": "stripe",
"payment_type": "card",
"card_brand": "visa",
"card_last4": "4242",
"is_default": true
}
}
تعيين طريقة الدفع الافتراضية
قم بتعيين طريقة دفع كطريقة افتراضية.
نقطة النهاية: PUT /api/payments/methods/set-default
الطلب:
curl -X PUT https://your-domain.com/api/payments/methods/set-default \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"customer_id": 123,
"payment_method_id": 790
}'
الاستجابة (200 OK):
{
"success": true,
"message": "تم تحديث طريقة الدفع الافتراضية",
"data": {
"payment_method_id": 790,
"is_default": true
}
}
حذف طريقة الدفع
احذف طريقة دفع محفوظة.
نقطة النهاية: DELETE /api/payments/methods/{payment_method_id}?customer_id={id}
الطلب:
curl -X DELETE "https://your-domain.com/api/payments/methods/789?customer_id=123" \
-H "Authorization: Bearer YOUR_API_KEY"
الاستجابة (200 OK):
{
"success": true,
"message": "تم حذف طريقة الدفع بنجاح"
}
واجهات برمجة تطبيقات تدفق الدفع
يدعم النظام عدة تدفقات دفع اعتمادًا على حالة الاستخدام الخاصة بك.
1. الدفع المباشر (رسوم بسيطة)
حالة الاستخدام: دفع بسيط بخطوة واحدة دون توفير الخدمة.
نقطة النهاية: POST /api/payments/charge
الطلب:
curl -X POST https://your-domain.com/api/payments/charge \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"customer_id": 123,
"amount": 50.00,
"currency": "USD",
"payment_method_id": 789,
"metadata": {
"order_id": "12345"
}
}'
جسم الطلب:
{
"customer_id": 123,
"amount": 50.00,
"currency": "USD", // الافتراضي: USD
"payment_method_id": 789, // اختياري - يستخدم الافتراضي إذا تم حذفه
"vendor": "stripe", // مطلوب إذا كنت تستخدم payment_token
"payment_token": "pm_xxxxx", // اختياري - رمز لمرة واحدة
"save_method": false, // حفظ طريقة الدفع للاستخدام في المستقبل؟
"metadata": {
"order_id": "12345"
}
}
الاستجابة (200 OK):
{
"success": true,
"message": "تم الدفع بنجاح",
"data": {
"transaction_id": "ch_xxxxx",
"capture_id": 101,
"amount": 50.00,
"currency": "USD",
"status": "succeeded"
}
}
2. دفع الفاتورة (توجيه المحفظة أولاً)
حالة الاستخدام: دفع فاتورة باستخدام رصيد المحفظة أولاً، ثم بطاقة للدفع المتبقي.
نقطة النهاية: POST /api/payments/invoice
التدفق:
- تحقق من رصيد المحفظة
- استخدم أموال المحفظة أولاً
- شحن البطاقة للقصور (إذا كان هناك أي)
- ائتمان المحفظة بمبلغ البطاقة
- خصم المحفظة للمبلغ الكامل للفاتورة
الطلب:
curl -X POST https://your-domain.com/api/payments/invoice \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"customer_id": 123,
"amount": 200.00,
"payment_method_id": 789,
"metadata": {
"invoice_id": 12345,
"description": "دفع الفاتورة"
}
}'
الاستجابة (200 OK):
{
"success": true,
"message": "تم معالجة دفع الفاتورة",
"data": {
"customer_id": 123,
"service_amount": 200.00,
"routing_mode": "hybrid",
"initial_balance": 150.00,
"wallet_portion_used": 150.00, // غطت المحفظة هذا المبلغ
"card_portion_used": 50.00, // تم شحن البطاقة للمبلغ المتبقي
"charged_amount": 50.00,
"wallet_credited": 50.00,
"wallet_debited": 200.00,
"final_balance": 0.00,
"payment_method_used": true
}
}
3. حجز التفويض (تجميد الأموال)
حالة الاستخدام: حجز الأموال للتقاط لاحقًا (على سبيل المثال، حجوزات الفنادق، الإيجارات).
🔧 تنفيذ Playbook: للحصول على أمثلة Playbook Ansible لتدفقات الدفع ذات المرحلتين، راجع نمط الالتزام ذو المرحلتين
الخطوة 1: إنشاء حجز تفويض
نقطة النهاية: POST /api/payments/authorize/hold
تدفق المحفظة أولاً:
- تحقق من رصيد المحفظة
- احسب القصور (المبلغ - wallet_balance)
- تفويض البطاقة للقصور فقط
- يحدث خصم المحفظة في وقت الالتقاط، وليس هنا
الطلب:
curl -X POST https://your-domain.com/api/payments/authorize/hold \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"customer_id": 123,
"amount": 200.00,
"payment_method_id": 789,
"use_wallet": true,
"metadata": {
"reservation_id": "RES-001"
}
}'
جسم الطلب:
{
"customer_id": 123,
"amount": 200.00,
"currency": "USD",
"payment_method_id": 789, // اختياري - يستخدم الافتراضي إذا تم حذفه
"vendor": "stripe", // مطلوب إذا كنت تستخدم payment_token
"payment_token": "pm_xxxxx", // اختياري - رمز لمرة واحدة
"save_method": false,
"use_wallet": true, // تمكين توجيه المحفظة أولاً (الافتراضي: true)
"metadata": {
"reservation_id": "RES-001"
}
}
الاستجابة (200 OK):
{
"success": true,
"message": "تم تفويض الدفع (تم إنشاء الحجز)",
"data": {
"authorization_id": 301,
"vendor_authorization_id": "auth_xxxxx",
"amount": 200.00,
"currency": "USD",
"status": "authorized",
"wallet_balance": 150.00,
"wallet_to_use": 150.00, // ستغطي المحفظة هذا المبلغ
"card_amount": 50.00, // تم تفويض البطاقة لهذا المبلغ
"message": "تم تفويض البطاقة بمبلغ 50 دولار (تعبئة المحفظة). سيتم خصم المحفظة بمبلغ 200 دولار في وقت الالتقاط."
}
}
الخطوة 2: التقاط التفويض
نقطة النهاية: POST /api/payments/capture/{authorization_id}
تدفق الالتقاط أولاً:
- التقاط البطاقة (إذا تم تفويضها) - تعبئة المحفظة
- ائتمان المحفظة بمبلغ البطاقة الملتقطة
- خصم المحفظة للمبلغ الكامل للخدمة
- إنشاء الفواتير/المعاملات (إذا تم الطلب)
الطلب:
curl -X POST https://your-domain.com/api/payments/capture/301 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"amount": 200.00,
"metadata": {
"invoice": true,
"title": "حجز الفندق",
"description": "إقامة لمدة 3 ��يالٍ",
"wholesale_cost": 100.00,
"contract_days": 3,
"send_email": true
}
}'
جسم الطلب:
{
"amount": 200.00, // اختياري - يتم التقاط المبلغ الكامل إذا تم حذفه
"metadata": {
"invoice": true, // إنشاء فاتورة ومعاملات؟
"create_transaction": true, // إنشاء سجل المعاملة؟
"title": "حجز الفندق",
"description": "إقامة لمدة 3 ليالٍ",
"wholesale_cost": 100.00,
"contract_days": 3,
"send_email": true // إرسال بريد إلكتروني للفاتورة؟
}
}
الاستجابة (200 OK):
{
"success": true,
"message": "تم التقاط التفويض",
"data": {
"capture_id": 103,
"transaction_id": "ch_xxxxx",
"authorization_id": 301,
"amount": 200.00,
"currency": "USD",
"status": "succeeded",
"wallet_credit": { // البطاقة قامت بتعبئة المحفظة
"ledger_id": 401,
"amount": 50.00
},
"wallet_debit": { // تم شحن الخدمة من المحفظة
"ledger_id": 402,
"amount": 200.00
},
"transaction": { // تم إنشاؤه إذا كانت الفاتورة=true
"transaction_id": 7001
},
"invoice": { // تم إنشاؤه إذا كانت الفاتورة=true
"invoice_id": 12345,
"invoice_number": "INV-2025-000001"
}
}
}
الخطوة 3: إفراج عن التفويض (إلغاء)
نقطة النهاية: POST /api/payments/release/{authorization_id}
حالة الاستخدام: إلغاء الحجز، فشل التوفير، أو تغيير رأي العميل.
الطلب:
curl -X POST https://your-domain.com/api/payments/release/301 \
-H "Authorization: Bearer YOUR_API_KEY"
الاستجابة (200 OK):
{
"success": true,
"message": "تم الإفراج عن التفويض",
"data": {
"authorization_id": 301,
"vendor_authorization_id": "auth_xxxxx",
"status": "released",
"released_at": "2025-12-27T10:45:00Z"
}
}
ملاحظة: مع تدفق المحفظة أولاً، لا حاجة لاسترداد المحفظة حيث لم يتم خصمها حتى وقت الالتقاط.
4. دفع التعبئة (مرحلتين مع توفير)
حالة الاستخدام: معالجة الدفع لتعبئة الخدمة التي تتطلب توفيرًا (على سبيل المثال، تفعيل نقطة اتصال/دونجل). إذا فشل التوفير، يتم الإفراج عن التفويض.
نقطة النهاية: POST /api/payments/topup
التدفق: تفويض → توفير الخدمة → التقاط
الطلب:
curl -X POST https://your-domain.com/api/payments/topup \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"customer_id": 123,
"amount": 30.00,
"payment_method_id": 789,
"service_uuid": "svc-uuid-123",
"imsi": "123456789012345",
"days": 30,
"metadata": {
"is_rental": false
}
}'
لإيجار/نقطة اتصال مجهولة (طريقة الدفع غير محفوظة):
curl -X POST https://your-domain.com/api/payments/topup \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"customer_id": 1,
"amount": 5.00,
"vendor": "stripe",
"payment_token": "pm_xxxxx",
"service_uuid": "hotspot-uuid",
"imsi": "123456789012345",
"days": 1,
"metadata": {
"is_rental": true,
"billing_email": "user@example.com"
}
}'
الاستجابة (200 OK):
{
"success": true,
"message": "تمت معالجة دفع التعبئة بنجاح",
"data": {
"transaction_id": "ch_xxxxx",
"authorization_id": 302,
"capture_id": 104,
"amount": 30.00,
"status": "succeeded",
"provision_result": {
"success": true,
"topup_result": {...},
"service_uuid": "svc-uuid-123",
"imsi": "123456789012345",
"days": 30
},
"payment_method_saved": false // خطأ للإيجار/نقطة اتصال مجهولة
}
}
5. دفع الإيجار (طرف ثالث)
حالة الاستخدام: شحن بطاقة عميل واحد لدفع خدمة عميل آخر.
نقطة النهاية: POST /api/payments/rental
الطلب:
curl -X POST https://your-domain.com/api/payments/rental \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"beneficiary_customer_id": 456,
"charge_customer_id": 123,
"amount": 75.00,
"payment_method_id": 789,
"service_description": "دفع خدمة الإيجار",
"metadata": {
"rental_agreement_id": "RA-001"
}
}'
لإيجار مجهو�� (بطاقة المستأجر غير محفوظة):
curl -X POST https://your-domain.com/api/payments/rental \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"beneficiary_customer_id": 456,
"amount": 75.00,
"vendor": "stripe",
"payment_token": "pm_xxxxx",
"service_description": "دفع إيجار مجهول",
"metadata": {
"billing_email": "renter@example.com"
}
}'
الاستجابة (200 OK):
{
"success": true,
"message": "تمت معالجة دفع الإيجار",
"data": {
"transaction_id": "ch_xxxxx",
"amount": 75.00,
"payment_method_saved": false // مجهول: لم يتم حفظ الطريقة
}
}
6. استرداد الدفع
نقطة النهاية: POST /api/payments/refund
الطلب:
curl -X POST https://your-domain.com/api/payments/refund \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"transaction_id": "ch_xxxxx",
"vendor": "stripe",
"amount": 50.00,
"reason": "customer_request"
}'
جسم الطلب:
{
"transaction_id": "ch_xxxxx", // معرف معاملة البائع
"vendor": "stripe", // 'stripe', 'paypal', إلخ.
"amount": 50.00, // اختياري - استرداد كامل إذا تم حذفه
"reason": "customer_request" // سبب الاسترداد الاختياري
}
الاستجابة (200 OK):
{
"success": true,
"message": "تمت معالجة الاسترداد",
"data": {
"refund_id": "re_xxxxx",
"amount": 50.00,
"status": "succeeded"
}
}
واجهات برمجة تطبيقات المحفظة
تستخدم جميع نقاط النهاية الخاصة بالمحفظة عنوان URL الأساسي: /api/wallet/
الحصول على رصيد المحفظة
نقطة النهاية: GET /api/wallet/balance?customer_id={id}
الطلب:
curl -X GET "https://your-domain.com/api/wallet/balance?customer_id=123" \
-H "Authorization: Bearer YOUR_API_KEY"
الاستجابة (200 OK):
{
"customer_id": 123,
"balance": 150.50,
"currency": "USD"
}
الحصول على معلومات المحفظة
احصل على معلومات كاملة عن المحفظة والائتمان بما في ذلك إعدادات إعادة الشحن التلقائي.
نقطة النهاية: GET /api/wallet/info?customer_id={id}
الطلب:
curl -X GET "https://your-domain.com/api/wallet/info?customer_id=123" \
-H "Authorization: Bearer YOUR_API_KEY"
الاستجابة (200 OK):
{
"customer_id": 123,
"wallet": {
"wallet_account_id": 456,
"balance": 150.50,
"currency": "USD",
"auto_recharge_enabled": true,
"auto_recharge_amount": 100.00,
"auto_recharge_threshold": 10.00,
"low_balance_warning_threshold": 10.00
}
}
تعبئة المحفظة
قم بتعبئة المحفظة عن طريق شحن طريقة دفع.
نقطة النهاية: POST /api/wallet/topup
التدفق: شحن بطاقة/PayPal → ائتمان المحفظة
الطلب:
curl -X POST https://your-domain.com/api/wallet/topup \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"customer_id": 123,
"amount": 100.00,
"payment_method_id": 789
}'
جسم الطلب:
{
"customer_id": 123,
"amount": 100.00,
"currency": "USD", // الافتراضي: USD
"payment_method_id": 789 // اختياري - يستخدم الافتراضي إذا تم حذفه
}
الاستجابة (200 OK):
{
"success": true,
"payment": {
"transaction_id": "ch_xxxxx",
"amount": 100.00
},
"wallet": {
"ledger_id": 503,
"balance_after": 250.50
},
"message": "تم تعبئة المحفظة بمبلغ 100.00 دولار"
}
الحصول على معاملات المحفظة
احصل على تاريخ معاملات المحفظة (دفتر الأستاذ).
نقطة النهاية: GET /api/wallet/transactions?customer_id={id}&limit={n}&offset={n}&type={type}
الطلب:
curl -X GET "https://your-domain.com/api/wallet/transactions?customer_id=123&limit=50&offset=0&type=credit" \
-H "Authorization: Bearer YOUR_API_KEY"
معلمات الاستعلام:
customer_id(مطلوب): معرف العميلlimit(اختياري): عدد السجلات (الافتراضي: 50)offset(اختياري): إزاحة الصفحات (الافتراضي: 0)type(اختياري): تصفية حسب نوع المعاملة ('credit'، 'debit'، 'refund'، 'adjustment')
الاستجابة (200 OK):
{
"customer_id": 123,
"count": 2,
"transactions": [
{
"ledger_id": 501,
"transaction_type": "credit",
"amount": 100.00,
"balance_before": 150.50,
"balance_after": 250.50,
"currency": "USD",
"description": "تعبئة البطاقة",
"reference_type": "payment_capture",
"reference_id": 103,
"created_at": "2025-12-27T10:35:00Z"
},
{
"ledger_id": 502,
"transaction_type": "debit",
"amount": 50.00,
"balance_before": 250.50,
"balance_after": 200.50,
"currency": "USD",
"description": "رسوم الخدمة",
"reference_type": "service_charge",
"reference_id": 789,
"created_at": "2025-12-27T11:00:00Z"
}
]
}
ملخص مرجع واجهة برمجة التطبيقات
نقاط نهاية طريقة الدفع
| الطريقة | نقطة النهاية | الوصف |
|---|---|---|
| POST | /api/payments/methods | إضافة طريقة دفع |
| GET | /api/payments/methods?customer_id={id} | الحصول على جميع طرق الدفع |
| GET | /api/payments/methods/default?customer_id={id} | الحصول على طريقة الدفع الافتراضية |
| PUT | /api/payments/methods/set-default | تعيين طريقة الدفع الافتراضية |
| DELETE | /api/payments/methods/{id}?customer_id={id} | حذف طريقة الدفع |
نقاط نهاية تدفق الدفع
| الطريقة | نقطة النهاية | الوصف |
|---|---|---|
| POST | /api/payments/charge | دفع مباشر (خطوة واحدة) |
| POST | /api/payments/invoice | دفع فاتورة (المحفظة أولاً) |
| POST | /api/payments/topup | تعبئة مع توفير |
| POST | /api/payments/authorize/hold | إنشاء حجز تفويض |
| POST | /api/payments/capture/{id} | التقاط التفويض |
| POST | /api/payments/release/{id} | الإفراج عن التفويض |
| POST | /api/payments/rental | دفع إيجار/طرف ثالث |
| POST | /api/payments/refund | استرداد الدفع |
نقاط نهاية المحفظة
| الطريقة | نقطة النهاية | الوصف |
|---|---|---|
| GET | /api/wallet/balance?customer_id={id} | الحصول على رصيد المحفظة |
| GET | /api/wallet/info?customer_id={id} | الحصول على معلومات المحفظة + الإعدادات |
| POST | /api/wallet/topup | تعبئة المحفظة عبر طريقة الدفع |
| GET | /api/wallet/transactions?customer_id={id} | الحصول على تاريخ المعاملات |
نقاط نهاية محددة لـ PayPal
| الطريقة | نقطة النهاية | الوصف |
|---|---|---|
| POST | /api/payments/paypal/vault/setup-token | إنشاء رمز إعداد PayPal لمجموعة Card Fields SDK |
| POST | /api/payments/paypal/vault/finalize | إنهاء خزينة PayPal وحفظ طريقة الدفع |
| POST | /api/payments/paypal/vault/update-setup-token | تحديث رمز الإعداد لمعالجة 3DS/SCA |
حالات الاستخدام الشائعة
حالة الاستخدام 1: شحن العميل مقابل الخدمة (مدفوعة مسبقًا)
السيناريو: عميل يدفع مقابل 30 يومًا من الخدمة باستخدام توجيه المحفظة أولاً.
# دفع الفاتورة (المحفظة أولاً، البطاقة للقصور)
curl -X POST https://your-domain.com/api/payments/invoice \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"customer_id": 123,
"amount": 99.99,
"metadata": {
"service_id": 456,
"contract_days": 30,
"description": "خدمة متميزة لمدة 30 يومًا"
}
}'
الاستجابة:
{
"success": true,
"message": "تمت معالجة دفع الفاتورة",
"data": {
"service_amount": 99.99,
"wallet_portion_used": 50.00, // كانت المحفظة تحتوي على 50 دولار
"card_portion_used": 49.99, // تم شحن البطاقة بمبلغ 49.99 دولار
"final_balance": 0.00
}
}
حالة الاستخدام 2: دفع ذو مرحلتين مع توفير الخدمة
السيناريو: توفير خدمة فقط بعد تفويض الدفع. إذا فشل التوفير، لا يحدث أي شحن.
# دفع التعبئة مع توفير تلقائي
curl -X POST https://your-domain.com/api/payments/topup \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"customer_id": 123,
"amount": 149.99,
"payment_method_id": 789,
"service_uuid": "fiber-svc-uuid",
"imsi": "123456789012345",
"days": 30,
"metadata": {
"service_type": "fiber_internet"
}
}'
التدفق:
- تفويض 149.99 دولار على البطاقة
- توفير خدمة الإنترنت الألياف
- إذا نجح التوفير → التقاط الدفع
- إذا فشل التوفير → الإفراج عن التفويض (لا شحن)
حالة الاستخدام 3: دفع مجهول لنقطة اتصال
السيناريو: مستخدم مجهول يدفع للوصول إلى نقطة اتصال WiFi. لا سجل عميل، لا طريقة دفع محفوظة.
# دفع نقطة اتصال مجهولة
curl -X POST https://your-domain.com/api/payments/topup \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"customer_id": 1,
"amount": 5.00,
"vendor": "stripe",
"payment_token": "pm_xxxxx",
"service_uuid": "hotspot-downtown",
"imsi": "999999999999999",
"days": 1,
"metadata": {
"is_rental": true,
"billing_email": "user@example.com",
"hotspot_location": "مقهى وسط المدينة"
}
}'
النتيجة:
- تمت معالجة الدفع ✅
- تم تفعيل نقطة الاتصال ✅
- لم يتم حفظ طريقة الدفع ✅
- لم يتم إنشاء سجل عميل ✅
حالة الاستخدام 4: حجز الفندق (حجز التفويض + التقاط)
السيناريو: حجز الأموال لتفويض حجز الفندق، التقاط عند تسجيل الوصول، الإفراج إذا تم الإلغاء.
# الخطوة 1: تسجي�� الوصول - حجز الأموال
curl -X POST https://your-domain.com/api/payments/authorize/hold \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"customer_id": 123,
"amount": 500.00,
"use_wallet": true,
"metadata": {
"reservation_id": "RES-2025-001"
}
}'
# الاستجابة: {"authorization_id": 301, "status": "authorized"}
# الخطوة 2a: تسجيل الوصول - التقاط
curl -X POST https://your-domain.com/api/payments/capture/301 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"metadata": {
"invoice": true,
"title": "إقامة الفندق - 3 ليالٍ",
"description": "غرفة 302، 27-30 ديسمبر",
"send_email": true
}
}'
# الخطوة 2b: إلغاء العميل - الإفراج عن الحجز
curl -X POST https://your-domain.com/api/payments/release/301 \
-H "Authorization: Bearer YOUR_API_KEY"
حالة الاستخدام 5: إضافة طريقة دفع (Stripe)
السيناريو: عميل يضيف بطاقة Visa جديدة إلى حسابه.
# الخطوة 1: الواجهة الأمامية تنشئ رمز Stripe عبر Stripe.js
# const {token} = await stripe.createToken(cardElement);
# الخطوة 2: الواجهة الخلفية تحفظ طريقة الدفع
curl -X POST https://your-domain.com/api/payments/methods \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"customer_id": 123,
"vendor": "stripe",
"payment_token": "pm_xxxxx",
"is_default": true,
"card_nickname": "بطاقة Visa للعمل"
}'
حالة الاستخدام 6: تعبئة المحفظة
السيناريو: عميل يقوم بتعبئة محفظته بمبلغ 100 دولار باستخدام طريقة الدفع المحفوظة.
curl -X POST https://your-domain.com/api/wallet/topup \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"customer_id": 123,
"amount": 100.00
}'
الاستجابة:
{
"success": true,
"payment": {
"transaction_id": "ch_xxxxx",
"amount": 100.00
},
"wallet": {
"balance_after": 250.50
},
"message": "تمت تعبئة المحفظة بمبلغ 100.00 دولار"
}
معالجة الأخطاء
استجابات الأخطاء الشائعة
الأموال غير الكافية (400 طلب غ��ر صحيح):
{
"error": "رصيد المحفظة غير كاف. المتاح: 50.00، المطلوب: 200.00"
}
فشل الدفع (400 طلب غير صحيح):
{
"error": "فشل الدفع. يرجى المحاولة مرة أخرى."
}
خطأ في التحقق (400 طلب غير صحيح):
{
"error": "customer_id و amount مطلوبان"
}
غير موجود (404 غير موجود):
{
"error": "التفويض 999 غير موجود"
}
خطأ في الخادم (500 خطأ داخلي في الخادم):
{
"error": "حدث خطأ أثناء معالجة الدفع الخاص بك"
}
الاستردادات وتوجيه المحفظة أولاً
خيارات الاسترداد
يدعم النظام نوعين من الاستردادات اعتمادًا على احتياجات عملك:
1. استرداد إلى مصدر الدفع (Stripe/PayPal)
حالة الاستخدام: يطلب العميل استرداد كامل للخدمة الملغاة أو المنتج المعيب.
التدفق: تعود الأموال إلى طريقة الدفع الأصلية (البطاقة، حساب PayPal، إلخ.)
نقطة النهاية: POST /api/payments/refund
المثال:
curl -X POST https://your-domain.com/api/payments/refund \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"transaction_id": "ch_xxxxx",
"vendor": "stripe",
"amount": 100.00,
"reason": "customer_request"
}'
النتيجة:
- تعالج Stripe/PayPal الاسترداد إلى طريقة الدفع الأصلية
- يرى العميل الائتمان على بطاقته/حساب PayPal خلال 5-10 أيام عمل
- لا تذهب الأموال إلى المحفظة
- يتم الحفاظ على سجل تدقيق كامل في جدول
PaymentCapture
متى تستخدم:
- ✅ ألغى العميل الطلب
- ✅ الخدمة لم تُسلم
- ✅ خطأ في الفوترة
- ✅ يطلب العميل صراحة الاسترداد إلى البطاقة
2. ائتمان إلى المحفظة
حالة الاستخدام: استرداد جزئي، ائتمان الخدمة، أو الاحتفاظ بالأموال للشراء في المستقبل.
ملاحظة: يتم التعامل مع الائتمانات في المحفظة عادةً داخليًا بواسطة النظام خلال سيناريوهات الخطأ. للحصول على ائتمانات المحفظة الي��وية، اتصل بالدعم أو استخدم أدوات الإدارة.
النتيجة:
- الأموال متاحة على الفور في المحفظة
- لا فترة انتظار
- يمكن استخدامها للشراء في المستقبل
- يتم الحفاظ على سجل تدقيق كامل في جدول
WalletLedger
متى تستخدم:
- ✅ ائتمانات الخدمة (على سبيل المثال، تعويض عن التوقف)
- ✅ استردادات جزئية حيث سيعيد العميل الشراء
- ✅ تعويض عن الخطأ (فشل التوفير)
- ✅ ائتمانات ترويجية
استراتيجية استرداد هجينة
أفضل ممارسة: في سيناريوهات الخطأ خلال تدفق الدفع، يقوم النظام تلقائيًا بائتمان المحفظة بدلاً من استرداد البطاقة.
استرداد الخطأ التلقائي:
سيناريو المثال:
- يدفع العميل 100 دولار مقابل الخدمة
- يتم شحن البطاقة بنجاح
- يفشل التوفير
- بدلاً من استرداد 100 دولار إلى البطاقة (5-10 أيام + رسوم الاسترداد):
- ائتمان 100 دولار إلى المحفظة على الفور
- يمكن للعميل المحاولة مرة أخرى على الفور
- لا رسوم استرداد
- تجربة مستخدم أفضل
توجيه المحفظة أولاً: شحنات بطاقات محسّنة
يقوم النظام بشحن بطاقتك فقط للقصور، وليس المبلغ الكامل، عندما يكون لديك رصيد في المحفظة.
مثال 1: رصيد محفظة 1 دولار + شراء 10 دولارات
السيناريو: لديك 1 دولار في محفظتك وتريد شراء إضافة بقيمة 10 دولارات.
تدفق الدفع التقليدي (ليس كيف يعمل هذا النظام):
تدفق OmniCRM المحفظة أولاً:
طلب واجهة برمجة التطبيقات:
curl -X POST https://your-domain.com/api/payments/invoice \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"customer_id": 123,
"amount": 10.00,
"metadata": {
"addon_id": 456
}
}'
استجابة واجهة برمجة التطبيقات:
{
"success": true,
"message": "تمت معالجة دفع الفاتورة",
"data": {
"customer_id": 123,
"service_amount": 10.00,
"routing_mode": "hybrid",
"initial_balance": 1.00,
"wallet_portion_used": 1.00, // استخدم 1 دولار الموجود
"card_portion_used": 9.00, // تم شحن 9 دولارات فقط للقصور
"charged_amount": 9.00, // ← شحن البطاقة
"wallet_credited": 9.00, // ← تعبئة المحفظة
"wallet_debited": 10.00, // ← رسوم الخدمة
"final_balance": 0.00
}
}
مثال 2: رصيد محفظة 50 دولار + شراء 30 دولار
السيناريو: لديك 50 دولار في المحفظة وتكلفة الشراء 30 دولار.
تدفق المحفظة أولاً:
استجابة واجهة برمجة التطبيقات:
{
"success": true,
"data": {
"service_amount": 30.00,
"initial_balance": 50.00,
"charged_amount": 0, // ← لم يتم شحن البطاقة
"wallet_debited": 30.00,
"final_balance": 20.00,
"payment_method_used": false // ← لم يتم استخدام البطاقة
}
}
مثال 3: حجز التفويض مع رصيد المحفظة
السيناريو: حجز تفويض بمبلغ 500 دولار مع رصيد محفظة 150 دولار.
الخطوة 1: التفويض (POST /api/payments/authorize/hold):
استجابة واجهة برمجة التطبيقات:
{
"authorization_id": 301,
"amount": 500.00,
"status": "authorized",
"wallet_balance": 150.00,
"wallet_to_use": 150.00, // ستغطي المحفظة هذا المبلغ
"card_amount": 350.00, // تم تفويض البطاقة لهذا المبلغ
"message": "تم تفويض البطاقة بمبلغ 350 دولار (تعبئة المحفظة). سيتم خصم المحفظة بمبلغ 500 دولار في وقت الالتقاط."
}
الخطوة 2: الالتقاط (POST /api/payments/capture/301):
لماذا هذا مهم:
- ✅ يتم حجز 350 دولار فقط على بطاقتك، وليس 500 دولار
- ✅ يقلل من تأثير الائتمان المتاح للعميل
- ✅ مبالغ التفويض أكثر دقة
- ✅ تجربة مستخدم أفضل
تفاصيل التنفيذ
منطق توجيه المحفظة أولاً:
كيف يعمل:
- يتحقق النظام من الرصيد الحالي في المحفظة
- يحسب القصور:
المبلغ - wallet_balance - إذا كان القصور > 0، يشحن البطاقة فقط للقصور
- يئتم المحفظة بمبلغ الدفع من البطاقة
- يخصم المحفظة للمبلغ الكامل للخدمة
- النتيجة: يتم شحن العميل فقط لما لم تتمكن المحفظة من تغطيته
تجاوز وضع التوجيه
يمكنك تجاوز سلوك المحفظة أولاً إذا لزم الأمر:
وضع التجاوز - شحن البطاقة دائمًا حتى لو كان هناك أموال في المحفظة:
curl -X POST https://your-domain.com/api/payments/charge \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"customer_id": 123,
"amount": 100.00,
"metadata": {
"routing_mode": "bypass"
}
}'
النتيجة: تم شحن البطاقة بمبلغ 100 دولار، وتم ائتمان المحفظة بمبلغ 100 دولار، وتم خصم المحفظة بمبلغ 100 دولار (صافي: 0 دولار)
حالة الاستخدام: يريد العميل استخدام البطاقة للحصول على مكافآت/نقاط حتى مع وجود رصيد في المحفظة.
أفضل الممارسات
- استخدم دائمًا توجيه المحفظة أولاً لمدفوعات العملاء لتمكين الو��ائف المدفوعة مسبقًا
- استخدم المدفوعات ذات المرحلتين (نقطة نهاية التعبئة) عند توفير الخدمات لتجنب الشحن إذا فشل التوفير
- قم بتعيين البيانات الوصفية لجميع المدفوعات للحفاظ على سجل التدقيق
- استخدم المدفوعات المجهولة فقط للمستخدمين المجهولين حقًا (نقاط الاتصال، الإيجارات)
- تعامل مع الأخطاء بشكل جيد وقدم ملاحظات واضحة للمستخدم
- اختبر تدفقات الدفع في كل من سيناريوهات النجاح والفشل
- راقب انتهاء صلاحية التفويضات (عادةً 7 أيام للبطاقات)
- نفذ إعادة الشحن التلقائي للخدمات المتكررة لتحسين تجربة العميل
أفضل الممارسات الخاصة بـ Playbook
عند تنفيذ تدفقات الدفع في Playbooks Ansible:
- استخدم دائمًا نمط الكتلة/الإنقاذ - لف لف توفير في try/catch لاستعادة تلقائية
- قم بتخزين authorization_id - احفظه لعمليات الالتقاط/الإفراج
- تحقق من استجابات واجهة برمجة التطبيقات - تأكد من النجاح قبل المتابعة
- قم بتدوير قيم العملة - استخدم دائمًا مكانين عشريين
- تحقق من طرق الدفع - تحقق من أن العميل لديه طريقة دفع افتراضية قبل التفويض
راجع أفضل الممارسات في Playbook للحصول على تفاصيل كاملة وأمثلة.
المصادقة
تتطلب جميع نقاط نهاية واجهة برمجة التطبيقات المصادقة عبر مفتاح واجهة برمجة التطبيقات في رأس Authorization:
Authorization: Bearer YOUR_API_KEY
اتصل بالمسؤول عن النظام الخاص بك للحصول على توفير مفتاح واجهة برمجة التطبيقات.
دعم البائعين
المدعومون حاليًا
- Stripe - دعم كامل (بطاقات، ACH)
- PayPal - دعم كامل (حسابات PayPal، بطاقات عبر مجموعة Card Fields SDK)
إضافة بائعين جدد
تجعل الهيكلية المودولارية من السهل إضافة بائعين جدد. راجع قسم الهيكلية المودولارية للحصول على التفاصيل.
الوثائق ذات الصلة
أدلة التنفيذ
- التحصيل والمدفوعات من Playbooks - تنفيذ Playbook Ansible
أدلة خاصة بالميزات
- فواتير العملاء - إنشاء الفواتير، القوالب، والتخصيص
- طرق الدفع - إدارة طرق دفع العملاء، البطاقات، وحسابات PayPal
- المعاملات - إدارة المعاملات، الرسوم اليدوية، والائتمانات
- معالجة الدفع - تدفقات الدفع والمعالجة
- أساسيات الفوترة - أساسيات فوترة العملاء
التنقل السريع
- هل تضيف بائعين؟ → راجع الهيكلية المودولارية
- تكوين Stripe/PayPal؟ → راجع تكوين البائ��
- تخصيص الفواتير؟ → راجع فواتير العملاء
- توفير الخدمات؟ → راجع تكامل Playbook