Line เปิดให้บริการ
Messaging API มาระยะนึงแล้วแต่ก็ยังไม่ได้ลองเขียน ChatBot สักที ครั้งนี้ก็เลยมาลองเขียนดูบ้าง
Messaging API สามารถส่งข้อความไปยังผู้ใช้ได้ ส่งข้อความโต้ตอบผู้ใช้ ซึี่งรูปแบบข้อความความสามารถอยู่ในรูปแบบ rich content ได้ เช่น image, audio, video, button, carousel เป็นต้น เราสามารถใช้ rich content โต้ตอบกับผู้ใช้ได้ เช่น สั่งซื้อสินค้า, แนะนำสถานที่โดยใช้ location ของผู้ใช้, บริการแปลภาษา ฯลฯ
มาสร้างส่วน Webhook กัน LINE มีข้อกำหนดเรื่อง https เราใช้ PaaS อย่าง Heroku ที่มาพร้อมกับ https จะช่วยได้มาก
mkdir -p linebot/web
cd linebot
composer require php
composer require linecorp/line-bot-sdk
composer require monolog/monolog
echo "vendor/" > .gitignore
echo "web: vendor/bin/heroku-php-apache2 web/" > Procfile
echo " web/index.php
git init
git add . && git commit -am "init"
heroku create
git push heroku master
จากนั้นสั่ง
heroku open
สั่ง config heroku ให้บันทึก ACCESS_TOKEN และ CHANNEL_SECRET ลงใน ENV ดังนี้
heroku config:set LINEBOT_ACCESS_TOKEN=XXXXXXXXX
heroku config:set LINEBOT_CHANNEL_SECRET=XXXXXXXXX
แก้ไฟล์ index.php เพิ่มโค้ดลงไปดังนี้
| |
| |
| require_once '../vendor/autoload.php'; |
| |
| use Monolog\Logger; |
| use Monolog\Handler\StreamHandler; |
| use Monolog\Handler\FirePHPHandler; |
| |
| $logger = new Logger('LineBot'); |
| $logger->pushHandler(new StreamHandler('php://stderr', Logger::DEBUG)); |
| |
| $httpClient = new \LINE\LINEBot\HTTPClient\CurlHTTPClient($_ENV["LINEBOT_ACCESS_TOKEN"]); |
| $bot = new \LINE\LINEBot($httpClient, ['channelSecret' => $_ENV["LINEBOT_CHANNEL_SECRET"]]); |
| |
| $signature = $_SERVER['HTTP_' . \LINE\LINEBot\Constant\HTTPHeader::LINE_SIGNATURE]; |
| try { |
| $events = $bot->parseEventRequest(file_get_contents('php://input'), $signature); |
| } catch(\LINE\LINEBot\Exception\InvalidSignatureException $e) { |
| error_log('parseEventRequest failed. InvalidSignatureException => '.var_export($e, true)); |
| } catch(\LINE\LINEBot\Exception\UnknownEventTypeException $e) { |
| error_log('parseEventRequest failed. UnknownEventTypeException => '.var_export($e, true)); |
| } catch(\LINE\LINEBot\Exception\UnknownMessageTypeException $e) { |
| error_log('parseEventRequest failed. UnknownMessageTypeException => '.var_export($e, true)); |
| } catch(\LINE\LINEBot\Exception\InvalidEventRequestException $e) { |
| error_log('parseEventRequest failed. InvalidEventRequestException => '.var_export($e, true)); |
| } |
แล้วสั่ง commit และ push ใหม่ โค้ดข้างต้นจะอ่าน
Webhook Events ที่ได้รับมาจาก Line App เราจะอ่าน Events เหล่านี้มาสร้าง Bot กัน Events ที่เราจะเจอบ่อยๆ เช่น MessageEvent คือข้อความที่ส่งมาจากผู้ใช้ และ Postback Event คือ action ที่เกิดจากผู้ใช้ส่งกลับมาให้ Webhook เป็นต้น แนะนำให้เปิด
Line Bot SDK กับ
API Reference เอาไว้ดูตอนเขียนด้วยนะครับจะได้ไม่งง
เพิ่มโค้ดเพื่อตรวจสอบ Message Events ดังนี้
| |
| |
| require_once '../vendor/autoload.php'; |
| |
| use Monolog\Logger; |
| use Monolog\Handler\StreamHandler; |
| use Monolog\Handler\FirePHPHandler; |
| |
| $logger = new Logger('LineBot'); |
| $logger->pushHandler(new StreamHandler('php://stderr', Logger::DEBUG)); |
| |
| $httpClient = new \LINE\LINEBot\HTTPClient\CurlHTTPClient($_ENV["LINEBOT_ACCESS_TOKEN"]); |
| $bot = new \LINE\LINEBot($httpClient, ['channelSecret' => $_ENV["LINEBOT_CHANNEL_SECRET"]]); |
| |
| $signature = $_SERVER['HTTP_' . \LINE\LINEBot\Constant\HTTPHeader::LINE_SIGNATURE]; |
| try { |
| $events = $bot->parseEventRequest(file_get_contents('php://input'), $signature); |
| } catch(\LINE\LINEBot\Exception\InvalidSignatureException $e) { |
| error_log('parseEventRequest failed. InvalidSignatureException => '.var_export($e, true)); |
| } catch(\LINE\LINEBot\Exception\UnknownEventTypeException $e) { |
| error_log('parseEventRequest failed. UnknownEventTypeException => '.var_export($e, true)); |
| } catch(\LINE\LINEBot\Exception\UnknownMessageTypeException $e) { |
| error_log('parseEventRequest failed. UnknownMessageTypeException => '.var_export($e, true)); |
| } catch(\LINE\LINEBot\Exception\InvalidEventRequestException $e) { |
| error_log('parseEventRequest failed. InvalidEventRequestException => '.var_export($e, true)); |
| } |
| |
| foreach ($events as $event) { |
| |
| // Postback Event |
| if (($event instanceof \LINE\LINEBot\Event\PostbackEvent)) { |
| $logger->info('Postback message has come'); |
| continue; |
| } |
| |
| // Location Event |
| if ($event instanceof LINE\LINEBot\Event\MessageEvent\LocationMessage) { |
| $logger->info("location -> ".$event->getLatitude().",".$event->getLongitude()); |
| continue; |
| } |
| |
| // Message Event = TextMessage |
| if (($event instanceof \LINE\LINEBot\Event\MessageEvent\TextMessage)) { |
| // get message text |
| $messageText=strtolower(trim($event->getText())); |
| |
| } |
| |
| } |
จากโค้ดจะแยก Postback, Location Message และ TextMessage เพื่อใช้ในการเขียนโค้ดในการตอบโต้กับข้อความที่ผู้ใช้ส่งมา ลองมาดูในส่วนของ TextMessage กันก่อน เราสามารถแยก message ที่ส่งมาจากผู้ใช้โดยใช้ method getText เราจะได้ text message เอาไว้ใช้วิเคราะห์ประโยคหรือส่งไปให้ conversation service หรือ machine learning service ได้ หรือจะเอามาทำ chat bot แบบถามมาตอบไปเป็น rule base ง่ายๆ ได้เช่นกัน เพื่อให้เข้าใจการส่ง message กลับไปยังผู้ใช้ เรามาตั้ง rule base ง่ายๆ กันก่อนดังนี้
- พิมพ์ text จะส่งข้อความในรูปแบบ text กลับไปให้
- พิมพ์ image จะส่ง image กลับไปให้
- พิมพ์ location จะส่ง location message กลับไปให้
- พิมพ์ confirm จะส่ง confirm dialog กลับไปให้
- พิมพ์ button จะส่ง dialog พร้อมปุ่ม กลับไปให้
- พิมพ์ carousel จะส่งข้อความแบบ carousel กลับไปให้
ตัวอย่างการส่ง Text Message
| |
| |
| $outputText = new \LINE\LINEBot\MessageBuilder\TextMessageBuilder("text message"); |
| $bot->replyMessage($event->getReplyToken(), $outputText); |
ตัวอย่างการส่ง Image
| |
| |
| $img_url = "https://cdn.shopify.com/s/files/1/0379/7669/products/sampleset2_1024x1024.JPG?v=1458740363"; |
| $outputText = new LINE\LINEBot\MessageBuilder\ImageMessageBuilder($img_url, $img_url); |
| $response = $bot->replyMessage($event->getReplyToken(), $outputText); |
ตัวอย่างการส่ง Location
| |
| |
| $outputText = new \LINE\LINEBot\MessageBuilder\LocationMessageBuilder("Eiffel Tower", "Champ de Mars, 5 Avenue Anatole France, 75007 Paris, France", 48.858328, 2.294750); |
| $response = $bot->replyMessage($event->getReplyToken(), $outputText); |
ตัวอย่างการส่ง Confirm
| |
| |
| $actions = array ( |
| New \LINE\LINEBot\TemplateActionBuilder\PostbackTemplateActionBuilder("yes", "ans=y"), |
| New \LINE\LINEBot\TemplateActionBuilder\PostbackTemplateActionBuilder("no", "ans=N") |
| ); |
| $button = new \LINE\LINEBot\MessageBuilder\TemplateBuilder\ConfirmTemplateBuilder("confim message", $actions); |
| $outputText = new \LINE\LINEBot\MessageBuilder\TemplateMessageBuilder("confim message", $button); |
| $response = $bot->replyMessage($event->getReplyToken(), $outputText); |
ตัวอย่างการส่ง Button
| |
| |
| $actions = array ( |
| // general message action |
| New \LINE\LINEBot\TemplateActionBuilder\MessageTemplateActionBuilder("button 1", "text 1"), |
| // URL type action |
| New \LINE\LINEBot\TemplateActionBuilder\UriTemplateActionBuilder("Google", "http://www.google.com"), |
| // The following two are interactive actions |
| New \LINE\LINEBot\TemplateActionBuilder\PostbackTemplateActionBuilder("next page", "page=3"), |
| New \LINE\LINEBot\TemplateActionBuilder\PostbackTemplateActionBuilder("Previous page", "page=1") |
| ); |
| $img_url = "https://cdn.shopify.com/s/files/1/0379/7669/products/sampleset2_1024x1024.JPG?v=1458740363"; |
| $button = new \LINE\LINEBot\MessageBuilder\TemplateBuilder\ButtonTemplateBuilder("button text", "description", $img_url, $actions); |
| $outputText = new \LINE\LINEBot\MessageBuilder\TemplateMessageBuilder("Button template builder", $button); |
| $response = $bot->replyMessage($event->getReplyToken(), $outputText); |
ตัวอย่างการส่ง Carousel
| |
| |
| $columns = array(); |
| $img_url = "https://cdn.shopify.com/s/files/1/0379/7669/products/sampleset2_1024x1024.JPG?v=1458740363"; |
| for($i=0;$i<5;$i++) { |
| $actions = array( |
| new \LINE\LINEBot\TemplateActionBuilder\PostbackTemplateActionBuilder("Add to Cart","action=carousel&button=".$i), |
| new \LINE\LINEBot\TemplateActionBuilder\UriTemplateActionBuilder("View","http://www.google.com") |
| ); |
| $column = new \LINE\LINEBot\MessageBuilder\TemplateBuilder\CarouselColumnTemplateBuilder("Title", "description", $img_url , $actions); |
| $columns[] = $column; |
| } |
| $carousel = new \LINE\LINEBot\MessageBuilder\TemplateBuilder\CarouselTemplateBuilder($columns); |
| $outputText = new \LINE\LINEBot\MessageBuilder\TemplateMessageBuilder("Carousel Demo", $carousel); |
โค้ดทั้งหมด
| |
| |
| require_once '../vendor/autoload.php'; |
| |
| use Monolog\Logger; |
| use Monolog\Handler\StreamHandler; |
| use Monolog\Handler\FirePHPHandler; |
| |
| $logger = new Logger('LineBot'); |
| $logger->pushHandler(new StreamHandler('php://stderr', Logger::DEBUG)); |
| |
| $httpClient = new \LINE\LINEBot\HTTPClient\CurlHTTPClient($_ENV["LINEBOT_ACCESS_TOKEN"]); |
| $bot = new \LINE\LINEBot($httpClient, ['channelSecret' => $_ENV["LINEBOT_CHANNEL_SECRET"]]); |
| |
| $signature = $_SERVER['HTTP_' . \LINE\LINEBot\Constant\HTTPHeader::LINE_SIGNATURE]; |
| try { |
| $events = $bot->parseEventRequest(file_get_contents('php://input'), $signature); |
| } catch(\LINE\LINEBot\Exception\InvalidSignatureException $e) { |
| error_log('parseEventRequest failed. InvalidSignatureException => '.var_export($e, true)); |
| } catch(\LINE\LINEBot\Exception\UnknownEventTypeException $e) { |
| error_log('parseEventRequest failed. UnknownEventTypeException => '.var_export($e, true)); |
| } catch(\LINE\LINEBot\Exception\UnknownMessageTypeException $e) { |
| error_log('parseEventRequest failed. UnknownMessageTypeException => '.var_export($e, true)); |
| } catch(\LINE\LINEBot\Exception\InvalidEventRequestException $e) { |
| error_log('parseEventRequest failed. InvalidEventRequestException => '.var_export($e, true)); |
| } |
| |
| foreach ($events as $event) { |
| |
| // Postback Event |
| if (($event instanceof \LINE\LINEBot\Event\PostbackEvent)) { |
| $logger->info('Postback message has come'); |
| continue; |
| } |
| // Location Event |
| if ($event instanceof LINE\LINEBot\Event\MessageEvent\LocationMessage) { |
| $logger->info("location -> ".$event->getLatitude().",".$event->getLongitude()); |
| continue; |
| } |
| |
| // Message Event = TextMessage |
| if (($event instanceof \LINE\LINEBot\Event\MessageEvent\TextMessage)) { |
| $messageText=strtolower(trim($event->getText())); |
| switch ($messageText) { |
| case "text" : |
| $outputText = new \LINE\LINEBot\MessageBuilder\TextMessageBuilder("text message"); |
| break; |
| case "location" : |
| $outputText = new \LINE\LINEBot\MessageBuilder\LocationMessageBuilder("Eiffel Tower", "Champ de Mars, 5 Avenue Anatole France, 75007 Paris, France", 48.858328, 2.294750); |
| break; |
| case "button" : |
| $actions = array ( |
| // general message action |
| New \LINE\LINEBot\TemplateActionBuilder\MessageTemplateActionBuilder("button 1", "text 1"), |
| // URL type action |
| New \LINE\LINEBot\TemplateActionBuilder\UriTemplateActionBuilder("Google", "http://www.google.com"), |
| // The following two are interactive actions |
| New \LINE\LINEBot\TemplateActionBuilder\PostbackTemplateActionBuilder("next page", "page=3"), |
| New \LINE\LINEBot\TemplateActionBuilder\PostbackTemplateActionBuilder("Previous", "page=1") |
| ); |
| $img_url = "https://cdn.shopify.com/s/files/1/0379/7669/products/sampleset2_1024x1024.JPG?v=1458740363"; |
| $button = new \LINE\LINEBot\MessageBuilder\TemplateBuilder\ButtonTemplateBuilder("button text", "description", $img_url, $actions); |
| $outputText = new \LINE\LINEBot\MessageBuilder\TemplateMessageBuilder("this message to use the phone to look to the Oh", $button); |
| break; |
| case "carousel" : |
| $columns = array(); |
| $img_url = "https://cdn.shopify.com/s/files/1/0379/7669/products/sampleset2_1024x1024.JPG?v=1458740363"; |
| for($i=0;$i<5;$i++) { |
| $actions = array( |
| new \LINE\LINEBot\TemplateActionBuilder\PostbackTemplateActionBuilder("Add to Card","action=carousel&button=".$i), |
| new \LINE\LINEBot\TemplateActionBuilder\UriTemplateActionBuilder("View","http://www.google.com") |
| ); |
| $column = new \LINE\LINEBot\MessageBuilder\TemplateBuilder\CarouselColumnTemplateBuilder("Title", "description", $img_url , $actions); |
| $columns[] = $column; |
| } |
| $carousel = new \LINE\LINEBot\MessageBuilder\TemplateBuilder\CarouselTemplateBuilder($columns); |
| $outputText = new \LINE\LINEBot\MessageBuilder\TemplateMessageBuilder("Carousel Demo", $carousel); |
| break; |
| case "image" : |
| $img_url = "https://cdn.shopify.com/s/files/1/0379/7669/products/sampleset2_1024x1024.JPG?v=1458740363"; |
| $outputText = new LINE\LINEBot\MessageBuilder\ImageMessageBuilder($img_url, $img_url); |
| break; |
| case "confirm" : |
| $actions = array ( |
| New \LINE\LINEBot\TemplateActionBuilder\PostbackTemplateActionBuilder("yes", "ans=y"), |
| New \LINE\LINEBot\TemplateActionBuilder\PostbackTemplateActionBuilder("no", "ans=N") |
| ); |
| $button = new \LINE\LINEBot\MessageBuilder\TemplateBuilder\ConfirmTemplateBuilder("problem", $actions); |
| $outputText = new \LINE\LINEBot\MessageBuilder\TemplateMessageBuilder("this message to use the phone to look to the Oh", $button); |
| break; |
| default : |
| $outputText = new \LINE\LINEBot\MessageBuilder\TextMessageBuilder("demo command: text, location, button, confirm to test message template"); |
| break; |
| } |
| $response = $bot->replyMessage($event->getReplyToken(), $outputText); |
| } |
| |
| } |
ที่มา Thaiopensource