Skip to content

Kaikki WordPressistä, web-kehityksestä — ja paljon muuta

🤖 Viber-chatbotti PHP:lla: jäsenneltyjen viestien lähettäminen näppäimistövalikoilla

🤖 Viber-chatbotti PHP:lla: jäsenneltyjen viestien lähettäminen näppäimistövalikoilla

Käyttäjä painaa chatissa nappia ja saa vastaukseksi paljaan tekstin sijaan ruudukon kuvia, linkkejä ja värikoodattuja näppäimiä. Se näyttää natiivilta sovellukselta. Todellisuudessa se on pelkkää JSONia, jonka PHP-skriptisi palauttaa Viberin REST API:n kautta.

Useimpien tutoriaalien ongelma: ne opettavat vastaamaan tekstiin tekstillä. Oikean bisnesbotin täytyy näyttää näppäimistövalikko, jossa on linkkipainikkeita, kuvia ja karuselleja. Muuten käyttäjä ei yksinkertaisesti ymmärrä, mitä botti osaa tehdä, ja poistuu. Helmikuusta 2024 lähtien Viber on asettanut bottien luonnin kaupalliselle pohjalle (100 € kuukaudessa virallisten Rakuten Viber -kumppaneiden kautta), ja autentikointi kulkee nyt HTTP-otsakkeessa X-Viber-Auth-Token eikä pyynnön rungossa. Koodinpätkät, joissa auth_token on JSONin sisällä, eivät enää toimi.

Tässä on toimiva Viber-botti PHP:llä alusta alkaen: webhookin asetuksesta jäsennellyn näppäimistövalikon lähettämiseen reply- ja open-url-painikkeilla. Koodi on ajan tasalla API-versiolle 7.3.

💡 Pikakatsaus:

  • Rekisteröi kaupallinen botti Viber-kumppanin kautta ja hanki autentikointitoken
  • Määritä webhook set_webhook-kutsulla ja X-Viber-Auth-Token-otsakkeella
  • Vastaanota callback-tapahtumat Viberiltä: webhook → subscribed → message
  • Rakenna näppäimistövalikko (painikeruudukko, jossa mukautetut värit, koot ja toiminnot)
  • Lähetä jäsennelty vastaus: tekstiä, kuvia, linkkejä, karuselleja send_message-kutsulla

Miten Viber Bot API toimii

Viber Bot API toimii REST-mallilla: palvelimesi vastaanottaa callback-pyyntöjä webhookiin ja vastaa kutsumalla osoitetta https://chatapi.viber.com/pa/send_message. Jokainen pyyntö autentikoidaan tokenilla X-Viber-Auth-Token-otsakkeessa.

Perussykli näyttää tältä:

  • Rekisteröit botin Viber-kumppanin kautta ja saat tokenin "Edit Info" -paneelista.
  • Määrität webhookin (palvelimesi URL, jossa on kelvollinen SSL; Let's Encrypt toimii, koska se on Viberin luotetulla Java-varmenne-listalla; itse allekirjoitettuja varmenteita ei hyväksytä).
  • Viber lähettää POST-pyyntöjä tähän URLiin jokaisesta tapahtumasta: käyttäjä tilasi, lähetti viestin, painoi painiketta.
  • PHP-skriptisi lukee saapuvan JSONin, jäsentää event-kentän ja vastaa kutsumalla send_message-funktiota.

Ensimmäinen askel ymmärtämiseen on katsoa elävää bottia. Avaa Viber ja etsi minkä tahansa tunnetun brändin julkinen tili. Lähes jokaisella on chatbotti, jossa on valikko. Alla oleva kuvakaappaus näyttää tyypillisen julkisen tilin hakutuloksen.

Julkisen tilin haku Viberissä

Tilauksen jälkeen siirryt kahdenkeskiseen chattiin. Se näyttää suunnilleen tältä: avatar, tervetuloviesti ja painike keskustelun aloittamiseksi.

Viberin julkinen keskustelunäkymä tilauksen jälkeen

Napauta viestikuvaketta oikeassa yläkulmassa ja lähetä "Hei". Jos bottiin on määritetty näppäimistövalikko, näet vastauksen, jossa on painikeruudukko:

Näppäimistövalikko painikkeilla Viber-keskustelussa

Tämä on jäsennelty viesti. Painiketyyppejä on kaksi: reply lähettää tekstiä takaisin botille (painamalla "Uutiset" tai "Artikkelit"), kun taas open-url avaa linkin selaimessa. Kirjoitetaan nyt koodi, joka tuottaa tämän.

Vaihe 1: Hanki token ja määritä webhook

Token sijaitsee Viberin hallintapaneelissa: Edit Info -osio → App Key -kenttä. Se on kirjainten ja numeroiden yhdistelmä, jonka liität jokaiseen API-pyyntöön.

Webhook asetetaan yhdellä POST-pyynnöllä osoitteeseen https://chatapi.viber.com/pa/set_webhook. Pyynnön runko on JSONia, joka sisältää käsittelijäsi URL:n ja listan tapahtumista, jotka tilaat. Otsake on X-Viber-Auth-Token ja tokenisi.

Webhookin asetusskripti (tallenna nimellä setup.php ja aja kerran):

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}

Mitä tässä tapahtuu: cURL lähettää POST-pyynnön set_webhook-osoitteeseen. Token on tiukasti otsakkeessa, ei rungossa. Viber palauttaa {"status":0} onnistuessaan ja lähettää välittömästi webhook-callbackin määritettyyn URLiin varmistaakseen sen tavoitettavuuden. Vastaaminen tähän callbackiin viestillä {"status":0,"status_message":"ok"} on pakollista (käsittelemme tämän seuraavassa vaiheessa).

Jos saat vastauksen invalidUrl, tarkista SSL-varmenteesi. Let's Encrypt toimii; itse allekirjoitettu ei. Palvelimellasi riittää, että ajat certbot --nginx -d your-domain.com ja määrität automaattisen uusinnan cronin kautta.

Vaihe 2: Vastaanota callback-tapahtumat Viberiltä

Kun käyttäjä on vuorovaikutuksessa botin kanssa, Viber lähettää POST-pyynnön JSON-muodossa webhookiisi. Sinun tehtäväsi on lukea event-kenttä ja reagoida.

Minimaalinen käsittelijä webhook.php, joka vastaa oikein kaikkiin tapahtumiin:

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}

Tapahtumien erittely:

  • webhook saapuu kerran, kun webhook asetetaan. Sinun on palautettava {"status":0,"status_message":"ok"} ja lista tuetuista tapahtumista. Ilman tätä Viber ei vahvista URL-osoitetta eikä botti käynnisty.
  • subscribed tarkoittaa, että käyttäjä on tilannut botin. Tämä on ihanteellinen hetki lähettää tervetulovalikko.
  • conversation_started tarkoittaa, että käyttäjä avasi keskustelun (ensimmäistä kertaa tai uudelleen). Sopii myös päävalikon näyttämiseen.
  • message on tärkein työtapahtuma. text-kenttä sisältää joko mielivaltaisen käyttäjän viestin tai painetun painikkeen ActionBody-arvon (jos sen tyyppi on reply). Näin botti ymmärtää, mitä valittiin: "Uutiset", "Artikkelit" vai "Galleria".

match()-rakenne on käytettävissä PHP 8:sta alkaen. Jos käytössäsi on PHP 7.4, korvaa se switch-rakenteella.

Vaihe 3: Rakenna näppäimistövalikko

Näppäimistö liitetään mihin tahansa viestiin keyboard-kentän kautta send_message JSON-objektissa. Se on taulukko painikkeita, joille määritellään erikseen leveys (Columns, 1-6), korkeus (Rows, 1-2), taustaväri, teksti ja toiminto.

Funktio, joka kokoaa päävalikon seitsemästä reply-painikkeesta ja yhdestä linkkipainikkeesta:

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}

Painikkeet, joissa Columns=2 ja Rows=2, ovat neliön muotoisia, kolme per rivi (2+2+2=6). Linkkipainike, jossa Columns=4, vie oman rivinsä. Ruudukko kootaan vasemmalta oikealle, ylhäältä alas. Rivin Columns-arvojen summa määrittää asettelun.

Painikkeiden parametrit:

Parametri

Arvot

Tarkoitus

Columns

1-6

Painikkeen leveys ehdollisina sarakkeina

Rows

1-2

Painikkeen korkeus riveinä

ActionType

reply tai open-url

reply palauttaa tekstin botille, open-url avaa selaimen

ActionBody

merkkijono

reply-tyypillä teksti, jonka botti vastaanottaa; open-url-tyypillä URL-osoite

Text

merkkijono

Painikkeen teksti, tukee HTML-tageja b, i ja fontin väriä

BgColor

HEX

Painikkeen taustaväri

Image

URL

Kuva painikkeen päällä, JPEG, valinnainen

Vaihe 4: Lähetä data send_message-toiminnolla

Lähetysfunktio, jota kutsut tapahtumankäsittelijästä:

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}

Keskeinen ero vanhoihin tutoriaaleihin: token on otsikkotiedossa, ei JSON-rungossa. Runko sisältää vain kentät receiver, type, text, keyboard ja valinnaisesti sender.name, sender.avatar, tracking_data. JSONin maksimikoko on 30 kt. Jos ylität sen, Viber hylkää viestin hiljaisesti; tarkista strlen(json_encode($data)) ennen lähetystä.

Vaihe 5: Kokoa sisältö painikkeille

Kun käyttäjä painaa reply-painiketta, sen ActionBody lähetetään webhookiin viestin tekstinä. Jäsennät sen match()-rakenteessa ja kutsut sopivaa funktiota. Tässä esimerkki uutislistasta kuvien kanssa:

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}

Käyttäjän puolella tämä näyttää korttiruudukolta: kuva vasemmalla, otsikko oikealla. Minkä tahansa kohdan napauttaminen avaa linkin selaimeen.

Rich-viesti, jossa kuvia ja linkkejä Viberissä

Galleria, artikkelilista tai kyselyt kootaan täsmälleen samalla tavalla; vain $buttons-taulukon sisältö ja viestin teksti vaihtuvat. Jos sisältöä on paljon ja JSON lähestyy 30 kt:n rajaa, jaa se sivuille "Seuraava"-painikkeen avulla.

Jos haluat mieluummin työskennellä valmiin PHP-kirjaston kuin raa'an API:n kanssa, tutustu Bogdaanin viber-bot-php -kirjastoon. Se hoitaa allekirjoituksen validoinnin, tapahtumien reitityksen ja JSONin muodostamisen puolestasi.

Yhteenveto: koko käyttöönottopolku

  • Hanki token Viber Admin Panelista: Edit Info -osio → App Key.
  • Julkaise käsittelijä palvelimelle, jossa on HTTPS. Let's Encrypt toimii; itse allekirjoitettu varmenne ei. Viber validoi varmenteet luotettujen Java Root CA -varmenteiden listaa vasten.
  • Aseta webhook POST-pyynnöllä osoitteeseen https://chatapi.viber.com/pa/set_webhook bodynä {"url":"https://your-domain/webhook.php","event_types":[...]} ja otsakkeella X-Viber-Auth-Token.
  • Tarkista vastaus: {"status":0} tarkoittaa onnistumista. Viber lähettää heti webhook-kutsun URL-osoitteeseesi. Varmista, että skripti palauttaa {"status":0,"status_message":"ok"}.
  • Lähetä ensimmäinen valikko: conversation_started-tapahtumassa kutsu getMainMenu() ja välitä tulos sendToViber()-funktiolle.

⁉️🤔 Usein kysytyt kysymykset

Voinko käyttää itse allekirjoitettua SSL-varmennetta webhookille?

Et. Viber validoi varmenteen luotettujen Java-juurivarmenteiden listaa vasten. Itse allekirjoitettu varmenne aiheuttaa invalidUrl-virheen webhookia asetettaessa. Let's Encrypt on tällä listalla ja on ilmainen. Palvelimellasi aja certbot --nginx -d your-domain.com, lisää automaattinen uusinta croniin, ja Viber hyväksyy varmenteen ongelmitta.

Mikä on ero reply- ja open-url-toimintotyypin välillä?

reply lähettää ActionBody-kentän takaisin webhookille viestitekstinä. PHP-skripti näkee sen muuttujassa $input['message']['text'] ja reitittää sen match()-funktion kautta. Käytä tätä botin sisäiseen navigointiin. open-url avaa linkin ulkoisessa selaimessa eikä laukaise webhookia. Käytännössä valikot yhdistävät molempia tyyppejä: viisi tai kuusi reply-painiketta osioille ja yksi leveä open-url-painike verkkosivulle siirtymiseen.

Mitä viestityyppejä Viber Bot API tukee?

Viber Bot API tukee yhdeksää type-arvoa send_message-kutsussa: text (pelkkä teksti), picture (JPEG-kuva), video (videotiedosto), file (mikä tahansa tiedosto enintään 50 Mt), location (maantieteellinen piste), contact (yhteystietokortti), sticker (tarra), rich_media (korttikaruselli) ja url (linkin esikatselu). Ajantasainen lista pakollisine kenttineen löytyy Viber Developers Hubin dokumentaatiosta. Yleisin skenaario on text + keyboard valikoille ja picture kuvien lähettämiseen. Karusellit sopivat erinomaisesti verkkokauppojen julkisivuihin ja tuoteluetteloihin, mutta vaativat enemmän koodia.

Mitä teen, jos käyttäjä ei näe näppäimistöä?

Yleisiä syitä on kolme. Ensimmäinen: näppäimistön sisältävä JSON ylitti 30 kt, ja Viber hylkää tällaiset viestit äänettömästi. Tarkista strlen(json_encode($data)) ennen lähetystä. Toinen: vastaus set_webhook-kutsuun ei sisältänyt "status":0-arvoa, webhookia ei asetettu, eikä botti vastaanota viestejä. Kolmas: käytät vanhaa formaattia, jossa auth_token on JSON-bodyssä. API 7.0:sta lähtien tämä ohitetaan; tarvitset X-Viber-Auth-Token-otsakkeen. Vianetsintää varten ota käyttöön Viber API -vastauksen lokitus: se palauttaa luettavaa JSONia virhekoodeineen invalidAuthToken, badData tai missingData.

Voinko vaihtaa näppäimistön lähetyksen jälkeen?

Kyllä. Jokaisen uuden viestin mukana voit lähettää eri näppäimistön. Viber-sovellus näyttää aina viimeisimmän vastaanotetun. Tämän avulla voit rakentaa monitasoisia valikoita: päävalikko → osion alavalikko → tietty sisältö. Jokaisella tasolla on omat painikkeensa, ja käyttäjä liikkuu niiden välillä painamalla reply-näppäimiä.

Paljonko Viber-botin käynnistäminen maksaa vuonna 2026?

Helmikuun 5. päivästä 2024 alkaen uuden botin luominen maksaa 100 € kuukaudessa virallisten Rakuten Viber -kumppaneiden kautta. Ennen tätä päivämäärää luodut botit jatkavat vanhoilla ehdoilla. Kustannus sisältää oman tilin hallintapaneelilla, analytiikan ja pääsyn kaikkiin viestityyppeihin, mukaan lukien rich_media ja Viber Pay. API:n tekninen osa on identtinen kaupallisille ja vanhoille ilmaisboteille.

Botti on valmis: mitä seuraavaksi

Näppäimistövalikko on vasta sisäänkäynti. Kun perusmekaniikka toimii, lisää sisältökaruselleja rich_media-tyypillä, maksuja Viber Payn kautta ja käyttäjäsegmentointia sen perusteella, mitä painikkeita he painavat useimmin. Jokainen uusi taso ei muuta perustaa: luet edelleen event-kenttää ja lähetät edelleen send_message-kutsun X-Viber-Auth-Token-otsakkeella.

Jos tarvitset toimivan koodin live-esimerkin, katso viber-bot-php-repositorio GitHubissa. Se kattaa kaikki tapahtumat, pyyntöjen allekirjoittamisen ja kuvallisen näppäimistön rakentamisen. Ja visuaalista aloitusta varten tässä on puolen tunnin opastusvideo Viber-botin luomisesta alusta alkaen:

Tärkeintä on muistaa: Viber Bot API on aluksi yksinkertainen, mutta vaativa yksityiskohtien suhteen. Oikea todennusotsake, luotettu SSL, validi JSON alle 30 kt ja selkeä ActionBody-reititys riittävät pitämään botin toiminnassa ilman virheitä. Ota yllä olevat koodinpätkät, korvaa omalla tokenillasi ja domainillasi ja käynnistä ensimmäinen valikkosi tänään.