Documentação · Integrações
Chat dentro de apps
O mesmo chat do site abre dentro do seu app, numa webview, já com a pessoa identificada: as ações recebem quem ela é e a conta ativa, como no site. O app só precisa de uma página com o widget em tela cheia e de um jeito de pedir o token ao seu servidor.
Como funciona
- Seu servidor assina o token da pessoa com o segredo de identidade, como no site (veja Identificar usuários). O token vale 1 hora e o widget pede outro 5 minutos antes de vencer.
- Uma página sua (por exemplo
https://seuapp.com/chat-app.html) carrega owidget.jscommode: "fullscreen": o chat já abre, ocupando a tela toda, sem o botão flutuante. - O app abre essa página numa webview e passa a sessão dele antes de a página carregar. O
getTokenda página usa essa sessão para pedir o token ao seu servidor. - O X do chat chama o
onCloseda página, que avisa o app para fechar a tela.
O segredo de identidade fica só no seu servidor. Nem a página nem o app guardam o segredo: eles só repassam o token pronto.
A página do chat
html
<!doctype html>
<html lang="pt-BR">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body style="margin:0">
<script>
window.ChatWidgetConfig = {
mode: "fullscreen", // já aberto, na tela toda, sem o botão
// o mesmo token do site, pedido ao SEU servidor com a sessão que o app passou
getToken: async () => {
const r = await fetch("https://api.seuapp.com/chat-token", {
headers: { Authorization: "Bearer " + window.APP_SESSION },
});
return r.text();
},
// o X do chat: avise o app para fechar a tela
onClose: () => window.ReactNativeWebView?.postMessage("fechar"),
};
</script>
<script src="https://SEU-DOMINIO/widget.js" data-key="CHAVE_DO_WIDGET" async></script>
</body>
</html>| Opção | O que faz |
|---|---|
mode: "fullscreen" | Também como data-mode="fullscreen" no <script>. O chat abre na hora, na tela toda, sem o botão, a prévia e o contador. |
getToken | O mesmo do site: chamado ao abrir e 5 minutos antes de o token vencer. Sem ele, a conversa é anônima. |
onClose | Chamado quando a pessoa toca no X do chat. No modo tela cheia, o chat não some sozinho: quem fecha é o app. |
No app
React Native
tsx
// React Native (react-native-webview)
import { WebView } from "react-native-webview";
export function Atendimento({ sessao, fechar }) {
return (
<WebView
source={{ uri: "https://seuapp.com/chat-app.html" }}
// a sessão do app entra antes da página carregar (getToken usa)
injectedJavaScriptBeforeContentLoaded={`window.APP_SESSION = ${JSON.stringify(sessao)}; true;`}
onMessage={(e) => e.nativeEvent.data === "fechar" && fechar()}
// fotos e áudios: o seletor de arquivos do sistema
allowFileAccess
mediaPlaybackRequiresUserAction={false}
/>
);
}Flutter
dart
// Flutter (webview_flutter 4)
final controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..addJavaScriptChannel("App", onMessageReceived: (m) {
if (m.message == "fechar") Navigator.of(context).pop();
})
..setNavigationDelegate(NavigationDelegate(
onPageStarted: (_) => controller.runJavaScript(
"window.APP_SESSION = ${jsonEncode(sessao)};"),
))
..loadRequest(Uri.parse("https://seuapp.com/chat-app.html"));
// na página, troque o onClose por: () => App.postMessage("fechar")No Android nativo, o caminho é o mesmo com addJavascriptInterface (a ponte para o onClose) e evaluateJavascript (a sessão); no iOS, com WKUserScript no início do documento e um WKScriptMessageHandler.
Detalhes
- Sair da conta: chame
ChatWidget.logout()antes de fechar a webview, ou limpe os dados dela. A conversa de nível usuário já é presa ao token: outra pessoa no mesmo aparelho nunca vê a conversa da anterior. - Trocar de conta (workspace):
ChatWidget.setContext(novoToken)abre uma conversa nova, no contexto novo, como no site. - Fotos e arquivos: o botão de anexo usa o seletor de arquivos do sistema; libere o acesso a fotos e câmera na webview do seu app.
- Domínio: o
widget.jspode vir do domínio próprio da agência; a página do chat é sua e pode ficar em qualquer lugar.