
🤖 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_webhookmed headernX-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
eventoch svarar genom att anropasend_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.

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.

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:

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'); 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 }
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 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 }
Händelseuppdelning:
webhookkommer 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.subscribedbetyder att en användare har prenumererat på boten. Detta är det perfekta tillfället att skicka en välkomstmeny.conversation_startedbetyder 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ältettextinnehåller antingen ett godtyckligt användarmeddelande ellerActionBodyfrån en tryckt knapp (om dess typ ärreply). 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 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 }
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 |
|---|---|---|
| 1-6 | Knappbredd i villkorliga kolumner |
| 1-2 | Knapphöjd i rader |
|
|
|
| sträng | För |
| sträng | Etikett på knappen, stöder HTML-taggarna b, i och font color |
| HEX | Knappens bakgrundsfärg |
| 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 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 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 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å 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.

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_webhookmed bodyn{"url":"https://your-domain/webhook.php","event_types":[...]}och headernX-Viber-Auth-Token. - Kontrollera svaret:
{"status":0}betyder framgång. Viber skickar omedelbart enwebhook-callback till din URL. Se till att skriptet returnerar{"status":0,"status_message":"ok"}. - Skicka första menyn: vid
conversation_started-eventet anropagetMainMenu()och skicka resultatet tillsendToViber().
⁉️🤔 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örcertbot --nginx -d your-domain.compå 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?
replyskickarActionBodytillbaka till webhooken som meddelandetext. PHP-skriptet ser det i$input['message']['text']och dirigerar det viamatch(). 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 isend_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) ochurl(länkförhandsvisning). För aktuell lista med obligatoriska fält, se dokumentationen på Viber Developers Hub. Det vanligaste scenariot ärtext+keyboardför menyer ochpicturefö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_webhookinnehöll inte"status":0, webhooken sattes inte, och botten tar inte emot meddelanden. För det tredje: du använder det gamla formatet medauth_tokeni JSON-bodyn. Sedan API 7.0 ignoreras detta; du behöver headernX-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.



