Line Robot ( 三 ) - 實作echo Robot
前言: 此功能如標題所描述,當使用者對Line Robot傳送什麼訊息,Line Robot就回應什麼訊息至使用者。
編譯環境(工具):
JDK1.8、eclipse
開始製作:
前幾篇有提到,編寫Line Robot如同撰寫Web API,而在Java近幾年比較流行使用Spring boot開發,故作者以Spring boot框架去製作,而在Spring boot官網中有提供Spring Initializr製作Spring boot的開發包,故我們先點選我們所需要的套件後並下載。
編譯環境(工具):
JDK1.8、eclipse
開始製作:
前幾篇有提到,編寫Line Robot如同撰寫Web API,而在Java近幾年比較流行使用Spring boot開發,故作者以Spring boot框架去製作,而在Spring boot官網中有提供Spring Initializr製作Spring boot的開發包,故我們先點選我們所需要的套件後並下載。
將專案導入至eclipse
接著先撰寫測試的API街口判斷Spring boot是否正常運作(萬年的 Hello java出場)
@RequestMapping("/robot") @RestController public class RobotController { @Value("${line.user.secret}") private String LINE_SECRET; @Autowired private HttpServletRequest httpServletRequest; @GetMapping("/test") public ResponseEntitytest(){ return new ResponseEntity ("Hello J A V A", HttpStatus.OK); } }
完工後運行並在瀏覽器輸入 http://localhost:8080/robot/test ,網頁是否出現Hello Java等字樣,如果有的話證明了Spring boot功能正常,接著開始進入主題 - Line echo robot。
首先在第二章節有提到所有Line的訊息皆是由Line伺服器傳送至Line robot中,而其間的協定走的是Post Method,且還要處理第二章節提到的Line伺服器驗證故作者的程式如下:
public boolean checkFromLine(String requestBody, String X_Line_Signature) { SecretKeySpec key = new SecretKeySpec(LINE_SECRET.getBytes(), "HmacSHA256"); Mac mac; try { mac = Mac.getInstance("HmacSHA256"); mac.init(key); byte[] source = requestBody.getBytes("UTF-8"); String signature = Base64.encodeBase64String(mac.doFinal(source)); if(signature.equals(X_Line_Signature)) { return true; } } catch (NoSuchAlgorithmException | InvalidKeyException | UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } return false; }
接著定義接收Line platform訊息接口,但在那之前須先了解Line Platform回傳的訊息封裝格式有助於解析並做應用,在前一章有提到,其格式內容主要是用JSON進行封裝,JSON內會含兩項,destination及events,其中events所代表的是Line接收到使用者的各個訊息回應,而本章節會使用到的是Message event,其格式內容如下圖所示
@PostMapping("/messaging") public ResponseEntitymessagingAPI(@RequestHeader("X-Line-Signature") String X_Line_Signature, @RequestBody String requestBody) throws UnsupportedEncodingException, IOException{ if(checkFromLine(requestBody, X_Line_Signature)) { System.out.println("驗證通過"); JSONObject obje ct = new JSONO bject(requestBody); for(int i=0; i<object.getJSONArray("events").length(); i++) { if(object.getJSONArray("events").getJSONObject(i).getString("type").equals("message")) { messageHandler.doAction(object.getJSONArray("events").getJSONObject(i)); } } return new ResponseEntity<String>("OK", HttpStatus.OK); } System.out.println("驗證不通過"); return new ResponseEntity<String>("Not line platform", HttpStatus.BAD_GATEWAY); }
另外為了維護方便,作者另外撰寫了解析events訊息的class檔(MessageHandler)專門處理message event
@Component public class MessageHandler { private OkHttpClient client = new OkHttpClient(); @Value("${line.user.channel.token}") private String LINE_TOKEN; public void doAction(JSONObject event) { switch (event.getJSONObject("message").getString("type")) { case "text": text(event.getString("replyToken"), event.getJSONObject("message").getString("text")); break; case "sticker": sticker(event.getString("replyToken"), event.getJSONObject("message").getString("packageId"), event.getJSONObject("message").getString("stickerId")); break; } } private void text(String replyToken, String text) { JSONObject body = new JSONObject(); JSONArray messages = new JSONArray(); JSONObject message = new JSONObject(); message.put("type", "text"); message.put("text", text); messages.put(message); body.put("replyToken", replyToken); body.put("messages", messages); sendLinePlatform(body); } private void sticker(String replyToken, String packageId, String stickerId) { JSONObject body = new JSONObject(); JSONArray messages = new JSONArray(); JSONObject message = new JSONObject(); message.put("type", "sticker"); message.put("packageId", packageId); message.put("stickerId", stickerId); messages.put(message); body.put("replyToken", replyToken); body.put("messages", messages); sendLinePlatform(body); } public void sendLinePlatform(JSONObject json) { Request request = new Request.Builder() .url("https://api.line.me/v2/bot/message/reply") .header("Authorization", "Bearer {"+LINE_TOKEN+"}") .post(RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json.toString())) .build(); client.newCall(request).enqueue(new Callback() { @Override public void onResponse(Call call, Response response) throws IOException { System.out.println(response.body()); } @Override public void onFailure(Call call, IOException e) { System.err.println(e); } }); } }
其中可以看到兩個重點,一是Line Robot要回應訊息需透過Line官方提供的Reply-API("https://api.line.me/v2/bot/message/reply"),二是傳遞的格式,兩者會在之後的章節再詳細介紹,程式完成後就要將Line Robot正式上線。
上線的方法要先回到第一章節中Line機器人資訊,在Bassic Settings中的Channel secret為驗證Request是否來的Line Platform的LINE_SECRET,而在Messaging API中則要做一些基本資訊
在Webhook URL中須設定Line Robot的IP位置,其中Line官方的規範中,Line Robot須是走Https協定且不能是明碼,故本文章是使用Heroku免費的雲端平台進行測試,以及須開啟Use webhook選項
設定完成之後就可以實際上線測試咯~
留言
張貼留言