この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
Salesforceには、外部APIを呼び出すコールアウトの仕組みがあります。
いま、問い合わせを受け付けるフォームによってSalesforceにてリードが自動作成されているとします。 そして、リードに対応するチケットを Jira Cloud に自動で作りたいとします。
この要件をコールアウトを使用して実現したいと思います。
Jira API を呼び出すコールアウトの実装
設定
Salesforce のコールアウトを実装するために、Salesforceの認証プロバイダ、指定ログイン情報の設定、またJiraにAppを設定します。
Salesforce 認証プロバイダの設定
Jiraの認証プロバイダを設定します。認証プロバイダと後述する指定ログイン情報を使うことで、認証周りのコードをApexで書かなくてよくなります。
認証プロバイダに設定する各値は次の通りです。
項目 | 設定値 |
---|---|
プロバイダタイプ | Open ID Connect |
名前 | Jira1 |
URL 接尾辞 | auth |
コンシューマ鍵 | 後述するJira Appの設定から取得してセットする |
コンシューマの秘密 | 後述するJira Appの設定から取得してセットする |
承認エンドポイント URL | https://auth.atlassian.com/authorize?audience=api.atlassian.com |
トークンエンドポイント URL | https://auth.atlassian.com/oauth/token |
デフォルトの範囲 | read:jira-work manage:jira-project manage:jira-configuration read:jira-user write:jira-work manage:jira-data-provide offline_access |
ヘッダーでアクセストークンを送信 | チェックする |
API 応答にコンシューマの秘密を含める | チェックする |
他の項目 | 入力およびチェックしない |
設定して、認証プロバイダを保存すると自動的に「Salesforce 設定」ブロックの各URLが生成されます。 このうちの「コールバック URL」を後述するJira Appの設定で使いますので控えておきます。
Jira Appの作成
https://developer.atlassian.com/console/myapps/にアクセスして、Jira Appを作成します。
ここでは「SalesforceSync」というAppを作成しました。Appを選択し詳細設定を行います。
左メニューから「Permissions」を選びます。 Permissionsの一覧から「Jira platform REST API」を「Add」し、「Configure」ボタンをクリックします。
REST API で使えるスコープのリストが表示されるので、必要なスコープ(権限)を「Add」します。 私はここでは全スコープをAddしました。
次に左メニューから「Authorization」を選びます。
Authorization type 「OAuth 2.0 (3LO)」の「Configure」ボタンをクリックします。
Callback URLを設定する画面が表示されますので、認証プロバイダの設定で控えておいた「コールバック URL」を設定します。
次に左メニューから「Settings」を選びます。
ページの下部に「Client ID」と「Secret」が取得できますので控えます。 そして先に作成した認証プロバイダの「コンシューマ鍵」に「Client ID」を、「コンシューマの秘密」に「Secret」をそれぞれ設定します。
Salesforce 指定ログイン情報の設定
Jiraの指定ログイン情報を設定します。
指定ログイン情報に設定する各値は次の通りです。
項目 | 設定値 |
---|---|
表示ラベル | Jira |
名前 | Jira |
URL | https://<お使いのサブドメイン>.atlassian.net |
ID 種別 | 指定ユーザ |
認証プロトコル | OAuth 2.0 |
認証プロバイダ | Jira2 |
認証ヘッダーを生成 | チェックする |
保存時に認証フローを開始3 | チェックする |
他の項目 | 入力、チェックしない |
ここまでの設定が正しければ、JiraとSalesforce間の認証を求める画面が表示されますので、承諾して認証してください。 「認証状況」が「認証済み」になれば、コールアウトを使う準備は完了です。
接続検証
Salesforceの開発者コンソールを立ち上げて[Debug] > [Open Execute Anonymous Window]を選びます。
立ち上がったウィンドウで次のApexコードを記述し、「Execute」します。
HttpRequest req = new HttpRequest();
req.setEndpoint('callout:Jira/rest/api/3/user?accountId=<取得したいJiraアカウントのアカウントID>');
req.setMethod('GET');
Http http = new Http();
HttpResponse res = http.send(req);
System.debug(res);
System.debug(res.getBody());
ログを確認して、ステータスコード200が返ってきていれば成功です。
細かな認証の取り回しを実装しなくても、
req.setEndpoint('callout:<指定ログイン情報名><Rest API パス>');
でRest APIを簡単に呼び出すことができます。
実装
それでは、Salesforceでリード作成時にJiraにチケットを作成する処理を実装します。
public inherited sharing class JiraIssueGenerator {
private Fields fields;
private final static String CRLF = '\r\n';
@InvocableVariable
public List<Id> leadIds;
public JiraIssueGenerator(Id leadId) {
Lead lead = [SELECT Name, Company, Email, Phone FROM Lead WHERE Id = :leadId LIMIT 1];
String summary = lead.Name + ' からのお問い合わせ';
Description description = new Description(lead.Name + ' からお問い合わせがありました。' + CRLF + '連絡先はメールアドレスは ' + lead.Email + '、電話番号は ' + lead.Phone + ' です。');
this.fields = new Fields(summary, description, new Project('TEST'), new IssueType('10001'), new Assignee('6033128f2de69b006aed7155'));
}
@InvocableMethod(Label='JiraにIssueを作成する')
public static void generate(List<Id> leadIds) {
callHTTPRequest(leadIds);
}
@future(callout=true)
public static void callHTTPRequest(List<Id> leadIds){
for (Id leadId : leadIds) {
JiraIssueGenerator jig = new JiraIssueGenerator(leadId);
HttpRequest req = new HttpRequest();
req.setEndpoint('callout:Jira/rest/api/3/issue');
req.setMethod('POST');
req.setHeader('Content-Type', 'application/json');
req.setHeader('Accept', 'application/json');
req.setBody('{"fields": ' + JSON.serialize(jig.fields) + '}');
system.debug(req.getBody());
Http http = new Http();
HttpResponse res = http.send(req);
System.debug(res);
System.debug(res.getBody());
}
}
private class Fields {
private String summary;
private Description description;
private Project project;
private IssueType issuetype;
private Assignee assignee;
private Fields(String summary, Description description, Project project, IssueType issuetype, Assignee assignee) {
this.summary = summary;
this.description = description;
this.project = project;
this.issuetype = issuetype;
this.assignee = assignee;
}
}
private class Description {
private String type;
private Integer version;
private List<ParagraphContent> content;
private Description(String text) {
this.type = 'doc';
this.version = 1;
this.content = new List<ParagraphContent>();
this.content.add(new ParagraphContent(text));
}
}
private class ParagraphContent {
private String type;
private List<TextContent> content;
private ParagraphContent(String text) {
this.type = 'paragraph';
this.content = new List<TextContent>();
this.content.add(new TextContent(text));
}
}
private class TextContent {
private String type;
private String text;
private TextContent(String text) {
this.type = 'text';
this.text = text;
}
}
private class Project {
private String key;
private Project(String key) {
this.key = key;
}
}
private class IssueType {
private String id;
private IssueType(String id) {
this.id = id;
}
}
private class Assignee {
private String id;
private Assignee(String id) {
this.id = id;
}
}
}
大まかに以下の流れの処理を行っています。
- generateメソッドで対象リードのSalesforce Id(のリスト)を受け取る
- callHTTPRequestメソッドにリードIdのリストを渡して呼び出す
- 各リードId毎に当該リードの情報をSOQLで取り出す
- 取り出したリード情報からJiraのIssueを作成するためのJSONを作る
- 4で作成したJSONをbodyにセットして、Issue作成の
/rest/api/3/issue
エンドポイントにPOSTを実行する - 3〜5を2で受け取ったリストに含まれるIdの個数分繰り返す
求められるJSONのフォーマットは公式ドキュメントを参照してください。
プロセスビルダーからのApex起動
リード作成時に起動するプロセスをプロセスビルダーで作成します。
アクションの設定でApexのgenerateメソッドをコールし、引数として作成したリードのIdを渡しています。
先に作成したApexでgenerateメソッドに @InvocableMethod(Label='JiraにIssueを作成する')
と設定しているのでプロセスビルダーでは「JiraにIssueを作成する」を選ぶことでgenerateメソッドをコールできます。
また、 leadIdsに @InvocableVariable
と設定しているので、プロセスビルダーからleadIdsに対して先述の通りリードのIdを渡すことができます。
ちなみに、generateメソッドはcallHTTPRequestメソッドに受け取ったパラメータを渡しているだけなので一纏めにできそうですが、generateメソッドの中でコールアウトを行おうとするとプロセスビルダーから呼んだ時に
System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling
のエラーが発生します。そのため、コールアウト処理は別メソッドに括り出して @future(callout=true)
をつけて非同期で呼び出しています。
動作確認
Salesforceでリードを新規作成してみて、Jiraにチケットが作成されていることを確認します。
Jiraを見てみると…
Issueが作成されています!
まとめ
Salesforce から Jira の Rest APIをコールアウトすることで、リード作成時に Jira の Issue を自動で作成することができました。
また、Salesforce からコールアウトを行う時には認証プロバイダと指定ログイン情報を使うことで認証周りの複雑な取り回しをコードで実装しなくても済むこともおわかりいただけたかと思います。Apexコードがすっきりしますので是非ご活用ください。