Skip to content

Allt om WordPress, webbutveckling — och mer därtill

🤖 Viber chatbot i PHP: skicka strukturerade meddelanden med tangentbordsmenyer

🤖 Viber chatbot i PHP: skicka strukturerade meddelanden med tangentbordsmenyer

Användaren trycker på en knapp i chatten och får inte bara text tillbaka utan ett rutnät av bilder, länkar och färgade knappar. Det ser ut som en inbyggd app. I verkligheten är det vanlig JSON som ditt PHP-skript returnerar via Viber REST API.

Problemet med de flesta guider: de lär dig att svara med text på text. En riktig företagsbot måste visa en tangentbordsmeny med länkknappar, bilder och karuseller. Annars förstår användaren helt enkelt inte vad boten kan göra och lämnar. Sedan februari 2024 har Viber lagt botskapande på kommersiell basis (100 € per månad via officiella Rakuten Viber-partners), och autentisering sker nu i HTTP-headern X-Viber-Auth-Token istället för i request body. Kodsnuttar med auth_token inuti JSON fungerar inte längre.

Här är en fungerande Viber-bot i PHP från grunden: från att sätta upp webhooken till att skicka en strukturerad tangentbordsmeny med svars- och öppna-url-knappar. Koden är aktuell för API version 7.3.

💡 Snabb översikt:

  • Registrera en kommersiell bot via en Viber-partner och få en autentiseringstoken
  • Konfigurera webhooken via set_webhook med headern X-Viber-Auth-Token
  • Ta emot callback-händelser från Viber: webhook → subscribed → message
  • Bygg en tangentbordsmeny (ett knapprutnät med anpassade färger, storlekar och åtgärder)
  • Skicka ett strukturerat svar: text, bilder, länkar, karuseller via send_message

Hur Viber Bot API fungerar

Viber Bot API fungerar enligt en REST-modell: din server tar emot callback-förfrågningar på webhooken och svarar genom att anropa https://chatapi.viber.com/pa/send_message. Varje förfrågan autentiseras med en token i headern X-Viber-Auth-Token.

Den grundläggande cykeln ser ut så här:

  • Du registrerar en bot via en Viber-partner och får en token i panelen "Edit Info".
  • Du konfigurerar en webhook (URL:en till din server med giltig SSL; Let's Encrypt fungerar eftersom det finns med i Vibers betrodda Java-certifikatlista; självsignerade certifikat accepteras inte).
  • Viber skickar POST-förfrågningar till denna URL vid varje händelse: en användare prenumererade, skickade ett meddelande, tryckte på en knapp.
  • Ditt PHP-skript läser inkommande JSON, tolkar fältet event och svarar genom att anropa send_message.

Första steget för att förstå är att titta på en live-bot. Öppna Viber och sök efter ett publikt konto för ett välkänt varumärke. Nästan alla har en chatbot med en meny. Skärmdumpen nedan visar ett typiskt sökresultat för publika konton.

Söker efter ett offentligt konto i Viber

Efter att du prenumererat hamnar du i en en-till-en-chatt. Det ser ut ungefär så här: en avatar, ett välkomstmeddelande och en knapp för att starta konversationen.

Vibers skärm för offentlig chatt efter prenumeration

Tryck på meddelandeikonen i det övre högra hörnet och skicka "Hej". Om boten är konfigurerad med en tangentbordsmeny ser du ett svar med ett knapprutnät:

Tangentbordsmeny med knappar i en Viber-chatt

Detta är ett strukturerat meddelande. Det finns två knapptyper: reply skickar text tillbaka till boten (när man trycker på "Nyheter" eller "Artiklar"), medan open-url öppnar en länk i webbläsaren. Låt oss nu skriva koden som producerar detta.

Steg 1: Skaffa token och konfigurera webhooken

Token finns i Vibers adminpanel: sektionen Edit Info → fältet App Key. Det är en sträng av bokstäver och siffror som du inkluderar i varje API-förfrågan.

Webhooken sätts med en enda POST-förfrågan till https://chatapi.viber.com/pa/set_webhook. Request body är JSON med URL:en till din hanterare och en lista över händelser du prenumererar på. Headern är X-Viber-Auth-Token med din token.

Webhook-installationsskript (spara som setup.php och kör en gång):

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}

Vad som händer här: cURL skickar en POST till set_webhook. Token ligger strikt i headern, inte i body. Viber returnerar {"status":0} vid framgång och skickar omedelbart en webhook-callback till den angivna URL:en för att verifiera dess tillgänglighet. Att svara med {"status":0,"status_message":"ok"} på denna callback är obligatoriskt (vi täcker detta i nästa steg).

Om du får invalidUrl, kontrollera ditt SSL-certifikat. Let's Encrypt fungerar; självsignerat gör det inte. På din server räcker det att köra certbot --nginx -d your-domain.com och sätta upp automatisk förnyelse via cron.

Steg 2: Ta emot callback-händelser från Viber

När en användare interagerar med boten skickar Viber en POST-förfrågan med JSON till din webhook. Din uppgift är att läsa fältet event och reagera.

En minimal hanterare webhook.php som svarar korrekt på alla händelser:

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}

Händelseuppdelning:

  • webhook kommer en gång när webhooken sätts upp. Du måste returnera {"status":0,"status_message":"ok"} med en lista över händelser som stöds. Utan detta kommer Viber inte att bekräfta webbadressen och boten startar inte.
  • subscribed betyder att en användare har prenumererat på boten. Detta är det perfekta tillfället att skicka en välkomstmeny.
  • conversation_started betyder att en användare öppnade chatten (för första gången eller igen). Passar också för att visa huvudmenyn.
  • message är den huvudsakliga arbetshändelsen. Fältet text innehåller antingen ett godtyckligt användarmeddelande eller ActionBody från en tryckt knapp (om dess typ är reply). Det är så boten förstår vad som valdes: "Nyheter", "Artiklar" eller "Galleri".

Konstruktionen match() är tillgänglig från PHP 8. Om du har PHP 7.4, ersätt den med switch.

Steg 3: Bygg tangentbordsmenyn

Ett tangentbord bifogas till alla meddelanden via fältet keyboard i JSON-objektet send_message. Det är en array av knappar med separata inställningar för bredd (Columns, 1-6), höjd (Rows, 1-2), bakgrundsfärg, text och åtgärd.

En funktion som sätter ihop en huvudmeny av sju svarsknappar och en länkknapp:

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}

Knappar med Columns=2 och Rows=2 är kvadratiska, tre per rad (2+2+2=6). Länkknappen med Columns=4 upptar en egen rad. Rutnätet byggs upp från vänster till höger, uppifrån och ned. Summan av Columns på en rad bestämmer layouten.

Knappparametrar:

Parameter

Värden

Syfte

Columns

1-6

Knappbredd i villkorliga kolumner

Rows

1-2

Knapphöjd i rader

ActionType

reply eller open-url

reply returnerar text till boten, open-url öppnar webbläsaren

ActionBody

sträng

För reply texten som boten får tillbaka; för open-url webbadressen

Text

sträng

Etikett på knappen, stöder HTML-taggarna b, i och font color

BgColor

HEX

Knappens bakgrundsfärg

Image

URL

Bild ovanpå knappen, JPEG, valfritt

Steg 4: Skicka data via send_message

En sändarfunktion som du anropar från händelsehanteraren:

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 viktigaste skillnaden mot gamla handledningar: token ligger i headern, inte i JSON-body:n. Bodyn innehåller endast fälten receiver, type, text, keyboard och eventuellt sender.name, sender.avatar, tracking_data. Maximal JSON-storlek är 30 kB. Om du överskrider den kastar Viber meddelandet utan förvarning; kontrollera strlen(json_encode($data)) innan du skickar.

Steg 5: Sätt ihop innehåll för knappar

När en användare trycker på en svarsknapp skickas dess ActionBody till webhooken som meddelandetext. Du tolkar den i match() och anropar lämplig funktion. Här är ett exempel för en nyhetslista 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å användarens sida ser detta ut som ett rutnät av kort: bild till vänster, rubrik till höger. Ett tryck var som helst öppnar länken i webbläsaren.

Rich message med bilder och länkar i Viber

Ett galleri, en artikellista eller omröstningar sätts ihop på exakt samma sätt; endast innehållet i arrayen $buttons och meddelandetexten ändras. Om det finns mycket innehåll och JSON:en närmar sig 30 kB, dela upp det i sidor med en "Nästa"-knapp.

Om du föredrar att arbeta med ett färdigt PHP-bibliotek istället för det råa API:et, kolla in viber-bot-php av Bogdaan. Det hanterar signaturvalidering, händelseroutning och JSON-generering åt dig.

Sammanfattning: fullständig lanseringssekvens

  • Hämta token i Viber Admin Panel: avsnittet Edit Info → App Key.
  • Driftsätt hanteraren på en server med HTTPS. Let's Encrypt fungerar; ett självsignerat certifikat gör det inte. Viber validerar certifikat mot Javas lista över betrodda rotcertifikat.
  • Sätt webhooken med en POST-förfrågan till https://chatapi.viber.com/pa/set_webhook med bodyn {"url":"https://your-domain/webhook.php","event_types":[...]} och headern X-Viber-Auth-Token.
  • Kontrollera svaret: {"status":0} betyder framgång. Viber skickar omedelbart en webhook-callback till din URL. Se till att skriptet returnerar {"status":0,"status_message":"ok"}.
  • Skicka första menyn: vid conversation_started-eventet anropa getMainMenu() och skicka resultatet till sendToViber().

⁉️🤔 Vanliga frågor

Kan jag använda ett självsignerat SSL-certifikat för webhooken?

Nej. Viber validerar certifikatet mot listan över betrodda Java-rotcertifikatutfärdare. Ett självsignerat certifikat orsakar ett invalidUrl-fel när webhooken sätts. Let's Encrypt finns med i den listan och är gratis. Kör certbot --nginx -d your-domain.com på din server, lägg till automatisk förnyelse i cron, så accepterar Viber certifikatet utan problem.

Vad är skillnaden mellan reply och open-url i ActionType?

reply skickar ActionBody tillbaka till webhooken som meddelandetext. PHP-skriptet ser det i $input['message']['text'] och dirigerar det via match(). Använd detta för navigering inom botten. open-url öppnar en länk i en extern webbläsare och triggar inte webhooken. I praktiken kombinerar menyer båda typerna: fem eller sex reply-knappar för sektioner och en bred open-url-knapp för att navigera till webbplatsen.

Vilka meddelandetyper stöder Viber Bot API?

Viber Bot API stöder nio type-värden i send_message: text (ren text), picture (JPEG-bild), video (videofil), file (valfri fil upp till 50 MB), location (geopunkt), contact (kontaktkort), sticker (klistermärke), rich_media (kortkarusell) och url (länkförhandsvisning). För aktuell lista med obligatoriska fält, se dokumentationen på Viber Developers Hub. Det vanligaste scenariot är text + keyboard för menyer och picture för att skicka bilder. Karuseller är utmärkta för butiksfronter och kataloger men kräver mer kod.

Vad ska jag göra om användaren inte ser tangentbordet?

Det finns tre vanliga orsaker. För det första: JSON med tangentbordet överskred 30 KB, och Viber tystar sådana meddelanden. Kontrollera strlen(json_encode($data)) innan du skickar. För det andra: svaret på set_webhook innehöll inte "status":0, webhooken sattes inte, och botten tar inte emot meddelanden. För det tredje: du använder det gamla formatet med auth_token i JSON-bodyn. Sedan API 7.0 ignoreras detta; du behöver headern X-Viber-Auth-Token. För felsökning, aktivera loggning av Viber API-svaret: det returnerar läsbar JSON med felkoderna invalidAuthToken, badData eller missingData.

Kan jag ändra tangentbordet efter att det har skickats?

Ja. Med varje nytt meddelande kan du skicka ett annat tangentbord. Viber-klienten visar alltid det senast mottagna. Detta låter dig bygga menyer i flera nivåer: huvudmeny → sektionsundermeny → specifikt innehåll. Varje nivå har sin egen uppsättning knappar, och användaren rör sig mellan dem genom att trycka på reply-knappar.

Hur mycket kostar det att lansera en Viber-bot 2026?

Sedan 5 februari 2024 kostar det 100 € per månad att skapa en ny bot via officiella Rakuten Viber-partners. Bottar skapade före det datumet fortsätter på de gamla villkoren. Kostnaden inkluderar ett dedikerat konto med adminpanel, analys och tillgång till alla meddelandetyper inklusive rich_media och Viber Pay. Den tekniska delen av API:et är identisk för kommersiella och äldre gratibottar.

Botten är redo: vad kommer härnäst

En tangentbordsmeny är bara en ingångspunkt. När den grundläggande mekaniken fungerar, lägg till innehållskaruseller via rich_media, betalningar via Viber Pay och användarsegmentering baserat på vilka knappar de trycker på oftast. Varje ny nivå förändrar inte grunden: du läser fortfarande event och skickar fortfarande send_message med headern X-Viber-Auth-Token.

Om du behöver ett levande exempel på fungerande kod, kolla in viber-bot-php-repositoriet på GitHub. Det täcker alla event, signering av förfrågningar och att bygga ett tangentbord med bilder. Och för en visuell start, här är en halvtimmes handledning om att skapa en Viber-bot från grunden:

Det viktigaste att komma ihåg: Viber Bot API är enkelt i början men krävande när det gäller detaljer. En korrekt autentiseringsheader, betrott SSL, giltig JSON under 30 KB och tydlig ActionBody-dirigering räcker för att hålla botten igång utan fel. Ta kodsnuttarna ovan, ersätt med din token och domän, och lansera din första meny idag.