
🤖 Chatbot Viber in PHP: invio messaggi strutturati con menu a tastiera
L'utente preme un pulsante nella chat e riceve non del semplice testo, ma una griglia di immagini, link e tasti colorati. Sembra un'app nativa. In realtà, è semplice JSON che il tuo script PHP restituisce tramite le REST API di Viber.
Il problema della maggior parte dei tutorial: insegnano a rispondere con testo a del testo. Un bot aziendale reale deve mostrare un menu a tastiera con pulsanti link, immagini e caroselli. Altrimenti l'utente semplicemente non capirà cosa può fare il bot e se ne andrà. Da febbraio 2024, Viber ha messo la creazione di bot su base commerciale (100 € al mese tramite i partner ufficiali Rakuten Viber) e l'autenticazione ora passa nell'header HTTP X-Viber-Auth-Token anziché nel corpo della richiesta. Gli snippet con auth_token dentro il JSON non funzionano più.
Ecco un bot Viber funzionante in PHP da zero: dalla configurazione del webhook all'invio di un menu a tastiera strutturato con pulsanti di risposta e di apertura URL. Il codice è aggiornato per la versione API 7.3.
💡 Panoramica rapida:
- Registra un bot commerciale tramite un partner Viber e ottieni un token di autenticazione
- Configura il webhook via
set_webhookcon l'headerX-Viber-Auth-Token - Ricevi gli eventi di callback da Viber: webhook → subscribed → message
- Costruisci un menu a tastiera (una griglia di pulsanti con colori, dimensioni e azioni personalizzate)
- Invia una risposta strutturata: testo, immagini, link, caroselli via
send_message
Come funzionano le API di Viber Bot
Le API di Viber Bot operano su un modello REST: il tuo server riceve richieste di callback sul webhook e risponde chiamando https://chatapi.viber.com/pa/send_message. Ogni richiesta è autenticata con un token nell'header X-Viber-Auth-Token.
Il ciclo di base si presenta così:
- Registri un bot tramite un partner Viber e ricevi un token nel pannello "Edit Info".
- Configuri un webhook (l'URL del tuo server con un SSL valido; Let's Encrypt funziona poiché è nella lista di certificati Java fidati di Viber; i certificati autofirmati non sono accettati).
- Viber invia richieste POST a questo URL a ogni evento: un utente si è iscritto, ha inviato un messaggio, ha premuto un pulsante.
- Il tuo script PHP legge il JSON in arrivo, analizza il campo
evente risponde chiamandosend_message.
Il primo passo per capire è osservare un bot dal vivo. Apri Viber e cerca l'account pubblico di un qualsiasi marchio noto. Quasi tutti hanno un chatbot con un menu. Lo screenshot qui sotto mostra un tipico risultato di ricerca di un account pubblico.

Dopo l'iscrizione entri in una chat one-to-one. Appare più o meno così: un avatar, un messaggio di benvenuto e un pulsante per avviare la conversazione.

Tocca l'icona del messaggio nell'angolo in alto a destra e invia "Ciao". Se il bot è configurato con un menu a tastiera, vedrai una risposta con una griglia di pulsanti:

Questo è un messaggio strutturato. Ci sono due tipi di pulsanti: reply invia testo al bot (premendo "News" o "Articoli"), mentre open-url apre un link nel browser. Ora scriviamo il codice che produce tutto questo.
Passo 1: Ottenere il token e configurare il webhook
Il token si trova nel pannello di amministrazione Viber: sezione Edit Info → campo App Key. È una stringa di lettere e numeri che includi in ogni richiesta API.
Il webhook si imposta con una singola richiesta POST a https://chatapi.viber.com/pa/set_webhook. Il corpo della richiesta è JSON con l'URL del tuo gestore e un elenco di eventi a cui ti iscrivi. L'header è X-Viber-Auth-Token con il tuo token.
Script di configurazione del webhook (salva come setup.php ed esegui una volta sola):
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'); 10 curl_setopt($ch, CURLOPT_POST, 1); 11 curl_setopt($ch, CURLOPT_POSTFIELDS, $data); 12 curl_setopt($ch, CURLOPT_HTTPHEADER, [ 13 'Content-Type: application/json', 14 'X-Viber-Auth-Token: ' . $token, 15 ]); 16 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 17 18 $result = curl_exec($ch); 19 $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); 20 curl_close($ch); 21 22 echo "HTTP {$httpCode}: {$result}\n"; 23 24 if ($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 }
Cosa succede qui: cURL invia una POST a set_webhook. Il token è rigorosamente nell'header, non nel corpo. Viber restituisce {"status":0} in caso di successo e invia immediatamente un callback webhook all'URL specificato per verificarne la disponibilità. Rispondere con {"status":0,"status_message":"ok"} a questo callback è obbligatorio (lo tratteremo nel prossimo passo).
Se ricevi invalidUrl, controlla il tuo certificato SSL. Let's Encrypt funziona; gli autofirmati no. Sul tuo server è sufficiente eseguire certbot --nginx -d your-domain.com e impostare il rinnovo automatico via cron.
Passo 2: Ricevere gli eventi di callback da Viber
Quando un utente interagisce con il bot, Viber invia una richiesta POST con JSON al tuo webhook. Il tuo compito è leggere il campo event e reagire.
Un gestore minimo webhook.php che risponde correttamente a tutti gli eventi:
1 <?php 2 $request = file_get_contents("php://input"); 3 $input = json_decode($request, true); 4 5 if ($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 15 if ($input['event'] === 'subscribed') { 16 $sender_id = $input['sender']['id']; 17 sendWelcomeMessage($sender_id); 18 } 19 20 if ($input['event'] === 'conversation_started') { 21 $sender_id = $input['sender']['id']; 22 sendMainMenu($sender_id); 23 } 24 25 if ($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 }
Dettaglio eventi:
webhookarriva una volta sola, quando il webhook viene impostato. Devi restituire{"status":0,"status_message":"ok"}con la lista degli eventi supportati. Senza questo passaggio, Viber non confermerà l'URL e il bot non partirà.subscribedindica che un utente si è iscritto al bot. È il momento ideale per inviare un menu di benvenuto.conversation_startedindica che un utente ha aperto la chat (per la prima volta o di nuovo). Adatto anche per mostrare il menu principale.messageè l'evento di lavoro principale. Il campotextcontiene un messaggio libero dell'utente oppure l'ActionBodydi un pulsante premuto (se il suo tipo èreply). È così che il bot capisce cosa è stato selezionato: "News", "Articoli" o "Galleria".
Il costrutto match() è disponibile da PHP 8. Se hai PHP 7.4, sostituiscilo con switch.
Step 3: Costruisci il menu a tastiera
Una tastiera si allega a qualsiasi messaggio tramite il campo keyboard nell'oggetto JSON send_message. È un array di pulsanti con impostazioni separate per larghezza (Columns, 1-6), altezza (Rows, 1-2), colore di sfondo, testo e azione.
Una funzione che assembla un menu principale da sette pulsanti di tipo reply e uno di tipo link:
1 <?php 2 3 function 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 }
I pulsanti con Columns=2 e Rows=2 sono quadrati, tre per riga (2+2+2=6). Il pulsante link con Columns=4 occupa una riga a sé. La griglia viene composta da sinistra a destra, dall'alto in basso. La somma dei Columns in una riga determina il layout.
Parametri dei pulsanti:
Parametro | Valori | Scopo |
|---|---|---|
| 1-6 | Larghezza del pulsante in colonne condizionali |
| 1-2 | Altezza del pulsante in righe |
|
|
|
| stringa | Per |
| stringa | Etichetta sul pulsante, supporta i tag HTML b, i e font color |
| HEX | Colore di sfondo del pulsante |
| URL | Immagine sopra il pulsante, JPEG, opzionale |
Step 4: Invia dati tramite send_message
Una funzione di invio che richiami dal gestore degli eventi:
1 <?php 2 3 function 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 differenza chiave rispetto ai vecchi tutorial: il token va nell'header, non nel corpo JSON. Il corpo contiene solo i campi receiver, type, text, keyboard e, opzionalmente, sender.name, sender.avatar, tracking_data. La dimensione massima del JSON è 30 KB. Se la superi, Viber scarta il messaggio senza alcun avviso; controlla strlen(json_encode($data)) prima di inviare.
Step 5: Assembla i contenuti per i pulsanti
Quando un utente preme un pulsante di tipo reply, il suo ActionBody viene inviato al webhook come testo del messaggio. Lo analizzi nel match() e chiami la funzione appropriata. Ecco un esempio per una lista di notizie con immagini:
1 <?php 2 3 function 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 }
Dal lato utente questo appare come una griglia di card: immagine a sinistra, titolo a destra. Toccando qualsiasi parte si apre il link nel browser.

Una galleria, una lista di articoli o un sondaggio si assemblano esattamente allo stesso modo; cambiano solo i contenuti dell'array $buttons e il testo del messaggio. Se i contenuti sono molti e il JSON si avvicina ai 30 KB, dividili in pagine con un pulsante "Avanti".
Se preferisci lavorare con una libreria PHP già pronta invece che con l'API nativa, dai un'occhiata a viber-bot-php di Bogdaan. Gestisce per te la validazione della firma, l'instradamento degli eventi e la generazione del JSON.
Riepilogo: sequenza completa di lancio
- Ottieni il token nel Pannello di Amministrazione Viber: sezione Modifica Info → App Key.
- Distribuisci il gestore su un server con HTTPS. Let's Encrypt funziona; un certificato autofirmato no. Viber convalida i certificati rispetto all'elenco delle Root CA Java attendibili.
- Imposta il webhook con una richiesta POST a
https://chatapi.viber.com/pa/set_webhookcon body{"url":"https://your-domain/webhook.php","event_types":[...]}e headerX-Viber-Auth-Token. - Controlla la risposta:
{"status":0}significa successo. Viber invierà immediatamente un callbackwebhookal tuo URL. Assicurati che lo script restituisca{"status":0,"status_message":"ok"}. - Invia il primo menu: sull'evento
conversation_startedchiamagetMainMenu()e passa il risultato asendToViber().
⁉️🤔 Domande frequenti
Posso usare un certificato SSL autofirmato per il webhook?
No. Viber convalida il certificato rispetto all'elenco delle autorità di certificazione root Java attendibili. Un certificato autofirmato causa un errore
invalidUrldurante l'impostazione del webhook. Let's Encrypt è in questo elenco ed è gratuito. Sul tuo server, eseguicertbot --nginx -d your-domain.com, aggiungi il rinnovo automatico a cron e Viber accetterà il certificato senza problemi.
Qual è la differenza tra reply e open-url in ActionType?
replyinviaActionBodyal webhook come testo del messaggio. Lo script PHP lo vede in$input['message']['text']e lo instrada tramitematch(). Usalo per la navigazione all'interno del bot.open-urlapre un link in un browser esterno e non attiva il webhook. In pratica, i menu combinano entrambi i tipi: cinque o sei pulsanti reply per le sezioni e un ampio pulsante open-url per andare al sito web.
Quali tipi di messaggio supporta l'API Viber Bot?
L'API Viber Bot supporta nove valori
typeinsend_message:text(testo semplice),picture(immagine JPEG),video(file video),file(qualsiasi file fino a 50 MB),location(punto geografico),contact(scheda contatto),sticker(adesivo),rich_media(carosello di card) eurl(anteprima link). Per l'elenco aggiornato con i campi obbligatori, consulta la documentazione del Viber Developers Hub. Lo scenario più comune ètext+keyboardper i menu epictureper inviare immagini. I caroselli sono ottimi per vetrine e cataloghi ma richiedono più codice.
Cosa devo fare se l'utente non vede la tastiera?
Ci sono tre cause comuni. Prima: il JSON con la tastiera ha superato i 30 KB e Viber scarta silenziosamente questi messaggi. Controlla
strlen(json_encode($data))prima di inviare. Seconda: la risposta aset_webhooknon conteneva"status":0, il webhook non è stato impostato e il bot non riceve messaggi. Terza: stai usando il vecchio formato conauth_tokennel body JSON. Dalla API 7.0 questo viene ignorato; serve l'headerX-Viber-Auth-Token. Per il debug, abilita il logging della risposta dell'API Viber: restituisce JSON leggibile con codici di errore invalidAuthToken, badData o missingData.
Posso cambiare la tastiera dopo averla inviata?
Sì. Con ogni nuovo messaggio puoi inviare una tastiera diversa. Il client Viber mostra sempre l'ultima ricevuta. Questo ti permette di costruire menu multilivello: menu principale → sottomenu di sezione → contenuto specifico. Ogni livello ha il proprio set di pulsanti e l'utente si sposta tra di essi premendo i tasti reply.
Quanto costa lanciare un bot Viber nel 2026?
Dal 5 febbraio 2024, creare un nuovo bot costa 100 € al mese tramite i partner ufficiali Rakuten Viber. I bot creati prima di tale data continuano con le vecchie condizioni. Il costo include un account dedicato con pannello di amministrazione, analytics e accesso a tutti i tipi di messaggio, inclusi rich_media e Viber Pay. La parte tecnica dell'API è identica per i bot commerciali e quelli gratuiti legacy.
Il bot è pronto: cosa fare dopo
Un menu a tastiera è solo un punto di ingresso. Una volta che la meccanica di base funziona, aggiungi caroselli di contenuti tramite rich_media, pagamenti tramite Viber Pay e segmentazione degli utenti in base ai pulsanti che premono più spesso. Ogni nuovo livello non cambia le fondamenta: leggi ancora event e invii ancora send_message con l'header X-Viber-Auth-Token.
Se ti serve un esempio reale di codice funzionante, dai un'occhiata al repository viber-bot-php su GitHub. Copre tutti gli eventi, la firma delle richieste e la costruzione di una tastiera con immagini. E per un avvio visivo, ecco un tutorial di mezz'ora su come creare un bot Viber da zero:
La cosa principale da ricordare: l'API Viber Bot è semplice all'inizio ma esigente sui dettagli. Un header di autenticazione corretto, SSL attendibile, JSON valido sotto i 30 KB e un instradamento chiaro di ActionBody sono sufficienti per mantenere il bot in funzione senza guasti. Prendi gli snippet qui sopra, sostituisci il tuo token e il dominio e lancia il tuo primo menu oggi stesso.



