はじめに
(Mac環境の記事ですが、Windows環境も同じ手順になります。環境依存の部分は読み替えてお試しください。)
この記事を最後まで読むと、次のことができるようになります。
- SalesforceのAPI(OAuth 設定の有効化)を設定する
- Python, Java, Shell ScriptでSalesforceのデータを取得する
- SalesforceのApexでREST Webサービスを実装する
サンプルコード
python_sfdc_get_user.py
sf = Salesforce(username=USERNAME, password=PASSWORD,
security_token=SECURITY_TOKEN, sandbox=False)
res = sf.query(
'SELECT Id, Name, LastLoginDate FROM User WHERE Name =\'nsuhara\'')
print(json.dumps(res, indent=4))
実行結果
python_result.json
{
"totalSize": 1,
"done": true,
"records": [
{
"attributes": {
"type": "User",
"url": "/services/data/v38.0/sobjects/User/0056F000006StK9QAK"
},
"Id": "0056F000006StK9QAK",
"Name": "nsuhara",
"LastLoginDate": "2019-05-18T13:07:00.000+0000"
}
]
}
関連する記事
実行環境
環境 | Ver. | Note |
---|---|---|
macOS Mojave | 10.14.4 | OS |
Salesforce | Spring'19 | SaaS |
Python | 3.7.3 | Python |
simple-salesforce | 0.74.2 | Python |
requests | 2.22.0 | Python |
Java | 1.8.0_192 | Java |
httpclient | 4.5.6 | Java |
json | 20180813 | Java |
jackson-databind | 2.9.8 | Java |
ソースコード
実際に実装内容やソースコードを追いながら読むとより理解が深まるかと思います。是非ご活用ください。
事前準備
SalesforceのOAuth設定
設定 > 作成 > アプリケーション > 接続アプリケーション > 新規
をクリックする
項目名 | 設定値 |
---|---|
接続アプリケーション名 | Sample |
API 参照名 | Sample |
取引先責任者 メール | sample@gmail.com |
OAuth 設定の有効化 | TRUE |
コールバック URL | https://sample.auth0.com/login/callback |
選択した OAuth 範囲 | 基本情報へのアクセス |
Web サーバフローの秘密が必要 | TRUE |
接続アプリケーションを使用する前に、サーバ上で変更が有効になるまで 2 ~ 10 分お待ちください。
パラメータの概要
変数名 | 説明 | 備考 |
---|---|---|
HOST | Production: login.salesforce.com, Sandbox: test.salesforce.com | |
CLIENT_ID | コンシューマ鍵 | 参照1 |
CLIENT_SECRET | コンシューマの秘密 | 参照1 |
USERNAME | Salesforceのユーザ名 | |
PASSWORD | Salesforceのパスワード | |
SECURITY_TOKEN | Salesforceのセキュリティトークン | 参照2 |
PASSWORD_AND_SECURITY_TOKEN | Salesforceのパスワード + セキュリティトークン |
(参照1)
(参照2)
セキュリティトークンは、私の設定 > 個人用 > 私のセキュリティトークのリセット
から再発行ができます。
Shell Scriptサンプル
shell_script_sfdc_get_user.sh
#!/bin/sh
export HOST='<パラメータ参照>'
export CLIENT_ID='<パラメータ参照>'
export CLIENT_SECRET='<パラメータ参照>'
export USERNAME='<パラメータ参照>'
export PASSWORD_AND_SECURITY_TOKEN='<パラメータ参照>'
export INSTANCE_URL=`curl -s https://$HOST/services/oauth2/token -d "grant_type=password" -d "client_id=$CLIENT_ID" -d "client_secret=$CLIENT_SECRET" -d "username=$USERNAME" -d "password=$PASSWORD_AND_SECURITY_TOKEN" | awk 'BEGIN{FS="instance_url\":"}{print $2}' | awk 'BEGIN{FS=","}{print $1}' | sed -e 's/\"//g'`
export ACCESS_TOKEN=`curl -s https://$HOST/services/oauth2/token -d "grant_type=password" -d "client_id=$CLIENT_ID" -d "client_secret=$CLIENT_SECRET" -d "username=$USERNAME" -d "password=$PASSWORD_AND_SECURITY_TOKEN" | awk 'BEGIN{FS="access_token\":"}{print $2}' | awk 'BEGIN{FS=","}{print $1}' | sed -e 's/\"//g'`
export SOQL="SELECT+Id,Name,LastLoginDate+FROM+User+WHERE+Name='nsuhara'"
curl $INSTANCE_URL/services/data/v45.0/query?q=$SOQL -H "Authorization: OAuth $ACCESS_TOKEN" -H "X-PrettyPrint:1"
shell_script_result.json
{
"totalSize": 1,
"done": true,
"records": [
{
"attributes": {
"type": "User",
"url": "/services/data/v45.0/sobjects/User/0056F000006StK9QAK"
},
"Id": "0056F000006StK9QAK",
"Name": "nsuhara",
"LastLoginDate": "2019-05-18T14:04:05.000+0000"
}
]
}
Pythonサンプル
python_sfdc_get_user.py
import json
from simple_salesforce import Salesforce
USERNAME = '<パラメータ参照>'
PASSWORD = '<パラメータ参照>'
SECURITY_TOKEN = '<パラメータ参照>'
def main():
sf = Salesforce(username=USERNAME, password=PASSWORD,
security_token=SECURITY_TOKEN, sandbox=False)
res = sf.query(
'SELECT Id, Name, LastLoginDate FROM User WHERE Name =\'nsuhara\'')
print(json.dumps(res, indent=4))
if __name__ == '__main__':
main()
python_result.json
{
"totalSize": 1,
"done": true,
"records": [
{
"attributes": {
"type": "User",
"url": "/services/data/v38.0/sobjects/User/0056F000006StK9QAK"
},
"Id": "0056F000006StK9QAK",
"Name": "nsuhara",
"LastLoginDate": "2019-05-18T14:06:19.000+0000"
}
]
}
Javaサンプル
java_App.java
package rest_api;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicHeader;
import org.apache.http.util.EntityUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
public class App {
static final String HOST = "<パラメータ参照>";
static final String CLIENT_ID = "<パラメータ参照>";
static final String CLIENT_SECRET = "<パラメータ参照>";
static final String USERNAME = "<パラメータ参照>";
static final String PASSWORD_AND_SECURITY_TOKEN = "<パラメータ参照>";
static final String GRANT_SERVICE = "/services/oauth2/token?grant_type=password";
public static void main(String[] args) {
String UA = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36";
List<Header> headers = new ArrayList<Header>();
headers.add(new BasicHeader("User-Agent", UA));
HttpClient httpClient = HttpClientBuilder.create().setDefaultHeaders(headers).build();
String loginURL = "https://" + HOST + GRANT_SERVICE + "&client_id=" + CLIENT_ID + "&client_secret="
+ CLIENT_SECRET + "&username=" + USERNAME + "&password=" + PASSWORD_AND_SECURITY_TOKEN;
HttpPost httpPost = new HttpPost(loginURL);
HttpResponse response = null;
try {
response = httpClient.execute(httpPost);
} catch (ClientProtocolException cpException) {
// Handle protocol exception
} catch (IOException ioException) {
// Handle system IO exception
}
final int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
System.out.println("Error authenticating to Force.com: " + statusCode);
// Error is in EntityUtils.toString(response.getEntity())
return;
}
String getResult = null;
try {
getResult = EntityUtils.toString(response.getEntity());
} catch (IOException ioException) {
// Handle system IO exception
}
JSONObject jsonObject = null;
String loginAccessToken = null;
String loginInstanceUrl = null;
try {
jsonObject = (JSONObject) new JSONTokener(getResult).nextValue();
loginInstanceUrl = jsonObject.getString("instance_url");
loginAccessToken = jsonObject.getString("access_token");
} catch (JSONException jsonException) {
// Handle JSON exception
}
System.out.println(response.getStatusLine());
httpPost.releaseConnection();
try {
final URIBuilder builder = new URIBuilder(loginInstanceUrl);
final String SOQL = "SELECT Id, Name, LastLoginDate FROM User WHERE Name = \'nsuhara\'";
builder.setPath("/services/data/v45.0/query/").setParameter("q", SOQL);
final HttpGet get = new HttpGet(builder.build());
get.setHeader("Authorization", "Bearer " + loginAccessToken);
final HttpResponse queryResponse = httpClient.execute(get);
ObjectMapper mapper = new ObjectMapper();
final JsonNode queryResults = mapper.readValue(queryResponse.getEntity().getContent(), JsonNode.class);
System.out.println("queryResults:" + queryResults);
} catch (Exception e) {
// Handle exception
}
}
}
java_result.json
{
"totalSize": 1,
"done": true,
"records": [
{
"attributes": {
"type": "User",
"url": "/services/data/v45.0/sobjects/User/0056F000006StK9QAK"
},
"Id": "0056F000006StK9QAK",
"Name": "nsuhara",
"LastLoginDate": "2019-05-18T14:09:31.000+0000"
}
]
}
REST Webサービスの実装サンプル
Apex実装
apex_SampleRestApi.cls
@RestResource(urlMapping='/sample/restapi/*')
global without sharing class SampleRestApi {
@HttpGet
global static List<User> getUsers() {
return [SELECT Id, Name, LastLoginDate FROM User WHERE Name = 'nsuhara' LIMIT 1];
}
}
Apex REST サービス有効化
設定 > ユーザの管理 > 権限セット (または プロファイル) > システム権限
を編集する
Apex クラスアクセス有効化
設定 > ユーザの管理 > 権限セット (または プロファイル) > Apex クラスアクセス
を編集する
HTTPメソッドGET テスト
python_requests_sfdc.py
import requests
HOST = '<パラメータ参照>'
CLIENT_ID = '<パラメータ参照>'
CLIENT_SECRET = '<パラメータ参照>'
USERNAME = '<パラメータ参照>'
PASSWORD_AND_SECURITY_TOKEN = '<パラメータ参照>'
def main():
params = {
'grant_type': 'password',
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
'username': USERNAME,
'password': PASSWORD_AND_SECURITY_TOKEN
}
res_post = requests.post(
'https://{}/services/oauth2/token'.format(HOST), params=params)
access_token = res_post.json().get('access_token')
instance_url = res_post.json().get('instance_url')
services_url = '/services/apexrest/sample/restapi'
headers = {
'Content-type': 'application/json',
'Accept-Encoding': 'gzip',
'Authorization': 'Bearer {}'.format(access_token)
}
res_get = requests.request(method='get', url=instance_url+services_url,
headers=headers, params={'xxx': 'yyy'}, timeout=10)
print(res_get.status_code)
print(res_get.json())
if __name__ == '__main__':
main()
python_result.json
[
{
"attributes": {
"type": "User",
"url": "/services/data/v45.0/sobjects/User/0056F000006StK9QAK"
},
"Id": "0056F000006StK9QAK",
"Name": "nsuhara",
"LastLoginDate": "2019-05-18T14: 11: 22.000+0000"
}
]
まとめ - 実装モデルの検討
環境や条件をもとに実装モデルを検討する
No. | 検討条件 | 実装モデル | サンプル |
---|---|---|---|
1 | Salesforce向けのパッケージが用意されている場合 | パッケージを使用して実装する | Pythonサンプル |
2 | SOQLの実行結果で事足りる場合 | HTTPリクエストを使用して実装する | Shell Scriptサンプル, Javaサンプル |
3 | 上記以外の場合 | Apex REST Webサービスを実装する | REST Webサービスの実装サンプル |