@natyapp/meta 1.6.6 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/copilot-instructions.md +1540 -0
- package/README.md +513 -40
- package/dist/elements/index.d.ts +1 -0
- package/dist/elements/index.js +1 -0
- package/dist/elements/mediaTemplate.d.ts +45 -0
- package/dist/elements/mediaTemplate.js +47 -0
- package/dist/elements/textTemplate.d.ts +12 -1
- package/dist/elements/textTemplate.js +13 -6
- package/dist/index.d.ts +7 -2
- package/dist/index.js +11 -2
- package/dist/interfaces/IConnection.d.ts +2 -2
- package/dist/interfaces/ILog.d.ts +2 -2
- package/dist/interfaces/ILogger.d.ts +62 -0
- package/dist/interfaces/ILogger.js +2 -0
- package/dist/interfaces/ISdk.d.ts +4 -2
- package/dist/interfaces/IWebhook.d.ts +2 -2
- package/dist/interfaces/index.d.ts +1 -0
- package/dist/interfaces/index.js +1 -0
- package/dist/queue/messageQueue.d.ts +1 -1
- package/dist/queue/messageQueue.js +45 -0
- package/dist/routes/webhooks/methods/connection.js +78 -11
- package/dist/routes/webhooks/methods/messages.js +18 -3
- package/dist/services/axiosInstances.d.ts +14 -5
- package/dist/services/axiosInstances.js +111 -23
- package/dist/services/middlewares/validations.d.ts +2 -2
- package/dist/services/middlewares/validations.js +1 -2
- package/dist/services/mutations/connection.js +1 -1
- package/dist/services/mutations/logs.js +1 -1
- package/dist/services/mutations/messages.js +1 -1
- package/dist/services/mutations/validation.d.ts +1 -1
- package/dist/services/mutations/validation.js +1 -1
- package/dist/services/mutations/webhooks.js +1 -1
- package/dist/types/logs.d.ts +1 -1
- package/dist/types/requestTypes.d.ts +2 -0
- package/dist/useCases/connection/index.d.ts +9 -9
- package/dist/useCases/connection/index.js +156 -7
- package/dist/useCases/events/NatyEvents.d.ts +4 -2
- package/dist/useCases/events/NatyEvents.js +13 -1
- package/dist/useCases/log/index.d.ts +5 -5
- package/dist/useCases/log/index.js +65 -3
- package/dist/useCases/message/whatsappResponse.d.ts +48 -22
- package/dist/useCases/message/whatsappResponse.js +672 -105
- package/dist/useCases/messages/index.d.ts +5 -5
- package/dist/useCases/messages/index.js +66 -3
- package/dist/useCases/sdk/index.d.ts +8 -4
- package/dist/useCases/sdk/index.js +38 -6
- package/dist/useCases/webhook/index.d.ts +9 -9
- package/dist/useCases/webhook/index.js +154 -7
- package/dist/utils/consoleLogger.d.ts +20 -0
- package/dist/utils/consoleLogger.js +51 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.js +6 -0
- package/dist/utils/loggerContext.d.ts +57 -0
- package/dist/utils/loggerContext.js +90 -0
- package/dist/utils/methodContext.d.ts +34 -0
- package/dist/utils/methodContext.js +48 -0
- package/dist/utils/parseError.d.ts +12 -0
- package/dist/utils/parseError.js +27 -3
- package/dist/utils/pinoAdapter.d.ts +30 -0
- package/dist/utils/pinoAdapter.js +68 -0
- package/dist/utils/sanitize.d.ts +42 -0
- package/dist/utils/sanitize.js +120 -0
- package/dist/utils/tryCatch.d.ts +10 -1
- package/dist/utils/tryCatch.js +40 -5
- package/docs/01-visao-geral.md +355 -0
- package/docs/02-contexto-negocio.md +596 -0
- package/docs/03-arquitetura.md +925 -0
- package/docs/04-fluxos-funcionais.md +887 -0
- package/docs/05-integracoes.md +960 -0
- package/docs/06-entidades.md +849 -0
- package/docs/07-guia-pratico.md +1133 -0
- package/docs/08-troubleshooting.md +816 -0
- package/docs/README.md +125 -0
- package/examples/logger-example.ts +279 -0
- package/package.json +2 -2
- /package/dist/{Entities → entities}/Logs.d.ts +0 -0
- /package/dist/{Entities → entities}/Logs.js +0 -0
- /package/dist/{Entities → entities}/connection.d.ts +0 -0
- /package/dist/{Entities → entities}/connection.js +0 -0
- /package/dist/{Entities → entities}/errorLogs.d.ts +0 -0
- /package/dist/{Entities → entities}/errorLogs.js +0 -0
- /package/dist/{Entities → entities}/index.d.ts +0 -0
- /package/dist/{Entities → entities}/index.js +0 -0
- /package/dist/{Entities → entities}/messages.d.ts +0 -0
- /package/dist/{Entities → entities}/messages.js +0 -0
- /package/dist/{Entities → entities}/webhooks.d.ts +0 -0
- /package/dist/{Entities → entities}/webhooks.js +0 -0
- /package/dist/{Entities → entities}/whatsappMessage.d.ts +0 -0
- /package/dist/{Entities → entities}/whatsappMessage.js +0 -0
- /package/dist/{Errors → errors}/Either.d.ts +0 -0
- /package/dist/{Errors → errors}/Either.js +0 -0
- /package/dist/{Errors → errors}/ErrorHandling.d.ts +0 -0
- /package/dist/{Errors → errors}/ErrorHandling.js +0 -0
- /package/dist/{Errors → errors}/index.d.ts +0 -0
- /package/dist/{Errors → errors}/index.js +0 -0
|
@@ -0,0 +1,596 @@
|
|
|
1
|
+
# 02 - Contexto e Regras de Negócio
|
|
2
|
+
|
|
3
|
+
[⬅️ Voltar ao Índice](README.md)
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 📋 Sumário
|
|
8
|
+
- [Domínio de Negócio](#-domínio-de-negócio)
|
|
9
|
+
- [Modelo Operacional](#-modelo-operacional)
|
|
10
|
+
- [Regras de Negócio](#-regras-de-negócio)
|
|
11
|
+
- [Políticas da Meta WhatsApp](#-políticas-da-meta-whatsapp)
|
|
12
|
+
- [Multi-Tenancy e Isolamento](#-multi-tenancy-e-isolamento)
|
|
13
|
+
- [Perfis e Permissões](#-perfis-e-permissões)
|
|
14
|
+
- [Ciclo de Vida de Tokens](#-ciclo-de-vida-de-tokens)
|
|
15
|
+
- [Limitações e Restrições](#-limitações-e-restrições)
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 🏢 Domínio de Negócio
|
|
20
|
+
|
|
21
|
+
### Contexto Geral
|
|
22
|
+
|
|
23
|
+
O SDK **@natyapp/meta** opera no domínio de **Comunicação Empresarial B2B via WhatsApp**, fornecendo uma camada de integração entre:
|
|
24
|
+
|
|
25
|
+
- **Provedores de Software (SaaS)** que desenvolvem soluções de atendimento, e-commerce, fintech, etc.
|
|
26
|
+
- **Empresas Clientes** (tenants) que possuem contas WhatsApp Business
|
|
27
|
+
- **Usuários Finais** (consumidores) que interagem via WhatsApp
|
|
28
|
+
|
|
29
|
+
### Modelo de Plataforma
|
|
30
|
+
|
|
31
|
+
```mermaid
|
|
32
|
+
graph TD
|
|
33
|
+
subgraph "Plataforma Naty"
|
|
34
|
+
PLAT[Naty Platform]
|
|
35
|
+
SDK[SDK Meta]
|
|
36
|
+
API[Naty Meta API]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
subgraph "SaaS Providers"
|
|
40
|
+
SAAS1[SaaS 1<br/>CRM/Atendimento]
|
|
41
|
+
SAAS2[SaaS 2<br/>E-commerce]
|
|
42
|
+
SAAS3[SaaS 3<br/>Chatbot]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
subgraph "Empresas Clientes"
|
|
46
|
+
TENANT1[Empresa A<br/>companyId: ABC123]
|
|
47
|
+
TENANT2[Empresa B<br/>companyId: XYZ789]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
subgraph "Meta Infrastructure"
|
|
51
|
+
META[Meta WhatsApp<br/>Business API]
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
SAAS1 --> SDK
|
|
55
|
+
SAAS2 --> SDK
|
|
56
|
+
SAAS3 --> SDK
|
|
57
|
+
SDK --> API
|
|
58
|
+
API --> TENANT1
|
|
59
|
+
API --> TENANT2
|
|
60
|
+
TENANT1 --> META
|
|
61
|
+
TENANT2 --> META
|
|
62
|
+
|
|
63
|
+
style PLAT fill:#4CAF50,color:#fff
|
|
64
|
+
style SDK fill:#66BB6A,color:#fff
|
|
65
|
+
style META fill:#25D366,color:#fff
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Proposta de Valor
|
|
69
|
+
|
|
70
|
+
1. **Para SaaS Providers:**
|
|
71
|
+
- Redução de complexidade técnica
|
|
72
|
+
- Gestão centralizada de múltiplos clientes
|
|
73
|
+
- Atualização transparente frente a mudanças da API Meta
|
|
74
|
+
|
|
75
|
+
2. **Para Empresas Clientes:**
|
|
76
|
+
- Onboarding facilitado (conexão simplificada)
|
|
77
|
+
- Gestão automática de credenciais
|
|
78
|
+
- Rastreamento e logs de todas comunicações
|
|
79
|
+
|
|
80
|
+
3. **Para Usuários Finais:**
|
|
81
|
+
- Experiência nativa no WhatsApp
|
|
82
|
+
- Respostas rápidas e interativas
|
|
83
|
+
- Privacidade e segurança (E2E encryption do WhatsApp)
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## 📐 Modelo Operacional
|
|
88
|
+
|
|
89
|
+
### Hierarquia de Entidades
|
|
90
|
+
|
|
91
|
+
```mermaid
|
|
92
|
+
graph TD
|
|
93
|
+
PLATFORM[Plataforma Naty<br/>appToken]
|
|
94
|
+
|
|
95
|
+
PLATFORM --> COMPANY1[Empresa 1<br/>companyId: ABC123]
|
|
96
|
+
PLATFORM --> COMPANY2[Empresa 2<br/>companyId: XYZ789]
|
|
97
|
+
|
|
98
|
+
COMPANY1 --> CONN1A[Conexão 1A<br/>+55 11 99999-0001]
|
|
99
|
+
COMPANY1 --> CONN1B[Conexão 1B<br/>+55 11 99999-0002]
|
|
100
|
+
|
|
101
|
+
COMPANY2 --> CONN2A[Conexão 2A<br/>+55 21 88888-0001]
|
|
102
|
+
|
|
103
|
+
CONN1A --> MSG1[Mensagens]
|
|
104
|
+
CONN1A --> WH1[Webhooks]
|
|
105
|
+
CONN1A --> LOG1[Logs]
|
|
106
|
+
|
|
107
|
+
style PLATFORM fill:#1976D2,color:#fff
|
|
108
|
+
style COMPANY1 fill:#42A5F5,color:#fff
|
|
109
|
+
style COMPANY2 fill:#42A5F5,color:#fff
|
|
110
|
+
style CONN1A fill:#90CAF9
|
|
111
|
+
style CONN1B fill:#90CAF9
|
|
112
|
+
style CONN2A fill:#90CAF9
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Níveis de Autenticação
|
|
116
|
+
|
|
117
|
+
| Nível | Credencial | Escopo | Validade |
|
|
118
|
+
|-------|-----------|--------|----------|
|
|
119
|
+
| **Plataforma** | `appToken` | Acesso ao SDK e Naty Meta API | Não expira (gerenciado pela Naty) |
|
|
120
|
+
| **Empresa** | `companyId` | Isolamento de dados por tenant | Permanente (identificador) |
|
|
121
|
+
| **Conexão** | `accessToken` (Meta) | Acesso à API WhatsApp de um número específico | 60 dias (renovável) |
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## 📜 Regras de Negócio
|
|
126
|
+
|
|
127
|
+
### RN001 - Isolamento de Dados por Empresa (Multi-Tenancy)
|
|
128
|
+
|
|
129
|
+
**Descrição:** Todas as operações devem ser isoladas por `companyId`.
|
|
130
|
+
|
|
131
|
+
**Regra:**
|
|
132
|
+
- Cada entidade (`Connection`, `Message`, `Webhook`, `Log`) possui um campo `companyId`
|
|
133
|
+
- Consultas sempre filtram por `companyId` para evitar vazamento de dados entre tenants
|
|
134
|
+
- Um `companyId` pode ter múltiplas conexões (múltiplos números WhatsApp)
|
|
135
|
+
|
|
136
|
+
**Implementação:**
|
|
137
|
+
```typescript
|
|
138
|
+
// Exemplo: Buscar conexão sempre filtra por companyId
|
|
139
|
+
const connection = await getConnection({
|
|
140
|
+
companyId: 'ABC123',
|
|
141
|
+
phoneNumberId: '123456789'
|
|
142
|
+
});
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
**Impacto:** Garante conformidade com LGPD e isolamento de clientes.
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
### RN002 - Gestão Automática de Tokens
|
|
150
|
+
|
|
151
|
+
**Descrição:** Tokens de acesso da Meta expiram e devem ser renovados automaticamente.
|
|
152
|
+
|
|
153
|
+
**Regra:**
|
|
154
|
+
- **Short-Lived Token:** Válido por ~1 hora, obtido inicialmente
|
|
155
|
+
- **Long-Lived Token:** Válido por 60 dias, obtido via exchange do short-lived
|
|
156
|
+
- **Refresh Automático:** Executado toda vez que um `WhatsappResponse` é instanciado
|
|
157
|
+
- **Persistência:** Token atualizado é salvo na Naty Meta API automaticamente
|
|
158
|
+
|
|
159
|
+
**Fluxo:**
|
|
160
|
+
```mermaid
|
|
161
|
+
sequenceDiagram
|
|
162
|
+
participant App as Aplicação
|
|
163
|
+
participant SDK as SDK
|
|
164
|
+
participant Naty as Naty API
|
|
165
|
+
participant Meta as Meta API
|
|
166
|
+
|
|
167
|
+
App->>SDK: WhatsappResponse(companyId, phoneNumberId)
|
|
168
|
+
SDK->>Naty: GET /connection (buscar accessToken)
|
|
169
|
+
Naty-->>SDK: { accessToken, appId, appSecret }
|
|
170
|
+
SDK->>Meta: POST /oauth/access_token (exchange token)
|
|
171
|
+
Meta-->>SDK: { access_token: newToken, expires_in: 5184000 }
|
|
172
|
+
SDK->>Naty: PUT /connection (salvar novo token)
|
|
173
|
+
SDK-->>App: Instância pronta para uso
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**Exceções:**
|
|
177
|
+
- Se o token não puder ser renovado (credenciais inválidas), um erro é retornado
|
|
178
|
+
- Aplicação deve reagir ao erro e solicitar re-autenticação do cliente
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
### RN003 - Validação de Números de Telefone
|
|
183
|
+
|
|
184
|
+
**Descrição:** Números devem estar no formato E.164 internacional.
|
|
185
|
+
|
|
186
|
+
**Regra:**
|
|
187
|
+
- **Formato:** `+[código país][DDD][número]`
|
|
188
|
+
- **Exemplo válido:** `+5511999999999` (Brasil)
|
|
189
|
+
- **Exemplo inválido:** `11999999999` (sem código do país)
|
|
190
|
+
|
|
191
|
+
**Validação:**
|
|
192
|
+
```typescript
|
|
193
|
+
// O SDK não valida o formato, é responsabilidade da aplicação
|
|
194
|
+
// Recomenda-se usar bibliotecas como libphonenumber-js
|
|
195
|
+
import { parsePhoneNumber } from 'libphonenumber-js';
|
|
196
|
+
|
|
197
|
+
const phone = parsePhoneNumber('11999999999', 'BR');
|
|
198
|
+
const e164 = phone.format('E.164'); // +5511999999999
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
**Impacto:** Meta API rejeita requisições com números mal formatados (erro 400).
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
### RN004 - Ordem de Processamento de Webhooks
|
|
206
|
+
|
|
207
|
+
**Descrição:** Webhooks de mensagens podem chegar fora de ordem.
|
|
208
|
+
|
|
209
|
+
**Regra:**
|
|
210
|
+
- Meta não garante ordem de entrega de webhooks
|
|
211
|
+
- Aplicação deve usar `timestamp` da mensagem para ordenação
|
|
212
|
+
- IDs de mensagem (`message.id`) são únicos e podem ser usados para deduplicação
|
|
213
|
+
|
|
214
|
+
**Exemplo de Deduplicação:**
|
|
215
|
+
```typescript
|
|
216
|
+
const processedMessages = new Set<string>();
|
|
217
|
+
|
|
218
|
+
sdk.on('message', async (data) => {
|
|
219
|
+
const messageId = data.message.id;
|
|
220
|
+
|
|
221
|
+
if (processedMessages.has(messageId)) {
|
|
222
|
+
console.log('Mensagem já processada, ignorando');
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
processedMessages.add(messageId);
|
|
227
|
+
// Processar mensagem...
|
|
228
|
+
});
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
### RN005 - Janela de Mensagens (24h Message Window)
|
|
234
|
+
|
|
235
|
+
**Descrição:** Empresas só podem iniciar conversas com clientes após interação do cliente ou via templates aprovados.
|
|
236
|
+
|
|
237
|
+
**Regra Meta:**
|
|
238
|
+
- **Dentro de 24h da última mensagem do cliente:** Empresa pode enviar qualquer mensagem
|
|
239
|
+
- **Fora da janela de 24h:** Empresa só pode enviar **Message Templates** previamente aprovados pela Meta
|
|
240
|
+
|
|
241
|
+
**Tipos de Template:**
|
|
242
|
+
- **Marketing:** Promoções, novidades
|
|
243
|
+
- **Utility:** Notificações transacionais (pedidos, agendamentos)
|
|
244
|
+
- **Authentication:** OTPs, códigos de verificação
|
|
245
|
+
|
|
246
|
+
**Implementação:**
|
|
247
|
+
```typescript
|
|
248
|
+
// Enviar template fora da janela de 24h
|
|
249
|
+
await whatsapp.send_text_template({
|
|
250
|
+
to: '5511999999999',
|
|
251
|
+
template: {
|
|
252
|
+
name: 'pedido_confirmado', // Nome do template aprovado
|
|
253
|
+
language: 'pt_BR',
|
|
254
|
+
components: [
|
|
255
|
+
{
|
|
256
|
+
type: 'body',
|
|
257
|
+
parameters: [
|
|
258
|
+
{ type: 'text', text: '#12345' } // Número do pedido
|
|
259
|
+
]
|
|
260
|
+
}
|
|
261
|
+
]
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
**Exceção:** Esta regra não se aplica a mensagens enviadas pelo cliente (resposta via webhook sempre funciona).
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
### RN006 - Tipos de Mensagem Suportados
|
|
271
|
+
|
|
272
|
+
**Descrição:** O SDK suporta todos os tipos de mensagem da API WhatsApp Business.
|
|
273
|
+
|
|
274
|
+
**Tipos Implementados:**
|
|
275
|
+
|
|
276
|
+
| Tipo | Método | Uso |
|
|
277
|
+
|------|--------|-----|
|
|
278
|
+
| Texto | `send_text()` | Mensagens simples de texto |
|
|
279
|
+
| Imagem | `send_image()` | Fotos, infográficos |
|
|
280
|
+
| Vídeo | `send_video()` | Vídeos curtos |
|
|
281
|
+
| Áudio | `send_audio()` | Mensagens de voz, podcasts |
|
|
282
|
+
| Documento | `send_document()` | PDFs, planilhas, apresentações |
|
|
283
|
+
| Localização | `send_location()` | Coordenadas geográficas |
|
|
284
|
+
| Contato | `send_contact()` | vCards |
|
|
285
|
+
| Reação | `send_reaction()` | Emoji reação a mensagem |
|
|
286
|
+
| Botões | `send_buttons()` | Até 3 botões de ação rápida |
|
|
287
|
+
| Lista | `send_list()` | Menu com seções e múltiplas opções |
|
|
288
|
+
| Template | `send_*_template()` | Templates aprovados (texto, mídia) |
|
|
289
|
+
|
|
290
|
+
**Limitações por Tipo:**
|
|
291
|
+
- **Botões:** Máximo 3 botões por mensagem
|
|
292
|
+
- **Lista:** Máximo 10 seções, 10 itens por seção
|
|
293
|
+
- **Áudio:** Apenas áudio (não pode ser música, deve ser voz)
|
|
294
|
+
- **Vídeo:** Tamanho máximo ~16MB
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
### RN007 - Webhooks Configuráveis por Tenant
|
|
299
|
+
|
|
300
|
+
**Descrição:** Cada empresa pode ter URLs de webhook personalizadas.
|
|
301
|
+
|
|
302
|
+
**Regra:**
|
|
303
|
+
- Webhooks de **mensagens** e **conexões** são configurados separadamente
|
|
304
|
+
- Cada `companyId` pode ter suas próprias URLs de webhook
|
|
305
|
+
- Campo `active` controla se o webhook está ativo ou não
|
|
306
|
+
|
|
307
|
+
**Estrutura:**
|
|
308
|
+
```typescript
|
|
309
|
+
interface WebhooksEntity {
|
|
310
|
+
companyId: string;
|
|
311
|
+
connection: {
|
|
312
|
+
url: string; // URL para eventos de conexão
|
|
313
|
+
active: boolean;
|
|
314
|
+
};
|
|
315
|
+
messages: {
|
|
316
|
+
url: string; // URL para mensagens recebidas
|
|
317
|
+
active: boolean;
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
**Comportamento:**
|
|
323
|
+
- Se `active: false`, eventos não são enviados para aquela URL
|
|
324
|
+
- Permite ativar/desativar webhooks sem remover configuração
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
### RN008 - Logs e Auditoria Obrigatórios
|
|
329
|
+
|
|
330
|
+
**Descrição:** Todas as operações devem ser logadas para auditoria.
|
|
331
|
+
|
|
332
|
+
**Tipos de Log:**
|
|
333
|
+
|
|
334
|
+
| Tipo | Quando Registrar | Informações |
|
|
335
|
+
|------|------------------|-------------|
|
|
336
|
+
| `Access` | Toda requisição à API | IP, método, URL, user agent |
|
|
337
|
+
| `Error` | Erros em operações | Stack trace, código HTTP, contexto |
|
|
338
|
+
| `Update` | Modificações em entidades | Antes/depois, quem modificou |
|
|
339
|
+
| `Observer` | Eventos monitorados | Tipo de evento, payload |
|
|
340
|
+
| `Middleware` | Processamento de middleware | Etapa, duração |
|
|
341
|
+
|
|
342
|
+
**Retenção:** Logs devem ser mantidos por no mínimo 90 dias para conformidade.
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
## 📱 Políticas da Meta WhatsApp
|
|
347
|
+
|
|
348
|
+
### Limites de Taxa (Rate Limits)
|
|
349
|
+
|
|
350
|
+
A Meta impõe limites de envio por número WhatsApp:
|
|
351
|
+
|
|
352
|
+
| Tier | Mensagens/dia | Como alcançar |
|
|
353
|
+
|------|---------------|---------------|
|
|
354
|
+
| **Tier 1** | 1.000 | Número recém-registrado |
|
|
355
|
+
| **Tier 2** | 10.000 | Após enviar 1.000 mensagens em 7 dias |
|
|
356
|
+
| **Tier 3** | 100.000 | Após enviar 10.000 mensagens em 7 dias |
|
|
357
|
+
| **Unlimited** | Sem limite | Aprovação manual da Meta (enterprise) |
|
|
358
|
+
|
|
359
|
+
**Impacto:**
|
|
360
|
+
- SDK não controla rate limiting (responsabilidade da aplicação)
|
|
361
|
+
- Recomenda-se implementar throttling na camada da aplicação
|
|
362
|
+
- Mensagens que excedem o limite são rejeitadas pela Meta (erro 429)
|
|
363
|
+
|
|
364
|
+
---
|
|
365
|
+
|
|
366
|
+
### Qualidade da Conta (Quality Rating)
|
|
367
|
+
|
|
368
|
+
Meta avalia qualidade com base em:
|
|
369
|
+
- **Bloqueios de usuários:** Clientes bloqueando o número da empresa
|
|
370
|
+
- **Relatórios de spam:** Clientes reportando como spam
|
|
371
|
+
- **Conformidade:** Uso de templates aprovados, respeito à janela de 24h
|
|
372
|
+
|
|
373
|
+
**Status da Conta:**
|
|
374
|
+
- 🟢 **Verde (High Quality):** Sem restrições
|
|
375
|
+
- 🟡 **Amarelo (Medium Quality):** Aviso, monitoramento aumentado
|
|
376
|
+
- 🔴 **Vermelho (Low Quality):** Restrições severas, risco de suspensão
|
|
377
|
+
|
|
378
|
+
**Ação recomendada:** Monitorar métricas via Meta Business Manager.
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
### Tipos de Conteúdo Proibidos
|
|
383
|
+
|
|
384
|
+
Meta proíbe envio de:
|
|
385
|
+
- ❌ Conteúdo adulto ou sexual
|
|
386
|
+
- ❌ Discurso de ódio, discriminação
|
|
387
|
+
- ❌ Desinformação relacionada à saúde
|
|
388
|
+
- ❌ Violência ou conteúdo gráfico
|
|
389
|
+
- ❌ Produtos ilegais (drogas, armas)
|
|
390
|
+
- ❌ Esquemas financeiros fraudulentos
|
|
391
|
+
|
|
392
|
+
**Consequência:** Suspensão imediata da conta.
|
|
393
|
+
|
|
394
|
+
---
|
|
395
|
+
|
|
396
|
+
## 🏢 Multi-Tenancy e Isolamento
|
|
397
|
+
|
|
398
|
+
### Conceito
|
|
399
|
+
|
|
400
|
+
Multi-tenancy (multi-inquilinato) permite que uma única instância do SDK sirva múltiplas empresas (tenants) com isolamento completo de dados.
|
|
401
|
+
|
|
402
|
+
### Arquitetura de Isolamento
|
|
403
|
+
|
|
404
|
+
```mermaid
|
|
405
|
+
graph TD
|
|
406
|
+
subgraph "Tenant A - companyId: ABC123"
|
|
407
|
+
A_CONN1[Conexão 1<br/>+55 11 99999-0001]
|
|
408
|
+
A_CONN2[Conexão 2<br/>+55 11 99999-0002]
|
|
409
|
+
A_MSG[Mensagens A]
|
|
410
|
+
A_WEBHOOK[Webhooks A]
|
|
411
|
+
A_LOG[Logs A]
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
subgraph "Tenant B - companyId: XYZ789"
|
|
415
|
+
B_CONN1[Conexão 1<br/>+55 21 88888-0001]
|
|
416
|
+
B_MSG[Mensagens B]
|
|
417
|
+
B_WEBHOOK[Webhooks B]
|
|
418
|
+
B_LOG[Logs B]
|
|
419
|
+
end
|
|
420
|
+
|
|
421
|
+
SDK[SDK Naty Meta] --> A_CONN1
|
|
422
|
+
SDK --> A_CONN2
|
|
423
|
+
SDK --> B_CONN1
|
|
424
|
+
|
|
425
|
+
A_CONN1 --> A_MSG
|
|
426
|
+
A_CONN1 --> A_WEBHOOK
|
|
427
|
+
A_CONN1 --> A_LOG
|
|
428
|
+
|
|
429
|
+
B_CONN1 --> B_MSG
|
|
430
|
+
B_CONN1 --> B_WEBHOOK
|
|
431
|
+
B_CONN1 --> B_LOG
|
|
432
|
+
|
|
433
|
+
style SDK fill:#4CAF50,color:#fff
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
### Garantias de Isolamento
|
|
437
|
+
|
|
438
|
+
1. **Dados:** Consultas sempre filtram por `companyId`
|
|
439
|
+
2. **Webhooks:** Cada tenant recebe apenas seus próprios eventos
|
|
440
|
+
3. **Tokens:** Cada conexão tem seu próprio `accessToken`
|
|
441
|
+
4. **Logs:** Registros são isolados por `companyId`
|
|
442
|
+
|
|
443
|
+
---
|
|
444
|
+
|
|
445
|
+
## 🔐 Perfis e Permissões
|
|
446
|
+
|
|
447
|
+
### Níveis de Acesso
|
|
448
|
+
|
|
449
|
+
#### 1. **Plataforma (SDK Level)**
|
|
450
|
+
|
|
451
|
+
**Autenticação:** `appToken`
|
|
452
|
+
|
|
453
|
+
**Permissões:**
|
|
454
|
+
- ✅ Validar credencial no Naty Meta API
|
|
455
|
+
- ✅ Acessar todas as funcionalidades do SDK
|
|
456
|
+
- ✅ Gerenciar múltiplos `companyId`
|
|
457
|
+
|
|
458
|
+
**Quem possui:** SaaS Provider (desenvolvedor que integra o SDK)
|
|
459
|
+
|
|
460
|
+
---
|
|
461
|
+
|
|
462
|
+
#### 2. **Empresa (Tenant Level)**
|
|
463
|
+
|
|
464
|
+
**Identificação:** `companyId`
|
|
465
|
+
|
|
466
|
+
**Permissões:**
|
|
467
|
+
- ✅ Gerenciar suas próprias conexões
|
|
468
|
+
- ✅ Enviar mensagens via seus números WhatsApp
|
|
469
|
+
- ✅ Configurar webhooks
|
|
470
|
+
- ✅ Visualizar logs de suas operações
|
|
471
|
+
- ❌ **NÃO pode** acessar dados de outras empresas
|
|
472
|
+
|
|
473
|
+
**Quem possui:** Cliente do SaaS Provider
|
|
474
|
+
|
|
475
|
+
---
|
|
476
|
+
|
|
477
|
+
#### 3. **Conexão (WhatsApp Number Level)**
|
|
478
|
+
|
|
479
|
+
**Autenticação:** `accessToken` (Meta), `phoneNumberId`
|
|
480
|
+
|
|
481
|
+
**Permissões:**
|
|
482
|
+
- ✅ Enviar mensagens via número específico
|
|
483
|
+
- ✅ Receber mensagens endereçadas àquele número
|
|
484
|
+
- ✅ Gerenciar mídia (upload/download)
|
|
485
|
+
- ❌ **NÃO pode** enviar mensagens por outros números
|
|
486
|
+
|
|
487
|
+
**Quem possui:** Número WhatsApp Business registrado na Meta
|
|
488
|
+
|
|
489
|
+
---
|
|
490
|
+
|
|
491
|
+
### Matriz de Permissões
|
|
492
|
+
|
|
493
|
+
| Operação | appToken | companyId | accessToken |
|
|
494
|
+
|----------|----------|-----------|-------------|
|
|
495
|
+
| Conectar ao SDK | ✅ Obrigatório | - | - |
|
|
496
|
+
| Criar Conexão | ✅ | ✅ | ✅ |
|
|
497
|
+
| Enviar Mensagem | ✅ | ✅ | ✅ |
|
|
498
|
+
| Receber Webhook | ✅ | ✅ | - |
|
|
499
|
+
| Criar Log | ✅ | ✅ | - |
|
|
500
|
+
| Visualizar Logs | ✅ | ✅ (filtrado) | - |
|
|
501
|
+
|
|
502
|
+
---
|
|
503
|
+
|
|
504
|
+
## 🔄 Ciclo de Vida de Tokens
|
|
505
|
+
|
|
506
|
+
### Fluxo Completo de Tokens
|
|
507
|
+
|
|
508
|
+
```mermaid
|
|
509
|
+
sequenceDiagram
|
|
510
|
+
participant Dev as Desenvolvedor
|
|
511
|
+
participant Meta as Meta for Developers
|
|
512
|
+
participant App as Aplicação
|
|
513
|
+
participant SDK as SDK Naty
|
|
514
|
+
participant Naty as Naty API
|
|
515
|
+
participant Graph as Meta Graph API
|
|
516
|
+
|
|
517
|
+
Note over Dev,Meta: 1. Setup Inicial
|
|
518
|
+
Dev->>Meta: Cria aplicação WhatsApp Business
|
|
519
|
+
Meta-->>Dev: Gera App ID + App Secret
|
|
520
|
+
Dev->>Meta: Adiciona número WhatsApp
|
|
521
|
+
Meta-->>Dev: Gera Short-Lived Token (1h)
|
|
522
|
+
|
|
523
|
+
Note over App,SDK: 2. Primeira Conexão
|
|
524
|
+
Dev->>App: Configura credenciais
|
|
525
|
+
App->>SDK: CreateConnection({ appId, appSecret, accessToken })
|
|
526
|
+
SDK->>Graph: POST /oauth/access_token (exchange)
|
|
527
|
+
Graph-->>SDK: Long-Lived Token (60 dias)
|
|
528
|
+
SDK->>Naty: POST /connection (salvar)
|
|
529
|
+
Naty-->>SDK: { connectionId }
|
|
530
|
+
|
|
531
|
+
Note over App,Graph: 3. Uso Normal (< 60 dias)
|
|
532
|
+
App->>SDK: WhatsappResponse(companyId, phoneNumberId)
|
|
533
|
+
SDK->>Naty: GET /connection (buscar token)
|
|
534
|
+
SDK->>Graph: POST /messages (usar token)
|
|
535
|
+
Graph-->>SDK: Mensagem enviada
|
|
536
|
+
|
|
537
|
+
Note over SDK,Graph: 4. Refresh Automático
|
|
538
|
+
SDK->>Graph: POST /oauth/access_token (refresh)
|
|
539
|
+
Graph-->>SDK: Novo token (60 dias)
|
|
540
|
+
SDK->>Naty: PUT /connection (atualizar)
|
|
541
|
+
|
|
542
|
+
Note over Dev,Meta: 5. Token Expirado (> 60 dias)
|
|
543
|
+
SDK->>Graph: POST /messages
|
|
544
|
+
Graph-->>SDK: 401 Unauthorized
|
|
545
|
+
SDK-->>App: Error: Token expirado
|
|
546
|
+
App-->>Dev: Alerta para renovar manualmente
|
|
547
|
+
Dev->>Meta: Gera novo Short-Lived Token
|
|
548
|
+
Dev->>App: Atualiza conexão
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
### Estados do Token
|
|
552
|
+
|
|
553
|
+
| Estado | Duração | Ação Requerida |
|
|
554
|
+
|--------|---------|---------------|
|
|
555
|
+
| **Short-Lived** | ~1 hora | Exchange para long-lived imediatamente |
|
|
556
|
+
| **Long-Lived** | 60 dias | Refresh automático a cada uso |
|
|
557
|
+
| **Quase Expirando** | < 7 dias | Aplicação deve alertar administrador |
|
|
558
|
+
| **Expirado** | > 60 dias | Reautenticação manual necessária |
|
|
559
|
+
|
|
560
|
+
---
|
|
561
|
+
|
|
562
|
+
## ⚠️ Limitações e Restrições
|
|
563
|
+
|
|
564
|
+
### Limitações Técnicas
|
|
565
|
+
|
|
566
|
+
1. **Tipos de Mídia:**
|
|
567
|
+
- Tamanho máximo: 100MB (varia por tipo)
|
|
568
|
+
- Formatos suportados: Definidos pela Meta (ver [documentação oficial](https://developers.facebook.com/docs/whatsapp/cloud-api/reference/media))
|
|
569
|
+
|
|
570
|
+
2. **Mensagens Interativas:**
|
|
571
|
+
- Botões: Máximo 3 por mensagem
|
|
572
|
+
- Listas: Máximo 10 seções, 10 itens/seção
|
|
573
|
+
|
|
574
|
+
3. **Webhooks:**
|
|
575
|
+
- Timeout: 15 segundos
|
|
576
|
+
- Retry: Meta tenta 3x com backoff exponencial
|
|
577
|
+
|
|
578
|
+
### Limitações de Negócio
|
|
579
|
+
|
|
580
|
+
1. **Custo:** Meta cobra por mensagens enviadas (varia por país)
|
|
581
|
+
2. **Conformidade:** LGPD, GDPR devem ser respeitadas pela aplicação
|
|
582
|
+
3. **Suporte:** Apenas contas WhatsApp Business (não suporta contas pessoais)
|
|
583
|
+
|
|
584
|
+
---
|
|
585
|
+
|
|
586
|
+
## 🔗 Próximos Passos
|
|
587
|
+
|
|
588
|
+
Agora que você entende o contexto e regras de negócio:
|
|
589
|
+
|
|
590
|
+
- **[Arquitetura Técnica](03-arquitetura.md)** - Veja como o sistema é estruturado
|
|
591
|
+
- **[Fluxos Funcionais](04-fluxos-funcionais.md)** - Entenda os processos em detalhes
|
|
592
|
+
- **[Guia Prático](07-guia-pratico.md)** - Implemente na prática
|
|
593
|
+
|
|
594
|
+
---
|
|
595
|
+
|
|
596
|
+
[⬅️ Anterior: Visão Geral](01-visao-geral.md) | [⬆️ Voltar ao Índice](README.md) | [➡️ Próximo: Arquitetura](03-arquitetura.md)
|