2018.03.22

SalesforceからBacklogAPIを利用してみる

はじめに

こんにちは。
2回目になる八木です。

さて、弊社では課題やタスクの管理にBacklogを利用しています。
ただ、勤怠管理など社内業務ではSalesforceにログインする必要があります。
両方にログインすることなく、情報を見られればなぁと考えていました。
そこで今回はSalesforceで作成した画面に、BacklogAPIを利用して情報を表示したいと思います。(自分の勉強も兼ねて)

Backlogとの連携方法は?

Backlogの情報を取得するにはBacklogから提供されているAPIを利用する必要があります。
今回はOAuth2.0方式を使用してみたいと思います。
詳細は以下リンク先を参照ください。

Salesforce側の画面構築は?

こちらはLightningコンポーネントで実装してみたいと思います。
※Lightningコンポーネント自体の説明は割愛させて頂きます。

事前準備~認可まで

1.Backlogアプリケーション登録を行い、CLIENT_IDとCLIENT_SECRETを入手します。

Backlogアプリケーション登録

Redirect URIは認可後に遷移するURLを指定します。今回はLightningコンポーネントで作成するページになります。

Salesforce2Backlog

2.入手したCLIENT_IDとCLIENT_SECRETなどをカスタム表示ラベルに定義し、Apexで利用します。

    private static final String BASE_URL        = System.Label.BACKLOG_BASE_URL;
    private static final String CLIENT_ID       = System.Label.BACKLOG_CLIENT_ID;
    private static final String CLIENT_SECRET   = System.Label.BACKLOG_CLIENT_SECRET;
    private static final String REDIRECT_URI    = System.Label.BACKLOG_REDIRECT_URI;
BacklogAPICaller.cls

3.Lightningコンポーネントから認可リクエストを実行します。

「Backlog連携」ボタンを押下すると認可リクエストを実行します。

認可リクエスト

    @AuraEnabled
    public static String goAccessRequest() {
        PageReference pr = new PageReference(BASE_URL + '/OAuth2AccessRequest.action?response_type=code&client_id=' + CLIENT_ID);
        aura.redirect(pr);
        return null;
    }
BacklogAPICaller.cls

ポイント!

PageReferenceを戻り値にはできないため、リダイレクトするには、aura#redirectを呼び出す必要があります。
この方法がわからず、かなりの時間を費やすことに。。。

4.認可します。

認可リクエスト先の画面が起動し、認可を求めてきます。

認可リクエスト先

認可後~トークン情報取得

1.認可コードが返されるので、その値を使いトークン情報を取得します。

引数codeが認可コードに該当し、searchMyTaskは自分が担当になっている課題を取得しています。
TokenInformationDao#upsertTokenは取得したトークン情報をSalesforce上に格納しています。(2回目以降やリフレッシュ時に利用想定)
    @AuraEnabled
    public static String getTokenAndSearchMyTask(String code) {
        String token = getAuthorizationCode(code);

        String myTask = searchMyTask(token);
        TokenInformationDao.upsertToken(TOKEN_KEY, token);

        return myTask;
    }
BacklogAPICaller.cls

2.Lightningコンポーネントから上記トークン情報取得メソッドを呼び出します。

    getTokenInfoAndSearchMyTaskInfo: function(component, event, code) {
        var action = component.get("c.getTokenAndSearchMyTask");
        action.setParams({
            "code": code
        });
        action.setCallback(this, function(response) {
            if (response.getState() == "SUCCESS") {
                this.setMyTaskInfo(component, event, response.getReturnValue());
                this.showToast(component, event, "success", "データ取得成功", "Response State is " + response.getState());
            } else {
                this.showToast(component, event, "error", "トークン/データ取得失敗", "Response State is " + response.getState() + " - " + response.getReturnValue());
            }
        });
        $A.enqueueAction(action);
    }
BacklogAPICallerHelper.js
※各APIコール用メソッドを個々に定義しておくと再利用しやすいと思います。
    /**
     * アクセストークンを取得する
     */
    @TestVisible
    private static String getAuthorizationCode(String code) {

        String endpoint      = BASE_URL + '/api/v2/oauth2/token';
        String method        = 'POST';
        String accept        = null;
        String contentType   = 'application/x-www-form-urlencoded';
        String authorization = null;
        String body          = 'grant_type=authorization_code&code=' + code + '&client_id=' + CLIENT_ID + '&client_secret=' + CLIENT_SECRET;

        return callRequest(endpoint, method, accept, contentType, authorization, body);
    }

    /**
     * アクセストークンを更新する
     */
    @TestVisible
    private static String getRefreshToken(String refreshToken) {

        String endpoint      = BASE_URL + '/api/v2/oauth2/token';
        String method        = 'POST';
        String accept        = null;
        String contentType   = 'application/x-www-form-urlencoded';
        String authorization = null;
        String body          = 'grant_type=refresh_token&client_id=' + CLIENT_ID + '&client_secret=' + CLIENT_SECRET + '&refresh_token=' + refreshToken;

        return callRequest(endpoint, method, accept, contentType, authorization, body);
    }

    /**
     * 自分が担当で未完了となっている課題を取得する
     */
    @TestVisible
    private static String getMyIncompleteIssues(String accessToken, String tokenType, String myselfId, Set<String> incompleteStatusIdSet, Integer count) {

        String statusParam = '';
        for (String s : incompleteStatusIdSet) {
            statusParam += '&statusId[]=' + s;
        }
        String queryString   = 'assigneeId[]=' + myselfId + statusParam + '&count=' + count + '&sort=priority&order=asc';
        String endpoint      = BASE_URL + '/api/v2/issues?' + queryString;
        String method        = 'GET';
        String accept        = 'application/json';
        String contentType   = 'application/json;charset=utf-8';
        String authorization = tokenType + ' ' + accessToken;
        String body          = null;

        return callRequest(endpoint, method, accept, contentType, authorization, body);
    }
    etc.
BacklogAPICaller.cls

ポイント!

外部アクセスになるため、リモートサイトの設定を忘れずにしておきましょう。

3.トークン情報の格納先。

取得したトークン情報の格納先として、トークン情報オブジェクト[TokenInformation__c]を作成します。以下項目を用意しています。
非公開に設定し、トークン情報はAPIで取得したJSON形式のまま格納しています。
項目名 API名 備考
トークン情報キー TokenInformationKey__c ユニーク、外部ID
トークン情報(JSON) TokenInformationJSON__c JSONのまま

成功すると・・・

カード形式

表形式

無事自分のタスクが表示されました!
カード形式は lightning:cardタグ 、バッチ表示は lightning:badgeタグ を使用して見た目を整えています。

ポイント!

Lightningコンポーネントが標準で採用している LIGHTNING DESIGN SYSTEM を利用すれば、レスポンシブもこの通り簡単に対応可能です。

スマホ形式

おわりに

LightningコンポーネントでのAPI連携という自分にとっては少し未知の領域でしたがうまく連携できました。
様々なサービスを利用している方はこのようにAPIを利用し情報をひとつで確認できると助かるのではないでしょうか。
日々使っているサービスでもAPIを利用して効率的に作業ができると良いですね!

資料ダウンロード

46 件
     
  • banner
  • banner

関連する記事