Skip to content

Tout pour WordPress, le développement web — et plus encore

🤖 Chatbot Viber en PHP : envoi de messages structurés avec menus clavier

🤖 Chatbot Viber en PHP : envoi de messages structurés avec menus clavier

L’utilisateur appuie sur un bouton dans le chat et reçoit non pas du texte brut, mais une grille d’images, de liens et de touches colorées. Cela ressemble à une application native. En réalité, il s’agit simplement de JSON que votre script PHP renvoie via l’API REST de Viber.

Le problème avec la plupart des tutoriels: ils vous apprennent à répondre du texte à du texte. Un vrai bot professionnel doit afficher un menu sous forme de clavier avec des boutons de lien, des images et des carrousels. Sinon, l’utilisateur ne comprend tout simplement pas ce que le bot peut faire et s’en va. Depuis février 2024, Viber a rendu la création de bots payante (100 € par mois via les partenaires officiels Rakuten Viber), et l’authentification passe désormais par l’en-tête HTTP X-Viber-Auth-Token et non plus dans le corps de la requête. Les extraits de code avec auth_token dans le JSON ne fonctionnent plus.

Voici un bot Viber fonctionnel en PHP de A à Z: de la configuration du webhook à l’envoi d’un menu structuré avec des boutons de réponse et d’ouverture de lien. Le code est à jour pour la version 7.3 de l’API.

💡 Aperçu rapide:

  • Enregistrez un bot commercial auprès d’un partenaire Viber et obtenez un jeton d’authentification
  • Configurez le webhook via set_webhook avec l’en-tête X-Viber-Auth-Token
  • Recevez les événements de rappel de Viber: webhook → subscribed → message
  • Construisez un menu clavier (une grille de boutons avec couleurs, tailles et actions personnalisées)
  • Envoyez une réponse structurée: texte, images, liens, carrousels via send_message

Fonctionnement de l’API Viber Bot

L’API Viber Bot fonctionne sur un modèle REST: votre serveur reçoit des requêtes de rappel sur le webhook et répond en appelant https://chatapi.viber.com/pa/send_message. Chaque requête est authentifiée par un jeton dans l’en-tête X-Viber-Auth-Token.

Le cycle de base est le suivant:

  • Vous enregistrez un bot via un partenaire Viber et recevez un jeton dans le panneau «Edit Info».
  • Vous configurez un webhook (l’URL de votre serveur avec un certificat SSL valide; Let’s Encrypt fonctionne car il figure dans la liste de certificats Java de confiance de Viber; les certificats auto-signés ne sont pas acceptés).
  • Viber envoie des requêtes POST à cette URL à chaque événement: un utilisateur s’est abonné, a envoyé un message, a appuyé sur un bouton.
  • Votre script PHP lit le JSON entrant, analyse le champ event et répond en appelant send_message.

La première étape pour comprendre est d’observer un bot en direct. Ouvrez Viber et recherchez le compte public d’une marque connue. Presque toutes en ont un avec un chatbot et un menu. La capture d’écran ci-dessous montre un résultat de recherche de compte public typique.

Recherche d'un compte public sur Viber

Après vous être abonné, vous entrez dans une conversation individuelle. Cela ressemble à peu près à ceci: un avatar, un message de bienvenue et un bouton pour démarrer la conversation.

Écran de discussion publique Viber après abonnement

Appuyez sur l’icône de message en haut à droite et envoyez «Bonjour». Si le bot est configuré avec un menu clavier, vous verrez une réponse avec une grille de boutons:

Menu clavier avec boutons dans une discussion Viber

Il s’agit d’un message structuré. Il existe deux types de boutons: reply renvoie du texte au bot (en appuyant sur «Actualités» ou «Articles»), tandis que open-url ouvre un lien dans le navigateur. Écrivons maintenant le code qui produit cela.

Étape 1: Obtenir le jeton et configurer le webhook

Le jeton se trouve dans le panneau d’administration Viber: section Edit Info → champ App Key. Il s’agit d’une chaîne de lettres et de chiffres que vous incluez dans chaque requête API.

Le webhook se configure avec une seule requête POST vers https://chatapi.viber.com/pa/set_webhook. Le corps de la requête est du JSON contenant l’URL de votre gestionnaire et une liste des événements auxquels vous vous abonnez. L’en-tête est X-Viber-Auth-Token avec votre jeton.

Script de configuration du webhook (enregistrez-le sous setup.php et exécutez-le une fois):

1<?php
2$token = 'ВАШ_X_VIBER_AUTH_TOKEN';
3
4$data = json_encode([
5 'url' => 'https://your-domain.com/webhook.php',
6 'event_types' => ['message', 'subscribed', 'conversation_started'],
7]);
8
9$ch = curl_init('https://chatapi.viber.com/pa/set_webhook');
10curl_setopt($ch, CURLOPT_POST, 1);
11curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
12curl_setopt($ch, CURLOPT_HTTPHEADER, [
13 'Content-Type: application/json',
14 'X-Viber-Auth-Token: ' . $token,
15]);
16curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
17
18$result = curl_exec($ch);
19$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
20curl_close($ch);
21
22echo "HTTP {$httpCode}: {$result}\n";
23
24if ($httpCode === 200) {
25 $response = json_decode($result, true);
26 if (($response['status'] ?? -1) === 0) {
27 echo "Вебхук установлен успешно.\n";
28 } else {
29 echo "Ошибка Viber: " . ($response['status_message'] ?? 'неизвестная') . "\n";
30 }
31}

Ce qui se passe ici: cURL envoie un POST à set_webhook. Le jeton est strictement dans l’en-tête, pas dans le corps. Viber renvoie {"status":0} en cas de succès et envoie immédiatement un rappel webhook à l’URL spécifiée pour vérifier sa disponibilité. Il est obligatoire de répondre {"status":0,"status_message":"ok"} à ce rappel (nous verrons cela à l’étape suivante).

Si vous recevez invalidUrl, vérifiez votre certificat SSL. Let’s Encrypt fonctionne; un certificat auto-signé non. Sur votre serveur, il suffit d’exécuter certbot --nginx -d your-domain.com et de configurer le renouvellement automatique via cron.

Étape 2: Recevoir les événements de rappel de Viber

Lorsqu’un utilisateur interagit avec le bot, Viber envoie une requête POST avec du JSON à votre webhook. Votre tâche consiste à lire le champ event et à réagir.

Un gestionnaire minimal webhook.php qui répond correctement à tous les événements:

1<?php
2$request = file_get_contents("php://input");
3$input = json_decode($request, true);
4
5if ($input['event'] === 'webhook') {
6 $response = [
7 'status' => 0,
8 'status_message' => 'ok',
9 'event_types' => ['delivered', 'seen', 'message', 'subscribed', 'conversation_started'],
10 ];
11 echo json_encode($response);
12 exit;
13}
14
15if ($input['event'] === 'subscribed') {
16 $sender_id = $input['sender']['id'];
17 sendWelcomeMessage($sender_id);
18}
19
20if ($input['event'] === 'conversation_started') {
21 $sender_id = $input['sender']['id'];
22 sendMainMenu($sender_id);
23}
24
25if ($input['event'] === 'message') {
26 $type = $input['message']['type'];
27 $text = $input['message']['text'];
28 $sender_id = $input['sender']['id'];
29 $sender_name = $input['sender']['name'];
30
31 $data = match ($text) {
32 'News' => getNewsList($sender_id),
33 'Articles' => getArticleList($sender_id),
34 'Gallery' => getGalleryList($sender_id),
35 default => getMainMenu($sender_id),
36 };
37
38 sendToViber($data);
39}

Détail des événements:

  • webhook arrive une fois lors de la configuration du webhook. Vous devez renvoyer {"status":0,"status_message":"ok"} avec la liste des événements supportés. Sans cela, Viber ne confirmera pas l'URL et le bot ne démarrera pas.
  • subscribed signifie qu'un utilisateur s'est abonné au bot. C'est le moment idéal pour envoyer un menu de bienvenue.
  • conversation_started signifie qu'un utilisateur a ouvert la conversation (pour la première fois ou à nouveau). Convient également pour afficher le menu principal.
  • message est l'événement de travail principal. Le champ text contient soit un message libre de l'utilisateur, soit le ActionBody d'un bouton pressé (si son type est reply). C'est ainsi que le bot comprend ce qui a été sélectionné: «Actualités», «Articles» ou «Galerie».

La structure match() est disponible à partir de PHP 8. Si vous utilisez PHP 7.4, remplacez-la par switch.

Étape 3: Construire le menu du clavier

Un clavier est attaché à tout message via le champ keyboard dans l'objet JSON send_message. Il s'agit d'un tableau de boutons avec des paramètres distincts pour la largeur (Columns, 1-6), la hauteur (Rows, 1-2), la couleur de fond, le texte et l'action.

Une fonction qui assemble un menu principal à partir de sept boutons de réponse et d'un bouton de lien:

1<?php
2
3function getMainMenu(string $user_id): array
4{
5 $buttons = [];
6
7 $addReplyButton = function (string $label, string $actionBody, int $cols = 2, int $rows = 2) use (&$buttons) {
8 $buttons[] = [
9 'Columns' => $cols,
10 'Rows' => $rows,
11 'Text' => $label,
12 'TextSize' => 'regular',
13 'TextVAlign' => 'bottom',
14 'TextHAlign' => 'center',
15 'TextOpacity' => 100,
16 'ActionType' => 'reply',
17 'ActionBody' => $actionBody,
18 'BgColor' => '#FFFFFF',
19 ];
20 };
21
22 $addReplyButton('NEWS', 'News');
23 $addReplyButton('ARTICLES', 'Articles');
24 $addReplyButton('INTERVIEWS', 'Interviews');
25 $addReplyButton('GALLERY', 'Gallery');
26 $addReplyButton('POLL', 'Poll');
27 $addReplyButton('PLAYER OF THE MONTH','POTM');
28 $addReplyButton('QUOTE OF THE DAY', 'Quote');
29
30 $buttons[] = [
31 'Columns' => 4,
32 'Rows' => 2,
33 'Text' => 'VISIT OUR WEBSITE',
34 'TextSize' => 'regular',
35 'TextVAlign' => 'bottom',
36 'TextHAlign' => 'center',
37 'TextOpacity' => 100,
38 'ActionType' => 'open-url',
39 'ActionBody' => 'https://your-site.com',
40 'BgColor' => '#FFFFFF',
41 ];
42
43 return [
44 'receiver' => $user_id,
45 'type' => 'text',
46 'text' => 'Please select one of the options below:',
47 'keyboard' => [
48 'Type' => 'keyboard',
49 'BgColor' => '#FFFFFF',
50 'Buttons' => $buttons,
51 ],
52 ];
53}

Les boutons avec Columns=2 et Rows=2 sont carrés, trois par ligne (2+2+2=6). Le bouton de lien avec Columns=4 occupe sa propre ligne. La grille est assemblée de gauche à droite, de haut en bas. La somme des Columns dans une ligne détermine la disposition.

Paramètres des boutons:

Paramètre

Valeurs

Rôle

Columns

1-6

Largeur du bouton en colonnes conditionnelles

Rows

1-2

Hauteur du bouton en lignes

ActionType

reply ou open-url

reply renvoie du texte au bot, open-url ouvre le navigateur

ActionBody

chaîne

Pour reply, le texte que le bot recevra en retour; pour open-url, l'URL

Text

chaîne

Libellé sur le bouton, supporte les balises HTML b, i et la couleur de police

BgColor

HEX

Couleur de fond du bouton

Image

URL

Image au-dessus du bouton, JPEG, optionnelle

Étape 4: Envoyer des données via send_message

Une fonction d'envoi que vous appelez depuis le gestionnaire d'événements:

1<?php
2
3function sendToViber(array $data): void
4{
5 $token = 'ВАШ_X_VIBER_AUTH_TOKEN';
6
7 $ch = curl_init('https://chatapi.viber.com/pa/send_message');
8 curl_setopt($ch, CURLOPT_POST, 1);
9 curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
10 curl_setopt($ch, CURLOPT_HTTPHEADER, [
11 'Content-Type: application/json',
12 'X-Viber-Auth-Token: ' . $token,
13 ]);
14 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
15
16 $result = curl_exec($ch);
17 $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
18 curl_close($ch);
19
20 if ($httpCode !== 200) {
21 error_log("Viber API error: HTTP {$httpCode} - {$result}");
22 }
23}

La différence clé par rapport aux anciens tutoriels: le token est dans l'en-tête, pas dans le corps JSON. Le corps contient uniquement les champs receiver, type, text, keyboard, et optionnellement sender.name, sender.avatar, tracking_data. La taille maximale du JSON est de 30 Ko. Si vous la dépassez, Viber ignore le message silencieusement; vérifiez strlen(json_encode($data)) avant l'envoi.

Étape 5: Assembler le contenu des boutons

Lorsqu'un utilisateur appuie sur un bouton de réponse, son ActionBody est envoyé au webhook comme texte du message. Vous l'analysez dans match() et appelez la fonction appropriée. Voici un exemple pour une liste d'actualités avec images:

1<?php
2
3function getNewsList(string $user_id): array
4{
5 $newsItems = [
6 [
7 'title' => 'Your Article Title',
8 'link' => 'https://your-site.com/article-1',
9 'image' => 'https://your-site.com/images/article-1.jpg',
10 ],
11 [
12 'title' => 'Another Article',
13 'link' => 'https://your-site.com/article-2',
14 'image' => 'https://your-site.com/images/article-2.jpg',
15 ],
16 ];
17
18 $buttons = [];
19 foreach ($newsItems as $item) {
20 $buttons[] = [
21 'Columns' => 2,
22 'Rows' => 2,
23 'ActionType' => 'open-url',
24 'ActionBody' => $item['link'],
25 'BgColor' => '#FFFFFF',
26 'Image' => $item['image'],
27 ];
28 $buttons[] = [
29 'Columns' => 4,
30 'Rows' => 2,
31 'Text' => $item['title'],
32 'TextSize' => 'regular',
33 'TextHAlign' => 'left',
34 'TextVAlign' => 'top',
35 'ActionType' => 'open-url',
36 'ActionBody' => $item['link'],
37 'BgColor' => '#F5F5F5',
38 ];
39 }
40
41 return [
42 'receiver' => $user_id,
43 'type' => 'text',
44 'text' => 'Here are the latest updates:',
45 'keyboard' => [
46 'Type' => 'keyboard',
47 'BgColor' => '#DDDDDD',
48 'Buttons' => $buttons,
49 ],
50 ];
51}

Du côté de l'utilisateur, cela ressemble à une grille de cartes: image à gauche, titre à droite. Appuyer sur n'importe quelle partie ouvre le lien dans le navigateur.

Message enrichi avec images et liens dans Viber

Une galerie, une liste d'articles ou des sondages sont assemblés exactement de la même manière; seuls le contenu du tableau $buttons et le texte du message changent. S'il y a beaucoup de contenu et que le JSON approche les 30 Ko, divisez-le en pages avec un bouton «Suivant».

Si vous préférez travailler avec une bibliothèque PHP prête à l'emploi plutôt qu'avec l'API brute, jetez un œil à viber-bot-php par Bogdaan. Elle gère pour vous la validation de signature, le routage des événements et la génération du JSON.

Résumé: séquence complète de lancement

  • Obtenez le token dans le panneau d'administration Viber: section Edit Info → App Key.
  • Déployez le gestionnaire sur un serveur avec HTTPS. Let's Encrypt fonctionne; un certificat auto-signé non. Viber valide les certificats par rapport à la liste de confiance des autorités de certification racine Java.
  • Définissez le webhook avec une requête POST vers https://chatapi.viber.com/pa/set_webhook avec le corps {"url":"https://your-domain/webhook.php","event_types":[...]} et l'en-tête X-Viber-Auth-Token.
  • Vérifiez la réponse: {"status":0} signifie que c'est réussi. Viber enverra immédiatement un callback webhook à votre URL. Assurez-vous que le script renvoie {"status":0,"status_message":"ok"}.
  • Envoyez le premier menu: lors de l'événement conversation_started, appelez getMainMenu() et passez le résultat à sendToViber().

⁉️🤔 Foire aux questions

Puis-je utiliser un certificat SSL auto-signé pour le webhook?

Non. Viber valide le certificat par rapport à la liste des autorités de certification racine Java de confiance. Un certificat auto-signé provoque une erreur invalidUrl lors de la définition du webhook. Let's Encrypt figure dans cette liste et est gratuit. Sur votre serveur, exécutez certbot --nginx -d your-domain.com, ajoutez le renouvellement automatique dans cron, et Viber acceptera le certificat sans problème.

Quelle est la différence entre reply et open-url dans ActionType?

reply renvoie ActionBody au webhook comme texte de message. Le script PHP le voit dans $input['message']['text'] et le route via match(). Utilisez ceci pour la navigation au sein du bot. open-url ouvre un lien dans un navigateur externe et ne déclenche pas le webhook. En pratique, les menus combinent les deux types: cinq ou six boutons reply pour les sections et un bouton large open-url pour naviguer vers le site web.

Quels types de messages l'API Viber Bot prend-elle en charge?

L'API Viber Bot prend en charge neuf valeurs type dans send_message: text (texte brut), picture (image JPEG), video (fichier vidéo), file (tout fichier jusqu'à 50 Mo), location (point géographique), contact (fiche contact), sticker (autocollant), rich_media (carrousel de cartes) et url (aperçu de lien). Pour la liste actuelle avec les champs obligatoires, consultez la documentation du Viber Developers Hub. Le scénario le plus courant est text + keyboard pour les menus et picture pour l'envoi d'images. Les carrousels sont excellents pour les vitrines et les catalogues, mais nécessitent plus de code.

Que dois-je faire si l'utilisateur ne voit pas le clavier?

Il y a trois causes fréquentes. Premièrement: le JSON avec le clavier a dépassé 30 Ko, et Viber écarte silencieusement ces messages. Vérifiez strlen(json_encode($data)) avant l'envoi. Deuxièmement: la réponse à set_webhook ne contenait pas "status":0, le webhook n'a pas été défini et le bot ne reçoit pas de messages. Troisièmement: vous utilisez l'ancien format avec auth_token dans le corps JSON. Depuis l'API 7.0, cela est ignoré; vous avez besoin de l'en-tête X-Viber-Auth-Token. Pour le débogage, activez la journalisation de la réponse de l'API Viber: elle renvoie du JSON lisible avec les codes d'erreur invalidAuthToken, badData ou missingData.

Puis-je changer le clavier après l'envoi?

Oui. Avec chaque nouveau message, vous pouvez envoyer un clavier différent. Le client Viber affiche toujours le dernier reçu. Cela vous permet de construire des menus à plusieurs niveaux: menu principal → sous-menu de section → contenu spécifique. Chaque niveau a son propre ensemble de boutons, et l'utilisateur navigue entre eux en appuyant sur les touches reply.

Combien coûte le lancement d'un bot Viber en 2026?

Depuis le 5 février 2024, la création d'un nouveau bot coûte 100 € par mois via les partenaires officiels Rakuten Viber. Les bots créés avant cette date continuent sous les anciennes conditions. Le coût inclut un compte dédié avec un panneau d'administration, des analyses et l'accès à tous les types de messages, y compris rich_media et Viber Pay. La partie technique de l'API est identique pour les bots commerciaux et les anciens bots gratuits.

Le bot est prêt: la suite

Un menu clavier n'est qu'un point d'entrée. Une fois les mécanismes de base opérationnels, ajoutez des carrousels de contenu via rich_media, des paiements via Viber Pay et une segmentation des utilisateurs basée sur les boutons sur lesquels ils appuient le plus souvent. Chaque nouveau niveau ne change pas la base: vous lisez toujours event et vous envoyez toujours send_message avec l'en-tête X-Viber-Auth-Token.

Si vous avez besoin d'un exemple concret de code fonctionnel, consultez le dépôt viber-bot-php sur GitHub. Il couvre tous les événements, la signature des requêtes et la construction d'un clavier avec des images. Et pour un démarrage visuel, voici un tutoriel d'une demi-heure sur la création d'un bot Viber à partir de zéro:

La principale chose à retenir: l'API Viber Bot est simple au départ, mais exigeante sur les détails. Un en-tête d'authentification correct, un SSL de confiance, un JSON valide de moins de 30 Ko et un routage clair des ActionBody suffisent pour que le bot fonctionne sans échec. Prenez les extraits ci-dessus, substituez votre token et votre domaine, et lancez votre premier menu dès aujourd'hui.