$contactIds * @return array{counts: array, total: int} */ public static function getSurveyCounts(array $contactIds): array { $ids = array_values(array_unique(array_filter(array_map(static function ($id) { return trim((string) $id); }, $contactIds)))); if (count($ids) === 0) { return ['counts' => [], 'total' => 0]; } $base = rtrim((string) env('TGICS_API_BASE', ''), '/'); if ($base === '') { Log::warning('TGICS_API_BASE is not configured; survey counts defaulting to 0'); return ['counts' => array_fill_keys($ids, 0), 'total' => 0]; } try { $response = Http::timeout(8)->acceptJson()->get($base.'/api/surveys/counts', [ 'contact_ids' => implode(',', $ids), ]); if (!$response->successful()) { Log::warning('TGICS survey counts request failed', [ 'status' => $response->status(), 'body' => $response->body(), ]); return ['counts' => array_fill_keys($ids, 0), 'total' => 0]; } $json = $response->json(); $countsRaw = $json['data']['counts'] ?? []; $counts = []; $total = 0; foreach ($ids as $id) { $n = (int) ($countsRaw[$id] ?? 0); $counts[$id] = $n; $total += $n; } return ['counts' => $counts, 'total' => $total]; } catch (\Throwable $e) { Log::error('TGICS survey counts error: '.$e->getMessage()); return ['counts' => array_fill_keys($ids, 0), 'total' => 0]; } } /** * Resolve a Rapport contact access token for a domain (e.g. lifemankind). */ public static function resolveContactAccessToken(string $domain): string { $domain = trim($domain); if ($domain === '') { return ''; } $tokenRows = DB::table('users') ->select('access_token') ->where('domain', $domain) ->where('permissions', 'like', '%contact_create%') ->orderBy('updated_at', 'desc') ->skip(0) ->take(1) ->get(); if ($tokenRows->isEmpty() || empty($tokenRows[0]->access_token)) { return ''; } return (string) $tokenRows[0]->access_token; } public static function isWhatsappValidatedFlag($value): bool { if ($value === true || $value === 1 || $value === '1') { return true; } return strtolower(trim((string) $value)) === 'yes'; } /** * Read validation flag from a contact object (supports attribute_ prefix). */ public static function contactHasWhatsappValidated($item): bool { if (!$item) { return false; } $direct = $item->tgics_whatsapp_validated ?? null; if (self::isWhatsappValidatedFlag($direct)) { return true; } $prefixed = $item->attribute_tgics_whatsapp_validated ?? null; return self::isWhatsappValidatedFlag($prefixed); } /** * Map contact_id => whether WhatsApp is validated for TGICS. * Prefers TGICS API (same RAPPORT token that wrote the flag); falls back to contact/get_one. * * @param array $contactIds * @return array */ public static function getWhatsappValidationStatus(array $contactIds, string $domain = 'lifemankind'): array { $ids = array_values(array_unique(array_filter(array_map(static function ($id) { return trim((string) $id); }, $contactIds)))); if (count($ids) === 0) { return []; } $status = array_fill_keys($ids, false); $base = rtrim((string) env('TGICS_API_BASE', ''), '/'); if ($base !== '') { try { $response = Http::timeout(10)->acceptJson()->get($base.'/api/whatsapp/status', [ 'contact_ids' => implode(',', $ids), ]); if ($response->successful()) { $json = $response->json(); $validatedRaw = $json['data']['validated'] ?? []; foreach ($ids as $id) { $status[$id] = !empty($validatedRaw[$id]); } Log::info('[TGICS_WA_STATUS] via TGICS API', [ 'ids' => $ids, 'status' => $status, 'http' => $response->status(), ]); return $status; } Log::warning('TGICS WhatsApp status request failed', [ 'status' => $response->status(), 'body' => $response->body(), ]); } catch (\Throwable $e) { Log::warning('[TGICS_WA_STATUS] TGICS API error: '.$e->getMessage()); } } else { Log::warning('TGICS_API_BASE is not configured; falling back to Rapport contact/get_one'); } // Fallback: Rapport via a lifemankind user token from local users table $accessToken = self::resolveContactAccessToken($domain); if ($accessToken === '') { Log::warning('TGICS WhatsApp validation: no contact access token for domain '.$domain); return $status; } foreach ($ids as $id) { try { $resp = LambdaRequest::getrequest('contact', 'contact/get_one', ['id' => $id], $accessToken); $item = $resp->data->item ?? null; $validated = self::contactHasWhatsappValidated($item); $status[$id] = $validated; Log::info('[TGICS_WA_STATUS] contact lookup fallback', [ 'contact_id' => $id, 'validated' => $validated, 'flag' => $item->tgics_whatsapp_validated ?? ($item->attribute_tgics_whatsapp_validated ?? null), 'api_status' => $resp->status ?? null, ]); } catch (\Throwable $e) { Log::warning('[TGICS_WA_STATUS] lookup failed for '.$id.': '.$e->getMessage()); } } return $status; } /** * Single-contact validation check for poll endpoint. */ public static function isContactWhatsappValidated(string $contactId, string $domain = 'lifemankind'): bool { $contactId = trim($contactId); if ($contactId === '') { return false; } $map = self::getWhatsappValidationStatus([$contactId], $domain); return !empty($map[$contactId]); } }