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 montaruseEffect(() => {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 FacebookuseEffect(() => {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 cadastroconst 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 DEVconst 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 SDKfetch("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 Facebookwindow.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ãodocument.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 DEVconst 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 ativadoapp.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-mailconsole.log(`Número ${numberId} agora está ATIVO!`);}});
Problemas comuns
| Problema | Solução |
|---|---|
| Popup bloqueado | Acione FB.login() diretamente de um evento de clique do usuário (não em setTimeout/async) |
code é undefined | O usuário cancelou o fluxo — trate isso graciosamente |
403 de /complete | O code expirou (válido por ~5 minutos) — peça ao usuário para tentar novamente |
| Domínio não permitido | Entre em contato com o suporte do Muchaw DEV para adicionar seu domínio à lista de permitidos |