51
50

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

REST APIを使ってSalesforceのデータを取得する

Last updated at Posted at 2019-05-19

はじめに

(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

ソースコード

実際に実装内容やソースコードを追いながら読むとより理解が深まるかと思います。是非ご活用ください。

GitHub

事前準備

SalesforceのOAuth設定

設定 > 作成 > アプリケーション > 接続アプリケーション > 新規をクリックする

項目名 設定値
接続アプリケーション名 Sample
API 参照名 Sample
取引先責任者 メール sample@gmail.com
OAuth 設定の有効化 TRUE
コールバック URL https://sample.auth0.com/login/callback
選択した OAuth 範囲 基本情報へのアクセス
Web サーバフローの秘密が必要 TRUE
スクリーンショット 2018-12-19 23.42.27.png

接続アプリケーションを使用する前に、サーバ上で変更が有効になるまで 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)

スクリーンショット 2018-12-20 0.29.33.png

(参照2)

セキュリティトークンは、私の設定 > 個人用 > 私のセキュリティトークのリセットから再発行ができます。

スクリーンショット 2018-12-20 0.43.24.png

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 サービス有効化

設定 > ユーザの管理 > 権限セット (または プロファイル) > システム権限を編集する

スクリーンショット 2019-05-19 0.17.52.png

Apex クラスアクセス有効化

設定 > ユーザの管理 > 権限セット (または プロファイル) > Apex クラスアクセスを編集する

スクリーンショット 2019-05-19 0.18.41.png

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サービスの実装サンプル
51
50
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
51
50

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?