integrationsModel = new IntegrationsModel(); } public function __invoke(ServerRequestInterface $request) { if (!$this->isAuthorized($request)) { return Payload::fail('Unauthorized', [], 'E_VALIDATE', 401); } $body = json_decode((string) $request->getBody(), true) ?: []; $status = (string) ($body['status'] ?? ''); $accountId = (string) ($body['account_id'] ?? ''); $name = (string) ($body['name'] ?? ''); if ($status === '' || $accountId === '' || $name === '') { return Payload::fail('Invalid callback payload', [], 'E_VALIDATE', 400); } $identity = $this->decodeName($name); if ($identity === null) { return Payload::fail('Invalid callback identity', [], 'E_VALIDATE', 400); } try { $integration = $this->integrationsModel->upsertWhatsappIntegration( (int) $identity['company_id'], (int) $identity['user_id'], (int) $identity['operator_id'], $accountId, $status, $body ); return Payload::ok(['integration' => $this->integrationsModel->formatIntegration($integration)]); } catch (\Throwable $e) { Logger::error('Failed to process Unipile hosted auth callback', ['error' => $e->getMessage()]); return Payload::fail('Failed to process callback', [], 'E_GENERIC', 500); } } private function isAuthorized(ServerRequestInterface $request): bool { $expected = (string) ($_ENV['UNIPILE_NOTIFY_SECRET'] ?? ''); if ($expected === '') { return false; } $provided = (string) ($request->getQueryParams()['secret'] ?? ''); if ($provided === '') { $provided = $request->getHeaderLine('Unipile-Notify-Secret'); } return hash_equals($expected, $provided); } private function decodeName(string $name): ?array { $parts = explode('.', $name, 2); if (count($parts) !== 2) { return null; } [$encoded, $signature] = $parts; $secret = (string) ($_ENV['JWT_SECRET'] ?? ''); $expected = hash_hmac('sha256', $encoded, $secret); if (!hash_equals($expected, $signature)) { return null; } $padded = str_pad(strtr($encoded, '-_', '+/'), strlen($encoded) % 4 === 0 ? strlen($encoded) : strlen($encoded) + 4 - strlen($encoded) % 4, '=', STR_PAD_RIGHT); $json = base64_decode($padded, true); if ($json === false) { return null; } $payload = json_decode($json, true); if (!is_array($payload)) { return null; } foreach (['company_id', 'user_id', 'operator_id'] as $key) { if (!isset($payload[$key]) || (int) $payload[$key] < 0) { return null; } } return $payload; } }