feat(channel): canal EvoHub — proxy da Meta Cloud (Fase 1)#2577
Merged
Conversation
EvoHub é um canal adicional, espelho transparente do canal Meta (Cloud API)
roteado pelo proxy do EvoHub. Não altera o comportamento do canal Meta existente.
Data-plane: EvoHubStartupService extends BusinessStartupService, sobrescreve só
o transporte (URL {HUB}/meta sem versão + Bearer channel_token).
Control-plane: EvoHubClient + rotas /evohub/* (apikey global). Fase 1 entrega o
fluxo link-existing (resolve token + phone_number_id server-side via
GET /api/v1/channels/:id; o front nunca vê o token).
Webhook: EvoHubController reusa o parser Meta + valida HMAC X-Hub-Signature-256
sobre raw body (soft-mode na Fase 1).
Edição mínima na base Meta (autorizada): 3 private→protected + helper
fetchMediaFromGraph (JS emitido idêntico; bloco S3 inline roteado pelo helper
p/ evitar vazamento de mídia inbound EvoHub para a Meta com S3 ligado).
tsc --noEmit verde, eslint limpo, tsup build success.
…ints
- listChannels: o hub retorna { channels: [...], count } (channel_handler.go
GetChannels), não um array nu — causava 'channels.filter is not a function'
na rota /evohub/available-channels. Adiciona normalizeChannelList (tolera
channels|data|array nu).
- getPlan/getMetaAppOptions: corrige paths para /me/plan e /me/meta-app-options
(endpoints self-service do hub; /plan é admin-por-id e exige UUID). Fase 2.
… filtros whatsapp
- evohub.client: listChannels normaliza a resposta do hub { channels: [] }
(não array nu) — corrige 'channels.filter is not a function'.
- evohub.client.provisionChannel: monta o request correto do hub { name, type,
channel_credentials_id?, webhook_url } (antes passava o body cru → 400) e
registra o webhook do evolution-api (single-shot, register-with-own-secret).
Normaliza a resposta { channel } | plano.
- getPlan/getMetaAppOptions: paths corretos /me/plan e /me/meta-app-options.
- controlplane.router: /provision mapeia instanceName→name, fixa type=whatsapp,
monta webhook_url do SERVER.URL; /available-channels filtra só type=whatsapp
(evolution-api é API de WhatsApp; o hub devolve fb/ig também).
- env: EVOLUTION_HUB_FRONTEND_URL default corrigido p/ o domínio do hub.
Atualiza manager/dist com o build do evolution-manager-v2 incluindo a opção de canal EvoHub na criação de instância (vincular-existente + criar-novo).
Contributor
There was a problem hiding this comment.
Sorry @DavidsonGomes, your pull request is larger than the review limit of 150000 diff characters
| * server-side; o front NUNCA vê o token. | ||
| */ | ||
| async getChannel(id: string): Promise<HubChannel> { | ||
| const { data } = await this.http.get(`/channels/${id}`); |
| * Evolution; 'byo' exige channel_credentials no hub. | ||
| */ | ||
| async connectToMeta(channelId: string, req: MetaConnectRequest): Promise<MetaConnectResponse> { | ||
| const { data } = await this.http.post(`/channels/${channelId}/meta-connect`, req); |
| this.router | ||
| .get(this.routerPath('webhook/evohub', false), async (req, res) => { | ||
| if (req.query['hub.verify_token'] === configService.get<EvolutionHub>('EVOLUTION_HUB').TOKEN_WEBHOOK) | ||
| res.send(req.query['hub.challenge']); |
Comment on lines
+20
to
+31
| .post(this.routerPath('webhook/evohub', false), async (req, res) => { | ||
| const signature = req.headers['x-hub-signature-256'] as string | undefined; | ||
| const ok = evoHubController.verifyHmac((req as any).rawBody, signature); | ||
| if (!ok) { | ||
| return res.status(401).json({ error: 'invalid signature' }); | ||
| } | ||
|
|
||
| const { body } = req; | ||
| const response = await evoHubController.receiveWebhook(body); | ||
|
|
||
| return res.status(200).json(response); | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
O que é
Adiciona o canal EvoHub ao evolution-api: um canal adicional que espelha o canal Meta (WhatsApp Cloud), roteado pelo proxy transparente do EvoHub. O canal Meta existente continua funcionando byte-a-byte — zero regressão.
Arquitetura
EvoHubStartupService extends BusinessStartupServicesobrescreve só o transporte (URL{HUB}/metasem versão + Bearer channel_token). Toda a lógica de mensagem/eventos/persistência é herdada intacta do Meta.EvoHubClient+ rotas finas/evohub/*(apikey global) que delegam ao hub. O front nunca fala com o hub direto nem manuseia a API-key.EvoHubControllerreusa o parser do Meta + valida HMACX-Hub-Signature-256sobre o raw body (register-with-own-secret).Edição mínima na base Meta (autorizada)
whatsapp.business.service.ts: 3private→protected(JS emitido idêntico) + extração do helperfetchMediaFromGraph(refactor comportamentalmente neutro). Necessário porque uma subclasse não pode sobrescrever métodoprivateem TS (TS2415), e o bloco de download de mídia inline (S3) precisava do mesmo override para não vazar mídia inbound EvoHub para a Meta.Fluxos (Fase 1)
POST /evohub/link-existingresolve token + phone_number_id viaGET /api/v1/channels/:idserver-side e cria a Instance.POST /evohub/provisioncria o canal no hub + registra o webhook + devolve opublic_link.Config (.env)
EVOLUTION_HUB_URL,EVOLUTION_HUB_API_KEY,EVOLUTION_HUB_WEBHOOK_SECRET,EVOLUTION_HUB_TOKEN_WEBHOOK,EVOLUTION_HUB_FRONTEND_URL.Acompanha
build(manager)).Verificação
tsc --noEmit✅ ·tsupbuild ✅ · eslint ✅