Skip to main content

chatbuss_chat 1.4.0 copy "chatbuss_chat: ^1.4.0" to clipboard
chatbuss_chat: ^1.4.0 copied to clipboard

PlatformAndroid

Support client in-app pour applications Flutter — messagerie temps réel, pièces jointes et enquête de satisfaction, adossés à la plateforme ChatBuss.

chatbuss_chat — SDK de chat in-app ChatBuss (Flutter) #

Permet à n'importe quelle application mobile d'offrir un support client (messagerie + IA + agents) via ChatBuss — l'équivalent du widget web livechat, mais pour les apps.

Comment ça marche #

Le SDK parle à la façade mobile, /api/v1/app-chat/v1/* — distincte de celle du widget web, et versionnée à dessein : une application publiée met des jours à passer les stores, là où un site se redéploie en une minute.

Étape Endpoint
Ouvrir/reprendre la session POST /session (renvoie un user_id persisté)
Envoyer un message POST /messages
Recevoir les réponses agent WS /api/v1/ws/app-chat/v1, avec relecture de GET /messages/{user_id} en filet

Chaque appel porte l'en-tête X-Chatbuss-SDK : le serveur sait ainsi quelle génération d'application lui parle, et peut répondre 426 à une version périmée plutôt que de deviner. Le user_id est stocké (SharedPreferences, clé chatbuss_visitor_<channel_id>) → la conversation reprend au relancement de l'app.

Prérequis côté ChatBuss #

Le canal doit être de type app_chat, pas livechat. Les deux servent le même noyau, mais par des façades séparées : /api/v1/app-chat/v1/* pour les applications, /api/v1/livechat/* pour le widget web. Un site se redéploie en une minute, une application publiée met des jours à passer les stores et une partie du parc ne se met jamais à jour — les deux ne peuvent pas partager un contrat. Un identifiant de canal livechat est refusé par le SDK.

  1. Créer un canal de type app_chat dans la console ChatBuss.
  2. Récupérer son channel_id (UUID public).
  3. Le donner à l'app hôte (avec l'URL du serveur).

Intégration (côté app cliente) #

flutter pub add chatbuss_chat
# ou à la main, dans le pubspec.yaml de l'app hôte
dependencies:
  chatbuss_chat: ^1.0.0
import 'package:chatbuss_chat/chatbuss_chat.dart';

// Ouvrir le support depuis un bouton "Aide" :
Navigator.push(context, MaterialPageRoute(
  builder: (_) => ChatbussChatScreen(
    serverUrl: 'https://chatbuss-server.h.gandyam.com',
    channelId: 'VOTRE-CHANNEL-ID',
    // L'app connaît déjà son utilisateur → pré-identification, pas de formulaire :
    user: ChatUser(name: 'Awa Diop', email: 'awa@exemple.com'),
  ),
));

C'est tout. L'utilisateur discute avec le support sans quitter l'app.

Tester l'intégration (app d'exemple) #

cd chatbuss_chat_sdk/example
# 1) Éditer lib/main.dart : mettre kServerUrl et kChannelId
flutter pub get
flutter run          # sur un émulateur ou un téléphone branché

Puis, côté ChatBuss (console agent), réponds au message : il apparaît dans l'app (polling ~3 s).

Checklist de validation :

  • ❌ Le chat s'ouvre et affiche le message d'accueil.
  • ❌ L'envoi d'un message → il apparaît + arrive dans la console agent ChatBuss (canal app_chat).
  • ❌ La réponse de l'agent apparaît dans l'app en quelques secondes.
  • ❌ Fermer/rouvrir l'app → la conversation est reprise (même visitor_id).

API du SDK #

  • ChatbussChatScreen(...) — écran de chat clé en main.
  • ChatbussClient(...) — client bas niveau si tu veux ta propre UI :
    • init() · sendMessage(text) · fetchMessages() · getConfig()
    • sendMedia(bytes:, filename:, mimeType:) — pièce jointe
    • answerSurvey(surveyId:, rating:, comment:) — note de satisfaction

Enquête de satisfaction (CSAT) #

Rien à câbler : si le canal a csat_enabled, l'enquête arrive dans le fil comme un message et ChatbussChatScreen l'affiche en étoiles cliquables. Pour une interface sur mesure, ChatMessage.isSurvey et ChatMessage.survey portent le barème, et ChatbussClient.answerSurvey enregistre la note.

Pièces jointes #

Le bouton trombone est présent par défaut et s'appuie sur file_selector, le plugin officiel de Flutter. Depuis la 1.2.0, le SDK ne dépend plus de file_picker : ton application peut utiliser la version de file_picker de son choix sans conflit. Formats acceptés (depuis la 1.4.0, ceux de la console ChatBuss, sans l'audio ni le zip) : images JPEG, PNG, WebP, GIF (5 Mo), vidéos MP4, MOV, WebM, MPEG (50 Mo), documents PDF, Word, Excel, PowerPoint, TXT, CSV (10 Mo) — le serveur vérifie le contenu réel du fichier, pas seulement son extension.

Sous Android, le sélecteur par défaut ne propose pas les vidéos : file_selector_android charge le fichier entier en mémoire avant de le rendre, et une vidéo de téléphone pourrait faire tomber ton application. Pour que tes utilisateurs Android en envoient, branche un sélecteur qui vérifie la taille avant de lire (ci-dessous, image.length() avant readAsBytes()). Ailleurs, le sélecteur par défaut refuse un fichier trop lourd sans le charger.

Si ton application possède déjà un sélecteur, branche-le pour ne pas en avoir deux :

ChatbussChatScreen(
  serverUrl: kServerUrl,
  channelId: kChannelId,
  pickAttachment: () async {
    final image = await ImagePicker().pickImage(source: ImageSource.gallery);
    if (image == null) return null; // annulé
    return ChatPickedFile(
      bytes: await image.readAsBytes(),
      filename: image.name,
      // Le serveur refuse application/octet-stream : déduis le type du nom.
      mimeType: mimeDepuisNom(image.name),
    );
  },
)

Pour une interface sur mesure, ChatbussClient.sendMedia ne demande que des octets — aucun sélecteur imposé.

À savoir : une pièce jointe dont l'envoi échoue ne survit pas à la fermeture de l'application. Le texte, lui, est conservé et rejoué au redémarrage.

Notifications push #

Quand un conseiller répond, l'utilisateur reçoit une notification — application fermée, en arrière-plan ou ouverte. Le SDK ne touche pas à Firebase : ton application garde sa propre initialisation, récupère son jeton FCM et le passe au SDK, qui l'enregistre auprès de ChatBuss et le retire à la déconnexion.

// L'app hôte récupère son jeton (firebase_messaging est déjà configuré chez elle) :
final fcmToken = await FirebaseMessaging.instance.getToken();

Navigator.push(context, MaterialPageRoute(builder: (_) => ChatbussChatScreen(
  serverUrl: 'https://ton-serveur',
  channelId: 'TON-CHANNEL-ID',
  user: ChatUser(externalUserId: me.id, name: me.name),
  deviceToken: fcmToken,          // ← active le push
  platform: 'android',            // ou 'ios'
)));

Qui envoie la notification #

Ce jeton appartient au projet Firebase de ton application. ChatBuss ne peut pas l'utiliser depuis son propre projet : Firebase refuse l'envoi (SenderIdMismatch) et rien n'arrive. Le choix se fait sur le canal, dans Canaux → ton canal App Chat → Réglages → Envoi des notifications :

  • Par votre serveur (relais) — à chaque réponse, ChatBuss appelle une route HTTPS de ton serveur, qui envoie la notification avec son propre Firebase. Tu ne confies aucun identifiant. L'appel porte l'externalUserId de l'utilisateur, ses jetons, le texte de la réponse et le badge.
  • Par ChatBuss (Firebase) — tu colles le JSON d'un compte de service de ton projet, créé pour l'occasion avec le seul rôle Firebase Cloud Messaging API Admin. Pas la clé firebase-adminsdk, qui ouvre tout le projet.

Format de l'appel, vérification de la signature et dépannage : chatbuss.com/documentation/#push.

Application ouverte #

Au premier plan, ni Android ni iOS n'affichent d'eux-mêmes une notification Firebase : elle arrive dans ton application, qui doit l'afficher.

  • iOS : une ligne au démarrage suffit.
    await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
        alert: true, badge: true, sound: true);
    
  • Android : écoute FirebaseMessaging.onMessage et affiche toi-même la notification (avec flutter_local_notifications, par exemple), sur le canal déclaré dans Canal de notification Android. Ce champ attend l'identifiant du canal (support_messages), pas son libellé : sinon Android range la notification dans un canal par défaut, sans son ni priorité.

Si l'utilisateur avait la conversation sous les yeux dans les 15 dernières secondes, la notification part quand même, avec visitor_present à vrai (dans l'appel du relais, ou "1" dans les data Firebase) : à toi de choisir si tu affiches une bannière par-dessus.

Vérification de l'identité (recommandé) #

Par défaut, l'identité transmise dans ChatUser est crue sur parole. Connaître l'email d'un utilisateur suffit alors à ouvrir une session en son nom et à lire son historique de support. Tant que l'option est désactivée, le comportement reste celui-ci.

Pour la fermer, active « Exiger une identité signée » sur le canal, dans la console ChatBuss, et renseigne un secret partagé.

Ce que ton backend doit calculer #

import hmac, hashlib

user_hash = hmac.new(
    CHATBUSS_IDENTITY_SECRET.encode(),
    str(user.id).encode(),        # le sujet — voir l'ordre ci-dessous
    hashlib.sha256,
).hexdigest()

Le sujet signé suit un ordre figé, qui fait partie du contrat : external_user_id, sinon email, sinon phone. Autrement dit, dès que tu fournis externalUserId, c'est lui qui doit être signé.

Ce que l'application fait de la signature #

ChatbussChatScreen(
  serverUrl: 'https://<api>',
  channelId: '<channel_id>',
  user: ChatUser(
    externalUserId: me.id,      // pivot d'identité, stable même si l'email change
    name: me.name,
    email: me.email,
    userHash: me.chatbussHash,  // récupéré auprès de TON backend
  ),
)

Le secret ne doit jamais être embarqué dans l'application. Un APK se décompile : quiconque en extrait le secret peut signer l'identité de n'importe quel client. L'application demande la signature à son propre serveur, au moment de la connexion de l'utilisateur.

Erreurs possibles #

Situation Réponse
Signature valide 200
Signature absente alors que le canal l'exige 403 Identité non vérifiée.
Signature d'un autre utilisateur 403
Canal en vérification sans secret configuré 403 — échec fermé, volontaire
Aucune identité fournie (visiteur anonyme) 200, rien à vérifier

Utilisateur non connecté #

Quand l'application hôte ne fournit pas d'identité et que le canal en exige une, le SDK affiche son propre formulaire. Ce que l'utilisateur y saisit — nom, email, téléphone — est mémorisé sur l'appareil : à la réouverture du support, il retrouve sa conversation au lieu de repartir de zéro. La signature userHash, elle, n'est jamais écrite sur l'appareil.

Une identité fournie par l'application hôte prime toujours sur cette trace locale : elle connaît l'état courant de son utilisateur, la trace ne connaît que le passé.

À la déconnexion de votre utilisateur, appelez ChatbussClient.reset(). Session, file d'attente, identité mémorisée et jeton push partent ensemble. Sans cela, sur un appareil partagé — une tablette en boutique — le compte suivant reprendrait la conversation du précédent.

Écran distant (1.1.0) #

Un canal peut servir un écran distant : la conversation est alors une page servie par le serveur ChatBuss, affichée plein écran dans l'application. Ses corrections sont déployées côté ChatBuss et visibles à la prochaine ouverture du support, sans nouvelle version de l'application.

  • Rien à écrire côté application. ChatbussChatScreen et ChatbussChat.instance.open() choisissent l'écran d'après le réglage du canal.
  • Activation, côté ChatBuss : réglage ecran du canal à "web". Toute autre valeur, ou son absence, garde l'écran natif.
  • Repli automatique sur l'écran natif si la page ne peut pas servir (page injoignable, ouverture de plus de 15 s, session impossible, plateforme sans WebView). Remettre le réglage à "natif" ramène tout le parc sur l'écran natif, sans passer par les stores.
  • Garder l'écran natif en toutes circonstances : ChatbussChatScreen(allowRemoteScreen: false, ...).
  • La page ne reçoit aucun identifiant : elle échange un ticket à usage unique, remis par JavaScript, contre un cookie de session inaccessible aux scripts. Les liens externes s'ouvrent dans le navigateur du système.
  • Une identité fournie par l'application mais incomplète pour le canal garde l'écran natif, dont le formulaire la complète sans séparer l'historique.

Limites connues #

  • Le SDK ne fait pas l'init Firebase : c'est à l'app hôte de fournir le jeton.
  • Une pièce jointe dont l'envoi échoue ne survit pas à la fermeture de l'application. Le texte, lui, est conservé et rejoué au redémarrage.

Temps réel #

Le WebSocket est utilisé quand il est disponible, et la relecture périodique de l'historique reste le filet — elle passe simplement de 3 s à 20 s une fois la connexion établie. Aucun réglage n'est nécessaire : un réseau qui bloque le WebSocket dégrade le délai, jamais la réception.

Après une coupure — tunnel, changement de réseau, mise en veille — le SDK demande un ticket de connexion neuf et se reconnecte, en espaçant ses tentatives (5 s, puis 10, 20, 40, 60 au plus). Rien à appeler : un retour au premier plan relance immédiatement.

0
likes
160
points
267
downloads

Documentation

Documentation
API reference

Publisher

verified publisherchatbuss.com

Weekly Downloads

Support client in-app pour applications Flutter — messagerie temps réel, pièces jointes et enquête de satisfaction, adossés à la plateforme ChatBuss.

Homepage

Topics

#chat #support #messaging #livechat

License

MIT (license)

Dependencies

file_selector, flutter, http, http_parser, shared_preferences, url_launcher, web_socket_channel, webview_flutter, webview_flutter_android

More

Packages that depend on chatbuss_chat