whatsAppBusinessService = $whatsAppBusinessService; } /** * Get WhatsApp link for admin showroom * * @param int $categoryId - The category/car ID (optional) * @return \Illuminate\Http\JsonResponse */ public function getAdminWhatsAppLink($categoryId = null) { try { // Get admin phone number from centralized service configuration. $phoneNumber = config('services.whatsapp.admin_recipient'); $adminName = config('services.whatsapp.admin_name', 'Showroom'); if (!$phoneNumber) { return response()->json([ 'success' => false, 'message' => 'Nomor WhatsApp admin tidak dikonfigurasi', ], 422); } $carName = null; $carImageUrl = null; $carDetailUrl = null; $category = null; if ($categoryId) { $category = Category::find($categoryId); if ($category) { $carName = $category->name; $carImageUrl = $this->getCarImageUrl($category); $carDetailUrl = $this->getCarDetailUrl($category); } } // Format phone number $formattedPhone = $this->formatPhoneNumber($phoneNumber); // Create WhatsApp message $message = $this->buildWhatsAppMessage($category, $carImageUrl, $carDetailUrl); $encodedMessage = urlencode($message); // WhatsApp Web link format $whatsappLink = "https://wa.me/{$formattedPhone}?text={$encodedMessage}"; return response()->json([ 'success' => true, 'message' => 'Link WhatsApp berhasil dibuat', 'data' => [ 'admin_name' => $adminName, 'phone_number' => $phoneNumber, 'whatsapp_link' => $whatsappLink, 'car_name' => $carName, 'car_image_url' => $carImageUrl, 'car_detail_url' => $carDetailUrl, ] ], 200); } catch (\Exception $e) { return response()->json([ 'success' => false, 'message' => 'Terjadi kesalahan: ' . $e->getMessage(), ], 500); } } /** * Direct redirect to WhatsApp admin. * * @param int $categoryId - The category/car ID (optional) * @return \Illuminate\Http\RedirectResponse */ public function redirectAdminWhatsApp($categoryId = null) { try { $phoneNumber = config('services.whatsapp.admin_recipient'); if (!$phoneNumber) { return redirect()->back()->with('error', 'Nomor WhatsApp admin tidak dikonfigurasi'); } // Format phone number $formattedPhone = $this->formatPhoneNumber($phoneNumber); $carImageUrl = null; $carDetailUrl = null; $category = null; if ($categoryId) { $category = Category::find($categoryId); if ($category) { $carImageUrl = $this->getCarImageUrl($category); $carDetailUrl = $this->getCarDetailUrl($category); $this->sendBusinessImageNotification($category, auth()->user()); } } // Create message $message = $this->buildWhatsAppMessage($category, $carImageUrl, $carDetailUrl); $encodedMessage = urlencode($message); // Redirect to WhatsApp, but keep catalog/detail URLs based on this local app host. $whatsappLink = "https://wa.me/{$formattedPhone}?text={$encodedMessage}"; return redirect($whatsappLink); } catch (\Exception $e) { return redirect()->back()->with('error', 'Terjadi kesalahan saat membuka WhatsApp'); } } /** * Send a WhatsApp Business notification with the car image to admin. * * @param \Illuminate\Http\Request $request * @param int $categoryId * @return \Illuminate\Http\JsonResponse */ public function notifyAdminWithCarImage(Request $request, $categoryId) { try { $category = Category::find($categoryId); if (!$category) { return response()->json([ 'success' => false, 'message' => 'Mobil tidak ditemukan.', ], 404); } $result = $this->whatsAppBusinessService->sendCarNotificationToAdmin( $category, $request->user() ); return response()->json($result, $result['success'] ? 200 : 422); } catch (\Exception $e) { return response()->json([ 'success' => false, 'message' => 'Terjadi kesalahan saat mengirim notifikasi ke admin.', 'error' => $e->getMessage(), ], 500); } } /** * Format phone number to WhatsApp format * Converts various formats to 62xxxxxxxxxx * * @param string $phoneNumber * @return string */ private function formatPhoneNumber($phoneNumber) { // Remove all non-numeric characters $phoneNumber = preg_replace('/[^0-9]/', '', $phoneNumber); // Handle Indonesian phone numbers // 081234567890 -> 6281234567890 if (strlen($phoneNumber) == 10 && substr($phoneNumber, 0, 1) == '8') { $phoneNumber = '62' . $phoneNumber; } // 08xxxxxxxxxx -> 62xxxxxxxxxx elseif (strlen($phoneNumber) >= 11 && substr($phoneNumber, 0, 2) == '08') { $phoneNumber = '62' . substr($phoneNumber, 1); } // If doesn't start with 62, prepend it elseif (substr($phoneNumber, 0, 2) != '62') { $phoneNumber = '62' . $phoneNumber; } return $phoneNumber; } /** * Build WhatsApp message with optional car image link. * * @param \App\Models\Category|null $category * @param string|null $carImageUrl * @param string|null $carDetailUrl * @return string */ private function buildWhatsAppMessage(?Category $category = null, $carImageUrl = null, $carDetailUrl = null) { if (!$category) { return "Halo admin, saya tertarik dengan salah satu mobil bekas yang ada di website. Apakah masih tersedia?"; } $lines = [ 'Halo admin, saya tertarik dengan mobil katalog ini.', '', 'Nama mobil: ' . $category->name, 'Harga: Rp ' . number_format((float) $category->price, 0, ',', '.'), 'Tahun: ' . ($category->year ?: '-'), ]; if ($carImageUrl) { $lines[] = 'Foto katalog: ' . $carImageUrl; } if ($carDetailUrl) { $lines[] = 'Link detail: ' . $carDetailUrl; } $lines[] = ''; $lines[] = 'Apakah mobil ini masih tersedia?'; return implode("\n", $lines); } /** * Get absolute public URL for the car image if available. * * @param \App\Models\Category $category * @return string|null */ private function getCarImageUrl(Category $category) { if (!$category->image) { return null; } return $this->publicUrl(Storage::disk('public')->url($category->image), $this->getClickableBaseUrl()); } /** * Get absolute detail page URL for the car. * * @param \App\Models\Category $category * @return string */ private function getCarDetailUrl(Category $category) { return $this->publicUrl('/mobil-bekas/' . $category->id, $this->getClickableBaseUrl()); } /** * Build an absolute URL from the current local app host. * * @param string $path * @return string */ private function publicUrl($path, $baseUrl = null) { if (filter_var($path, FILTER_VALIDATE_URL)) { return $path; } $baseUrl = $baseUrl ?: url('/'); return rtrim($baseUrl, '/') . '/' . ltrim($path, '/'); } /** * Prefer a public local tunnel URL for WhatsApp, because WhatsApp often * does not turn 127.0.0.1/localhost links into clickable links. * * @return string */ private function getClickableBaseUrl() { $requestUrl = rtrim(request()->getSchemeAndHttpHost(), '/'); if ($requestUrl) { return $requestUrl; } $configuredUrl = rtrim((string) config('app.url'), '/'); if ($configuredUrl && ! preg_match('/^https?:\/\/(127\.0\.0\.1|localhost)(:\d+)?$/i', $configuredUrl)) { return $configuredUrl; } return url('/'); } /** * Send selected catalog image through WhatsApp Business Cloud API. * The direct WhatsApp redirect still works if the API send fails. */ private function sendBusinessImageNotification(Category $category, $customer = null) { try { if ($this->whatsAppBusinessService->isConfigured()) { $this->whatsAppBusinessService->sendCarNotificationToAdmin($category, $customer); } } catch (\Throwable $e) { report($e); } } }