LINEと繋がってみよう

はじめに

皆さん、こんにちは
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アカウントに対して
キャンペーンやイベント情報の発信は可能かと思いますので
是非一度試してみてはと思います。