كلاود
أدلة

ربط SADAD مع نظامك: دليل تقني شامل

كلاود|١ مارس ٢٠٢٦|5 دقائق قراءة|٧٧٥ مشاهدة
ربط SADAD مع نظامك: دليل تقني شامل

SADAD = نظام المدفوعات السعودي. الربط يتطلب سيرفر سعودي + اتفاقية + شهادات أمان. نشرح الخطوات الكاملة.

نظام سداد — الخلفية والأهمية

سداد هو نظام دفع الفواتير الإلكتروني في المملكة العربية السعودية، تشغله شركة سداد للخدمات الإلكترونية بالشراكة مع البنك المركزي السعودي (SAMA). يُمكّن العملاء من دفع فواتير الشركات عبر جميع قنوات الدفع السعودية: البنوك الإلكترونية، ATM، تطبيقات الدفع، وMadaPay.

لماذا سداد مهم لشركتك؟

  • 30+ بنك سعودي مربوط بالنظام
  • 90%+ من السعوديين يستخدمون الخدمات المصرفية الرقمية
  • عميلك يدفع دون الحاجة لبطاقة ائتمان أو حساب أبشر
  • الدفع فوري وتأكيده فوري لنظامك

كيف يعمل سداد؟

تدفق الدفع عبر سداد:
┌──────────────────────────────────────────────┐
│ 1. شركتك تُنشئ فاتورة في نظام سداد │
│ وتحصل على رقم الفاتورة (Biller Code) │
│ ↓ │
│ 2. العميل يذهب لتطبيق بنكه │
│ → دفع الفواتير → سداد → اسم شركتك │
│ → يُدخل رقم الفاتورة │
│ ↓ │
│ 3. سداد يسحب تفاصيل الفاتورة من API شركتك │
│ (Bill Inquiry Request) │
│ ↓ │
│ 4. العميل يؤكد الدفع │
│ ↓ │
│ 5. سداد يُرسل إشعار الدفع لنظامك │
│ (Bill Payment Advice) │
│ ↓ │
│ 6. نظامك يؤكد الاستلام ويُفعّل الخدمة │
└──────────────────────────────────────────────┘

متطلبات التسجيل

للتسجيل كـ Biller في سداد:
- سجل تجاري ساري في السعودية
- IBAN سعودي للتحويلات
- سيرفر سعودي (IP موثق)
- API endpoint متاح 24/7
- SSL/TLS صالح
- اتفاقية مع مزود خدمة سداد (SADAD Service Provider)
 أو مباشرة مع شركة سداد للشركات الكبيرة

التكامل التقني مع Laravel

الإعداد

// config/sadad.php
return [
 'biller_code' => env('SADAD_BILLER_CODE'),
 'merchant_id' => env('SADAD_MERCHANT_ID'),
 'secret_key' => env('SADAD_SECRET_KEY'),
 'base_url' => env('SADAD_BASE_URL', 'https://sadad.com.sa/api/v1'),
 'inquiry_url' => env('SADAD_INQUIRY_CALLBACK', '/api/sadad/inquiry'),
 'payment_url' => env('SADAD_PAYMENT_CALLBACK', '/api/sadad/payment'),
];

Bill Inquiry Endpoint

// هذا الـ endpoint يُستدعى من سداد عندما يريد عميل دفع فاتورة
// app/Http/Controllers/SadadController.php

class SadadController extends Controller
{
 /**
 * Bill Inquiry — سداد يسأل عن تفاصيل فاتورة
 */
 public function inquiry(Request $request): JsonResponse
 {
 // التحقق من صحة الطلب من سداد
 if (!$this->validateRequest($request)) {
 return response->json(['status' => '31', 'message' => 'Invalid signature'], 401);
 }

 $billNumber = $request->input('billNumber');
 $invoice = Invoice::where('sadad_bill_number', $billNumber)
 ->with('user')
 ->first;

 if (!$invoice) {
 // رمز 17 = الفاتورة غير موجودة
 return response->json([
 'status' => '17',
 'billNumber' => $billNumber,
 'message' => 'Bill not found',
 ]);
 }

 if ($invoice->isPaid) {
 // رمز 16 = مدفوعة مسبقاً
 return response->json([
 'status' => '16',
 'billNumber' => $billNumber,
 'message' => 'Bill already paid',
 ]);
 }

 // رمز 0 = ناجح، عرض تفاصيل الفاتورة
 return response->json([
 'status' => '0',
 'billNumber' => $billNumber,
 'amount' => $invoice->total / 100, // هللة → ريال
 'currency' => 'SAR',
 'billDate' => $invoice->created_at->format('Y-m-d'),
 'dueDate' => $invoice->due_at->format('Y-m-d'),
 'billInfo' => [
 'customerName' => $invoice->user->name,
 'serviceType' => $invoice->service_type,
 'billerCode' => config('sadad.biller_code'),
 ],
 ]);
 }

 /**
 * Payment Advice — سداد يُخبرنا بأن العميل دفع
 */
 public function paymentAdvice(Request $request): JsonResponse
 {
 if (!$this->validateRequest($request)) {
 return response->json(['status' => '31'], 401);
 }

 $billNumber = $request->input('billNumber');
 $transactionId = $request->input('transactionId');
 $amount = $request->input('amount');
 $paymentDate = $request->input('paymentDate');

 $invoice = Invoice::where('sadad_bill_number', $billNumber)->firstOrFail;

 // التحقق من المبلغ
 if (abs(($invoice->total / 100) - (float) $amount) > 0.01) {
 Log::warning('SADAD amount mismatch', [
 'expected' => $invoice->total / 100,
 'received' => $amount,
 'bill' => $billNumber,
 ]);
 return response->json(['status' => '19', 'message' => 'Amount mismatch']);
 }

 // تسجيل الدفع
 DB::transaction(function use ($invoice, $transactionId, $amount, $paymentDate) {
 $invoice->markAsPaid;

 Payment::create([
 'invoice_id' => $invoice->id,
 'gateway' => 'sadad',
 'transaction_id' => $transactionId,
 'amount' => $amount * 100, // ريال → هللة
 'currency' => 'SAR',
 'status' => 'completed',
 'paid_at' => Carbon::parse($paymentDate),
 ]);
 });

 // تفعيل الخدمة
 ProvisioningService::handlePaymentCompleted($invoice);

 // رمز 0 = تم الاستلام بنجاح
 return response->json([
 'status' => '0',
 'billNumber' => $billNumber,
 'transactionId' => $transactionId,
 'message' => 'Payment acknowledged',
 ]);
 }

 private function validateRequest(Request $request): bool
 {
 $signature = $request->header('X-SADAD-Signature');
 $body = $request->getContent;
 $expected = hash_hmac('sha256', $body, config('sadad.secret_key'));

 return hash_equals($expected, $signature ?? '');
 }
}

توليد رقم الفاتورة

// عند إنشاء فاتورة جديدة، أضف رقم سداد
class Invoice extends Model
{
 protected static function booted: void
 {
 static::creating(function (Invoice $invoice) {
 $invoice->sadad_bill_number = self::generateBillNumber;
 });
 }

 private static function generateBillNumber: string
 {
 // يجب أن يكون فريداً وقصيراً (8-12 رقم)
 do {
 $number = config('sadad.biller_code') . rand(100000, 999999);
 } while (self::where('sadad_bill_number', $number)->exists);

 return $number;
 }
}

Routes

// routes/api.php
Route::prefix('sadad')->group(function {
 Route::post('/inquiry', [SadadController::class, 'inquiry'])
 ->middleware('throttle:100,1');
 Route::post('/payment', [SadadController::class, 'paymentAdvice'])
 ->middleware('throttle:100,1');
});

اختبار التكامل

# محاكاة طلب Inquiry من سداد
SIGNATURE=$(echo -n '{"billNumber":"12345678"}' | openssl dgst -sha256 -hmac "your_secret" -binary | base64)

curl -X POST https://yoursite.com/api/sadad/inquiry \
 -H "Content-Type: application/json" \
 -H "X-SADAD-Signature: $SIGNATURE" \
 -d '{"billNumber":"12345678"}'

الإشعارات عند الدفع

// إشعار العميل فور استلام الدفع من سداد
class SadadPaymentReceived extends Notification
{
 use Queueable;

 public function via(object $notifiable): array
 {
 return ['mail', 'database'];
 }

 public function toMail(object $notifiable): MailMessage
 {
 return (new MailMessage)
 ->subject('تم استلام دفعتك — كلاود')
 ->line("تم استلام دفعة بمبلغ {$this->amount} ريال عبر سداد")
 ->line("رقم الفاتورة: {$this->invoice->id}")
 ->action('عرض الفاتورة', route('portal.invoices.show', $this->invoice->id));
 }
}

على سيرفرات كلاود

سيرفرات كلاود (cloud.net.sa) في الرياض وجدة مثالية لاستضافة API التكامل مع سداد:

  • IP سعودي ثابت (متطلب أساسي لسداد)
  • Uptime 99.99% — سداد يتوقع availability شبه كاملة
  • Latency < 8ms للبنوك السعودية
  • SSL مجاني + نسخ احتياطي يومي

خلاصة

سداد يفتح أمامك قناة دفع يثق بها 30+ مليون سعودي. التكامل تقنياً مباشر: endpoint للاستعلام وآخر لإشعار الدفع. المتطلب الرئيسي هو السيرفر السعودي والـ IP الثابت. استوفِ هذين الشرطين ويصبح التكامل مجرد كود بسيط.


ابدأ الآن

جاهز تبني مشروعك؟ اختر خادمك السحابي بالمواصفات اللي يحتاجها تطبيقك، أو راجع الباقات والأسعار.

مشاركة