Skip to content

Latest commit

 

History

History
461 lines (344 loc) · 12.2 KB

File metadata and controls

461 lines (344 loc) · 12.2 KB

Guia de Push Notifications

Guia unificado para configuração e uso de Push Notifications em todas as plataformas suportadas pelo Dito SDK.

📋 Visão Geral

O Dito SDK suporta Push Notifications via Firebase Cloud Messaging (FCM) em todas as plataformas. Este guia fornece instruções passo a passo para configurar e usar Push Notifications em iOS, Android, Flutter e React Native.

🔥 Configuração Firebase Geral

1. Criar Projeto no Firebase Console

  1. Acesse o Firebase Console
  2. Crie um novo projeto ou selecione um existente
  3. Ative o Cloud Messaging no projeto

2. Obter Credenciais

Cada plataforma requer arquivos de configuração específicos:

  • iOS: GoogleService-Info.plist
  • Android: google-services.json
  • Flutter/React Native: Ambos os arquivos acima

📱 Configuração por Plataforma

iOS

1. Adicionar GoogleService-Info.plist

  1. Baixe o arquivo GoogleService-Info.plist do Firebase Console
  2. Adicione o arquivo ao projeto Xcode
  3. Certifique-se de que está incluído no target do app

2. Configurar Capabilities

  1. No Xcode, selecione o target do app
  2. Vá em Signing & Capabilities
  3. Adicione Push Notifications
  4. Adicione Background Modes e marque Remote notifications

3. Configurar AppDelegate

Veja o exemplo completo em iOS README.

Ordem Importante (iOS 18+):

  1. FirebaseApp.configure()
  2. Messaging.messaging().delegate = self
  3. Dito.configure()

Android

1. Adicionar google-services.json

  1. Baixe o arquivo google-services.json do Firebase Console
  2. Adicione o arquivo ao diretório app/ do projeto
  3. Adicione o plugin no build.gradle.kts:
plugins {
    id("com.google.gms.google-services")
}

2. Configurar FirebaseMessagingService

Veja o exemplo completo em Android README.

Flutter

1. Instalar Dependências

dependencies:
  firebase_messaging: ^14.0.0
  firebase_core: ^2.0.0

2. Configurar Plataformas Nativas

Siga as instruções de iOS e Android.

3. Inicializar Firebase

import 'package:firebase_core/firebase_core.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}

React Native

1. Instalar Dependências

npm install @react-native-firebase/app @react-native-firebase/messaging

2. Configurar Plataformas Nativas

Siga as instruções de iOS e Android.

🔔 Interceptação de Notificações

O SDK intercepta automaticamente notificações do canal Dito quando o campo channel nos dados da notificação é igual a "DITO" (case-insensitive).

Como Funciona

  1. Quando uma notificação é recebida, o SDK verifica o campo channel
  2. Se channel == "DITO", o SDK processa a notificação automaticamente
  3. Se channel != "DITO", a notificação é ignorada pelo SDK e deve ser processada normalmente pelo app

Payload Esperado

{
  "channel": "DITO",
  "notification": "notification-id",
  "reference": "user-reference",
  "link": "https://app.example.com/product/123",
  "log_id": "log-id",
  "notification_name": "Nome da Notificação",
  "user_id": "user-id"
}

Notas sobre deeplink:

  • O campo canônico no payload é link (string).
  • Os wrappers Flutter e React Native aceitam deeplink como alias quando você precisa montar um userInfo manualmente (por exemplo, vindo de firebase_messaging).

📊 Tracking Automático

O SDK rastreia automaticamente quando uma notificação é recebida:

  • iOS: Evento receive-ios-notification
  • Android: Evento receive-android-notification

Os eventos incluem:

  • Canal: "mobile"
  • Token do dispositivo
  • ID do disparo (log_id)
  • ID da notificação
  • Nome da notificação
  • Provedor: "firebase"
  • Sistema operacional

👆 Handling de Clicks

Quando o usuário clica em uma notificação, o SDK:

  1. Registra o clique no CRM Dito
  2. Extrai o deeplink (link) se disponível
  3. Dispara o evento/callback exposto pela plataforma, para que o app faça navegação (ou abra navegador, etc.)

Fluxo (alto nível)

sequenceDiagram
    participant User as Usuário
    participant OS as Sistema Operacional
    participant Native as SDK Nativo
    participant Bridge as Bridge
    participant App as App

    User->>OS: Clica na notificação
    OS->>Native: Entrega a interação
    Native->>Native: Tracking do clique
    Native->>Native: Extrai link
    alt iOS_AndroidNativo
        Native->>App: Callback com link
    end
    alt Flutter
        Native->>Bridge: EventChannel
        Bridge->>App: Stream emite evento
    end
    alt ReactNative
        Native->>Bridge: EventEmitter
        Bridge->>App: Listener recebe evento
    end
Loading

Ciclo de vida (estados)

stateDiagram-v2
    [*] --> Recebida
    Recebida --> Exibida
    Exibida --> Clicada
    Exibida --> Descartada
    Clicada --> Processada
    Processada --> EventoDisparado
    EventoDisparado --> [*]
    Descartada --> [*]
Loading

Versão detalhada (com responsabilidades do SDK):

stateDiagram-v2
    [*] --> Enviada: Plataforma Dito envia
    Enviada --> Recebida: FCM entrega ao dispositivo
    Recebida --> Exibida: Sistema exibe notificação
    Exibida --> Clicada: Usuário clica
    Exibida --> Descartada: Usuário descarta
    Clicada --> Processada: SDK processa clique
    Processada --> CallbackExecutado: Callback com link
    CallbackExecutado --> Navegação: App navega
    Navegação --> [*]
    Descartada --> [*]

    note right of Recebida
        SDK rastreia evento
        receive-*-notification
    end note

    note right of Processada
        SDK extrai link
        e chama callback/evento
    end note
Loading

Decisão de processamento (payload)

flowchart TD
    Start[Notificação recebida] --> CheckChannel{channel == DITO?}
    CheckChannel -->|Não| Ignore[Ignorar no SDK]
    CheckChannel -->|Sim| Process[Processar no SDK]
    Process --> TrackReceive[Tracking de recebimento]
    TrackReceive --> TrackClick[Tracking de clique]
    TrackClick --> Emit[Disparar evento/callback]
    Ignore --> End[Fim]
    Emit --> End
Loading

Estrutura do payload (diagrama)

graph LR
    subgraph Payload[Payload FCM]
        Channel[channel: DITO]
        Notification[notification: ID]
        Reference[reference: User Ref]
        Deeplink[link: deeplink URL]
        LogID[log_id: Log ID]
        NotifName[notification_name: Nome]
        UserID[user_id: User ID]
    end

    subgraph Extracted[Dados extraídos]
        SDK[SDK processa]
    end

    subgraph Callback[Callback/evento retorna]
        DeeplinkStr[deeplink: string]
        NotifObj[notification: object]
    end

    Channel --> SDK
    Notification --> SDK
    Reference --> SDK
    Deeplink --> SDK
    LogID --> SDK
    NotifName --> SDK
    UserID --> SDK

    SDK --> DeeplinkStr
    SDK --> NotifObj
Loading

Troubleshooting (fluxo)

flowchart TD
    Start[Callback não funciona?] --> Q1{Notificação chega?}

    Q1 -->|Não| CheckFCM[Verificar configuração FCM]
    Q1 -->|Sim| Q2{SDK processa?}

    Q2 -->|Não| CheckChannel{channel == DITO?}
    Q2 -->|Sim| Q3{Callback/evento executado?}

    CheckChannel -->|Não| FixPayload[Corrigir payload da notificação]
    CheckChannel -->|Sim| CheckInit[Verificar inicialização do SDK]

    Q3 -->|Não| Q4{Plataforma?}
    Q3 -->|Sim| Q5{Link existe?}

    Q4 -->|Android| CheckListener[Verificar notificationClickListener]
    Q4 -->|iOS| CheckDelegate[Verificar callback no AppDelegate]
    Q4 -->|Flutter| CheckStream[Verificar Stream listener]
    Q4 -->|React Native| CheckSubscribe[Verificar subscription do listener]

    Q5 -->|Não| CheckPayloadDeeplink[Verificar campo link no payload]
    Q5 -->|Sim| Q6{Navegação funciona?}

    Q6 -->|Não| CheckNavigation[Verificar implementação de navegação]
    Q6 -->|Sim| Success[Tudo funcionando]

    CheckFCM --> End[Fim]
    FixPayload --> End
    CheckInit --> End
    CheckListener --> End
    CheckDelegate --> End
    CheckStream --> End
    CheckSubscribe --> End
    CheckPayloadDeeplink --> End
    CheckNavigation --> End
    Success --> End
Loading

Exemplo iOS

Dito.notificationClick(userInfo: userInfo) { deeplink in
    if let url = URL(string: deeplink) {
        UIApplication.shared.open(url)
    }
}

Exemplo Android

Dito.notificationClick(userInfo) { deeplink ->
    val intent = Intent(Intent.ACTION_VIEW, Uri.parse(deeplink))
    startActivity(intent)
}

Exemplo Flutter

import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:dito_sdk/dito_sdk.dart';

final ditoSdk = DitoSdk();

void setupPushClickHandling() {
  DitoSdk.onNotificationClick.listen((event) {
    final deeplink = event.deeplink;
    if (deeplink.isEmpty) return;
    // Navegação do seu app aqui
  });

  FirebaseMessaging.onMessageOpenedApp.listen((message) async {
    await ditoSdk.handleNotificationClick(message.data);
  });
}

Exemplo React Native

import DitoSdk, { addNotificationClickListener } from '@ditointernet/dito-sdk';

const unsubscribe = addNotificationClickListener((event) => {
  if (!event.deeplink) return;
  // Navegação do seu app aqui
});

// Quando o clique for detectado no JS (ex.: firebase messaging), delegue para o SDK:
await DitoSdk.handleNotificationClick(message.data);

🔗 Deeplinks e Navegação

O SDK extrai automaticamente o link do payload da notificação e fornece através do callback/evento.

Formato de Deeplink

O deeplink deve estar no formato de URL:

  • https://app.example.com/product/123
  • myapp://product/123
  • dito://action/123

Navegação

Cada plataforma tem sua própria forma de processar deeplinks:

  • iOS: Usar UIApplication.shared.open(url)
  • Android: Usar Intent com ACTION_VIEW
  • Flutter: Usar plugins de navegação/deeplink
  • React Native: Usar bibliotecas de navegação/deeplink

🐛 Troubleshooting Unificado

Notificações não são recebidas

Checklist Geral:

  1. ✅ Firebase configurado corretamente
  2. ✅ Arquivos de configuração adicionados (GoogleService-Info.plist / google-services.json)
  3. ✅ Permissões solicitadas
  4. ✅ Token FCM registrado no SDK (Dito.registerDevice(token) / DitoSdk.registerDeviceToken(token))
  5. ✅ Campo channel igual a "DITO" no payload

Notificações não são interceptadas pelo SDK

Causa: Campo channel não é "DITO" ou não está presente.

Solução: Certifique-se de que o payload da notificação inclui "channel": "DITO".

Deeplinks não funcionam

Causa: Deeplink não está no formato correto ou não está sendo processado.

Solução:

  1. Verifique se o deeplink está no payload como "link"
  2. Implemente o callback corretamente
  3. Configure o tratamento de deeplinks no app

iOS: Erro "APNS device token not set"

Causa: Ordem incorreta de inicialização no iOS 18+.

Solução: Siga a ordem exata:

  1. FirebaseApp.configure()
  2. Messaging.messaging().delegate = self
  3. Dito.configure()
  4. No didRegisterForRemoteNotificationsWithDeviceToken, defina Messaging.messaging().apnsToken = deviceToken ANTES de solicitar o token FCM

📝 Exemplos de Payload

Payload Completo

{
  "channel": "DITO",
  "notification": "notif-123",
  "reference": "user-456",
  "link": "https://app.example.com/product/789",
  "log_id": "log-abc",
  "notification_name": "Promoção Especial",
  "user_id": "user-456",
  "data": {
    "custom_field": "custom_value"
  }
}

Payload Mínimo

{
  "channel": "DITO",
  "notification": "notif-123",
  "reference": "user-456"
}

🔗 Links Úteis