Quantcast
Channel: Salesforce –ぱーくん plus idea
Viewing all 62 articles
Browse latest View live

Salesforceのデータを検索・確認できるGUIツール① WorkBench

$
0
0

Salesforceのデータを手軽に検索、更新する場合に使えるのが、Workbenchです。

オープンソースのWebベースの別アプリケーションですが、

Salesforceとのシングルサインオンも実現されているので、Salesforceと同じログインIDを使用することができます。

SalesforceのIDでOAuth認証を行って権限委譲し、APIを使ってSalesforceからデータを取得したり、操作したりしているイメージですね。

Workbenchを使うと以下のようなことができます。

 

Workbenchでできること

  • Salesforce の APIを使って、データの検索・更新・削除等ができる
  • 検索の結果を CSV ・XML形式に出力できる
  • CSV ・XML形式からのデータ更新(Dataloaderと同じようなこと)ができる
  • データの検索結果からSalesforce上のデータを閲覧できる
  • WebベースのクライアントでREST-APIの確認ができる

では、早速つかってみることにしましょう。

 

ログイン

はじめにログインを行います。

ここから接続先の環境とAPIバージョンを選択して、進みます。

ここで選択した内容が、接続先のEndpointになります。

 

 

先に進むと、Salesforceのログイン画面が表示されます。

 

上記で入力したユーザIDでSalesforceに対して認証を行い、OKであれば、

下記のアクセス許可の内容で許可した権限がWorkbenchに委譲されます。

 

 

さて、ログインできたら、ひととおりWorkbenchでできることを確認してみます。

 

オブジェクトのメタ情報確認

メニューの「Info」⇒「Standard & Custom Objects」を選択すると、以下のような画面になります。

ここで、対象のオブジェクトを選びます。

通常のオブジェクト情報を確認するには、「Standard & Custom Objects」を選ぶといいでしょう。

 

 

 

その後、対象のオブジェクトを選ぶと、そのオブジェクトのメタ情報が書くにできます。

フィールドや属性が確認できますね。

 

 

 

SOQLによるデータ検索

Workbenchには、WebのGUIで、SOQLを構築し、データを確認できる機能もあります。

下記のように、オブジェクトを選択し、セレクト対象のカラムを

「Ctrl」を押しながら複数選択すると、SOQL文が構築され、「Query」ボタンを押せば結果が表示されます。

Id項目はリンクになっており、押下すると、そのレコードの詳細を確認したり、

更新したりできる画面に遷移します。

 

 

 

SOSLによるデータ検索

SOSLによる検索もできます。

SOSLはグローバル検索のように、複数のオブジェクトを跨いだ検索が可能です。

SOSLクエリは癖があり、構文に慣れるまではSOSLクエリを書きにくいので、

GUIで構築できるWorkbenchは結構重宝します。

 

 

データの挿入・更新・削除

メニューの「data」には、Insert,Update,Upsert,Delete,Undelete,Purgeなどのリストがあり、DataloaderでできるようなことがWebから実行できます。

ファイルでの更新にも対応していますが、

あまりに大量のデータで実行するとタイムアウトする可能性もあるので、注意しましょう。

ただ、手軽にデータを更新するには非常に便利な機能です。

 

 

 

REST APIの実行、確認

Salesforceで提供しているREST APIを実行したり、確認したりすることができます。

REST APIによる開発時にクエリの構文や実行結果を確認するのに便利です。

 

 

/services/data/v36.0/query?q=SELECT+Id+,+Name+,+AccountNumber+FROM+Account

 

 

 

まとめ

いかがでしたでしょうか。

SalesforceのAPIを使って構築されているWebアプリなので、

非常に直感的で、特に、開発者にとっては

イメージしやすいのではないかとおもいます。


Salesforceのデータを検索・確認できるGUIツール② Force.com Explorer

$
0
0

Force.com ExplorerはAdobe Flashでできたデータベースエクスプローラです。

オブジェクトのフィールドや、ラベルを確認するのに便利で、

SOQLクエリの構築も行えますので、構文を確認したりするのにも重宝します。

あまりバージョン更新がされず、APIが少し古かったりもするのですが、

それでも、Workbenchよりもすばやくデータの確認を行える手軽さは、

開発時に大いに役立つはずです。

 

 

Force.com Explorerの便利な使い方

いろいろと便利に使えますが、代表的なTipsをご紹介します。

 

1.クエリの確認を行う。

左ペインにオブジェクトが表示されていますので、

それを選択したり、項目を選択することで、クエリの構築ができます。

自分で項目名を記述する必要がないので、間違いが少ないのと、

複雑なクエリが正しいのかの確認にも使えます。

 

 

 

2.レコードの更新を行う。

発行したクエリの結果は、更新することができます。

結果のカラムをダブルクリックすれば、編集可能ですので、

そのまま変更すれば、Salesforceのデータも更新されています。

 

 

3.検索結果をcsvにエクスポートする

地味に重宝するのが、クエリの結果csvファイルにエクスポートできることです。

テスト時のエビデンスを取得するのに便利ですよー。

 

Salesforceオブジェクトのキープレフィクス(PrefixId)を知っているとレコードの一覧Viewがすぐに表示できて超便利だよー

$
0
0

Salesforceのオブジェクトには一意なID(ObjectId)があり、

以下のようにURLにつけてアクセスすると、そのオブジェクトの詳細画面にいけるのは皆さんよくご存知でしょう。

 

https://ap2.salesforce.com/a002800000VUWrW

⇒「a002800000VUWrW」の部分がObjectId

 

そればかりでなく、ObjectIdからいろいろなことが分かり、

知っていると便利なことがあるのでご紹介します。

 

ObjectIDの命名規則

ObjectIdには以下のような意味があります。

たとえば、私が組織に作成したカスタムオブジェクト「SampleObject1」を例に取ると、詳細画面のURLは

 

https://ap2.salesforce.com/a002800000VUWrW

 

となっていました。

a002800000VUWrW は15桁表記のIdで実際のIdは
a002800000VUWrWAAX の18桁です。

a00・・・最初の3文字は「キープレフィクス(PrefixId)」と呼ばれ、オブジェクトを特定するのに使います。たとえば、皆さんよくご存知の「CONTACT(取引先責任者」のキープレフィクスは「003」です。

280・・・最初の2文字(ここでは「28」)で組織の属するサーバを特定します。ドメインの最初についている「ap2」とかの識別子ですね。最後の1文字(ここでは「0」は将来のために予約されています。)

0000VUWrW・・・これがオブジェクトの識別子です。

AAX・・・最後の3文字は、大文字小文字を区別しないシステム用のキャラクタです。

 

キープレフィクス(PrefixId)の取得方法

1.先日ご紹介した「Force.com Explorer」でオブジェクトを展開すると、確認することができます。

 

 

 

2.そのオブジェクトのidの最初の3文字がキープレフィクスですから、オブジェクトをブラウザで確認すれば、すぐに分かりますね。

 

https://ap2.salesforce.com/a002800000VUWrW

 

レコード一覧の表示方法

キープレフィクス(PrefixId)を知っていると、

 

https://ap2.salesforce.com/a00

 

のように「ドメイン+キープレフィクス」で下記のようにレコード一覧の画面に遷移します。

 

 

通常は、カスタムオブジェクトを作成したら、タブも作って表示させますが、

タブ数が多くなって、選択しづらいときや、組織のタブ数の制限で、

タブを追加できないときなどでも、すぐに一覧を表示できるので、便利です。

Salesforceで、ブラウザからWebサービス(REST API)を呼ぶ

$
0
0

Salesforceでは、様々なAPIが公開されています。

今回は、REST APIを利用して、組織の情報を取得したり、オブジェクトの作成、更新、削除等を行ってみたいと思います。

Javaなどのプログラミング言語から呼び出す方法もありますが、外部からSalesforceのREST APIを呼び出す仕組みを理解するために、今回はブラウザのプラグインを使って、シンプルに呼び出してみましょう。

特に認証の仕組みなどは、HTTPのリクエストとレスポンスをそのままみれるこの方法が、仕組みを理解して、複雑なアプリケーションを作成していくサンプルとしても良いと思います。

では、早速ハンズオン開始!

 

Salesforce側にアプリを登録する

はじめに、Salesforce側にアプリケーション登録(定義)を行います。

Salesforceに登録するアプリケーションは、クライアント(今回の場合は、我々のブラウザ)からSalesforceにアクセスする「入り口」のような役割を担います。このアプリを介して、Oauth認証というセキュアな認証を行った後で、実際のREST APIをCallするというわけです。

アプリの登録は、Salesforceの管理コンソールから行います。

「設定」⇒「ビルド」⇒「作成」⇒「アプリケーション」に行き、セクション「接続アプリケーション」で「新規」ボタンを押します。

画像のアップロード  

 

 

すると、アプリの設定画面に遷移します。

アプリ名を入れると、API参照名が自動入力されます。

それ以外に入力するところは以下の通りです。

  1. 「OAuth設定の有効化」にチェックを入れます。
  2. 「コールバックURL」は今回は使用しませんが、必須入力項目なので、適当に入力します。
  3. 「利用可能なOAuth範囲」から、「フルアクセス(Full)」を選択し、右側に移します。

 

画像のアップロード  

 

 

上記設定が終わったら、「保存」ボタンでアプリを作成します。

下記が、作成されたアプリの画面です。

「コンシューマ鍵」の値と、クリックして公開リンクを押したら現れる「コンシューマの秘密」の値は、後ほど使いますので、メモしておきましょう。

画像のアップロード  

 

 

メモできたら、「Manage」ボタンでアプリの設定をさらに行います。

OAuthポリシーのところで、「許可されているユーザ」のプルダウンを「管理者が承認したユーザは承認済み」に変更します。

これで、事前に権限を与えたユーザに関しては、アプリの使用承認画面なしでAPIを実行できます。

バッチユーザなど、決まった特定のユーザからREST APIを呼ぶ場合は、この形式が良いかともいます。

もうひとつは、「すべてのユーザは自己承認可能」という選択肢です。

これは、Twitter APIの使用確認のようなイメージで、各ユーザに承認を行わせるものです。

 

画像のアップロード  

 

 

上記設定を行うと、画面の下の方に、「プロファイル」というセクションが表示されるようになります。

ここで、「プロファイルを管理する」ボタンを押すと、プロファイルの選択画面が開きますので、API呼び出しの権限をあげたいユーザのプロファイルを選択しましょう。

 

画像のアップロード  

 

 

画像のアップロード  

 

 

なお、選択したプロファイルに「APIの有効化」の権限があることは確認しておきます。

 

画像のアップロード  

 

 

以上で、Salesforce側のアプリの登録、設定は終了です。

それでは、いよいよ、ブラウザからREST APIを呼んでみましょう。

 

REST APIを呼ぶ

「DHC」のインストール

Chromeエクステンションの「DHC」を使用しました。

非常に使いやすいHTTPクライアントなので、別の記事でも使い方の解説します。

 

Salesforceにクライアントから接続する

接続を行うには、以下のようなフォーマットでPOSTする必要があります。

https://login.salesforce.com/services/oauth2/token?grant_type=password&client_id=<コンシューマ鍵>&client_secret=<コンシューマの秘密>&username=<Salesforceユーザ>&password=<パスワード>

DHCでの設定は、以下の画面のように行います。

注意する点は、

メソッドは「POST」

「Content-Type」は「application/x-www-form-urlencoded」

にする。といったところでしょうか。

 

画像のアップロード  

 

 

レスポンスが200で返ってきたら成功です。

戻りのJSONの中に、「access_token」という項目がありますが、次のステップで使いますので、メモしておきましょう。

 

REST APIをコールする

では、先ほどメモした「access_token」を手に、いよいよRST APIをコールしましょう!

 

情報を取得する

REST APIは、操作する内容によって、HTTPメソッドとURLが異なってきます。

情報を取得する場合は、GETを使用し、下記のようなURLを使用します。

https://<インスタンスID>.salesforce.com/services/data/v36.0/

注意するところは、ヘッダに、「Authorization」という項目を指定し、内容は、 「Bearer <先ほどメモしたaccess_token>」とすることです。

画像のアップロード  

オブジェクトを作成する

作成の場合は、POSTを使用し、下記のようなURLを使用します。

https://<インスタンスID>.salesforce.com/services/data/v36.0/sobjects/Account

また、「Content-Type」は「application/json」にしましょう。

その上で、BODYに、各オブジェクトの項目を記述したJSONを書きます。

どのような指定をすればいいかは、REST APIのドキュメント等を参照してください。

 

画像のアップロード  

 

 

まとめ

いかがでしたか?

RST APIのクエリを試してみるだけなら、以前書いた記事の「Workbench」を使ってもできますが、 ブラウザの機能拡張を使うと、構造が理解できると思います。

Salesforceのサイトには、curlを使ったサンプルもありますが、このツールも癖があるので、またの機会に具体的なやり方を検証して、ご紹介したいと思います。

 

MavensMateとSublimeText3でサクサクSalesforce開発環境を構築!まとめ

$
0
0

今まで、Salesforceの開発環境といえば、DeveloperConsoleか、EclipseのForceIDEを使ってきました。

どちらもいいツールなのですが、前者は

  1. ・Webベースなので、動きがまったりしている。
  2. ・ネットワークなどの調子により、書いたソースが保存されず、無駄になったことも何度か。。。

など、Webでの開発環境であるがゆえの使いづらさがあったり、後者は

  1. ・Eclipseという統合開発環境ゆえ、開くまでに時間がかかる。
  2. ・ソースのSFDCへの反映がどうもうまくいかない場合がある。
  3. ・Apexログの確認やデバッグがやりにくい。

などの不満がありました。

SublimeText3

 

最近、「SublimeText3というすばらしいテキストエディタがあって、Salesforceの開発環境も構築できるよ。しかも軽いから快適!」ということを教えてもらったので、早速試してみました。

 

開発環境の全体構成

最初に、開発環境の全体的な構造を理解しておきましょう。

この仕組みには2つのアプリのインストールと設定が必要です。MavensMate(MavensMate-Desktop)SublimeText3です。

SublimeText3は基本的にはテキストエディタですので、ソースの編集などに使用します。SublimeText3のコード補完機能や便利なマクロが利用できるので、快適なコーディング環境が用意できるというわけですね。

MavensMateはSublimeText3とSalesforceの中に位置し、両者をつなぐプロキシ・サーバのような役割を担います。

SublimeText3から要求やコマンドを投げると、代わりにSFDCにログインしてメタデータ情報を取得したり、データを更新したりします。

 

開発環境の構築手順

MavensMate-Desktopのインストール

まずはMavensMate-Desktopをこのページのリリースページからダウンロードしてインストールします。特に難しいところは無いと思います。

SublimeText3から利用するときには起動させておかないと、SFDCに接続できませんので、そこは注意しましょう。

 

proxyの中の環境からアクセスするには

環境によってはProxyServerを経由してSFDCにアクセスする必要があります。そんなときには、MavensMateのグローバル設定でプロキシを設定しておきます。

下記の矢印のように、「歯車」アイコンをクリックして設定を表示し、「HTTP PROXY (MM_HTTP_PROXY)」と「HTTPS PROXY (MM_HTTPS_PROXY)」にサーバを指定します。

どちらもhttpであることに気をつけてください。(環境によるでしょうが。)

MM_HTTPS_PROXY

 

SublimeText3のインストールと設定

次にSublimeText3をここからダウンロードしてインストールします。

その後、SublimeText3を起動して、いくつか設定を行います。

まずは、パッケージコントロールの仕組みを導入しましょう。開発環境は「MavensMate」というパッケージを使うので、それをインストールするためです。

 

Package Control のインストールは「View > Show Console」でコンソールを開き、このページの赤枠のテキストをコピーして、コンソールに貼り付け、Enterを押します。

コンソール

 

下記の図の矢印のように、PreferanceにPackageControlがあればインストールされているはずです。

PackageControl

 

OKでしたたら、「MavensMate」パッケージをSublimeText3に追加します。

Preferance->PackageControlを選択し、「Insta..」と入力して表示される「Install Packages」を選択します。

すると、パッケージ管理の状態になるので、ここで「Mavens..」と入力して表示される「MavensMate」をインストールします。(MavensMate-Desktopは起動しておかないとエラーになるので、きをつけてください。)

こんな感じでメニューに「MavensMate」が表示されていれば成功です。後は、「Create Project」で新しいSFDCプロジェクトを作って開発を開始しましょう。

MavensMate

 

具体的な開発過程やTipsはまた別の記事で。

 

よくあるエラーと対処法

開発環境構築時に良く遭遇するエラーとその対処法をまとめておきます。まぁ、「良く」というか、私が遭遇したエラーですが、、、。

 

MavensMate-Desktopが起動してない

[ERROR]: Could not contact local MavensMate server, please ensure MavensMate-app is installed and running.

このエラーはMavensMate-Desktopが起動していないためにおきます。直訳すると「ローカルのMavensMateサーバに接続せきません。インストールされて動いているか確認してください。」ということなので。。

 

SublimeText3.exeへのパスが間違っている

[ERROR]: result.resolve is not a function

または

[ERROR]: Could not open project. mm_sublime_text_executable_location path does not exist, please check your user plugin settings.

のエラーが出る場合は、SublimeText3.exeのパスを疑ってみましょう。お互いにそのパスを知らないと、コマンドの起動とかができないために上記のようなエラーが出ます。

設定場所は、

MavensMate側はグローバルセッティングの「SUBLIME TEXT LOCATION (MM_SUBL_LOCATION)」の項目

SublimeText3側は、「MavensMate」->「Setting」->「User Plugin Settings」から開いた設定ファイルの出「mm_sublime_text_executable_location」の項目です。

ここに、SublimeText3.exeへの絶対パスを指定すればOKです。

SalesforceのProcessBuilderからApexクラスを呼ぶためのクラス定義とその設定

$
0
0

Salesforceのプロセスビルダーはフロー図を描くようにビジネスフローを定義でき、

あるオブジェクトの作成時や更新時の項目の値などをもとに、他の項目の値を更新したり出来ます。

使いこなすと非常に便利な機能で、ワークフローよりもメンテナンスも楽に設計することも可能なのではないかと思います。

また、オブジェクトの項目設定だけではなく、メールアクションを呼んだり、Apexクラスを呼んだりすることも出来るので、複数のオブジェクトを更新したり、外部のWebサービスを呼んだりなど、もう少し複雑なビジネスロジックを処理したい場合も重宝します。

ただ、最初にオブジェクトの種類を決めて、そのオブジェクトの項目値によって条件分岐等を行うので、複数の種類のオブジェクトが作成・更新されたときに、汎用的にログを書いたりするのは難しいかと思っていましたが、引数の渡し方も結構フレキシブルにできる方法がありましたので、ご紹介しておきます。

 

ProcessBuilderからApexクラスを呼ぶためのクラスとその設定

Apexクラスの記述方法

はじめに、呼ばれる側のApexクラスを作成します。

InvocableLoggerというクラスにします。

内容は、デバッグログを吐くだけのクラスですが、ログ出力の部分を変更して、ビジネスロジックを入れれば、様々なことができます。

global class InvocableLogger {
             
        global class LoggingRequest {
        
               @InvocableVariable(required=true)
               public ID objId;
               
               @InvocableVariable
               public String strComment;
       
       }     
       
       
       @InvocableMethod(label='Called Method for Logging')
       global static void createLog(List<LoggingRequest> requests){
       
           for(LoggingRequest requestObj:requests){        

               System.debug('requestObj.objId@@:'+requestObj.objId);          
               System.debug('requestObj.strComment@@:'+requestObj.strComment);
               //Do something for business logic
               
           }
             
       }
      
}

簡単に解説すると、

「@InvocableMethod」のアノーテーションのついたメソッドを、プロセスビルダーの中から呼ぶことができます。そのときの名称(見え方)は「label=」のところに記述します。

今回の場合は、「Called Method for Logging」ですね。

次のここがミソですが、引数のリストのクラスをグローバルで定義します。

「LoggingRequest」としました。なお、この引数の変数に「@InvocableVariable」アノーテーションをつけることで、引数として、プロセスビルダーの中で指定することができます。

今回は、「objId」と「strComment」を定義しましたが、好きなだけ増やすことも出来ますので、ご自由に。

 

上記クラスを呼び出すProcessBuilderの作成

では、上で作成したApexクラスを呼びだすプロセスビルダーを作成してみましょう。

はじめに行うのは、プロセス名と開始のタイミングの指定ですね。

タイミングの指定

 

それが終わったら、プロセスを開始する対象のオブジェクトを指定します。

今回は、「リード」オブジェクトにしました。

オブジェクトを指定

 

それが終わったら、発動の条件を設定します。

今回は、「メールアドレス」がNullで無かった場合 と指定しています。

発動の条件を設定

 

いよいよ、Apexの指定です。Apexクラスのプルダウンには「@InvocableMethod」のアノーテーションがついたメソッドが表示されますので、「createLog」メソッド(見た目は「Called Method for Logging」)を指定します。

すると、自動で、「@InvocableVariable」の必須項目である「objId」が表示されますので、値を設定します。

もうひとつの「strComment」は必須ではないですが、ログに設定するコメント文言を設定したいので、「行を追加」で追加して、任意の文字列を設定しておきます。

引数設定

 

以上で、設定は終了です。右上の「有効化」ボタンを押して、有効化し、リードオジェクトを作成して、メールアドレスがNullで無いように設定します。

これで、設定したプロセスが発動し、Apexが呼ばれることになります。

引数設定2

 

すると、デバッグログを確認すると、値が渡ってきていることが分かりますね。

debaglog

 

Salesforce移行ツール(Migration Tool)の最初の一歩

$
0
0

How to use Salesforce Migration Tool for the first time.

Salesforceでの組織間、本番⇔サンドボックス間のリリース、デプロイはMigration Tool (移行ツール)を使うと便利です。

ChangeSetでも可能な部分はありますが、リソースの管理が煩雑になってしまいがち。 その点、Migration Tool を使うと、リリース対象のリソースをファイルに記述しておけるので、リリース漏れも少なく、リソース管理も厳密に行えます。

この記事では、はじめてMigration Tool を使う人のために、その使い方をお伝えします。

 

Migration Toolの概要

Migration Toolは、Antで動く移行ツールです。Salesforce社がメンテしているので、公式ツールという位置づけですね。

Salesforceでは、本番へのリリースやサンドボックス間のデプロイを行うのに、チェンジセット(ChangeSet)を使ったりしますが、それをコマンドラインで行うツールだと思えば大丈夫でしょう。 コマンドラインで実行できるということは、バッチ化して、定刻実行したりも可能だということなので、使いようによっては便利ですよね。

Migration Tool はMetadataAPIを使ってデプロイ対象のリソースを取得したり、デプロイしたりするので、MetadataAPIと非常に密接な関係があります。 逆に言うと、MetadataAPIを解析すれば、いろんなことができるということなのですが、それはまた、別の機会に。

 

Migration Toolのインストールとセットアップ

最初にAntのインストール

Migration ToolはJavaのAntで動きますので、実行するためにはAntをセットアップしておく必要があります。

ここから、Antをダウンロードして解凍しておきます。

必要に応じて、ANT_HOMEやJAVA_HOME、PATHなどの環境変数を設定します。

その後、コマンドプロンプトで、「ant -version」を打って、下記のようにバージョン情報が表示されれば、インストール成功です。

ant version

 

いよいよMigration Toolのインストール

では次に、Migration Toolをインストールします。

ここからマイグレーションツールをダウンロードしましょう。

今回は、「 Winter ’17 release .zip (version 38.0)」をダウンロードしました。

インストールする手順はここのページに書いていますが、

手順を追うと、

ファイルを解凍したら、「ant-salesforce.jar」のファイルがあることが分かります。

これがAntタスクの定義のjarなので、これをAntディレクトリの「lib」配下にコピーします。 古いバージョンの「ant-salesforce.jar」がある場合は置き換えてください。

 

最初のプロジェクトの作成

解凍したフォルダの下に「sample」フォルダがあり、サンプルがあるので、まずはこれをコピーしてシンプルなマイグレーション用のプロジェクトを動かしてみましょう。

今回は「mytest」という名前で「sample」フォルダをコピーしました。「mytest」配下に、以下のファイルがあると思います。

build.properties・・・プロジェクトで使用する変数を定義するファイル

build.xml・・・実際のタスク(デプロイや情報取得など)を定義するファイル

まずは、接続情報を確認・設定するので「build.properties」を開きます。

sf.serverurl = https://login.salesforce.com

という設定がありますが、この設定は本番用なので、Sandboxなら、https://test.salesforce.com に変更しましょう。

次に、接続ユーザとパスワードの設定を行います。

sf.username = <Insert your Salesforce username here>
sf.password = <Insert your Salesforce password here>

上記のところに、ユーザ名とパスワードを設定します。

 

プロキシーの設定

もし、開発環境がプロキシー・サーバの背後だったら、その設定を以下のプロパティで追加します。

proxy.host = <Insert your Proxy host server here>
proxy.port = <Insert your Proxy port here>

設定を行ったら、その設定を使うための設定を「build.xml」の最後に追記します。

あとは、この設定を各Antタスクの

depends=”proxy”

で使うように設定します。(下の例に出てくるので参考にしてください。)

 

具体的なタスクを作ってみる

では、シンプルなタスクをコピーして、自分のタスクとして動かしてみましょう。

「retrieveUnpackaged」というタスクがシンプルにメタデータを取ってくるタスクなので、これを改造してみることにします。build.xmlの中を見ると、以下のような記述があるはずです。

これをコピーして

に変更してみました。

次に、unpackagedディレクトリに入っているpackage.xml をコピーして、「myproject」フォルダを作って、そこに入れます。

なお、上記のxmlのタスク設定に出てくるキーワードの意味は、

target name・・・このタスクの名前です。「ant 」で実行します。

depends・・・このタスクが依存するタスクを指定します。この例では、プロキシー・サーバを経由してSFDCに接続するので、「build.xml」の最後に追記した「proxy」を設定します。

retrieveTarget・・・ここには、retrieveしたリソースを置くフォルダを指定します。ここに指定したフォルダにメタデータがダウンロードされます。

unpackaged・・・ここに指定したxmlファイルを読み込んで、リソースの取得を行います。

では、

作成したmytestフォルダにコマンドプロンプトで移動して、プロンプトから「ant retrieveMyProject」という風にタスク名を指定して起動しましょう。

「ant retrieveMyProject -f build.xml」のように「build.xml」ファイルを指定しても実行可能です。環境を切り替えたりする場合に使えそうですね。

Renta

 

こんな感じにBUILD SUCCESSFUL になったら成功です。

「retrieveMyProject」ディレクトリにpackage.xmlで指定した内容のファイルがダウンロードされているはずです。

次回は、このシンプルなタスクを元に、もっと実践的なタスクを実行していくことにしましょう。

Salesforceの最新APIのWSC(Web Service Connector)のjarファイルをコンパイルして使用する

$
0
0

以前のエントリ「Salesforceに接続して、オブジェクト加工等を行うEclipseプロジェクトのテンプレート」でご紹介しましたが、SalesforceのAPIをWebService経由でJavaから呼び出すには、Salesforceから取得した WSDLファイルが必要です。

「WSDLファイル」とは、Webサービスの呼び出し情報を定義したXMLファイルで、このファイルからJavaなどのプログラミング言語に応じたクラスを生成して、 そのクラスを使用してAPIの呼び出しを行います。

クラス群の生成は、

“C:\Program Files\Java\jdk1.7.0_79\bin\java” -classpath wsc-23.jar com.sforce.ws.tools.wsdlc partner.wsdl partner.jar

のようなコマンドで生成し、呼び出すAPIごとに生成してjarにまとめ、「enterprise.jar」「partner.jar」「metadata.jar」「tooling.jar」 などを作成して利用します。

さて、上記のコマンドで「wsc-23.jar」とあるのが、クラスファイルを生成するのに必要なライブラリなのですが、 23とはいささか古いですよね。

Salesforceは、常にバージョンアップが行われていて、このエントリを書いた2016年12月はAPIバージョンは38が最新です。 その間に、新しいオブジェクトのタイプが追加されたり、構造が変わったりしているので、WSDLファイルに記述されている内容も変化しています。

つまり、最新のバージョンに対応したwscファイルでクラスファイルを生成しなければ、使えない機能があったり、APIを呼び出しても、エラーに なったりすることがあるということです。

そのため、最新のAPIバージョンでwscを生成する手順をメモしておきます。

 

最新のwsc.jarの作り方

wscのソースファイルをダウンロードしてくる

まずは、最新のバージョンに対応したソースファイルをダウンロードします。 最新のwscは以下のページで公開されています。

https://github.com/forcedotcom/wsc

ここから、gitにてソースを自分のPCにダウンロードします。

Mavenプロジェクトを作成

 

上図の赤囲みのところに、gitのURLが掲載されていますので、それをコピーしてきましょう。

https://github.com/forcedotcom/wsc.git

ダウンロードすると、以下のようなディレクトリ構成になります。 srcフォルダ配下のjavaソースと、pom.xmlは、後ほど使用します。

Mavenプロジェクトを作成

 

Mavenでコンパイルする

落としてきたソースをEclipseのMavenプロジェクトでコンパイルし、jarファイルを作りましょう。さきほど、「pom.xml」というファイルがありましたが、これは、Mavenを使って「コンパイル→jarへのまとめ」を行う設定ファイルです。

そのために、EclipseでMavenプロジェクトを作成しました。

Mavenプロジェクトを作成

 

上記の手順でシンプルなMavenプロジェクトを作ると、以下のようなディレクトリ構成のプロジェクトができます。この、src配下とpom.xmlをgitからダウンロードしたものに置き換えます。

完成したMavenプロジェクト

 

ここまできたら、いよいよコンパイルします。プロジェクトを右クリックし、「Maven build..」を選んで、Goals(ゴール)を「package」に設定します。「Skip Tests」にもチェックを入れておくと良いでしょう。

完成したMavenプロジェクト

 

上記のようなjarファイル群ができていたらOKです。使用するのは、「force-wsc-38.0.4-uber.jar」になりますので、これができていたらOKです。

 

いくつか起こりえるエラー

まぁ、すんなり行けばいいですが、それは、何度もエラーが出るのが世の常。私もいくつかエラーでました。同じことをする方も引っかかるかもしれないので、メモしておきます。

 

Mavenプロジェクトのコンパイルエラー

MavenプロジェクトでMaven buildすると以下のようなエラーが出る場合があります。

[ERROR] COMPILATION ERROR : 
[INFO] -------------------------------------------------------------
[ERROR] No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK?
[INFO] 1 error
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.272 s
[INFO] Finished at: 2016-12-01T14:01:03+09:00
[INFO] Final Memory: 7M/17M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project wsc38: Compilation failure
[ERROR] No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK?
[ERROR] -> [Help 1]

これは、「コンパイルできないけど、jdkじゃないんじゃないの?」といわれていますね。私の場合は、Eclipse出指定されているjavaのJAVA_HOME\bin配下にjavac.exeがない「jre」を指定していたためでした。同じエラーが出る方は、ちゃんとjdkを指定していて、javacが含まれているかを確認してみましょう。

 

Mavenプロジェクトの最後のパッケージングエラー

Maven buildが最後の最後でエラーになっています。私は、「force-wsc-38.0.4-uber.jar」が出来ていたのでよしとしましたが。。。

[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 02:30 min
[INFO] Finished at: 2016-12-01T14:25:03+09:00
[INFO] Final Memory: 23M/367M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-gpg-plugin:1.2:sign (sign-artifacts) on project force-wsc: Cannot obtain passphrase in batch mode -> [Help 1]

なんだか、最後のゴールでこけたみたいですが、すみません。良く調査していないです。回避方法分かった方は教えてください。。。

 


SalesforceのSoqlでlike句が使えるテキスト項目の種類と、使えない場合の代替方法

$
0
0

Salesforceでは、Like句を使って、selectできるデータタイプが限定されています。

SELECT Id, Name from Lead WHERE qTextAreaRitch__c Like ‘aa%’

みたいなsoql文を使って検索すると、

[object Object]: SELECT Id, Name from Lead WHERE qTextAreaRitch__c Like ‘aa%’ ^ ERROR at Row:1:Column:33 field ‘qTextAreaRitch__c’ can not be filtered in query call

といったエラーが出て、検索結果が返ってきません。では、どのデータ型が大丈夫で、どれが大丈夫でないかを表にしてみます。

データ型 データ型詳細 サンプルで作成したカラム名 Like句を使用可能か
テキスト テキスト(255) qText__c
テキストエリア テキストエリア(255) qTextArea__c
テキストエリア (リッチ) リッチテキストエリア(32768) qTextAreaRitch__c ×
ロングテキストエリア ロングテキストエリア(32768) qLongText__c ×

後ろの3つが日本語で「テキストエリア」となっていて分かりにくいのですが、実際には 最初の2つは文字列型で、項目を作成するときに指定できる文字数が255文字以内となっていて、Like句も使用可能です。 後の2つはテキストエリア型で、256文字以上の文字数しか指定できません。Like句も使用不可能です。

ただ、多くの文字が入力される可能性のある項目にはやはり255文字以上を指定したいですよね。

 

テキストエリア型でLike句のような振る舞いをさせる方法

String strKey = ‘ccc*’; List> arrayOfArray = [FIND :strKey IN ALL FIELDS RETURNING Lead(Id, Name)]; List arrayOfAccount = (List)arrayOfArray[0];

FIND {ccc*} IN ALL FIELDS RETURNING Lead(Id, Name)

でSOSL文を使います。

グローバル検索と同じ振る舞いになりますので、インデックスが作られるまで検索対象にならなかったり、検索対象のデータ型のすべての項目が対象になるなど、少しクセはありますが、テキストエリアを含めたカラムが対象になるのは便利だと思います。

特定のカラムに検索対象の文字列が含まれているような振る舞いにするには、検索結果のレコード配列をさらにcontainsで見るなどの工夫をすればいいかもしれませんね。

もうひとつの方法は、レコードを取得した後で必要な項目に対して文字列が含まれているかを判断する方法です。

以下のようなapexコードを書けばいいでしょう。

List leads = new List();
for(Lead lead : [SELECT Id, Name, qText__c, qTextArea__c, qTextAreaRitch__c, qLongText__c FROM Lead]) {
    
    if(lead.qTextAreaRitch__c != '' && lead.qTextAreaRitch__c != null){
        if(lead.qTextAreaRitch__c.contains('ccc')) {
            leads.add(lead);
            system.debug('★added');
        }
    }
}

nullと、空文字の判定をした後出ないと、null pointerのエラーが出る場合があるので、気をつけましょう。

salesforceのSOQLで、削除済み、マージ済みのレコードを取得する

$
0
0

salesforceでレコードを削除したり、マージしたりすると、削除されたレコード、マージされて無くなったレコードはゴミ箱に入ります。

通常、SOQLではゴミ箱に入っているレコードは検索対象にならないのですが、以下のようにALL ROWS句を使うと、ゴミ箱も含むすべてのレコードも検索対象となります。なお、ゴミ箱内のレコードを指定するWhere条件には、「IsDeleted = true」を使用します。

System.assertEquals(2, [SELECT COUNT() FROM Contact WHERE AccountId = a.Id ALL ROWS]);

↑ ↑ ↑ 参考(Querying All Records with a SOQL Statement)

なお、ALL ROWSを使ったSOQLはAPEXコード内か、SOAP APIなどのqueryAll()メソッド内で有効で、開発者コンソールから直接SOQLを投げるとエラーになってしまいます。

 

画面からSOQLを指定して簡単に確認するには

そのため、開発者コンソールからSOQLをたたいて簡単に確認したいなーというときには試せません。

そんなときには以前紹介した、Salesforce Workbench(Salesforceのデータを検索・確認できるGUIツール① WorkBench)を使うとクエリの結果に「ゴミ箱のデータを含む/含まない」の指定が画面からできて、便利です。

workbench

 

Workbenchにログインして、画面上部のメニューから「queries」→「SOQL Query」と進むと上記ののような画面になります。

この画面の中央部のテキストエリアにSOQLを入力して「Query」ボタンを押せば結果が表示されるのですが、その結果にゴミ箱およびアーカイブされたデータ(IsDeleted=true または IsArchived=true)のデータも含めるには、「Deleted and archived records:」で「Include」にチェックを入れておきます。

salesforceでマージ後、どのレコードにマージされたのかをSOQLで確認する方法

$
0
0

Salesforceでは、重複するリード(Lead)や取引先責任者(Contact)を同士をマージ(Merge)して一つのレコードにすることができます。
※取引先責任者の場合は同じ取引先属している取引先責任者同士でしかマージできない。

マージするには、複数のレコードを選択して、以下のような画面で、マスタとなるレコード(メインになるレコードで、基本的にはこのレコードに寄せることで複数のレコードを一つにするが、それぞれの項目ごとにどのレコードの値を活かすかは指定可能)を決めます。

merge

 

上記でマスタレコードとしたレコードが残るのですが、マージされたレコードはどうなるかというと、IsDeletedフラグがtrueになって、ゴミ箱に行きます。そして、基本的には15日程度経った後に、完全に物理削除されることになるわけです。

で、このゴミ箱に入ったデータをSOQL等で覗いてみると面白いことが分かります。「MasterRecordId」という項目に、統合されて残ったマスタのレコードのSalesforceIdが入っているのです。

つまり、この項目を確認すれば、「マージされたレコードが、どのレコード(マージ先)にマージされたのか」が分かるというわけです。

そのため、マージされてゴミ箱に行ったデータを確認するときには、

SELECT Id FROM Contact WHERE isDeleted=true and masterRecordId != null 
   AND SystemModstamp > 2006-01-01T23:01:01+01:00

↑ ↑ ↑ 参考(merge())

といったSOQLで見つけることができます。(ただし、開発者コンソールとかからでは確認できず、Apex等を使う必要があるので、簡単に確認する方法については、この記事「salesforceのSOQLで、削除済み、マージ済みのレコードを取得する」を参考にしてください。)

 

実際に確認してみる

マージ前とマージ後の2レコードを比較してみた図

merge

 

上記のように、マージ後のデータには「MaterRecordId」にオブジェクトIdが入っていることが分かります。

ただし、少し覚えておきたいのは、ゴミ箱から復元すると、この項目の値は「空」になってしまいますが、マージ先のデータは元に戻るわけではないため、「どのレコードにマージされたか」が分からなくなってしまうことです。

SalesforceのApexメソッド、Database.query()とDatabase.getQueryLocator()の違いとそれぞれの使いどころ

$
0
0

Salesforceでデータのセレクト結果を返すメソッドに2種類あり、どういうときに使い分けた方が良いのかが「あやふや」だったので調査したことをまとめておきます。

 

Database.Query()とDatabase.getQueryLocator()の違い

 

Database.Query()・・・このメソッドは、実行時に動的に生成したSOQLで検索を行いたいときに使用します。最大50,000件のレコードを取得することができます。もし、BatchApexなどで使用しても、50,000件以上処理することは出来ません。以下のような例でSOQLを動的に組み立てられます。

String fieldName = ',Name,Email';
String dynQuery = 'select Id ' + fieldName + ' From Account';
Database.query(dynQuery);

 

Database.getQueryLocator()・・・ApexBatchとVisualForceページで使用されることが多いですが、使う場所によって扱える件数が異なります。ApexBatchのなかで使用すると、最大5,000万件までのデータを扱うことができます。ただし、一回でまとめて取ってくるわけではなく、指定したバッチサイズの件数(デフォルト200件)ごとに取ってきて、それを繰り返しで処理します。データベースでいうところのカーソルのフェッチみたいな仕組みをイメージすると良いかもしれません。一回で取得する件数を抑えながらも、最終的には大量のデータを扱うことができるので、Batch Apexの処理内で使われるのは納得ですよね。

もうひとつの使いどころは、StandardSetControllerを使ったVisualForcePageで、主にページング処理を実現するのに使用されます。ここで使用するときには、取得できる最大の件数は10,000件に制限されます。

 

VisualForcePageでの使用イメージ

ここで、VisualForcePageのページング処理での使用イメージを載せておきます。

StandardSetControllerのコンストラクタは以下の2種類を持っています。

前者はsObjectのリストを渡す形式、後者はQueryLocatorを渡す形式です。

sObjectのリストを渡す形式

List accountList = [SELECT Name FROM Account LIMIT 20];
ApexPages.StandardSetController ssc = new ApexPages.StandardSetController(accountList);

 

QueryLocatorを渡す形式

ApexPages.StandardSetController ssc = 
new ApexPages.StandardSetController(Database.getQueryLocator([SELECT Name,CloseDate FROM Opportunity]));

さて、StandardSetController のインスタンス化の際に受け取ることの出来るレコード数は10,000件に制限されています。ただし10,000件以上のレコードがHitして、コンストラクタに渡ったときの振る舞いは両者で異なります。

前者のsObjectのリストを渡したときには10,000件でレコードが切り捨てられ、エラーは出ません。しかし、後者のQueryLocatorの場合は、10,001件以上だとエラーになります。(Too many query locator rows)。

なお、ApexではStandardSetControllerを使用することで簡単にページネーション機能を実装することができますが、大量な件数を表示する場合は、ページのプロパティの中に、readOnly=trueを設定します。これで、通常は1000件までのレコード表示が50,000件まで行えるようになります。(でも、上で述べたように、QueryLocatorの場合は、10,001件以上だとエラーになります。)

 

違いを表にまとめると、、、

Database.query() Database.getQueryLocator()
50,000レコードまで扱える 10,000レコードまで扱える
Batch Apexで使ったとしたら、レコード数は50,000レコードまでに制限される Batch Apexで使ったとしたら、レコード数は5千万レコードまで扱える
VFページでread onlyを使わないのであればこちらを使う。 VFページでread onlyを使うのであればこちらを使う。

のようになると思います。

LineのMessaging(Push)APIを使ってWebサービスを作る(環境構築編)

$
0
0

LineのMessagingAPIを使うと、決められた言葉に自動で反応するBotやお客様への一斉配信などが行えるので、ビジネス・シーンでも利用範囲は大きいと思います。

今回はその中でもPushAPIを使ったメッセージ配信を試してみましたので、その過程をご紹介します。

 

利用料金

今回私が試してみたのは「Developer Trial」で、メッセージを受け取ってから一定時間の間に返信することの出来る「Reply API」と能動的なメッセージ配信に使える「Push API」の両方を無料で使うことができます。

ただし、友達に追加できる人数は50人に限定されています。

それ以上の人数に配信する場合には、プロなどの適切なプランを選択する必要がありますが、時期によって条件も変わると思いますので、詳しくは公式ページで確認してください。

Line料金

 

各種アカウント作成

Lineアカウントの作成

MessagingAPIを使うには、まず、Lineのアカウントが必要です。

持っていない人はスマホにLineアプリを入れるなどして作成してください。

作成したら、スマホのLineアプリの設定で「アカウント」→「メールアドレス登録」が「登録完了」になっていて、「ログイン許可」にチェックがあることを確認しておきます。

 

Developer Trialの申込

Lineのアカウントがあることを確認したら、改めて以下のリンクから「Developer Trial」を申し込みましょう。

https://business.line.me/ja/services/bot

Line料金

 

「Developer Trialを始める」ボタンを押すと、以下のログインダイアログが出ます。

Line料金

 

初めてログインするブラウザでは本人確認が必要なので、Lineに番号が届くはずです。

それを入力すると、続行できます。

続行したら、ビジネスアカウントのマネージャの作成が行われます。

ビジネスアカウントは、Lineアカウントとは別の、「Line@」という種類のアカウントを複数持つことができ、マネージャアカウントで管理します。

Line料金

 

マネージャアカウントの作成が終わったら、ひとつのビジネスアカウント(Line@アカウント)を作成します。

アイコンをアップロードし、名前を入力しましょう。

Line料金

 

Line料金

 

できたら、上記の画面で「LINE@MANAGERへ」のボタンを押すと、作成したLine@アカウントの管理画面にいけます。

Line@アカウントの設定

では、Lineメッセージを送信するのに必要な設定を行っていきましょう。

はじめにAPI利用を有効にします。

下記の画面の「Bot設定」で「APIを利用する」ボタンを押します。

Line料金

 

下記のような注意書きが出ますので、よく読んで先に進みましょう。

LINE DevelopersでのChannel設定が必要なようですね。

Line料金

 

API利用を有効にすると以下のような画面になります。

さらに、Webhook送信を「利用する」に変更してください。

このWebhook送信は、このアカウント(Bot)に対して友達申請やメッセージの送信が行われた際に、そのURLに対して、Line側からJSONがPOSTされます。

このJSONから友達になってくれたユーザのMID(ユーザID)などを取得できたり、返信のための情報を取得してWebサービスを作っていくことになりますので、外部に公開されたサーバにWebhook用のプログラムを作って配置し、そこを指定するようにします。(別の記事で詳しく解説します。)

Line料金

 

Webhookを有効にしたら、「LINE Develiper」に移動します。上記のリンクから行くと行きやすいでしょう。

「LINE Develiper」側では、実際のWebhookのURLを設定したり、先ほど出てきたChannelを有効にしたりします。

Webhookはプログラムを作る必要があるので、今はひとまず、Channelを有効にするために、「Channel Access Token」の「ISSUE」ボタンを押しましょう。

すると、「Channel Access Token」が生成されます。(APIの呼び出しに必要なので、覚えておきましょう。)

Line料金

 

TwilioのSMS送信APIの使い方(準備・環境構築編)

$
0
0

Twilioは、スマホなどの携帯機器に対して、音声応答を行ったり、SMS(ショート・メッセージ)を送信したりすることのできるAPIを提供しています。

世界では様々なキャリアや携帯機器が使われていて、そのすべてに対応するとなると非常に大きな工数が必要ですが、それらの環境の違いについてはTwilioが吸収してくれるので、

我々技術者やサービス提供者は、少ない工数で世界のほとんどの携帯機器に音声やメッセージの配信を行うことが可能になります。

そんなTwilioでサービスを作ってみようと思っている方に参考になるよう、私がTwilioを使ったサービスを作ってみたときの過程をメモしておきます。

Twilioを使ってサービスを作成するときには、開発言語としてJavaやPHP、Python、RubyやSalesforceなど、いろいろなものを選べます。

それぞれの言語での開発の仕方は別の記事にまとめますが、今回は、それらに共通の、最初のアカウント登録のやり方とその注意点にフォーカスを当てたいと思います。

なお、以下は無料の開発者アカウントでの作業の過程をご紹介したものですが、実際にサービスを開始する際も、アカウントをアップグレードできますので、ほとんど同じプロセスで可能だと思います。

 

TwilioでWebサービスを作る過程

無料開発アカウントのサインアップ

はじめにアカウントを作成します。

http://twilio.kddi-web.com/

日本では、KDDIがTwilioの代理店なので、日本でアカウントを作っておいた方が、何かと便利だと思います。

KDDI Twilio

 

上記ページにアクセスしたら、右上の「サインアップ」からアカウントを作成します。

AccountTwilio

 

なぜか、「現在アカウントを作成できません。」というエラーになってしまい先に進めませんでしたが、質問に対する回答を変えて何度かトライすると作成できました。

私がOKになったのは、「どのサービスを最初に利用する予定ですか?」→「SMS」、「お作りになるサービス」→「Account Alerts」、「利用言語」→「利用言語がこの中にはない」という選択肢でしたが、この選択肢が良かったのか、何度かトライしたのが良かったのかは定かではありません。

次に表示されるのは、SMSによるアカウントのべリファイです。

入力した電話番号にショートメッセージが送られますので、携帯の番号を入力し、「Verify via SMS」ボタンを押します。

Twilio Verify

 

SMSが届いたら、メッセージに書いてある番号を確認して、下記画面で入力し、「Submit」を押せば、OKです。

Twilio Code add

 

電話番号の取得

さて、アカウントのサインアップが完了すると、以下のような管理コンソールが表示されます。

はじめに行うのは、「電話番号の取得」ではないでしょうか。

サーバやアプリなどのプログラムから電話をかけたり、SMSを送るには、送信元の電話番号が必要になってくるからです。

Twilio tel add

 

「最初のTwilio電話番号を取得」を押すと、日本の電話番号が無作為に選択されます。

ここで注意したいのは、番号によってできることが異なるということです。

下記の図の日本の電話番号の場合、「着信コールを受信および発信」が出来るとありますね。

SMSのメッセージングを行うには、アメリカの電話番号でないといけません。

Twilio call add

 

私は、SMSも行いたかったので、「別の番号を検索する」で、別な番号を選択することにしました。

すると、以下のように用途や国で電話番号を検索できます。

米国の番号ならSMS等が使えるので、そのまま検索すると、、、

Twilio american tell add

 

以下のように結果が表示されます。

「利用可能な機能」のところに、「音声通話」「SMS」「MMS」があるので、取得する電話番号で使いたい機能を使えるかを確認して、「Choose this Number」で選択します。

Twilio american tell add

 

以下のようなダイアログが表示されたら、取得できたということです。

おめでとうございます。

Twilio get tell

 

ダッシュボードのホームにいくと、「ACCOUNT SID」と「AUTH TOKEN」が既に発行されていることが確認できます。

発信元の電話番号とこの「ACCOUNT SID」と「AUTH TOKEN」があれば、プログラムで音声やSMS送信は出来ます。

Twilio auth key

 

無料トライアルでの送信について

無料トライアル期間中は、送信先として指定できるのは、登録に使った認証済みの携帯電話番号のみとなります。

それ以外の電話番号に送信した場合は、APIから「The number +81xxxxxxx is unverified. Trial accounts cannot send messages to unverified numbers; verify +81xxxxxxxxx at twilio.com/user/account/phone-numbers/verified, or purchase a Twilio number to send messages to unverified numbers.」のエラーが返ってきます。

送信できるようにするには、検証済み電話番号に追加する必要があります。

アップグレードすると、この通信制限は解除されます。

 

Twilioの利用料金について

Twilioは、

・発信元の電話番号

・音声やSMSを送信した分だけの利用料

を月々払うだけのシンプルな契約です。

発信元の電話番号は月々、150円程度から使用できますので、お得だと思います。

http://twilio.kddi-web.com/price/

Twilio price

 

SalesforceでRestAPIを自作し、外部からPOST/GETで呼ぶ方法とJson引数の解析

$
0
0

Salesforceでは、自分でREST APIを作成して、それを外部のプログラムから呼ぶことができます。

ここでは、REST APIの作成方法と、GETやPOSTでのCallの仕方、それぞれのメソッドで引数を取得して、それを解析する方法もご紹介します。

作成した自作のRESTを外部から呼ぶ方法については、こちらの記事をご参照ください。ブラウザでの呼び出し方法ですが、同じ様なことをJavaなどのプログラムで行えば、プログラムからも呼び出し可能です。

 

SalesforceでのREST APIの作成

アノーテーション「@RestResource」を使うとRESTサービスを作ることができます。

まずは、例を見てみましょう。

@RestResource(urlMapping='/MyRestServices/*')
global class MyRestController {

	@HttpGet
	global static ReturnObj getAccountInfo() {

		RestRequest req = RestContext.request;
		RestResponse res = RestContext.response;

		// パラメータ取得
		String param1 = req.params.get('param1');

		return '' ;       
	}
    
    
	@HttpPost 
	global static String updateAccountInfo() {

		RestRequest req = RestContext.request;
		RestResponse res = RestContext.response;

		// パラメータ取得
		Map<String, Object> requestParams = (Map<String, Object>)JSON.deserializeUntyped(req.requestBody.ToString());

        	Map<String, Object> resultParam2 = (Map<String, Object>)requestParams.get('param2');
        	String resultParam2_1 = (String)resultParamKokyaku.get('param2_1');

        
        	List<Object> resultParams = (List<Object>)requestParams.get('param3');
        	for (Object obj : resultParams) {
            		Map<String, Object> params = (Map<String, Object>)obj;
            		String eventType = (String)params.get('param3_1');
        	}

		return '';
	}

 }

アノーテーションのプロパティに(urlMapping=’/MyRestServices/*’)とありますが、これは、MyRestServicesというURLで以下のHTTPメソッドを公開するという意味です。

メソッド(GET,POST,PUT,DELETE等)は、1つのRestクラス(ここではMyRestController )で各一つずつ定義することができます。

「*」は、各クラスメソッド名がそのままURLにマッピングされるということになります。

RESTを作成すると、決められたエントリポイントで公開され、たとえば、MyRestController.getAccountInfo()は

https://<SFDCインスタンス>/services/apexrest/MyRestServices/getAccountInfo

でCallすることができます。

 

パラメータの解析

さて、RESTを呼び出すことができるようになったら、HTTPのリクエストで渡された引数を取得することにしましょう。

 

GETパラメータの場合

一つ目はGETパラメータで、<URL>/getAccountInfo?param1=aaaa

のような形で渡ってきます。

この場合は、「 req.params.get(‘param1’)」のように、パラメータ名を引数に取得します。

 

POSTパラメータ(Json)の場合

POSTのパラメータがJson形式でわたってきた場合は、クラスを定義して、MyRestController.updateAccountInfo(定義したクラス)のようにすると、Salesforceで自動でJsonのでシリアライズが行われます。

ただ、この方法だと、インターフェースが変更になった場合にエラーを起こしやすいため、私は、Stringで取得し、Jsonのパースを行った後で、Mapのキー名で取得するようにしています。

Map requestParams = (Map)JSON.deserializeUntyped(req.requestBody.ToString());

の部分ですね。

パースが行われると、Map形式で格納されますので、パラメータ名で簡単に値を取得できます。

上記のサンプルでは、

{“param2”:{“param2_1” : “aaaaa”,”param2_2″ : “bbbbb”},
“param3”:[{“param3_1”: “cccccc”, “param3_2”: “dddddd”},{“param3_1”: “eeeee”, “param3_2”: “fff” }]}

のような、入れ子で、配列の形のJsonから値を取得しています。


SalesforceでのDataloaderでの日付の扱いと、インポート時に一日ずれる件の検証

$
0
0

Salesforceは、複数言語や世界中のタイムゾーンに対応しており、ユーザごとに自由に言語設定やタイムゾーンを設定できます。

便利なのですが、注意しないと、エクスポート/インポート時に思わぬ時刻ずれが発生してしまうことにもなりかねません。

私自身、いろいろな場面であぶないなーと感じていることもあり、ここらへんの振る舞いをまとめておこうと思います。

 

Dataloaderでエクスポートした時のフォーマット

データローダーでエクスポートすると、

日付型項目(2016/09/01)  → 2016-09-01
日時型項目(2017/01/01 1:00)  → 2016-12-31T16:00:00.000Z

のようになります。

形式は、「YYYY-MM-DDThh:mm:ss.SSSZ」の形となっています。

エクスポート時、日時の項目はすべて、GMT(グリニッジ標準時)に変換されて上記のように出力されますが、日付項目は、日付で切り捨てされて出力されます。

ここで、「T」は、時刻の要素が始まりますよという印の文字列で、ISO8601で定義されています。

また、「SSS」はミリ秒、最後の「Z」はGMTをあらわします。

 

Dataloaderのインポート時の問題と振る舞いの整理

ここで、「2016-09-01」の項目をDataloaderでインポートすると、日付が一日前になってしまう問題が知られています。(https://help.salesforce.com/articleView?id=000047804&language=ja&type=1)にも書いてあり、この通りなのですが、ややこしいので、検証して整理してみました。

 

Dataloaderのタイムゾーン指定

前提として、Salesforceの内部では、日付型、日付時間型項目のデータは全てGMT(グリニッジ標準時)に変換され格納される仕様です。

なお、DataloaderのSettingでは、タイムゾーンを指定でき、「Asia/Tokyo」(GMT+9:00)のように設定することができます。(多くの場合、タイムゾーンには「Asia/Tokyo」が設定されていると思います。)

では、「Asia/Tokyo」はタイムゾーンに指定された設定のDataloaderでSalesforceへのインポートを行うと、何が起こるでしょうか。

この場合、「データにタイムゾーンの指定が無ければ、(GMT+9:00)としてインポートを行う」という動きになります。

つまり、「2016-09-01」は、インポート時に「2016-09-01 00:00(GMT+9:00)」と解釈されるため、「2016-08-31 15:00(GMT)」と変換され、日付としては「2016-08-31」が格納されることになります。

ここでキモなのは「タイムゾーンの指定が無ければ」というところで、日付型は時間の指定がないため、暗黙的にDataloaderの設定のタイムゾーンが使われることになりますが、日時型はそれに限りません。

日時型の項目へは、Dataloaderでは以下のようなフォーマットでもインポートができます。

①「YYYY-MM-DDThh:mm:ss.SSSZ」・・・例:2016-12-31T16:00:00.000Z
②「YYYY-MM-DDThh:mm:ssZ」・・・例:2016-12-31T16:00:00Z
③「YYYY-MM-DDThh:mm:ss」・・・例:2017-01-01T09:00:00

①と②の場合はインポート時もGMTとみなされ、SFDC内に格納されるデータは「2016-12-31T16:00:00.000Z」になります。そして、表示時に、ログインしているユーザのタイムゾーン設定に変換されますので、「Asia/Tokyo」のユーザであれば、「2017/01/01 1:00」と表示されることになります。

③は、インポート時に「2017-01-01T09:00:00(GMT+9:00)」と解釈され、SFDC内に格納されるデータは「2017-01-01T00:00:00.000Z」となり、表示は「Asia/Tokyo」のユーザであれば、「2017/01/01 9:00」となります。

 

どの運用が良いか

上記の振る舞いの整理を踏まえて、対処法と注意点を考えてみます。

 

Dataloaderのタイムゾーン設定を「GMT」にする。

運用上、一番間違いが少なさそうなのは、Dataloaderのタイムゾーン設定を「GMT」にすることだと思います。

下記のように日時項目であっても、時刻まで指定したり、一日前の日付を指定するという方法もありますが、エクスポート時に切り捨てられて「2016-09-01」のような形式となってしまうので、それを再度インポートするときにまた一日前に変換しないといけません。

特に、開発時やインポート/エクスポート運用が頻繁な場合は、GMTを指定した方が変換が無く、間違いが少ないと思います。

 

GMT指定でインポートする

日付項目であっても時刻指定の形式でインポートできますので、「2017-01-01T00:00:00.000Z」のようにGMT指定でインポートすることができます。

こうすると、インポート時にGMTとみなされ、変換が発生しないので、内部的にも「2017-01-01」で格納されます。上記で述べたように、エクスポート時に「2017-01-01」となってしまいますので、再インポート時には注意したいですね。

 

9時間足した日時をインポートする

「2017-01-01T09:00:00」のようにタイムゾーンの指定無しでインポートすると、Dataloaderのタイムゾーン設定がいかされますので、「Asia/Tokyo」であれば、変換されて、「2017-01-01T00:00:00」でインポートされます。

このやり方も、エクスポート/インポート時に気をつけたい方法ではあります。

SalesforceからTwilioのAPIを使ってSMSメッセージを送信する

$
0
0

この記事では、SalesforceからTwilioでSMS発信を行うための設定と、Apexソースをご紹介します。

SalesforceでTwilioを使うには、Twilioから提供されている、無料のヘルパークラスを使うと便利です。

APexによるクラスが提供されているので、環境の設定とわずか数行の記述でSMS送信等が実現できます。

https://jp.twilio.com/docs/libraries/salesforce

twilio

 

TWILIO セールスフォースヘルパーライブラリーのセットアップ

ヘルパーライブラリーは2つの方法でSalesforce組織にセットアップできます。

ひとつは、パッケージのインストール・プロセスを利用することが可能で、上記URLの「セルフビルド・パッケージ」をクリックしてSalesforce組織にログインすれば、その組織に自動でインストールできます。

もうひとつは、既にインストールされている場合は、MigrationToolを使って、Githubから取得したソースをAntのビルドプロセスで組織にデプロイできます。(MigrationToolの使い方はこちらの記事を参考に。)

 

Salesforce組織の設定

ヘルパーライブラリーのセットアップができたら、環境設定を行います。

主な設定箇所は以下の2点です。

 

Twilio用カスタム設定を行う

ヘルパーライブラリーのセットアップを行うと、「Twilio Config」というカスタム設定ができています。

「ACCOUNT SID」と「AUTH TOKEN」の設定を、APexではなく、レコードに行えるので、デプロイ時の柔軟性がアップします。

ここにレコードを追加して、前回の記事で確認した「ACCOUNT SID」と「AUTH TOKEN」を設定しておきましょう。

sfdc setting

 

リモートサイト設定

SalesforceのApex内から外部にWebサービスのコールを行うには、リモートサイトを設定して、Calloutを許可しておく必要があります。

TwilioのAPIポイントである「https://api.twilio.com」を適当な名前で追加して、許可しておきましょう。

 

Apexのソース記述例

上記までの設定を行えば、後は、TwilioのAPI呼び出しをApexコードに記述するだけです。

public void SendSMS()
{
    
    System.debug('SendSMS');
    Try{
        textMessage = 'tests';
        FromMobileNumber = '+xxxxxxx';
        ToMobileNumber = '+yyyyyyy';
        
        if(ToMobileNumber != '')
        {
            List<TwilioConfig__c> AdminInfo = TwilioConfig__c.getall().values();
            String ACCOUNT_SID = '';
            String AUTH_TOKEN  = '' ;            
            String SenderMobileNumber = '' ;
            // Informaton getting from custom setting
            if(AdminInfo.size()>0)
            {          
                ACCOUNT_SID             = AdminInfo[0].AccountSid__c;
                AUTH_TOKEN              = AdminInfo[0].AuthToken__c;                
            }            
            TwilioRestClient client = new TwilioRestClient(ACCOUNT_SID, AUTH_TOKEN);
           
            Map properties = new Map {
                        'To'   => ToMobileNumber ,
                        'From' => FromMobileNumber,
                        'Body' => textMessage
                };
            TwilioSMS message = client.getAccount().getSmsMessages().create(properties);
            ApexPages.addMessage(new ApexPages.message(ApexPages.severity.INFO, 'Message has been sent'));
        }
        else
        {
            ApexPages.addMessage(new ApexPages.message(ApexPages.severity.Error, 'Pelase provide valid Mobile Number '));
        }
    }catch(Exception e )
    {
        ApexPages.addMessages(e);      
        return ;
    }
}

使い方はここを参考にできます。

http://twilio-salesforce.readthedocs.io/en/latest/

SalesforceでLineのMessaging(PUSH)APIを使ってみる

$
0
0

この記事では、SalesforeからLineにメッセージを送る方法をご紹介します。

APIを利用して送ること自体はそんなに大変ではないですが、送るための情報を取得する仕組みや、そのためのSalesforce側の設定は少しコツが必要なので、具体的に解説しています。

 

Calloutのためのリモートサイトの設定

まずはSalesforceのApexからLineのMessagingAPIを呼べるようにセキュリティの設定を行っておきます。

Salesforceの管理コンソールの「設定」→「リモートサイトの設定」で、LineAPIのURLを登録して、Calloutできるように許可しておきます。

Line API

 

 

Webhookの設定

次に行うのは、前回の記事にも出てきた、Webhookの設定です。

メッセージ送信を行うLine@アカウントへの友達の申請やメッセージ送信のたびにそのURLにJSONがPOSTされるのでしたね。

そのため、Line側から呼べるURLになっていなければいけません。ここが少しコツのいる部分です。

通常、Salesforce上でApexでWebサービスのエントリポイントを作った場合、それを呼ぶにはログインが必要です。

しかし、Line側はSalesforceのログインIDは知りませんから、ログインできません。

つまり、ログインしないでも呼び出し可能なWebサービス(Webhook)を作成して公開する必要があります。

ApexでWebサービスを作って、匿名呼び出しも可能なように公開する設定については、長くなるので、こちらの記事で詳しく説明しておきます。

Webhook自体はシンプルなものです。下記のようなWebサービスを作成し、上記記事を参考に、匿名で公開しましょう。

@RestResource(urlMapping='/line_webhook_callback')
global with sharing class LineWebHookCallback {
    static String LINE_GET_PROFILE_URI = 'https://api.line.me/v2/bot/profile/';
	static String CH_ACCESS_TOKEN = 'xxxxxxxxxxxxxxxxxxx';
    
    @HttpPost
    global static Map<String,String> doPost(){
        RestRequest req = RestContext.request;
        RestResponse res = RestContext.response;
        
        System.debug('★★req.requestBody.ToString(): ' + req.requestBody.ToString());
        
        Map<String, Object> callbackParams = (Map<String, Object>)JSON.deserializeUntyped(req.requestBody.ToString());
        
        
        List<Object> resultParams = (List<Object>)callbackParams.get('events');
        for (Object obj : resultParams) {
            Map<String, Object> params = (Map<String, Object>)obj;
            String eventType = (String)params.get('type');
            Map sourceParams = (Map<String, Object>)params.get('source');

            if( eventType == 'follow' ){
                String sourceType = (String)sourceParams.get('type');
                String userId = (String)sourceParams.get('userId');

            }else if( eventType == 'message' ){
                String sourceType = (String)sourceParams.get('type');
                String userId = (String)sourceParams.get('userId');

            }

		Contact newCt = new Contact();
                newCt.LastName = displayName;
                insert newCt;
        }
        
        Map m1 = new Map<String, String>();
		m1.put('result', 'success');
        
        
        return m1;
    }

}

https://<サイトURL>/services/apexrest/line_webhook_callback

で呼び出せます。

公開まで出来たら、Line DevelopersのWebhookのところに上記URLを設定します。これで、メッセージが送信された時などにこのURLの情報がPOSTされます。

「userId」という項目を取得してとりあえず取引先に保存していますが、これが、メッセージをPushAPIなどで送信する際にToに設定するIDになります。スマホの設定で確認できるLineのIDではなく、MIDと呼ばれるLine内部の識別子なので、注意してください。

また、このMIDはユーザごとに一意ではありません。

Line@アカウントが異なれば、同じLineユーザであっても識別するMIDが異なるので、Bot(Line@アカウント)ごとに友達申請してもらって、取得する必要があります。

 

友達追加

ここで、友達追加をしてもらう方法をメモしておきます。

LINE@MANAGERの「アカウント設定」→「基本設定」に、QRコードや友達追加ボタンのコードがあるので、サイトに貼り付けたりすると、簡単にこのLine@アカウントを追加できます。

Line API

 

 

メッセージ送信(Push API)

HttpRequest req = new HttpRequest();
req.setHeader('Content-Type', 'application/json');
req.setHeader('Authorization', 'Bearer '+ CH_ACCESS_TOKEN);
req.setEndpoint(LINE_PUSH_URI);
req.setMethod('POST');
req.setBody('{"to": "取得したuserId(MID)","messages":[{"type":"text", "text":"Hello, world"}, { "type":"text", "text":"ハロー、ワールド" } ]}');


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());            
}

なお、APIのドキュメントは

https://devdocs.line.me/ja/

を参考にしましょう。

Salesforceのトリガでのoldとnewの使い方

$
0
0

Salesforceの開発を行っていると、トリガを作る機会が多くあります。

作るたびに調べたりするのですが、oldやnewの使い方や使いどころなどを一旦きちんとまとめておいた方が自分でも迷わないと思い、まとめておくことにしました。

 

実行のタイミング

まずは、基本的な実行のタイミングから。

 

beforeトリガ

レコードがDBに格納される前のタイミングで起動されます。DBに保存する前に何か前処理を行いたい場合に使うことが多いです。例えば、入力チェックなどが多いですね。

 

afterトリガ

レコードがDBに保存された後に起動されます。ObjectIdや自動採番などが振られた状態になりますので、それらの値が決定してからの処理を行うのに適しています。ただ、まだコミットされていないとはいえ、DBに格納されているのと同じ状態なので、その値を変更するには、DML文を使う必要があります。

 

実際に実行のタイミングをデバッグして確かめてみる

実際に、以下のようなApex文を用いて、どのような値が入っているのか、どういう操作をしたらどのようなエラーが出るのかを確かめてみました。

trigger testAccountTrigger on Account  (before update, after update, before insert, after insert) {
    if (Trigger.isBefore) {
        System.debug('********トリガーの値isBefore***********');
        System.debug('***SFDC: Trigger.old は: ' + Trigger.old);
        System.debug('***SFDC: Trigger.oldMap は: ' + Trigger.oldMap);
        System.debug('***SFDC: Trigger.new は: ' + Trigger.new);
        System.debug('***SFDC: Trigger.newMap は: ' + Trigger.newMap);
    }
   
    if (Trigger.isAfter) {
        System.debug('********トリガーの値isAfter***********');   
        System.debug('***SFDC: Trigger.old は: ' + Trigger.old);
        System.debug('***SFDC: Trigger.oldMap は: ' + Trigger.oldMap);
        System.debug('***SFDC: Trigger.new は: ' + Trigger.new);
        System.debug('***SFDC: Trigger.newMap は: ' + Trigger.newMap);
    }
}

上記のようなコードでデバッグしてみると、oldとnewには以下のような値が入ります。

基本的に、トリガーの中で用いられるoldとnewは、変更前の値と変更後の値が入るのですが、isBeforeなのか、isAfterなのかのタイミングによって、変更できるか、変更できるとしてもその方法が異なります。

 

insert系

では、Insertの場合は、oldとnewには何が入っているでしょうか。beforeとafterで確認してみると、以下のようになります。なお、before insertの場合のみ、Trigger.newとTrigger.newMapで結果が異なりました。

ちなみに、Trigger.newはList配列で、順番に処理するのに適していますが、Trigger.newMapはMap配列型で、順番は保証されません。

before insertの場合

Trigger.old・・・null
Trigger.oldMap・・・null
Trigger.new・・・新規登録する直前のオブジェクト(ただしDB格納後に決定する、Id=null,自動採番系=null,CreatedById等のシステム系=null)
Trigger.newMap・・・null

Apex上で、oldの値を変更すると、
execution of BeforeInsert caused by: System.NullPointerException: Attempt to de-reference a null object: ()
が発生します。
newは変更可能です。

 

after insertの場合

Trigger.old(oldMap)・・・null
Trigger.new(newMap)・・・新規にDBに登録されたオブジェクト(ただしDB格納後に決定する、Id=あり,自動採番系=あり,CreatedById等のシステム系=あり)

Apex上で、newの値を変更すると

execution of AfterInsert caused by: System.FinalException: Record is read-only: ()
が発生します。
oldを変更すると、
execution of AfterInsert caused by: System.NullPointerException: Attempt to de-reference a null object: ()
となります。

なので、after insertではDML文で変更必要があります(変更可)。ただし、条件を if (Trigger.isInsert && Trigger.isAfter)のように変更しないと、

execution of AfterInsert caused by: System.DmlException: Update failed. First exception on row 0 with id 00128000018cHWpAAM; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, testAccountTrigger: maximum trigger depth exceeded Account trigger event AfterInsert for [xxxxx] Account trigger event AfterUpdate for [xxxx] Account trigger event AfterUpdate for [xxxxxxx] Account trigger event AfterUpdate

のようなエラーになります。

これは、Insertの後、Updateが行われ、その後、さらにUpdateのトリガが走ってしまうので、無限ループになってしまうためです。

 

update系

before updateの場合

Trigger.old(oldMap)・・・新規登録する直前の、変更前のオブジェクト(DBに格納されている)
Trigger.new(newMap)・・・新規登録する直前の、変更予定のオブジェクト

oldを変更すると、
execution of BeforeUpdate caused by: System.FinalException: Record is read-only:
のエラーになり、変更できません。
newは変更可能で、その後、その値でDBにupdateされることになります。

 

after updateの場合

Trigger.old(oldMap)・・・変更前のオブジェクト(すでに変更されている)
Trigger.new(newMap)・・・DBに登録された、変更後のオブジェクト(コミット前)

oldを変更すると、

execution of AfterUpdate caused by: System.FinalException: Record is read-only

になります。newを変更すると、

execution of AfterUpdate caused by: System.FinalException: Record is read-only
となります。ただし、DMLでは値の変更が可能です。でも、Updateのトリガなので、うまく考えないと、無限ループになってしまいます。

「うまく」というのは、条件にフラグ項目を入れ、そこが変わればトリガを発動させないなどの工夫をする必要があるということです。

エラーの回避例

List listAcc=new List();
    for (Account a : Trigger.new) {

        Account updacc=[select id,Name,Fax from account where id = :a.id];
        
        if(a.<フラグ項目>!='22442222'){
            updacc.<フラグ項目>='22442222';
            listAcc.add(updacc);
        }
        
    }
    update listAcc;
}

のように、フラグ項目を持たせ、一旦変更されたら、変更されたことを検知して、それ以降、Updateは行わないようにするというようなことです。

SalesforceからGoogleCalendarを設定する方法(指定ログイン情報を利用した連携)

$
0
0

SalesforceとGoogleCalendarのサービスを連携する方法についてメモしておきます。

今回は、Calendarを例にしていますが、原理は同じなので、これができれば、Googleのほかのサービスや、Googel以外のWebサービスとの連携も可能になります。

最初に、その原理について簡単に説明します。

 

原理

SalesforceからGoogleCalenderの操作(イベントや予定の追加・変更・削除・予定の参照)を行うには、GoogleCalendarAPIを利用します。

もちろん、誰でもそのAPIを利用できてはセキュリティ上よろしくないので、APIを利用するには、認証を経なければいけません。

最近では、その認証をOAuth方式で行うWebサービスが多くなってきていますが、GoogleもそのOAuth方式の認証を行えます。

一方、Salesforce側にも「指定ログイン情報」という便利な仕組みがあり、「GoogleAPIを使うためのログイン、認証情報を定義」しておくことができます。

さらに、この「指定ログイン情報」には、一度認証してしまえば、認証済み情報を保存しておくこともでき、それをApexコード内などから「指定ログイン情報名」で使用することが出来ます。

 

SalesforceとGoogleCalendarの連携設定手順

Step1 Googleのデベロッパーコンソールで、クライアントの定義を行う。

はじめに、GoogleAPIの設定を行います。

Googleのアカウントにログインした状態で https://console.developers.google.com/?hl=JA

に行きます。

ここで、そのユーザが使用できるAPIを有効化したり、ログイン認証情報の生成等を行うのですが、はじめに、分かりやすさのために、この連携用のプロジェクトを作成しておきましょう。

「プロジェクトを作成」をクリック ↓ ↓ ↓
プロジェクトを作成

 

プロジェクト名を入力 ↓ ↓ ↓
プロジェクト名を入力

 

プロジェクトの作成が終わったら、このプロジェクトで使用できるAPIを有効化します。今回は、GoogleCalendarAPIを有効化しました。

Google calendarの有効化 ↓ ↓ ↓
GoogleCalendarAPIを有効

 

APIの有効化ができたら、次に、このAPIの認証を担うクライアントを設定します。OAuthで認証させたいので、「認証情報を作成」ボタンを押し「OAuthクライアントID」を選択します。

「認証情報を作成」から「OAuthクライアントID」を作成 ↓ ↓ ↓
OAuthクライアントID

 

「Webアプリケーション」を選ぶ ↓ ↓ ↓
Webアプリケーション

 

上記の「ウェブアプリケーションの種類」では、形式は「ウェブアプリケーション」を選択し、適宜名前をつけて作成します。

後ほど、「認証済みのリダイレクトURI」をセットすることになりますが、この時点ではまだ分からないので、空白のまま作成します。

ウェブアプリケーション

 

作成すると、「クライアントID」と「クライアントシークレット」が発行され、下記のようなダイアログが表示されます。両方ともメモしておきましょう。

※後ほど、SFDCの画面で入力することになる。

 

Step2 SFDCの管理コンソールに行き、「認証プロバイダ」の作成を行う。

次に、SFDC側の設定を行います。SFDCの管理画面に行って、「認証プロバイダ」を「OpenID」形式で作成します。

※選択肢にGoogle形式もありますが、私が試したときにはうまく動きませんでした。OpenID形式の方が汎用性がある気がします。Google以外のサービスでも使えると思います。

「認証プロバイダ」の作成 ↓ ↓ ↓
OpenID

 

認証プロバイダ

 

新規作成時の入力画面では、先ほどメモした「クライアントID」と「クライアントシークレット」をそれぞれ「コンシューマ鍵」、「コンシューマの秘密」にセットします。他の入力項目は、以下のように入力しました。

  • 認証エンドポイント・・・https://accounts.google.com/o/oauth2/auth?access_type=offline&approval_prompt=force
  • トークンエンドポイント・・・https://accounts.google.com/o/oauth2/token
  • デフォルトの範囲・・・https://www.googleapis.com/auth/calendar

上記を入力して保存すると、下に「Salesforce設定」が表示されるので、このなかで「コールバックURL」をメモしておきます。

コールバックURL

 

メモしたコールバックURLは、GoogleAPIConsoleの以下のところ(「承認済みのリダイレクトURI」)に入力して保存します。

承認済みのリダイレクトURI

 

 

Step3 SFDCの管理コンソールに行き、「指定ログイン情報」の作成を行う。

「指定ログイン情報」の作成

 

先ほどSFDCの管理画面で作成した「認証プロバイダ」をここにセットします。

「保存時に認証フローを開始」にチェックしておくと、このレコードを作成(保存)したときに、OAuth認証も同時に行い、保存しておくことができます。

その他の入力項目は以下の通りです。

  • URL・・・https://www.googleapis.com/calendar/v3
  • 範囲・・・https://www.googleapis.com/auth/calendar

上記で保存ボタンを押すと、同時に認証が行われるので、以下のようなOAuth認証画面になります。

OAuth認証画面

 

認証すると、、、、

認証

 

「認証済み」で指定ログイン情報が作成され手いることが分かります。

 

Step4 SFDCの管理コンソールに行き、「リモートサイト」を作成

さて、いよいよ、ApexからGoogleCalendarAPIを呼ぶコードを書いていきますが、デフォルトでは、Salesforceでは、外部URLへのAPIコールが許可されていません。 そのため、リモートサイトの作成で、googleのサイトを登録し、Apexからのコールを許可するようにします。

リモートサイトの作成

 

 

Step5 作成した「指定ログイン情報」を利用して、ApexからGoogleにAPIを発行

 

使用例:
【検索】
String reqPath = 'callout:MyCalLogin(作成した指定ログイン情報名)/users/me/calendarList';
        
        System.debug(reqPath);
        
        HttpRequest req = new HttpRequest();
        req.setEndpoint(reqPath);
        req.setMethod('GET');

【イベント登録】
String reqPath = 'callout:MyCalLogin/calendars/<カレンダーID>/events';
        
        System.debug(reqPath);
        
        HttpRequest req = new HttpRequest();
        req.setEndpoint(reqPath);
        req.setMethod('POST');
         req.setHeader('Content-Type', 'application/json');
        req.setBody('{ "end": {  "dateTime": "2016-04-27T10:00:00+09:00" }, "start": {  "dateTime": "2016-04-27T10:00:00+09:00" }, "description": "sssq3333ss", "summary": "ddvddvdvdd"}');

 

ちなみに上記のコード例で出てくる「カレンダーID」の確認方法ですが、以下のように、Googleカレンダーの画面で確認できます。

Google calendarを開く

 

Google calendarIDの場所

 

Viewing all 62 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>