【Java】LINEのMessaging APIをサーブレットでさくっと実装してみたら未来が拓けた

Java 2016年10月4日


無限の可能性を感じる…(?)

0. はじめに

つい先日、遂にLINEのMessaging APIが公開されました。これを機に、今までLINE@に手を出していなかった個人・法人も、一斉に開発に乗り出すのではないでしょうか。


さて、早速このMessaging APIをJavaでさくっと試してみました。LINE@宛にメッセージが飛んできたら、それをWebhookで拾って、固定メッセージを返すという、超基本的サンプル的なものです。


さくっとなんで、説明もさくっとやります。



1. ざっくり用意するもの

  • Java8
  • Servlet(Tomcat)(Spring版SDKはこちらで公開されてます)
  • Jackson(JsonNode用)
  • Httpsサーバ(ちゃんと使えるやつを用意)



2. まずは登録から

こちらから登録します。手順などは割愛します。



3. Channel Secretとかをメモる

登録が済んだら、LINE Developersに行く。そして以下の画面を探す。


このChannel SecretChannel Access Tokenをメモる。



4. HTTPSのURLをWebhook URLに設定

HTTPSの環境構築はこれまた別の話なので割愛。


構築が済んだら、Webhook URLに登録する。画像は既に登録済み。ユーザからメッセージがあると、このURLにPOSTでリクエストが飛ぶようになる。VERIFYボタンでちゃんと使えるか確認できる。
リファレンス



5. ソースコード

省略してるところもありますが、大体以下のような感じ。

@WebServlet(name="LineServlet", urlPatterns={"/line"})
public class LineServlet extends HttpServlet {
    private static final String CHANNEL_SECRET = "channel_secret";
    private static final String CHANNEL_ACCESS_TOKEN = "channel_access_token";
    private static final String HMAC_SHA256 = "HmacSHA256";

    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 署名検証
        String body = null;
        try (Stream<String> stream = request.getReader().lines()) {
            String signature = request.getHeader("X-Line-Signature");
            body = stream.reduce((s1, s2) -> s1 + "\n" + s2).orElse("");
            SecretKeySpec key = new SecretKeySpec(CHANNEL_SECRET.getBytes(), HMAC_SHA256);
            Mac mac = Mac.getInstance(HMAC_SHA256);
            mac.init(key);
            byte[] source = body.getBytes(StandardCharsets.UTF_8);
            String createdSignature = Base64.encodeBase64String(mac.doFinal(source));
            if (!signature.equals(createdSignature)) {
                // LINEからのリクエストじゃない場合の処理
                // 常に200を返す
                response.setStatus(200);
                return;
            }
        } catch (IOException e) {
        } catch (NoSuchAlgorithmException e) {
        } catch (InvalidKeyException e) {}
        
        ObjectMapper mapper = new ObjectMapper();
        JsonNode events = mapper.readTree(body).path("events");
        // リプライの種類(今回はtext)
        String type = events.path(0).path("message").path("type").asText(null);
        // テキスト
        String query = events.path(0).path("message").path("text").asText(null);
        // 返信用Token
        String replyToken = events.path(0).path("replyToken").asText(null);
        // リプライを送る
        HttpPost httpPost = new HttpPost("https://api.line.me/v2/bot/message/reply");
        httpPost.setHeader("Content-Type", "application/json");
        httpPost.setHeader("Authorization", "Bearer " + CHANNEL_ACCESS_TOKEN);
        // 返信用のJSON
        // サンプルとして「リプライありがとう!」を返す
        String replyBody = String.format("{\"replyToken\":\"%s\", \"messages\":[{\"type\":\"text\", \"text\":\"リプライありがとう!\"}]}", replyToken);
        StringEntity params = new StringEntity(replyBody, StandardCharsets.UTF_8);
        httpPost.setEntity(params);
        try (CloseableHttpClient client = HttpClients.createDefault();
                CloseableHttpResponse resp = client.execute(httpPost);
                BufferedReader br = new BufferedReader(new InputStreamReader(resp.getEntity().getContent(), StandardCharsets.UTF_8)))
        {
            int statusCode = resp.getStatusLine().getStatusCode();
            switch (statusCode) {
            case 200:
                // ↓これは空のJSON({})が返るはず
                br.readLine();
                break;
            default:
            }
        } catch (final ClientProtocolException e) {
        } catch (final IOException e) {
        }
        response.setStatus(200);
    }
}

署名検証がちと長いかな。
以降の処理はよしなに書いてください。



6. LINE@アカウントにメッセージを送ってみよう

個別返信は出来ないと言っていたアカウントが…






こうじゃ!




ちゃんとお礼を言えるようになりました。良い子。



7. まとめ

めちゃくちゃ簡単に自動返信ができるようになりました。後はメッセージを解析してよしなに返信するスクリプトを組めば、もうLINEの既読に悩まされることも、未読スルーも関係ありませんね。


みなさんも是非Messaging APIを活用して、素敵なLINEライフを送りましょう!



参考

公式リファレンス

slont

金融ベンチャーでWebエンジニア

Great! You've successfully subscribed.
Great! Next, complete checkout for full access.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.