Skip to content

Alt om WordPress, webutvikling — og mer til

🤖 Viber chatbot i PHP: sende strukturerte meldinger med tastaturmenyer

🤖 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_webhook med X-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 å kalle send_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.

Searching for a public account in Viber

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.

Viber public chat screen after subscribing

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:

Keyboard menu with buttons in a Viber chat

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');
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}

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
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}

Hendelsesoversikt:

  • webhook kommer é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.
  • subscribed betyr at en bruker har abonnert på boten. Dette er det ideelle tidspunktet for å sende en velkomstmeny.
  • conversation_started betyr at en bruker åpnet chatten (for første gang eller på nytt). Også egnet for å vise hovedmenyen.
  • message er den viktigste arbeidshendelsen. Feltet text inneholder enten en vilkårlig brukermelding eller ActionBody fra en trykket knapp (hvis typen er reply). 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
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}

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

Columns

1-6

Knappebredde i betingede kolonner

Rows

1-2

Knappehøyde i rader

ActionType

reply eller open-url

reply returnerer tekst til boten, open-url åpner nettleseren

ActionBody

streng

For reply teksten boten vil motta; for open-url URL-en

Text

streng

Etikett på knappen, støtter HTML-taggene b, i og font color

BgColor

HEX

Knappens bakgrunnsfarge

Image

URL

Bilde øverst på knappen, JPEG, valgfritt

Steg 4: Send data via send_message

En senderfunksjon som du kaller fra hendelsesbehandleren:

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}

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
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}

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.

Rich message with images and links in Viber

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_webhook med body {"url":"https://your-domain/webhook.php","event_types":[...]} og header X-Viber-Auth-Token.
  • Sjekk responsen: {"status":0} betyr suksess. Viber sender umiddelbart et webhook-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, kall getMainMenu() og send resultatet til sendToViber().

⁉️🤔 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ør certbot --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?

reply sender ActionBody tilbake til webhooken som meldingstekst. PHP-skriptet ser den i $input['message']['text'] og ruter den via match(). 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 i send_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) og url (forhåndsvisning av lenke). For den oppdaterte listen med obligatoriske felter, se dokumentasjonen på Viber Developers Hub. Det vanligste scenarioet er text + keyboard for menyer og picture for 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_webhook inneholdt ikke "status":0, webhooken ble ikke satt, og boten mottar ikke meldinger. For det tredje: du bruker det gamle formatet med auth_token i JSON-bodyen. Siden API 7.0 ignoreres dette; du trenger X-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.