LINEと繋がってみよう

  • Posted on

はじめに

皆さん、こんにちは
SalesforceのイベントでLINEBotを活用したデモンストレーションや
DreamHouseサンプルアプリケーションでLINEBotを試した方も多いかと思います。

DreamHouseはLINEのWebHook先をHerokuアプリケーションに設定し、
Herokuを介してSalesforceと繋がっています。

今回、ご紹介する方法はHerokuを介さず、直接Salesforceに繋ぐ方法になります。
それでは設定していきましょう。

LINE Developersアカウントの取得

まずはLINE Business CenterからDeveloper用のアカウントを取得します。
https://business.line.me/ja/
Developer用としてアカウントを新規作成できなさそうなので、
自分のLINEアカウントを使用してDeveloper用を作成しました。

Webhook送信は「利用する」に設定する

2017-02-05_BotSetting001.png

  • QR Code:友達申請用のQR
  • Webhook URL:hook先のURL ⇒後で設定します

2017-02-05_LINESetting002.png

Salesforceの設定

1:WebService作成
Webhookから呼び出されるWebServiceを作成します。
LINEは「友達申請」「メッセージ送信」の度にWebhook先へJSONで
POSTしますので、「ApexRest」を使用します。

内容は単純にJSONの情報を元に「userId」が存在しなければ、取引先にレコードを作成。
「友達追加(follow)」されれば取引先の「LineFollow」をTrueに更新、
「ブロック(unfollow)」されれば取引先の「LineFollow」をfalseに更新します。
※LINEのAPIはhttps://devdocs.line.me/ja/#webhook-event-object参照

@RestResource(urlMapping='/line_webhook_callback')
global with sharing class LineWebHookCallback {
@HttpPost
global static Map<String,String> doPost(){
RestRequest req = RestContext.request;
RestResponse res = RestContext.response;
Map<String, Object> callbackParams = (Map<String, Object>)JSON.deserializeUntyped(req.requestBody.ToString());
List<Object> resultParams = (List<Object>)callbackParams.get('events');
List<Account> accList = new  List<Account>();
for (Object obj : resultParams) {
Map<String, Object> params = (Map<String, Object>)obj;
String eventType = (String)params.get('type');
Map<string, object> sourceParams = (Map<String, Object>)params.get('source');
Account acc = new Account();
String userId = (String)sourceParams.get('userId'); 
acc.Name = userId;          
acc.LineUserId__c = userId;
acc.AccountSource = 'Line';           
String sourceType = (String)sourceParams.get('type');           
if(eventType == 'follow'){
acc.LineFollow__c= true;
}else if(eventType == 'unfollow'){
acc.LineFollow__c= false;      
}else if( eventType == 'message' ){
acc.LineFollow__c= true;
}
if(acc != null){
accList.add(acc);
}
}
if(accList.size()>0){
Schema.SObjectField f = Account.Fields.LineUserId__c;
List<Database.upsertResult> uResults = Database.upsert(accList,f,false);
}
Map<string, string> result= new Map<String, String>();
result.put('result', 'success');         
return result;
}
}

2:サイト設定
WebServiceを公開しても、LINEのWebhookはSalesforceのログイン情報を
保持していないのでアクセスできません。
そのためサイト設定をし、ゲストユーザとしてWebServiceを起動します。
サイトの設定方法に関しては割愛します。
ここで重要なのが、カスタムURLの「ドメイン名」でWebhookの設定に使用します。

2017-02-05_SiteSetting.png

3:ゲストユーザのプロファイル設定
公開アクセス設定よりゲストユーザのプロファイル設定を行います。
「1:WebService作成」で作成したApexClassに対して権限を付与していきます。
取引先のCRUDに「参照・作成」権限を付与
有効な Apex クラスに「1:WebService作成」で作成したApexClassを追加します。

2017-02-05_AccountCRUD.png2017-02-05_ApexClassSetting.png

Salesforce側の設定は以上になります。
最後にLINE DevelopersからWebHookの設定を行います。

https://<サイトURL>/services/apexrest/<urlMapping>
※urlMappingはWebServiceの@RestResourceで指定した設定

2017-02-05_WebhookURLSetting.png

動作確認

では早速動作確認をしていきましょう。
まずはLINEから友達の追加を行います。
スマートフォンからLINE Developersの「QRCode」を読み込みます。

2017-02-05_LINEAddFriends.PNG

友達追加すると取引先ができました。
ただ、POST情報の中にはユーザのプロフィール情報がないので、
取引先に追加しましたが情報が乏しいですね。
ユーザのプロフィールを取得するAPIも提供されていますが、
「表示名」「画像」「ステータスメッセージ」ぐらいしかありません。

2017-02-05_AccountCreate001.png

SalesforceからLINEへの通知

先程までの手順はLINEからSalesforceへの通知でしたが次は
SalesforceからLINEへの通知を設定していきましょう。
今回はイベント(カスタムオブジェクト)のタイトルが変更された時に
Push通知を行うサンプルを作ってみます。

1:リモートサイトの設定
SalesforceからLINEへのコールアウトが発生するため、LINEをリモートサイトへ登録します。

  • リモートサイトの URL:https://api.line.me

2017-02-05_RemoteSite.png

2:Push通知機能の実装
Push通知はプロセスビルダーからオブジェクト変更時に
Apexを発火させる方法にしました。
また、同じトランザクション内でDML発効後にコールアウトはできないため、
Queueableを使用した非同期処理にしています。

  • CH_ACCESS_TOKEN:LINE Developersの「Channel Access Token」
public with sharing class LinePushMessageWs{
static String LINE_PUSH_MESSAGE_URI = 'https://api.line.me/v2/bot/message/push';
static String CH_ACCESS_TOKEN       = '----------';
@InvocableMethod(label='LINEへのPush通知')
public static void EventPushMessage(List<String> eventId){
//JSONデータ作成
List<EventEntrant__c> EeJson = new List<EventEntrant__c>();
EeJson =  [select 
id,
Event__r.Title__c,
Event__r.EventURL__c,
Entrant__r.LineUserId__c
from 
EventEntrant__c
where 
Event__c = :eventId and
Entrant__r.LineUserId__c <> null and
Entrant__r.LineFollow__c = true
];
String body ='';
for(EventEntrant__c eeObj:EeJson){       
body = body + '{"to": "' + eeObj.Entrant__r.LineUserId__c + '","messages":[{"type":"text", "text":"' + eeObj.Event__r.Title__c + 'が更新されました"}, { "type":"text", "text":"' + eeObj.Event__r.EventURL__c  + '" }]}';
}
System.debug('##body' + body);
System.enqueueJob(new QueueablePushCall(body));
}
public class QueueablePushCall implements System.Queueable, Database.AllowsCallouts {
String body;
public QueueablePushCall(String body) {
this.body= body;
}
public void execute(System.QueueableContext ctx) {
HttpRequest req = new HttpRequest();
req.setHeader('Content-Type', 'application/json');
req.setHeader('Authorization', 'Bearer '+ CH_ACCESS_TOKEN);
req.setEndpoint(LINE_PUSH_MESSAGE_URI);
req.setMethod('POST');
req.setBody(body);
//HTTPリクエストの送信
Http http = new Http();
HttpResponse res;
try {
res = http.send(req);
System.debug('##HTTP Response Code: ' + res.getStatusCode());
System.debug('##Response Body: ' + res.getBody());
} catch (Exception e) {
System.debug('##Callout Error:' + e.getMessage());           
}
}       
}
}

プロセスビルダの設定

2017-02-05_ProcessBuild.png

動作確認

イベントのタイトルを変更すると、LINEへ
通知がされたことを確認できましたね。

2017-02-05_EventSeeting.pngIMG_3041.PNG

最後に

LINEのアカウント作成から、Salesforceの設定、LINEへのPush通知と色々説明しましたが
簡単にLINEと繋がることができると感じて頂けたのではないでしょうか。
LINEの友達追加をリード情報として利用することはできますが、
プロフィール情報が少ないため物足りないかと思います。

ただ、Salesforceに溜まったLINEアカウントに対して
キャンペーンやイベント情報の発信は可能かと思いますので
是非一度試してみてはと思います。