detectPostponement($text); if ($postpone !== null) { $context['previous_step'] = $step; $hours = $postpone; return new FlowResult( "حاضر كابتن، تم تأجيل طلب الدفع. سأذكرك بعد {$hours} ساعات.\n" . "للمتابعة لاحقاً، أرسل 'دفع' مرة أخرى.", "postponed" ); } } // ── Country + method detection ── $country = $context['country'] ?? SiroService::detectCountry($phone); $context['country'] = $country; $paymentMethod = $context['payment_method'] ?? match ($country) { 'jordan' => 'cliq', default => 'shamcash', }; $context['payment_method'] = $paymentMethod; $methodName = $paymentMethod === 'cliq' ? 'كليك (Cliq)' : 'شام كاش (ShamCash)'; $currency = $paymentMethod === 'cliq' ? 'دينار أردني' : 'ل.س'; $countryName = match ($country) { 'jordan' => 'الأردن', 'egypt' => 'مصر', default => 'سوريا', }; switch ($step) { // ───────────────────────────────────────────────── // START // ───────────────────────────────────────────────── case 'start': $context['retry_count'] = 0; return new FlowResult( "أهلاً بك في خدمة التحقق من الدفع.\n\n" . "📍 الدولة: {$countryName}\n" . "💰 طريقة الدفع: {$methodName}\n" . "💵 العملة: {$currency}\n\n" . "📸 يرجى إرسال صورة واضحة لإيصال الدفع أو صورة الشاشة.\n" . "سيتم التحقق من الفاتورة المعلقة تلقائياً.\n\n" . "🟡 للخروج اكتب: إلغاء\n" . "⏰ للتأجيل اكتب: بعدين", "await_receipt" ); // ───────────────────────────────────────────────── // AWAIT_RECEIPT // ───────────────────────────────────────────────── case 'await_receipt': // ── No image sent ── if (empty($image)) { return new FlowResult( "📸 يرجى إرسال صورة الإيصال أو وصل التحويل.\n" . "تأكد من أن الصورة واضحة وتظهر المبلغ وتفاصيل التحويل.", "await_receipt" ); } // ── Validate image size ── $decoded = base64_decode($image, true); if ($decoded === false || strlen($decoded) < 1024) { $retry = ($context['retry_count'] ?? 0) + 1; $context['retry_count'] = $retry; if ($retry >= self::MAX_RETRIES) { return new FlowResult( "عذراً، لم نتمكن من قراءة الصورة بعد {$retry} محاولات.\n" . "يرجى التواصل مع خدمة العملاء لإتمام عملية الدفع يدوياً.", "finished", true ); } return new FlowResult( "⚠️ الصورة غير واضحة أو صغيرة جداً.\n" . "يرجى إرسال صورة واضحة وحجم أكبر (محاولة {$retry} من " . self::MAX_RETRIES . "):", "await_receipt" ); } // ── Normalize MIME type ── if (strpos($imageMimeType, ';') !== false) { $imageMimeType = trim(explode(';', $imageMimeType)[0]); } // ── Send to payment server ── $companyId = $context['company_id'] ?? 1; $result = \App\Controllers\WhatsAppController::verifyPaymentSlipStatic( companyId: $companyId, phone: $phone, jsonStr: '', userType: 'driver', paymentMethod: $paymentMethod, invoiceNumber: '', receiptImage: $image, imageMimeType: $imageMimeType, ); if ($result) { return new FlowResult($result, "finished", true); } $retry = ($context['retry_count'] ?? 0) + 1; $context['retry_count'] = $retry; if ($retry >= self::MAX_RETRIES) { return new FlowResult( "عذراً، تعذر التحقق من الدفع بعد {$retry} محاولات.\n" . "سيتم مراجعة العملية من قبل الإدارة.", "finished", true ); } return new FlowResult( "لم نتمكن من التحقق من الدفع حالياً (محاولة {$retry} من " . self::MAX_RETRIES . ").\n" . "يرجى إرسال صورة أوضح والإضاءة جيدة:", "await_receipt" ); case 'postponed': // Resume from postponed $step = $context['previous_step'] ?? 'await_receipt'; return new FlowResult( "مرحباً بك مرة أخرى! 👋\n" . "📸 أرسل صورة إيصال الدفع للمتابعة:", $step ); default: return new FlowResult("حدث خطأ في المسار.", "finished", true); } } /** * Detect if user wants to postpone (keyword-based, no AI call) */ private function detectPostponement(string $text): ?int { $keywords = [ 'بعدين' => 2, 'بكرا' => 12, 'بكرة' => 12, 'بعد' => 3, 'شوي' => 1, 'مشغول' => 4, 'تأجيل' => 6, 'لاحقاً' => 6, 'لاحقا' => 6, 'الحق' => 6, 'وقت ثاني' => 8, 'تعبان' => 6, 'بعدين برسل' => 3, 'بعدين ببعت' => 3, 'بعدين بكمل' => 4, 'ببعثها' => 3, 'ببعت' => 3, 'برسل' => 2, ]; $normalized = trim(mb_strtolower($text)); foreach ($keywords as $kw => $hours) { if (mb_strpos($normalized, $kw) !== false) { return $hours; } } return null; } }