
🤖 Viber chatbot i PHP: sende strukturerte meldinger med tastaturmenyer
Brukeren trykker på en knapp i chatten og mottar ikke ren tekst, men et rutenett med bilder, lenker og fargede taster. Det ser ut som en innebygd app. I virkeligheten er det vanlig JSON som PHP-skriptet ditt returnerer via Viber REST API.
Problemet med de fleste veiledninger: de lærer deg å svare med tekst på tekst. En bot for reell forretningsdrift må vise en tastaturmeny med lenkeknapper, bilder og karuseller. Ellers vil brukeren rett og slett ikke forstå hva boten kan gjøre, og vil forlate samtalen. Siden februar 2024 har Viber satt bot-opprettelse på kommersiell basis (100 € per måned gjennom offisielle Rakuten Viber-partnere), og autentisering går nå i HTTP-headeren X-Viber-Auth-Token i stedet for i forespørselsinnholdet. Kodebiter med auth_token inne i JSON fungerer ikke lenger.
Her er en fungerende Viber-bot i PHP fra bunnen av: fra oppsett av webhook til sending av en strukturert tastaturmeny med svar- og åpne-url-knapper. Koden er oppdatert for API versjon 7.3.
💡 Rask oversikt:
- Registrer en kommersiell bot gjennom en Viber-partner og få et autentiseringstoken
- Konfigurer webhooken via
set_webhookmedX-Viber-Auth-Token-headeren - Motta tilbakeringingshendelser fra Viber: webhook → subscribed → message
- Bygg en tastaturmeny (et knapperutenett med egendefinerte farger, størrelser og handlinger)
- Send et strukturert svar: tekst, bilder, lenker, karuseller via
send_message
Slik fungerer Viber Bot API
Viber Bot API opererer etter en REST-modell: serveren din mottar tilbakeringingsforespørsler på webhooken og svarer ved å kalle https://chatapi.viber.com/pa/send_message. Hver forespørsel autentiseres med et token i X-Viber-Auth-Token-headeren.
Den grunnleggende syklusen ser slik ut:
- Du registrerer en bot gjennom en Viber-partner og mottar et token i «Rediger info»-panelet.
- Du konfigurerer en webhook (URL-en til serveren din med gyldig SSL; Let's Encrypt fungerer siden det er i Vibers klarerte Java-sertifikatliste; selvsignerte sertifikater godtas ikke).
- Viber sender POST-forespørsler til denne URL-en ved hver hendelse: en bruker abonnerte, sendte en melding, trykket på en knapp.
- PHP-skriptet ditt leser den innkommende JSON-en, analyserer
event-feltet og svarer ved å kallesend_message.
Det første steget for å forstå er å se på en live bot. Åpne Viber og søk etter en offentlig konto for et hvilket som helst kjent merke. Nesten alle har en chatbot med en meny. Skjermbildet nedenfor viser et typisk søkeresultat for en offentlig konto.

Etter at du abonnerer, går du inn i en en-til-en-chat. Det ser omtrent slik ut: en avatar, en velkomstmelding og en knapp for å starte samtalen.

Trykk på meldingsikonet øverst til høyre og send «Hallo». Hvis boten er konfigurert med en tastaturmeny, vil du se et svar med et knapperutenett:

Dette er en strukturert melding. Det finnes to knappetyper: reply sender tekst tilbake til boten (ved å trykke på «Nyheter» eller «Artikler»), mens open-url åpner en lenke i nettleseren. La oss nå skrive koden som produserer dette.
Steg 1: Få tokenet og konfigurer webhooken
Tokenet ligger i Viber-administrasjonspanelet: Rediger info-delen → App Key-feltet. Det er en streng med bokstaver og tall som du inkluderer i hver API-forespørsel.
Webhooken settes med en enkelt POST-forespørsel til https://chatapi.viber.com/pa/set_webhook. Forespørselsinnholdet er JSON med URL-en til behandleren din og en liste over hendelser du abonnerer på. Headeren er X-Viber-Auth-Token med tokenet ditt.
Webhook-oppsettskript (lagre som setup.php og kjør én gang):
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 }
Det som skjer her: cURL sender en POST til set_webhook. Tokenet er strengt tatt i headeren, ikke i innholdet. Viber returnerer {"status":0} ved suksess og sender umiddelbart et webhook-tilbakeringing til den angitte URL-en for å bekrefte tilgjengeligheten. Å svare med {"status":0,"status_message":"ok"} på denne tilbakeringingen er obligatorisk (vi dekker dette i neste steg).
Hvis du mottar invalidUrl, sjekk SSL-sertifikatet ditt. Let's Encrypt fungerer; selvsignert gjør det ikke. På serveren din er det nok å kjøre certbot --nginx -d your-domain.com og sette opp automatisk fornyelse via cron.
Steg 2: Motta tilbakeringingshendelser fra Viber
Når en bruker samhandler med boten, sender Viber en POST-forespørsel med JSON til webhooken din. Din oppgave er å lese event-feltet og reagere.
En minimal behandler webhook.php som svarer korrekt på alle hendelser:
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 }
Hendelsesoversikt:
webhookkommer én gang når webhooken settes opp. Du må returnere{"status":0,"status_message":"ok"}med en liste over støttede hendelser. Uten dette vil ikke Viber bekrefte URL-en, og boten starter ikke.subscribedbetyr at en bruker har abonnert på boten. Dette er det ideelle tidspunktet for å sende en velkomstmeny.conversation_startedbetyr at en bruker åpnet chatten (for første gang eller på nytt). Også egnet for å vise hovedmenyen.messageer den viktigste arbeidshendelsen. Feltettextinneholder enten en vilkårlig brukermelding ellerActionBodyfra en trykket knapp (hvis typen erreply). Slik forstår boten hva som ble valgt: «Nyheter», «Artikler» eller «Galleri».
Konstruksjonen match() er tilgjengelig fra PHP 8. Hvis du har PHP 7.4, erstatt den med switch.
Steg 3: Bygg tastaturmenyen
Et tastatur legges ved enhver melding via feltet keyboard i JSON-objektet send_message. Det er en matrise med knapper med separate innstillinger for bredde (Columns, 1-6), høyde (Rows, 1-2), bakgrunnsfarge, tekst og handling.
En funksjon som setter sammen en hovedmeny av sju svar-knapper og én lenkeknapp:
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 }
Knapper med Columns=2 og Rows=2 er kvadratiske, tre per rad (2+2+2=6). Lenkeknappen med Columns=4 opptar sin egen rad. Rutenettet settes sammen fra venstre mot høyre, ovenfra og ned. Summen av Columns i en rad bestemmer layouten.
Knappeparametere:
Parameter | Verdier | Formål |
|---|---|---|
| 1-6 | Knappebredde i betingede kolonner |
| 1-2 | Knappehøyde i rader |
|
|
|
| streng | For |
| streng | Etikett på knappen, støtter HTML-taggene b, i og font color |
| HEX | Knappens bakgrunnsfarge |
| URL | Bilde øverst på knappen, JPEG, valgfritt |
Steg 4: Send data via send_message
En senderfunksjon som du kaller fra hendelsesbehandleren:
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 }
Den viktigste forskjellen fra gamle veiledninger: tokenet ligger i headeren, ikke i JSON-brødteksten. Brødteksten inneholder kun feltene receiver, type, text, keyboard og eventuelt sender.name, sender.avatar, tracking_data. Maksimal JSON-størrelse er 30 KB. Overskrider du den, forkaster Viber meldingen uten varsel; sjekk strlen(json_encode($data)) før du sender.
Steg 5: Sett sammen innhold for knapper
Når en bruker trykker på en svar-knapp, sendes dens ActionBody til webhooken som meldingstekst. Du analyserer den i match() og kaller den aktuelle funksjonen. Her er et eksempel for en nyhetsliste med bilder:
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 }
På brukerens side ser dette ut som et rutenett av kort: bilde til venstre, tittel til høyre. Ved å trykke hvor som helst åpnes lenken i nettleseren.

Et galleri, en artikkelliste eller avstemninger settes sammen på nøyaktig samme måte; bare innholdet i $buttons-matrisen og meldingsteksten endres. Hvis det er mye innhold og JSON-en nærmer seg 30 KB, del det opp i sider med en «Neste»-knapp.
Hvis du foretrekker å jobbe med et ferdig PHP-bibliotek i stedet for det rå API-et, kan du sjekke ut viber-bot-php av Bogdaan. Det håndterer signaturvalidering, hendelsesruting og JSON-generering for deg.
Oppsummering: full lanseringssekvens
- Hent tokenet i Viber Admin Panel: Rediger info-delen → App-nøkkel.
- Distribuer handleren til en server med HTTPS. Let's Encrypt fungerer; et selvsignert sertifikat gjør det ikke. Viber validerer sertifikater mot den klarerte Java Root CA-listen.
- Sett webhooken med en POST-forespørsel til
https://chatapi.viber.com/pa/set_webhookmed body{"url":"https://your-domain/webhook.php","event_types":[...]}og headerX-Viber-Auth-Token. - Sjekk responsen:
{"status":0}betyr suksess. Viber sender umiddelbart etwebhook-callback til URL-en din. Sørg for at skriptet returnerer{"status":0,"status_message":"ok"}. - Send den første menyen: ved
conversation_started-hendelsen, kallgetMainMenu()og send resultatet tilsendToViber().
⁉️🤔 Ofte stilte spørsmål
Kan jeg bruke et selvsignert SSL-sertifikat for webhooken?
Nei. Viber validerer sertifikatet mot listen over klarerte Java-rotsertifikatutstedere. Et selvsignert sertifikat forårsaker en
invalidUrl-feil når du setter webhooken. Let's Encrypt er på denne listen og er gratis. På serveren din, kjørcertbot --nginx -d your-domain.com, legg til automatisk fornyelse i cron, så vil Viber godta sertifikatet uten problemer.
Hva er forskjellen på reply og open-url i ActionType?
replysenderActionBodytilbake til webhooken som meldingstekst. PHP-skriptet ser den i$input['message']['text']og ruter den viamatch(). Bruk dette for navigering inne i boten.open-urlåpner en lenke i en ekstern nettleser og utløser ikke webhooken. I praksis kombinerer menyer begge typene: fem eller seks reply-knapper for seksjoner og én bred open-url-knapp for å navigere til nettstedet.
Hvilke meldingstyper støtter Viber Bot API?
Viber Bot API støtter ni
type-verdier isend_message:text(ren tekst),picture(JPEG-bilde),video(videofil),file(enhver fil opptil 50 MB),location(geografisk punkt),contact(kontaktkort),sticker(klistremerke),rich_media(kortkarusell) ogurl(forhåndsvisning av lenke). For den oppdaterte listen med obligatoriske felter, se dokumentasjonen på Viber Developers Hub. Det vanligste scenarioet ertext+keyboardfor menyer ogpicturefor sending av bilder. Karuseller er flotte for butikkfronter og kataloger, men krever mer kode.
Hva bør jeg gjøre hvis brukeren ikke ser tastaturet?
Det er tre vanlige årsaker. For det første: JSON-en med tastaturet oversteg 30 KB, og Viber forkaster slike meldinger uten varsel. Sjekk
strlen(json_encode($data))før sending. For det andre: responsen påset_webhookinneholdt ikke"status":0, webhooken ble ikke satt, og boten mottar ikke meldinger. For det tredje: du bruker det gamle formatet medauth_tokeni JSON-bodyen. Siden API 7.0 ignoreres dette; du trengerX-Viber-Auth-Token-headeren. For feilsøking, aktiver logging av Viber API-responsen: den returnerer lesbar JSON med feilkodene invalidAuthToken, badData eller missingData.
Kan jeg endre tastaturet etter at det er sendt?
Ja. Med hver nye melding kan du sende et annet tastatur. Viber-klienten viser alltid det sist mottatte. Dette lar deg bygge menyer på flere nivåer: hovedmeny → seksjonsundermeny → spesifikt innhold. Hvert nivå har sitt eget sett med knapper, og brukeren beveger seg mellom dem ved å trykke på reply-taster.
Hvor mye koster det å lansere en Viber-bot i 2026?
Siden 5. februar 2024 koster det 100 € per måned å opprette en ny bot gjennom offisielle Rakuten Viber-partnere. Boter opprettet før den datoen fortsetter under de gamle vilkårene. Kostnaden inkluderer en dedikert konto med adminpanel, analyse og tilgang til alle meldingstyper, inkludert rich_media og Viber Pay. Den tekniske delen av API-et er identisk for kommersielle og eldre gratisboter.
Boten er klar: hva skjer videre
Et tastaturmeny er bare et inngangspunkt. Når den grunnleggende mekanikken fungerer, kan du legge til innholdskaruseller via rich_media, betalinger via Viber Pay og brukersegmentering basert på hvilke knapper de trykker oftest på. Hvert nye nivå endrer ikke fundamentet: du leser fortsatt event og sender fortsatt send_message med X-Viber-Auth-Token-headeren.
Hvis du trenger et levende eksempel på fungerende kode, sjekk ut viber-bot-php-repositoriet på GitHub. Det dekker alle hendelser, forespørselsignering og bygging av et tastatur med bilder. Og for en visuell start, her er en halvtimes veiledning i å lage en Viber-bot fra bunnen av:
Det viktigste å huske: Viber Bot API er enkelt i starten, men krevende når det gjelder detaljer. En korrekt autentiseringsheader, klarert SSL, gyldig JSON under 30 KB og tydelig ActionBody-ruting er nok til å holde boten i gang uten feil. Ta kodebitene ovenfor, bytt ut tokenet og domenet ditt, og lanser din første meny i dag.



