normalizePhone(config('app.admin_phone_number')); } return $this->normalizePhone($phone); } /** * Send an approved WhatsApp Cloud API template message. * * @param string $to E.164-ish digits without + * @param string $templateName * @param array $bodyParams Ordered body variables {{1}}, {{2}}, ... * @return array{ok:bool,status:int,body:mixed} */ public function sendTemplate($to, $templateName, array $bodyParams = [], $languageCode = null) { if (! $this->isEnabled()) { Log::warning('WhatsApp Cloud API skipped: not enabled or missing credentials.'); return ['ok' => false, 'status' => 0, 'body' => 'disabled']; } $to = $this->normalizePhone($to); if (! $to) { return ['ok' => false, 'status' => 0, 'body' => 'invalid_phone']; } $languageCode = $languageCode ?: config('whatsapp.template_lang', 'en_US'); $version = config('whatsapp.api_version', 'v25.0'); $phoneNumberId = config('whatsapp.phone_number_id'); $url = "https://graph.facebook.com/{$version}/{$phoneNumberId}/messages"; $template = [ 'name' => $templateName, 'language' => ['code' => $languageCode], ]; if (! empty($bodyParams)) { $template['components'] = [[ 'type' => 'body', 'parameters' => array_map(function ($value) { return [ 'type' => 'text', 'text' => (string) $value, ]; }, array_values($bodyParams)), ]]; } $payload = [ 'messaging_product' => 'whatsapp', 'to' => $to, 'type' => 'template', 'template' => $template, ]; $response = Http::withToken(config('whatsapp.token')) ->acceptJson() ->asJson() ->post($url, $payload); $result = [ 'ok' => $response->successful(), 'status' => $response->status(), 'body' => $response->json() ?? $response->body(), ]; if (! $result['ok']) { Log::error('WhatsApp Cloud API template send failed', [ 'to' => $to, 'template' => $templateName, 'status' => $result['status'], 'body' => $result['body'], ]); } else { Log::info('WhatsApp Cloud API template sent', [ 'to' => $to, 'template' => $templateName, 'message_id' => data_get($result['body'], 'messages.0.id'), ]); } return $result; } }