พอกันทีกับการเปลี่ยน webhook ที่ LINE developer console เมื่อ LINE มี API ใหม่ !!

Thachaparn Bunditlurdruk
incubate.co.th
Published in
4 min readNov 9, 2020

เมื่อเดือนตุลาคมที่ผ่านมา มีข่าวดี๊ดีสำหรับชาว LINE developer ด้วย นั่นก็คือ (รัวกลอง) LINE เขาปล่อย Messaging API ตัวใหม่แล้ว และตัวที่เราตื่นเต้น และอยากจะมาแชร์ให้กับทุกคนในบทความนี้ก็คือ API สำหรับตั้งค่า webhook นั่นเอง

ในบทความนี้เราจะมาเล่า used case ที่ได้นำ API ใหม่อันดีงามนี้มาแก้ปัญหา pain point ที่เราเจอกัน

ปัญหา: การทดสอบ LINE bot บน Colab

เวลาเราอยากจะทดสอบ LINE bot ที่เราสร้างขึ้นในภาษาไพธอน แต่ก็ขี้เกียจจะไปนั่งตั้งค่า server เอง ตัวเลือกที่เรามักใช้คือการไปรัน web app บน colab ด้วย Flask เมื่อเราใช้คำสั่ง Flask เราจะได้ localhost ของเราออกมา แต่ uri นี้ยังไม่สามารถเข้าถึงได้จากเซิร์ฟเวอร์ภายนอก เราจึงต้องใช้ ngrok เปิดอุโมงค์วิเศษทำให้ localhost ของเราเป็น public สามารถเข้าถึงได้ก่อน (วิธีเช็คว่าเป็น public/online ไหมแบบง่าย ๆ คือการนำลิ้งก์ไปเปิดในบราวเซอร์ดู) ถ้าลิ้งก์สามารถเปิดได้แล้ว เราก็แค่คัดลอก uri เติม path สำหรับการ callback แล้วแปะเป็น webhook ไว้ใน LINE developer console และจบด้วยการกลับมารัน Flask ทิ้งไว้เวลาที่เราจะทดสอบบอท

แต่ปัญหามันเกิดเมื่อเราอยากจะแก้ไขโค๊ด เช่น อยากจะแก้ไขวิธีการตอบกลับของบอท สิ่งที่เราต้องทำคือ

  1. สั่งให้เซลล์ที่ใช้รัน Flask ใน Colab อยู่หยุดการทำงาน ซึ่งจะทำให้ ngrok หยุดทำงานไปด้วย
  2. รันเซลล์ที่เราต้องการจะอัปเดตโค๊ด
  3. กลับมารัน Flask และเปิดอุโมงค์ ngrok ใหม่ — ผลที่ตามมาคือเราจะได้ uri ตัวใหม่ออกมา
  4. คัดลอก uri ตัวใหม่นั้น เติม path แล้วนำไปแปะใน LINE developer console อีกรอบ

เพื่อน ๆ ลองคิดภาพตามดูว่าเวลาเราจะพัฒนาบอทสักตัว เราต้องแก้โค๊ดกันเกิน 10 รอบแน่ และในแต่ละรอบก็ต้องมาคัดลอก uri เข้าไปอัปเดต webhook ใน LINE developer console ใหม่ทุกครั้ง แถมบางครั้งก็อาจแก้ uri พลาด ทำให้บอทไม่ตอบ นั่งหาบั๊กวนกันไปอีก แค่คิดก็ขอเหนื่อยรอเลย 😫 😫

แต่ปัญหานี้จะหมดไป เมื่อคุณพบกับ API ใหม่จาก LINE ที่ช่วยให้เรายิง request ไปเปลี่ยน webhook ได้แค่คลิกเดียว ไม่ต้องคัดลอกลิ้งก์…แก้ uri…เติม path…สลับไปแปะหน้า console อีกแล้ว

ทำความรู้จักส่วนประกอบของ API

https://developers.line.biz/en/reference/messaging-api/#set-webhook-endpoint-url
  • วิธีที่ใช้ยิง request ตัวนี้ (Method): PUT
  • เราจะยิง request ไปที่ไหน (Endpoint): https://api.line.me/v2/bot/channel/webhook/endpoint
  • ข้อมูลทั่วไปที่ส่งไปพร้อม request (Headers):
    — Content-Type : application/json
    — Authorization : Bearer {channel access token}
  • ข้อมูลเฉพาะที่ API นี้ต้องการ (Data/Body):
    — endpoint: webhook ที่เราต้องการให้ไปเปลี่ยน

ใครยังลืมๆว่าจะหา channel access token ได้ที่ไหน สามารถมาทวนกันได้จากบทความ Channel Access Token ของ LINE เอามาจากที่ไหนได้บ้างเนี่ย

ขั้นตอนการสร้าง LINE chatbot บน Colab แบบ Seamless

ถ้าเราเข้าใจปัญหา และรู้จักกับ API ที่จะใช้แล้ว ตอนนี้เราก็ได้เวลาที่จะมาเขียนโค๊ดสำหรับระบบทดสอบบอทแบบง่าย ๆ จบในแท็บเดียวกัน โดยขั้นตอนก็มีเพียง 6 ขั้นตอนเท่านั้น

1. ติดตั้งแพ็กเกจที่ต้องใช้

แพ็กเกจที่ต้องลงก็มีแค่ 2 ตัว คือ

  • line-bot-sdk ของภาษาไพธอน เพื่อจะได้มีฟังก์ชั่นสร้างบอทมาเรียกใช้กันง่าย ๆ
  • pyngrok ซึ่งคือ Python wrapper ของ ngrok สำหรับเปิดอุโมงค์ให้ webhook ของเราเข้าถึงได้ โดยเหตุผลที่เราเลือกใช้ pyngrok แทนที่จะใช้ ngrok ปกติเพราะ pyngrok ช่วยให้เราเรียก webhook ที่ ngrok ปล่อยออกมาไปใช้ในฟังก์ชั่นอื่นต่อได้ง่ายในรูปของ object

2. เชื่อมต่อกับ LINE Bot

สร้างตัวแปรสำหรับเชื่อมต่อกับบอทของเราด้วย LineBotApi โดยพารามิเตอร์ที่ใช้ คือ channel access token ซึ่งในบทความนี้เราจะยิง API ไปขอ channel access token ที่มีอายุ 30 วันมาใช้ (สามารถดูวิธีการเรียก API และดึงค่าของ channel access token ออกจาก json object ซึ่งได้มาจากการยิง API ได้ที่เซลล์ที่ 5 ในรูปด้านล่าง)

3. สร้างแอพที่รันบนเซิร์ฟเวอร์ของ Colab ด้วย Flask

พอเราทำการเชื่อมต่อกับบอทได้แล้ว ตอนนี้เราก็ต้องมาสร้างเซิร์ฟเวอร์เอาไว้พัฒนาบอทของเราด้วย Flask กับคำสั่ง app = Flask(__name__) และเสริม route ชี้ไปที่ callback ที่รองรับคำขอแบบ Post ด้วยคำสั่ง @app.route(“/callback”, methods=[‘POST’]) เมื่อมีคำขอเข้ามาที่ path นี้ก็จะไปเรียก callback() เพื่อตรวจสอบว่าคำขอส่งมานั้นมาจาก LINE จริง ๆ ไหม เพื่อป้องกันผู้ไม่หวังดีปลอมตัวมาขโมยข้อมูลของเรา

ปกติพอมี event เข้ามา handler ที่เราสร้างไว้ด้วยคำสั่ง WebhookHandler(channel_secret) ก็จะส่งไปหาฟังก์ชั่นที่รอจัดการ event ประเภทนั้น ๆ หลังจากตรวจสอบ signature แล้ว อย่างในบทความนี้เราจะทดสอบแค่ Message event ที่เป็น text เท่านั้น เมื่อผู้ใช้ส่งข้อความเข้ามา handler จะส่งไปที่ฟังก์ชั่น handle_message()แล้วบอทของเราก็จะตอบข้อความนั้นกลับไป (เรียกบอทประเภทนี้ว่า echo bot) แต่ถ้าอยากจะปรับให้บอทของเรารองรับ event อื่น ๆ ก็เพียงเสริมฟังก์ชั่นที่รอรับ event ประเภทนั้น ๆ เข้าไปต่อจากส่วนนี้ได้เลย

ใครอยากทำความรู้จักกับ Webhook event มากขึ้น สามารถอ่านเพิ่มเติมได้ที่บทความ 15 สัญญาณจาก Webhook Events ที่จะปลุกให้ LINE Bot ของคุณตื่นจากภวังค์ หรือ อ่าน doc การใช้ line-bot-sdk ในภาษาไพธอนได ้ที่นี่

4. ขุดอุโมงค์ให้ webhook เข้าถึงได้ด้วย pyngrok

หลังจากเรามี localhost ของตัวเองแล้ว ขั้นตอนต่อไปคือการทำให้เซิร์ฟเวอร์ LINE สามารถเข้าถึงได้ โดยการใช้ pyngrok โดยสิ่งที่เราต้องตั้งค่ามีแค่ 3 อย่างเท่านั้น คือ

  1. เราจะให้มีการเก็บ log ของ event ที่เข้ามา เพื่อดูว่า localhost ของเราเป็น public แล้วหรือยัง
  2. ตั้งค่า region ให้เป็นที่ประเทศญี่ปุ่น jp เพื่อให้บอทของเราตอบสนองได้เร็วขึ้น ไม่เกิดอาการบอทอ่านแล้วไม่ตอบ — ขอขอบคุณเทคนิคดีๆ จากชุมชน LINE Developers Thailand
  3. ตั้งค่าให้เปิด tunnel ที่ port 5000

จากนั้นเราก็จะได้ http uri ที่เป็นหน้าตาแบบนี้ http://<public_sub>.ngrok.io มาเก็บอยู่ใน http_tunnel.public_url เพื่อนำไปใช้ในข้อสำคัญข้อถัดไปของเรากัน

5. ตั้งค่า webhook ของ LINE bot ด้วย API (Set webhook endpoint URL)

มาถึงขั้นตอนการประกอบ API ตั้งค่า webhook ของเราให้เป็นฟังก์ชั่น ด้วยการใช้ไลบรารี่ requests และไลบรารี่ json โดยพารามิเตอร์ที่เราจะต้องใช้มีเพียง 2 ตัว คือ

  • http_tunnel.public_url — public uri จาก ngrok
  • channelAccessToken เจ้าเดิมของเรา

แต่ !! เราจะใช้ uri ที่ได้มาจาก ngrok เลยไม่ได้ เราต้องแก้ไขลิ้งก์ 2 จุดก่อนนั่นคือ

  1. เปลี่ยน http เป็น https
  2. เติม /callback ไปด้านท้าย เพื่อให้ event จาก LINE เข้าไปที่ route ที่เราเตรียมไว้ในข้อ 3

ในโค๊ดที่แสดง เราจัดการแก้ไข endpoint ที่รับเข้ามาด้วยคำสั่ง 'https://' + endpoint.split(‘//’)[-1] + ‘/callback’ และเก็บ uri ใหม่นี้ไว้ที่ตัวแปร endpointFixed เพื่อใช้ส่งไปในคำขอ

ถ้าเราส่งคำขอสำเร็จก็จะได้ status code 200 พร้อมกับ object เปล่าๆกลับมา 👏 👏

6. สั่งให้แอพรันบน Colab

มาถึงขั้นตอนสุดท้ายที่สั้นที่สุด และง่ายที่สุด นั่นคือการกดรัน App ด้วยคำสั่ง

app.run()

ในระหว่างที่เซลล์นี้กำลังรัน หมายความว่า app ที่เราสร้างด้วย Flask กำลังทำงานอยู่ ถ้าเราส่งข้อความเข้าไปในแชท ก็จะได้ข้อความเดิมตอบกลับมา แต่ถ้าส่ง sticker เข้าไปบอทจะไม่ตอบกลับ แม้ว่า status code จะเป็น 200 ก็ตาม (200 แปลว่าคำขอจาก LINE ถึงเซิร์ฟเวอร์ของเรา) เพราะเราไม่ได้เตรียม handler ไว้สำหรับ Message event ประเภทนี้

และถ้าเราหยุดการทำงานของเซลล์นี้แปลว่าเราได้รัน app ตัวใหม่ ส่งผลให้เกิด localhost ใหม่ ถ้าเราจะทดสอบบอทของเราก็แค่ restart runtime ทั้งหมด แล้วกดรันข้อ 3–6 อีกครั้งเพื่อเปิดอุโมงค์และอัปเดต webhook เท่านั้นเอง ไม่ต้องคัดลอก แต่งเติมและสลับไปหน้า LINE developer console อีกต่อไป

จบแล้วกับการพาทัวร์การใช้ API ตัวใหม่ให้ชีวิตการเขียนโปรแกรมของเราง่ายขึ้น เพื่อน ๆ สามารถเข้าไปลองรันโค๊ดในขั้นตอนต่าง ๆ เล่นได้ในลิ้งก์ด้านล่างนี้เลย

ปล. อย่าลืมเปลี่ยน channel id กับ channel secret ให้เป็นของบอทตัวเองกันก่อนนะ ไม่งั้นเจอ response 400 แน่นอน

Reference

ขอขอบคุณไอคอน จาก flaticon

--

--

Thachaparn Bunditlurdruk
incubate.co.th

An Arts graduate who’s trying to challenge herself with programming