Como incorporar o AnnA Chat com um usuário corporativo V3
Este guia mostra como incorporar o AnnA Chat para um usuário corporativo autenticado usando a API V3. O navegador recebe somente a URL gerada do AnnA Chat. Mantenha o hash da empresa, as credenciais do usuário, o token bearer e todas as chamadas da API V3 no seu backend.
Antes de começar
Seção intitulada “Antes de começar”Você precisa das seguintes informações do seu ambiente AnnA:
- O hash da empresa.
- O login e a senha usados com
REST/Credentials/GetToken. - O ID do usuário corporativo e, opcionalmente, o nome do usuário.
- A URL base do seu ambiente AnnA.
A V3 usa autenticação por token em vez das chaves de criptografia exigidas pela V2. O token tem curta duração e nunca deve ser exposto na página do cliente.
Fluxo de integração
Seção intitulada “Fluxo de integração”- Seu backend chama
REST/Credentials/GetTokencom o hash da empresa e as credenciais do serviço. - Seu backend usa o token retornado no cabeçalho
Authorization: Bearer <Token>. - Seu backend chama
REST/AnnACorporate/User/UserHashouREST/AnnACorporate/User/UserHashForcedcomgetAnnAChatLinkdefinido comotrue. - Seu backend lê
accessData.AnnAChatURLda resposta. - Seu código no cliente usa essa URL gerada como origem do iframe.
Use UserHash quando o usuário corporativo já existir. Use UserHashForced quando a AnnA deve criar ou atualizar o usuário com o userName informado antes de gerar o hash.
A URL gerada pode expirar. Gere-a no servidor para o usuário conectado e não coloque o hash da empresa, login, senha ou token bearer no código do navegador.
Obter uma URL do chat
Seção intitulada “Obter uma URL do chat”Primeiro solicite um token:
Endpoint: REST/Credentials/GetToken
{ "hash": "YOUR_COMPANY_HASH", "user": "YOUR_API_USER", "pass": "YOUR_API_PASSWORD"}Depois chame o endpoint do usuário corporativo com o token:
Endpoint: REST/AnnACorporate/User/UserHash
{ "getAnnAChatLink": true, "hash": "YOUR_COMPANY_HASH", "userId": "USER_ID", "startService": ""}Para um usuário que pode precisar ser criado ou atualizado, use REST/AnnACorporate/User/UserHashForced e adicione a propriedade userName.
Resposta da AnnA
Seção intitulada “Resposta da AnnA”A resposta bem-sucedida contém a URL em accessData.AnnAChatURL:
{ "success": true, "message": "User Hash generated successfully", "accessData": { "Hash": "USER_HASH", "ChatURL": "CHAT_URL_WITH_USER_HASH", "EmbeddedURL": "EMBEDDED_URL_WITH_USER_HASH", "AnnAChatURL": "ANNACHAT_URL_FOR_IFRAME", "Expires": "EXPIRATION_DATETIME" }}Se success for false, trate o valor de message no backend e não envie uma URL inválida ao navegador.
Exemplo completo
Seção intitulada “Exemplo completo”Substitua ANNACHAT_URL_FROM_BACKEND pelo valor de accessData.AnnAChatURL retornado pelo seu backend. O botão cria a janela do chat somente depois que o usuário clica nele.
<!doctype html><html lang="pt-BR"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Demo do AnnA Chat incorporado</title> </head> <body> <h1>Site do cliente corporativo</h1> <p>O widget autenticado do AnnA Chat aparece no canto inferior direito.</p>
<script> (function () { const ANNA_URL = "ANNACHAT_URL_FROM_BACKEND"; // Use o valor AnnAChatURL gerado pelo backend const CHAT_W = 400, CHAT_H = 600, BTN_SIZE = 60; const sideOffset = "clamp(16px, 2.2vw, 30px)"; const bottomOffset = "clamp(16px, 2.2vw, 30px)";
const btn = document.createElement("div"); btn.id = "anna-launcher"; Object.assign(btn.style, { position: "fixed", bottom: bottomOffset, right: sideOffset, width: BTN_SIZE + "px", height: BTN_SIZE + "px", borderRadius: "50%", cursor: "pointer", zIndex: "9999", background: "#7c3aed", display: "flex", alignItems: "center", justifyContent: "center", boxShadow: "0 4px 12px rgba(0,0,0,0.25)", transition: "transform 0.2s", }); btn.innerHTML = '<svg width="28" height="28" fill="#fff" viewBox="0 0 24 24"><path d="M20 2H4a2 2 0 0 0-2 2v18l4-4h14a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2z"/></svg>'; btn.onmouseenter = function () { btn.style.transform = "scale(1.1)"; }; btn.onmouseleave = function () { btn.style.transform = "scale(1)"; };
const chat = document.createElement("div"); chat.id = "anna-chat"; Object.assign(chat.style, { position: "fixed", bottom: `calc(${bottomOffset} + ${BTN_SIZE}px + 10px)`, right: sideOffset, width: `min(${CHAT_W}px, calc(100vw - 32px))`, height: CHAT_H + "px", maxHeight: `min(${CHAT_H}px, calc(100vh - 116px))`, borderRadius: "12px", overflow: "hidden", boxShadow: "0 8px 30px rgba(0,0,0,0.3)", display: "none", zIndex: "9998", }); chat.innerHTML = '<iframe src="' + ANNA_URL + '" style="width:100%;height:100%;border:none" allow="camera *; microphone *; geolocation *"></iframe>';
btn.addEventListener("click", function () { var open = chat.style.display === "none"; chat.style.display = open ? "block" : "none"; });
document.body.appendChild(chat); document.body.appendChild(btn); })(); </script> </body></html>Gerar a URL do chat no backend
Seção intitulada “Gerar a URL do chat no backend”Os exemplos abaixo chamam REST/Credentials/GetToken e depois REST/AnnACorporate/User/UserHash com getAnnAChatLink definido como true. Eles analisam accessData.AnnAChatURL e retornam o valor de um método do backend.
Para usar o fluxo forçado, substitua REST/AnnACorporate/User/UserHash por REST/AnnACorporate/User/UserHashForced e adicione userName ao corpo da requisição.
using var http = new HttpClient { BaseAddress = new Uri("https://YOUR_ANNA_ENVIRONMENT/") };var tokenResult = await http.PostAsJsonAsync("REST/Credentials/GetToken", new{ hash = "YOUR_COMPANY_HASH", user = "YOUR_API_USER", pass = "YOUR_API_PASSWORD"});var token = JObject.Parse(await tokenResult.Content.ReadAsStringAsync())["data"]["Token"];http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", (string)token);
var chatResult = await http.PostAsJsonAsync("REST/AnnACorporate/User/UserHash", new{ getAnnAChatLink = true, hash = "YOUR_COMPANY_HASH", userId = "USER_ID", startService = ""});var response = JObject.Parse(await chatResult.Content.ReadAsStringAsync());if ((bool?)response["success"] != true) throw new InvalidOperationException((string)response["message"]);var annaChatUrl = (string)response["accessData"]["AnnAChatURL"];using var http = new HttpClient { BaseAddress = new Uri("https://YOUR_ANNA_ENVIRONMENT/") };var tokenResult = await http.PostAsJsonAsync("REST/Credentials/GetToken", new{ hash = "YOUR_COMPANY_HASH", user = "YOUR_API_USER", pass = "YOUR_API_PASSWORD"});var token = (await tokenResult.Content.ReadFromJsonAsync<TokenResponse>())!.Data.Token;http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
var result = await http.PostAsJsonAsync("REST/AnnACorporate/User/UserHash", new{ getAnnAChatLink = true, hash = "YOUR_COMPANY_HASH", userId = "USER_ID", startService = ""});var response = await result.Content.ReadFromJsonAsync<ChatResponse>();if (response?.Success != true) throw new InvalidOperationException(response?.Message);var annaChatUrl = response.AccessData.AnnAChatURL;var client = HttpClient.newHttpClient();var baseUrl = "https://YOUR_ANNA_ENVIRONMENT/";var tokenRequest = HttpRequest.newBuilder().uri(URI.create(baseUrl + "REST/Credentials/GetToken")) .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString("{\"hash\":\"YOUR_COMPANY_HASH\",\"user\":\"YOUR_API_USER\",\"pass\":\"YOUR_API_PASSWORD\"}")) .build();var tokenResult = client.send(tokenRequest, HttpResponse.BodyHandlers.ofString());var token = new ObjectMapper().readTree(tokenResult.body()).get("data").get("Token").asText();
var body = "{\"getAnnAChatLink\":true,\"hash\":\"YOUR_COMPANY_HASH\",\"userId\":\"USER_ID\",\"startService\":\"\"}";var chatRequest = HttpRequest.newBuilder().uri(URI.create(baseUrl + "REST/AnnACorporate/User/UserHash")) .header("Content-Type", "application/json").header("Authorization", "Bearer " + token) .POST(HttpRequest.BodyPublishers.ofString(body)).build();var response = new ObjectMapper().readTree(client.send(chatRequest, HttpResponse.BodyHandlers.ofString()).body());var annaChatUrl = response.get("accessData").get("AnnAChatURL").asText();<?phpfunction postJson(string $url, array $payload, ?string $token = null): array { $headers = ["Content-Type: application/json"]; if ($token !== null) $headers[] = "Authorization: Bearer " . $token; $curl = curl_init($url); curl_setopt_array($curl, [CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => $headers, CURLOPT_POSTFIELDS => json_encode($payload)]); $body = curl_exec($curl); curl_close($curl); return json_decode($body, true, 512, JSON_THROW_ON_ERROR);}$baseUrl = "https://YOUR_ANNA_ENVIRONMENT/";$tokenResponse = postJson($baseUrl . "REST/Credentials/GetToken", [ "hash" => "YOUR_COMPANY_HASH", "user" => "YOUR_API_USER", "pass" => "YOUR_API_PASSWORD"]);$response = postJson($baseUrl . "REST/AnnACorporate/User/UserHash", [ "getAnnAChatLink" => true, "hash" => "YOUR_COMPANY_HASH", "userId" => "USER_ID", "startService" => ""], $tokenResponse["data"]["Token"]);$annaChatUrl = $response["accessData"]["AnnAChatURL"];&tokenBody = !'{"hash":"YOUR_COMPANY_HASH","user":"YOUR_API_USER","pass":"YOUR_API_PASSWORD"}'&tokenResponse = PostJson(!"YOUR_ANNA_ENVIRONMENT/REST/Credentials/GetToken", &tokenBody, !"")&tokenResponse.FromJson(&tokenData)&chatBody = !'{"getAnnAChatLink":true,"hash":"YOUR_COMPANY_HASH","userId":"USER_ID","startService":""}'&chatResponse = PostJson(!"YOUR_ANNA_ENVIRONMENT/REST/AnnACorporate/User/UserHash", &chatBody, !"Bearer " + &tokenData.Data.Token)&chatResponse.FromJson(&chatData)&annaChatUrl = &chatData.AccessData.AnnAChatURLimport requests
base_url = "https://YOUR_ANNA_ENVIRONMENT/"token_response = requests.post(f"{base_url}REST/Credentials/GetToken", json={ "hash": "YOUR_COMPANY_HASH", "user": "YOUR_API_USER", "pass": "YOUR_API_PASSWORD"}, timeout=30)token_response.raise_for_status()token = token_response.json()["data"]["Token"]result = requests.post(f"{base_url}REST/AnnACorporate/User/UserHash", headers={"Authorization": f"Bearer {token}"}, json={ "getAnnAChatLink": True, "hash": "YOUR_COMPANY_HASH", "userId": "USER_ID", "startService": ""}, timeout=30)result.raise_for_status()response = result.json()if response.get("success") is not True: raise RuntimeError(response.get("message", "AnnA request failed"))anna_chat_url = response["accessData"]["AnnAChatURL"]Use o valor retornado em accessData.AnnAChatURL como ANNACHAT_URL_FROM_BACKEND no exemplo do cliente. Não retorne o hash da empresa, as credenciais da API ou o token bearer ao navegador.
Veja também
Seção intitulada “Veja também”- Como acessar — como o link corporativo se comporta para quem o utiliza.
- Requisitos e limites — requisitos de navegador e permissões.