使用サービス
- AWS API Gateway
- AWS Lambda
- LINE Message API
開発環境等
- Java 1.8
- Eclipse
- Maven
目的
- Line Message APIとの話の仕方を知りたい
- AWS Lambdaの使い方を知りたい。
この記事で説明を省いていること
-
LINEのアカウント開設やWebhook URLの設定
-
API Gatewayの設定の仕方
-
Line Message API側で"Server IP Whitelist"を設定し、AWS側でも認証させる仕組み
-
リクエストの送信元がLINEであることを確認するために署名検証
-
Lineで設定されるChannel Access TokenはLambdaの環境変数から取得する仕組み
手順
1. LINE Message API
- アカウント開設
- Webhook URLの設定
2. AWS API Gateway
- リソース作成
- 作成したリソースとLambda Functionを連携
3. Lambda Function
3.1. JSONをPOJOで受け取るためのInputクラス作成
3.2. Outputクラス作成
3.3. InputからreplyToken, text取得し、Outputに格納。合わせてReply Messageに必要な情報もセット。
3.4. OutputをJSONに変換
3.5. リクエストを生成し送信
3.6. 全体コード
3.1. JSONをPOJOで受け取るためのInputクラス作成
下記のJSONオブジェクトが送信されるので、Inputクラスもそれに合わせて構築する
{
"events": [
{
"replyToken": "nHuyWiB7yP5Zw52FIkcQobQuGDXCTA",
"type": "message",
"timestamp": 1462629479859,
"source": {
"type": "user",
"userId": "U206d25c2ea6bd87c17655609a1c37cb8"
},
"message": {
"id": "325708",
"type": "text",
"text": "Hello, world"
}
},
{
"replyToken": "nHuyWiB7yP5Zw52FIkcQobQuGDXCTA",
"type": "follow",
"timestamp": 1462629479859,
"source": {
"type": "user",
"userId": "U206d25c2ea6bd87c17655609a1c37cb8"
}
}
]
}
Input.java
package jp.linebot;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Input {
private Events[] events;
}
Events.java
package jp.linebot;
import org.joda.time.DateTime;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Events {
private String replyToken;
private String type;
private Long timestamp;
private Source source;
private Message message;
}
Source.java
package jp.linebot;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Source {
private String type;
private String userId;
}
Message.java
package jp.linebot;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Message {
private String id;
private String type;
private String text;
}
3.2. Outputクラス作成
Output.java
package jp.linebot;
import java.util.ArrayList;
import java.util.List;
import lombok.Data;
@Data
public class Output {
private String replyToken;
private List<Messages> messages = new ArrayList<>();
}
Messages.java
package jp.linebot;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Messages {
private String type;
private String text;
}
3.3. InputからreplyToken, text取得し、Outputに格納。合わせてReply Messageに必要な情報もセット。
Output output = new Output();
output.setReplyToken(input.getEvents()[0].getReplyToken());
Messages outMessage = new Messages();
outMessage.setType("text");
outMessage.setText(input.getEvents()[0].getMessage().getText() + "?");
output.getMessages().add(outMessage);
3.4. OutputをJSONに変換
Gson gson = new Gson();
context.getLogger().log(gson.toJson(output));
3.5. リクエストを生成し送信
httpPost = new HttpPost("https://api.line.me/v2/bot/message/reply");
httpPost.setHeader("Content-Type", "application/json");
httpPost.setHeader("Authorization", "Bearer " + "{Channel Access Token}");
StringEntity entity = new StringEntity(gson.toJson(output), StandardCharsets.UTF_8);
httpPost.setEntity(entity);
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:
br.readLine();
break;
default:
}
} catch (final ClientProtocolException e) {
} catch (final IOException e) {
}
return null;
3.6. 全体コード
LambdaFunctionHandler.java
package jp.linebot;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.google.gson.Gson;
public class LambdaFunctionHandler implements RequestHandler<Input, Object> {
@Override
public Object handleRequest(Input input, Context context) {
// TODO Auto-generated method stub
context.getLogger().log("token : " + input.getEvents()[0].getReplyToken());
context.getLogger().log("text : " + input.getEvents()[0].getMessage().getText());
Output output = new Output();
output.setReplyToken(input.getEvents()[0].getReplyToken());
Messages outMessage = new Messages();
outMessage.setType("text");
outMessage.setText(input.getEvents()[0].getMessage().getText() + "?");
output.getMessages().add(outMessage);
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}");
Gson gson = new Gson();
context.getLogger().log(gson.toJson(output));
StringEntity entity = new StringEntity(gson.toJson(output), StandardCharsets.UTF_8);
httpPost.setEntity(entity);
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:
br.readLine();
break;
default:
}
} catch (final ClientProtocolException e) {
} catch (final IOException e) {
}
return null;
}
}