【Java】LINEのMessaging APIをサーブレットでさくっと実装してみたら未来が拓けた
無限の可能性を感じる…(?)
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 Secret
とChannel 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ライフを送りましょう!