20 دقائق قراءة

الدليل الشامل لدمج مدفوعات CIB وEdahabia عبر SATIM في الجزائر

دليل تقني خطوة بخطوة يغطي إعداد SATIM API، وتدفقات الدفع ببطاقات CIB الائتمانية وEdahabia المدينة، ومعالجة الأخطاء، والنشر في الإنتاج للتجارة الإلكترونية الجزائرية.

تكامل SATIM
دفع CIB الجزائر
دفع Edahabia
التجارة الإلكترونية الجزائرية
بوابة الدفع
satim-ts
Node.js مدفوعات

مشهد المدفوعات الجزائري

إذا كنت تبني منصة تجارة إلكترونية أو أي تطبيق يقبل مدفوعات عبر الإنترنت في الجزائر، ستواجه حتمًا SATIM. شركة أتمتة المعاملات البنكية والنقدية (SATIM) هي المحول الوطني للدفع الإلكتروني الذي يعالج عمليًا جميع المعاملات المبنية على البطاقات في الجزائر. يقع بين التجار والبنوك وشبكات البطاقات، ويعمل كطبقة التوجيه والتسوية المركزية.

نوعان من البطاقات يهيمنان على السوق الجزائري:

  • CIB (البطاقة بين البنوك): البطاقة الائتمانية/المدينة القياسية بين البنوك التي تصدرها البنوك الجزائرية. بطاقات CIB تحمل شعار شبكة CIB ومقبولة في أجهزة نقاط البيع والتجار عبر الإنترنت في جميع أنحاء البلاد.
  • Edahabia: بطاقة الخصم المباشر لبريد الجزائر، مرتبطة بحسابات CCP (الحساب الجاري البريدي). مع أكثر من 20 مليون حساب CCP في الجزائر، تمثل Edahabia أكبر قاعدة دفع محتملة في البلاد.

كلا نوعي البطاقات يُعالجان عبر بوابة الدفع SATIM (يُشار إليها أحيانًا بـ SATIM e-payment أو SATIM IPAY). من الناحية التقنية، تدفق التكامل متطابق تقريبًا لكليهما. تتعامل البوابة مع اكتشاف نوع البطاقة تلقائيًا بناءً على رقم البطاقة الذي يدخله العميل.

المتطلبات المسبقة

قبل كتابة أي كود، تحتاج ما يلي:

  1. حساب تاجر لدى بنك يدعم SATIM e-payment (معظم البنوك الجزائرية الكبرى تدعمه: BNA، CPA، BEA، BADR، Gulf Bank Algeria، من بين آخرين).
  2. معرف الجهاز (بصيغة: E010XXXXXX)، يُقدم عبر بوابة SATIM لتعريف جهاز التاجر الخاص بك.
  3. اسم المستخدم وكلمة المرور لواجهة SATIM API، يُقدمان عبر بوابة SATIM بعد الموافقة على حساب التاجر.
  4. بيانات اعتماد الاختبار لبيئة sandbox على test2.satim.dz، تُقدم أيضًا عبر بوابة SATIM.

عملية التسجيل تتم بالكامل عبر بوابة SATIM على cibweb.dz. اتبع التعليمات هناك لتقديم مستنداتك واستلام بيانات الاعتماد. الجداول الزمنية تختلف، لذا ابدأ مبكرًا. إذا كنت بحاجة لمساعدة في عملية الاعتماد، نقدم استشارات اعتماد SATIM.

كيف يعمل تدفق الدفع

يستخدم SATIM تدفق دفع قائم على إعادة التوجيه، مشابه مفاهيميًا لـ 3D Secure أو Stripe Checkout. خادمك لا يتعامل أبدًا مع بيانات البطاقة الخام. إليك التسلسل الكامل:

  1. تسجيل الطلب: يستدعي الخادم الخلفي نقطة النهاية register.do من SATIM مع مبلغ الطلب ورقم طلب فريد وعناوين URL للاستدعاء الراجع. يرد SATIM بـ orderId وformUrl.
  2. إعادة توجيه العميل: تعيد توجيه متصفح العميل إلى formUrl. يستضيف SATIM صفحة الدفع حيث يدخل العميل تفاصيل بطاقته CIB أو Edahabia.
  3. معالجة الدفع: يعالج SATIM المعاملة مع البنك المصدر. قد يرى العميل شاشة تحقق OTP/كلمة مرور (مشابهة لـ 3DS).
  4. إعادة التوجيه الراجع: بعد الدفع (نجاح أو فشل)، يعيد SATIM توجيه العميل إلى returnUrl أو failUrl مع orderId كمعامل استعلام.
  5. تأكيد من جانب الخادم: يستدعي الخادم الخلفي نقطة النهاية acknowledgeTransaction.do للتحقق من حالة المعاملة. هذه هي الخطوة الحرجة؛ لا تثق أبدًا بإعادة التوجيه من جانب العميل وحدها.
Customer         Your Server         SATIM Gateway         Bank
   |                  |                    |                  |
   |  Place Order     |                    |                  |
   |----------------->|                    |                  |
   |                  |  register.do       |                  |
   |                  |------------------->|                  |
   |                  |  orderId + formUrl |                  |
   |                  |<-------------------|                  |
   |  Redirect to     |                    |                  |
   |  formUrl         |                    |                  |
   |<-----------------|                    |                  |
   |  Enter card info |                    |                  |
   |---------------------------------------->|                |
   |                  |                    |  Process payment |
   |                  |                    |----------------->|
   |                  |                    |  Auth response   |
   |                  |                    |<-----------------|
   |  Redirect to     |                    |                  |
   |  returnUrl       |                    |                  |
   |<-----------------------------------------|              |
   |  Page loads      |                    |                  |
   |----------------->|                    |                  |
   |                  | acknowledgeTransaction.do             |
   |                  |------------------->|                  |
   |                  | Payment status     |                  |
   |                  |<-------------------|                  |
   |  Order confirmed |                    |                  |
   |<-----------------|                    |                  |

الإعداد باستخدام satim-ts

حزمة @bakissation/satim هي SDK جاهزة للإنتاج بـ TypeScript تغلف SATIM API بأنماط صارمة وتحقق من المدخلات وتحويل تلقائي للمبالغ ومعالجة شاملة للأخطاء.

التثبيت

1npm install @bakissation/satim

تدعم SDK كلاً من ESM وCommonJS، وتتطلب Node.js 18 أو أحدث، وليس لها تبعيات خارجية (تستخدم fetch API الأصلية).

الإعداد

أبسط نهج هو متغيرات البيئة. أنشئ ملف .env:

1SATIM_USERNAME=your_merchant_username 2SATIM_PASSWORD=your_merchant_password 3SATIM_TERMINAL_ID=E010XXXXXX 4SATIM_API_URL=https://test2.satim.dz/payment/rest

ثم هيئ العميل:

1import { createSatimClient, fromEnv } from '@bakissation/satim'; 2 3const satim = createSatimClient(fromEnv());

للتحكم الأكثر صراحة، مرر الإعداد مباشرة:

1import { createSatimClient, API_BASE_URLS } from '@bakissation/satim'; 2 3const satim = createSatimClient({ 4 userName: process.env.SATIM_USERNAME!, 5 password: process.env.SATIM_PASSWORD!, 6 terminalId: process.env.SATIM_TERMINAL_ID!, 7 apiBaseUrl: API_BASE_URLS.TEST, // switch to API_BASE_URLS.PRODUCTION for live 8 language: 'fr', 9 currency: '012', // DZD (ISO 4217) 10});

تنفيذ تدفق الدفع

الخطوة 1: تسجيل الطلب

عندما يكون عميلك مستعدًا للدفع، أنشئ طلبًا على الخادم الخلفي:

1import { createSatimClient, fromEnv } from '@bakissation/satim'; 2import { randomUUID } from 'crypto'; 3 4const satim = createSatimClient(fromEnv()); 5 6async function createPayment(orderNumber: string, amountDzd: number) { 7 const response = await satim.register({ 8 orderNumber, // Max 10 chars, must be unique per transaction 9 amount: amountDzd, // In DZD (minimum 50 DZD), auto-converted to minor units 10 returnUrl: 'https://yoursite.com/payment/callback', 11 failUrl: 'https://yoursite.com/payment/failed', 12 description: 'Purchase from YourStore', 13 udf1: orderNumber, // Required: your internal reference 14 idempotencyKey: randomUUID(), // Prevents duplicate orders on retry 15 }); 16 17 if (response.isSuccessful()) { 18 // Save response.orderId to your database, linked to the order 19 return { 20 orderId: response.orderId, 21 redirectUrl: response.formUrl, 22 }; 23 } 24 25 throw new Error('Failed to register order with SATIM'); 26}

نقاط رئيسية حول استدعاء register:

  • معالجة المبالغ: مرر المبالغ بالدينار كأرقام صحيحة أو عشرية (مثل 5000 لـ 5,000 دينار، أو 806.5 لـ 806.50 دينار). SDK تحول تلقائيًا إلى الوحدات الصغرى (سنتيمات) كما يتطلب API.
  • رقم الطلب: بحد أقصى 10 أحرف. يجب أن يكون فريدًا لكل معاملة. إذا أعدت استخدام رقم طلب، سيرجع SATIM رمز خطأ 1.
  • udf1: مطلوب من SATIM. استخدمه لمرجعك الداخلي (رقم فاتورة، معرف طلب، إلخ).
  • العدم التكرار: مرر دائمًا idempotencyKey في الإنتاج لمنع الرسوم المكررة إذا أُعيد طلبك بسبب مشاكل الشبكة.

الخطوة 2: إعادة توجيه العميل

على الواجهة الأمامية، أعد توجيه العميل إلى formUrl المرجع من استدعاء التسجيل:

1// In your API response handler (frontend) 2window.location.href = redirectUrl;

أو إذا كنت تبني خادمًا خلفيًا API-first، أرجع عنوان URL إلى واجهتك الأمامية/تطبيق الموبايل ودعه يتعامل مع إعادة التوجيه. صفحة الدفع SATIM تدعم الفرنسية والإنجليزية والعربية، قابلة للإعداد عبر معامل language.

الخطوة 3: معالجة الاستدعاء الراجع

بعد أن يكمل العميل (أو يتخلى عن) الدفع، يعيد SATIM توجيهه إلى returnUrl أو failUrl مع معامل استعلام orderId. على نقطة نهاية الاستدعاء الراجع، تحقق من الدفع من جانب الخادم:

1import { OrderStatus, interpretOrderStatus } from '@bakissation/satim'; 2 3async function handlePaymentCallback(orderId: string) { 4 const status = await satim.confirm(orderId); 5 6 if (status.isPaid()) { 7 // Payment successful, orderStatus === 2 (DEPOSITED) 8 console.log('Payment confirmed for order:', status.orderNumber); 9 console.log('Amount:', status.amount); 10 console.log('Card (masked):', status.pan); // e.g., 6280****7215 11 12 // Update your order status in the database 13 // Deliver the product/service 14 return { success: true, orderNumber: status.orderNumber }; 15 } 16 17 // Payment not successful 18 console.log('Payment status:', interpretOrderStatus(status.orderStatus)); 19 console.log('Details:', status.actionCodeDescription); 20 return { success: false, reason: status.actionCodeDescription }; 21}

طريقة confirm (المعروفة أيضًا بـ getOrderStatus) تستدعي نقطة النهاية acknowledgeTransaction.do من SATIM. هذه هي الطريقة الوحيدة الموثوقة لمعرفة ما إذا نجح الدفع. لا تعتمد أبدًا فقط على عنوان URL لإعادة التوجيه الذي وصل إليه العميل، لأنه يمكن تزويره أو التلاعب به.

الخطوة 4: الاسترجاع (عند الحاجة)

لاسترجاع معاملة مكتملة:

1async function refundPayment(orderId: string, amountDzd: number) { 2 const result = await satim.refund(orderId, amountDzd); 3 4 if (result.isSuccessful()) { 5 console.log('Refund processed successfully'); 6 return true; 7 } 8 9 console.error('Refund failed:', result.errorMessage); 10 return false; 11}

الاسترجاع يجب أن يشير إلى orderId الأصلي المرجع أثناء التسجيل. الاسترجاعات الجزئية مدعومة بتمرير مبلغ أقل من المعاملة الأصلية.

CIB مقابل Edahabia: ما يحتاج المطورون معرفته

من منظور تكامل API، مدفوعات CIB وEdahabia تُعالج بشكل متطابق من بوابة SATIM. لا تحتاج لتحديد نوع البطاقة عند تسجيل طلب. تحدد البوابة نوع البطاقة من رقم البطاقة الذي يدخله العميل في صفحة الدفع.

هناك بعض الاختلافات العملية يجب الانتباه لها:

  • صيغة رقم البطاقة: بطاقات CIB تبدأ عادة بـ 6280 (16 رقمًا). بطاقات Edahabia تتبع نظام ترقيم بريد الجزائر. كلاهما يُعالج عبر نفس نقاط النهاية register.do وacknowledgeTransaction.do.
  • حدود المعاملات: بطاقات Edahabia قد يكون لها حدود معاملات يومية أقل مقارنة ببطاقات CIB، حسب إعداد حامل البطاقة مع بريد الجزائر. يجب أن يتعامل تطبيقك بلطف مع رفض "تجاوز الحد".
  • جداول التسوية: قد تختلف التسوية لحسابك التجاري قليلاً بين معاملات CIB وEdahabia، حسب ترتيب البنك المكتسب. هذا يخص العمليات المصرفية وليس الكود.
  • تحقق OTP: كلا نوعي البطاقات قد يتطلبان إدخال OTP أو كلمة مرور على صفحة الدفع SATIM. حقل password في بطاقات الاختبار يُستخدم لهذا الغرض في بيئة sandbox.

إذا كنت تحتاج تحديدًا للتعامل مع دفع فواتير أو نوع معاملة معين، يمكنك استخدام معامل fundingTypeIndicator (مثل 'CP' أو '698')، لكن لمشتريات التجارة الإلكترونية القياسية هذا غير مطلوب.

معالجة الأخطاء

توفر SDK فئات أخطاء مُنمطة لكل سيناريو فشل. معالجة الأخطاء القوية مهمة بشكل خاص لتكاملات الدفع حيث الفشل الصامت يمكن أن يؤدي لخسارة إيرادات أو رسوم مكررة.

1import { 2 SatimApiError, 3 ValidationError, 4 HttpError, 5 TimeoutError, 6 ConfigError, 7 mapSatimErrorCode, 8} from '@bakissation/satim'; 9 10async function safePayment(orderNumber: string, amount: number) { 11 try { 12 const response = await satim.register({ 13 orderNumber, 14 amount, 15 returnUrl: 'https://yoursite.com/payment/callback', 16 udf1: orderNumber, 17 idempotencyKey: crypto.randomUUID(), 18 }); 19 return response; 20 } catch (error) { 21 if (error instanceof ValidationError) { 22 // Bad input: invalid amount, missing fields, etc. 23 console.error(`Validation error [${error.code}]:`, error.message); 24 } else if (error instanceof SatimApiError) { 25 // SATIM rejected the request 26 console.error(`SATIM error [${error.satimErrorCode}]:`, error.message); 27 } else if (error instanceof TimeoutError) { 28 // Request timed out, safe to retry with same idempotency key 29 console.error(`Timeout after ${error.timeoutMs}ms`); 30 } else if (error instanceof HttpError) { 31 // Network or HTTP-level failure 32 console.error(`HTTP error [${error.httpStatus}]:`, error.message); 33 } else if (error instanceof ConfigError) { 34 // Missing or invalid configuration 35 console.error('Config error, missing keys:', error.missingKeys); 36 } 37 throw error; 38 } 39}

مرجع رموز أخطاء SATIM

هذه هي رموز الأخطاء التي يرجعها SATIM API عبر نقاط النهاية:

الرمزregister.doacknowledgeTransaction.dorefund.do
0نجاحنجاحنجاح
1طلب تمت معالجته مسبقًا--
2-خطأ في بيانات الدفع-
3عملة غير معروفة--
4معامل مطلوب مفقود--
5معامل غير صالحرفض الوصولرفض الوصول / مبلغ غير صالح
6-طلب غير مسجلطلب غير مسجل
7خطأ في النظامخطأ في النظامخطأ في النظام
14طريقة دفع غير صالحة--

رموز حالة الطلب

بعد استدعاء confirm() أو getOrderStatus()، تحقق من حقل orderStatus:

الرمزالمعنىالإجراء
0مسجل ولم يُدفعالعميل تخلى أو لم يكمل الدفع بعد
-1رفض غير معروفتواصل مع دعم SATIM إذا استمر
1موافق عليه (تفويض مسبق محتجز)بانتظار الإيداع
2مُودع (الدفع مكتمل)نفّذ الطلب
3التفويض ملغىالدفع ملغى قبل التسوية
4مسترجعتم استرجاع المعاملة
6مرفوضالبطاقة رُفضت من البنك المصدر

الاختبار مع بيئة SATIM sandbox

يوفر SATIM بيئة sandbox على https://test2.satim.dz/payment/rest لاختبار التكامل. استخدم بطاقات الاختبار التالية:

رقم البطاقةCVV2انتهاء الصلاحيةكلمة المرورالسيناريو
628058111000721537301/2027123456دفع ناجح
628058111000671289701/2027123456بطاقة محظورة مؤقتًا
628058061006111026001/2027123456رصيد غير كافٍ
628058061006121904901/2027123456تجاوز الحد
628058111000651420501/2027123456CVV2 غير صحيح
628058061006101199201/2027123456بطاقة ائتمان صالحة

عند الاختبار:

  1. اضبط SATIM_API_URL على https://test2.satim.dz/payment/rest.
  2. استخدم بيانات اعتماد الاختبار المقدمة من بنكك (وليس بيانات الإنتاج).
  3. اختبر كل سيناريو: دفع ناجح، بطاقة مرفوضة، رصيد غير كافٍ، معالجة المهلة، ومنع تكرار الطلبات.
  4. تحقق أن استدعاء confirm() يفسر كل حالة طلب بشكل صحيح.
  5. اختبر رحلة المستخدم الكاملة، بما في ذلك ما يحدث عندما يغلق العميل المتصفح على صفحة الدفع SATIM دون إكمال المعاملة.

قائمة مراجعة نشر الإنتاج

قبل الانطلاق، راجع هذه القائمة:

الإعداد

  • غيّر SATIM_API_URL إلى https://satim.dz/payment/rest
  • استخدم بيانات اعتماد الإنتاج (اسم المستخدم، كلمة المرور، معرف الجهاز) من بنكك
  • خزّن جميع بيانات الاعتماد في متغيرات البيئة، وليس في الكود المصدري
  • تأكد أن ملفات .env في .gitignore
  • اضبط NODE_ENV=production لتعطيل التسجيل المفصل للتطوير

الأمان

  • استخدم طريقة POST لجميع استدعاءات SATIM API (SDK تفعل ذلك افتراضيًا)
  • تحقق دائمًا من حالة الدفع من جانب الخادم عبر confirm()، ولا تثق أبدًا بإعادة التوجيه من جانب العميل
  • قدّم عناوين URL للاستدعاء الراجع عبر HTTPS فقط
  • نفّذ مفاتيح عدم التكرار في كل استدعاء register() لمنع الرسوم المكررة
  • لا تسجل أو تخزن أرقام البطاقات الكاملة أبدًا (SDK لا تكشفها أبدًا)

الموثوقية

  • تعامل مع جميع أنواع الأخطاء (SatimApiError، TimeoutError، HttpError، ValidationError)
  • نفّذ منطق إعادة المحاولة لسيناريوهات TimeoutError (باستخدام نفس مفتاح عدم التكرار)
  • أعد مراقبة/تنبيهات للمدفوعات الفاشلة
  • سجّل نتائج المعاملات (باستخدام مسجل SDK المدمج أو خاصتك عبر خيار customLogger)
  • خزّن orderId من SATIM في قاعدة بياناتك لكل معاملة، مما يتيح فحوصات الحالة المستقبلية والاسترجاعات

الاختبار

  • شغّل اختبارات من طرف لطرف ضد بيئة sandbox قبل التحويل للإنتاج
  • اختبر مع جميع سيناريوهات بطاقات sandbox (نجاح، رفض، أموال غير كافية، محظورة)
  • تحقق أن تدفق الاسترجاع يعمل بشكل صحيح
  • اختبر ما يحدث عندما يكون SATIM غير قابل للوصول (معالجة المهلة)

الامتثال

  • تحقق مع بنكك أن تكاملك معتمد للاستخدام في الإنتاج
  • تأكد أن شروط الخدمة وسياسة الخصوصية تغطي المدفوعات الإلكترونية
  • احتفظ بسجلات جميع المعاملات كما تتطلب لوائح التجارة الجزائرية

متقدم: التكامل مع Fastify

إذا كنت تستخدم Fastify كإطار ويب، يوفر إضافة @bakissation/fastify-satim تكاملًا مبسطًا يسجل عميل SATIM كمزخرف Fastify:

1npm install @bakissation/fastify-satim
1import Fastify from 'fastify'; 2import satimPlugin from '@bakissation/fastify-satim'; 3 4const app = Fastify(); 5 6app.register(satimPlugin, { 7 userName: process.env.SATIM_USERNAME!, 8 password: process.env.SATIM_PASSWORD!, 9 terminalId: process.env.SATIM_TERMINAL_ID!, 10 apiBaseUrl: 'https://satim.dz/payment/rest', 11}); 12 13app.post('/pay', async (request, reply) => { 14 const { orderNumber, amount } = request.body as any; 15 16 const result = await app.satim.register({ 17 orderNumber, 18 amount, 19 returnUrl: 'https://yoursite.com/payment/callback', 20 udf1: orderNumber, 21 }); 22 23 if (result.isSuccessful()) { 24 return reply.redirect(result.formUrl!); 25 } 26 27 return reply.status(500).send({ error: 'Payment registration failed' }); 28});

هذا يتجنب إنشاء العميل يدويًا ويضمن إدارة دورة حياة عميل SATIM بواسطة Fastify.

هل تحتاج مساعدة في تكاملك؟

دمج المدفوعات عمل عالي المخاطر حيث الأخطاء تترجم مباشرة إلى خسارة إيرادات أو مشاكل امتثال. إذا كنت تحتاج مساعدة خبير في تكامل SATIM CIB/Edahabia، من الإعداد الأولي والتنسيق مع البنك إلى نشر الإنتاج والدعم المستمر، أقدم استشارات مخصصة لأنظمة الدفع الجزائرية.

تواصل لاستشارات تكامل SATIM

© 2026 عبد الباقي بركاتي. جميع الحقوق محفوظة.