Skip to navigation

Implementando o Embedded Signup

Visão geral

Este guia mostra como implementar o fluxo completo de Embedded Signup no seu frontend — permitindo que seus usuários conectem seus números de WhatsApp Business ao seu produto sem sair do seu app.

Pré-requisitos

  • Uma chave de API do Muchaw DEV
  • Seu domínio deve ser adicionado à lista de domínios permitidos do Muchaw DEV (entre em contato com o suporte)
  • Seu frontend deve ser servido via HTTPS

Implementação com React

Aqui está um componente React completo e pronto para usar:

import { useEffect, useState } from "react";
declare global {
interface Window {
FB: {
init: (config: object) => void;
login: (callback: (response: { authResponse?: { code?: string } }) => void, options: object) => void;
};
fbAsyncInit?: () => void;
}
}
interface EmbeddedSignupButtonProps {
apiKey: string;
onSuccess?: (numberId: string) => void;
onError?: (error: string) => void;
}
export function EmbeddedSignupButton({
apiKey,
onSuccess,
onError,
}: EmbeddedSignupButtonProps) {
const [sdkConfig, setSdkConfig] = useState<{
app_id: string;
config_id: string;
sdk_version: string;
} | null>(null);
const [status, setStatus] = useState<"idle" | "loading" | "pending" | "error">("idle");
// 1. Buscar configuração do SDK ao montar
useEffect(() => {
fetch("https://dev.muchau.com.br/api/embedded-signup/init", {
headers: { Authorization: `Bearer ${apiKey}` },
})
.then((r) => r.json())
.then(setSdkConfig)
.catch(() => setStatus("error"));
}, [apiKey]);
// 2. Carregar SDK do Facebook
useEffect(() => {
if (!sdkConfig) return;
window.fbAsyncInit = () => {
window.FB.init({
appId: sdkConfig.app_id,
xfbml: true,
version: sdkConfig.sdk_version,
});
};
if (!document.getElementById("facebook-jssdk")) {
const script = document.createElement("script");
script.id = "facebook-jssdk";
script.src = "https://connect.facebook.net/en_US/sdk.js";
script.async = true;
document.body.appendChild(script);
}
}, [sdkConfig]);
// 3. Acionar o fluxo de cadastro
const handleConnect = () => {
if (!sdkConfig || !window.FB) return;
setStatus("loading");
window.FB.login(
async (response) => {
const code = response.authResponse?.code;
if (!code) {
setStatus("error");
onError?.("Usuário fechou o popup ou negou a permissão");
return;
}
try {
// 4. Completar cadastro via Muchaw DEV
const res = await fetch("https://dev.muchau.com.br/api/embedded-signup/complete", {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ code }),
});
if (!res.ok) throw new Error(await res.text());
const { number_id } = await res.json();
setStatus("pending");
onSuccess?.(number_id);
} catch (err) {
setStatus("error");
onError?.(err instanceof Error ? err.message : "Erro desconhecido");
}
},
{
config_id: sdkConfig.config_id,
response_type: "code",
override_default_response_type: true,
}
);
};
if (!sdkConfig) return null;
return (
<div>
<button onClick={handleConnect} disabled={status === "loading"}>
{status === "loading" ? "Conectando..." : "Conectar WhatsApp"}
</button>
{status === "pending" && (
<p>Seu número está sendo ativado. Isso leva cerca de 30 segundos.</p>
)}
{status === "error" && (
<p>Algo deu errado. Por favor, tente novamente.</p>
)}
</div>
);
}

Implementação com HTML/JavaScript puro

<!DOCTYPE html>
<html>
<head><title>Conectar WhatsApp</title></head>
<body>
<button id="connect-btn">Conectar WhatsApp</button>
<p id="status"></p>
<script>
const API_KEY = "mk_live_...";
let sdkConfig = null;
// 1. Buscar configuração do SDK
fetch("https://dev.muchau.com.br/api/embedded-signup/init", {
headers: { Authorization: `Bearer ${API_KEY}` },
})
.then((r) => r.json())
.then((config) => {
sdkConfig = config;
// 2. Carregar SDK do Facebook
window.fbAsyncInit = () => {
FB.init({ appId: config.app_id, version: config.sdk_version });
};
const s = document.createElement("script");
s.src = "https://connect.facebook.net/en_US/sdk.js";
s.async = true;
document.head.appendChild(s);
});
// 3. Gerenciar clique no botão
document.getElementById("connect-btn").addEventListener("click", () => {
if (!sdkConfig || !window.FB) return;
document.getElementById("status").textContent = "Conectando...";
FB.login(
async (response) => {
const code = response.authResponse?.code;
if (!code) {
document.getElementById("status").textContent = "Cancelado.";
return;
}
// 4. Completar via Muchaw DEV
const res = await fetch(
"https://dev.muchau.com.br/api/embedded-signup/complete",
{
method: "POST",
headers: {
Authorization: `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ code }),
}
);
const { number_id } = await res.json();
document.getElementById("status").textContent =
`Ativando número ${number_id}... (~30 segundos)`;
},
{
config_id: sdkConfig.config_id,
response_type: "code",
override_default_response_type: true,
}
);
});
</script>
</body>
</html>

Aguardando a ativação

Após /complete, o número entra no status PENDING. Configure um webhook para number.activated para saber quando estiver pronto:

// Exemplo: atualizar UI quando o número for ativado
app.post("/webhooks/whatsapp", express.raw({ type: "application/json" }), (req, res) => {
res.sendStatus(200);
const event = JSON.parse(req.body.toString());
if (event.event === "number.activated") {
const numberId = event.data.id;
// Marcar o número como ativo no seu banco de dados
// Notificar o usuário via SSE/WebSocket/e-mail
console.log(`Número ${numberId} agora está ATIVO!`);
}
});

Problemas comuns

ProblemaSolução
Popup bloqueadoAcione FB.login() diretamente de um evento de clique do usuário (não em setTimeout/async)
code é undefinedO usuário cancelou o fluxo — trate isso graciosamente
403 de /completeO code expirou (válido por ~5 minutos) — peça ao usuário para tentar novamente
Domínio não permitidoEntre em contato com o suporte do Muchaw DEV para adicionar seu domínio à lista de permitidos