tyoshikawa1106のブログ

- Force.com Developer Blog -

SFDC:Community Cloud開発向け - Apex TriggerとConnect APIで試行錯誤した話

Community Cloudで顧客とChatterでやりとりする際に相手の投稿が通知されない問題に遭遇することがあると思います。例えば自分のユーザプロファイルに直接投稿してもらったり、メンションを指定してくれれば通知メールは届きますが、B2Cの顧客にそんなことをお願いするのは難しいと思います。


そこでApexトリガで対応するのはどうかと下記のトリガ処理をつくってみました。(サンプル処理なので本番向けではありません。)

trigger FeedItemTrigger on FeedItem (after insert) {

    private FeedItemTriggerHandler handler = new FeedItemTriggerHandler();

    if (Trigger.isAfter) {
        if (Trigger.isInsert) {
            // コミュニティユーザがサポートフィードに投稿したことを担当者に通知
            handler.notificationCustomerChatterPost(Trigger.new);
        }
    }
}
public with sharing class FeedItemTriggerHandler {

    /**
     * コンストラクタ
     */
    public FeedItemTriggerHandler() {
        
    }

    /**
     * コミュニティユーザがサポートフィードに投稿したことを担当者に通知
     */
    public void notificationCustomerChatterPost(List<FeedItem> feedItems) {
        // サポートフィードへの投稿を通知対象として取得
        List<FeedItem> targetFeedItems = new List<FeedItem>();
        for (FeedItem f : feedItems) {
            // オブジェクト判定
            if (String.isNotEmpty(f.ParentId) && f.ParentId.getSObjectType().getDescribe().getName() == 'Support__c') {
                targetFeedItems.add(f);
            }
        }
        // Chatterに投稿
        for (FeedItem f : targetFeedItems) {
            // new connect api
            ConnectApi.MentionSegmentInput mentionSegmentInput = new ConnectApi.MentionSegmentInput();    
            ConnectApi.FeedItemInput feedItemInput = new ConnectApi.FeedItemInput();
            ConnectApi.MessageBodyInput messageBodyInput = new ConnectApi.MessageBodyInput();
            ConnectApi.TextSegmentInput textSegmentInput = new ConnectApi.TextSegmentInput();
            ConnectApi.FeedElementCapabilitiesInput feedElementCapabilitiesInput = new ConnectApi.FeedElementCapabilitiesInput();
            // new List
            messageBodyInput.messageSegments = new List<ConnectApi.MessageSegmentInput>();
            // Post Message
            String post = '【システム通知】新しいメッセージが投稿されました。';
            // textSegment set
            textSegmentInput.text = post;
            messageBodyInput.messageSegments.add(textSegmentInput);
            
            // feedItem set
            feedItemInput.body = messageBodyInput;
            feedItemInput.feedElementType = ConnectApi.FeedElementType.FeedItem;

            // Use a group ID for the subject ID.
            feedItemInput.subjectId = '<TARGET_USER_ID>';

            // capabilities
            feedElementCapabilitiesInput.link = new ConnectApi.LinkCapabilityInput();
            feedElementCapabilitiesInput.link.url = 'https://<YOUR_DOMAIN>.salesforce.com/' + f.parentId;
            feedElementCapabilitiesInput.link.urlName = 'メッセージリンク';
            feedItemInput.capabilities = feedElementCapabilitiesInput;

            // Mention a group.
            mentionSegmentInput.id = 'TARGET_USER_ID';
            messageBodyInput.messageSegments.add(mentionSegmentInput);

            // Chatter Post
            ConnectApi.FeedElement feedElement = ConnectApi.ChatterFeeds.postFeedElement(Network.getNetworkId(), feedItemInput);
        }
    }
}

顧客がコミュニティから投稿すると・・・
f:id:tyoshikawa1106:20170305212000p:plain


Apexトリガの処理が実行され、所有者ユーザのプロファイルにメンション付きで通知投稿が行われます。それにより次のようなメール通知が届きます。
f:id:tyoshikawa1106:20170305212147p:plain


Salesforceにログインしてメール内のリンクをクリックすると対象の投稿ページに移動できます。
f:id:tyoshikawa1106:20170305212306p:plain


これで顧客の投稿時に通知メールを送信できるのではと考えました。

やってみてわかったこと

1. FeedItemトリガだけではコメント投稿時に処理が実行されない。

FeedItemオブジェクトはChatterの投稿用オブジェクトなのでコメント投稿時には実行されません。コメント投稿時には標準の通知機能が働くので大きな問題ではないですが、正しくやるにはコメントオブジェクトにもトリガを用意した方が安全かもしれません。

2. 社内用Chatterページにはコミュニティ側の投稿は表示されない

コミュニティ内で社内ユーザにメンション付きで投稿しても社内ユーザのプロファイルページには表示されませんでした。ここも大きな問題にはならないと思いますが地味に落とし穴です。
f:id:tyoshikawa1106:20170305212746p:plain

3. 社内のChatterグループはコミュニティ側ではアクセスできない。

例えばコミュニティユーザの連絡通知投稿をひとつにまとめるためにChatterグループを用意しても、コミュニティ側ではアクセスできません。コミュニティ側でChatterグループを作成すればアクセスは可能ですが、コミュニティに移動しないと見れませんし本来の用途としてはあまり意味のないものになってしまいました。
f:id:tyoshikawa1106:20170305213054j:plain

4. Community Login UserライセンスでもConnect APIは利用可能

そもそもライセンス的に実装可能なのか不安だったのですが、これは問題ありませんでした。APIの利用を許可の設定はプロファイルで指定できます。Community Login Userライセンスが問題なければ他のライセンスでもほぼ問題ないはずです。ただしConnect APIには利用時の制約があるので注意して下さい。

Salesforce Developers

5. 通知のための処理にApexトリガは向いていない..と思う

最終的に通知メールを送信するためにApexトリガを使うのは向いていないと思います。投稿時にトリガで通知用の別投稿を行うということがそもそも効率的ではないと思います。投稿機能自体を自作してしまい、投稿時にかならずメンションを付ける処理にした方が、投稿/コメント関係なく通知メールが届きますし、通知メールから直接返信も可能になります。


このトリガをつかった方法で一番の障壁は顧客のプロフィールページにApexトリガから投稿した内容が表示されてしまうことです。
f:id:tyoshikawa1106:20170305214802p:plain


これも致命的な問題では無いと思うのですがあまり綺麗ではないと思います。


こんな感じでいろいろ試行錯誤してみたのですが、ApexトリガでConnectAPIをつかって通知するのはイマイチな方法だと感じました。投稿機能が自作する方が綺麗なシステムになると思います。

Connect API (Chatter in Apex) のサンプル (Spring'16バージョン)

少し前のバージョン用ですがまだ利用できると思います。

Demo Video1

Demo Video2

Demo Video3