🎛️

goからsalesforceに接続(simpleforce使ってみた)

2024/11/26に公開

こんにちは。
推しの子が完結してカタルシスと喪失感が同時に来てどうしようもないため次の漫画を探し中のmachaです。
今回はsimpleforceというSalesforceクライアントライブラリを利用してgo言語からSalesforceに接続してみました。

simpleforceとは

https://github.com/simpleforce/simpleforce

go言語のsalesforceライブラリがいくつかある中でなぜこれを選んだかというと..."force"が付いていたからです。
なぜかSalesforceのライブラリって慣例なのか"force"と名が付くものが多いんです。
pythonではsimple-salesforce、rubyではrestforcesoapforce
Visual Studio Codeの拡張機能にForceCodeがあります。

どんなライブラリなのか検証する意味でもsimpleforceを使ってみたいと思います

Salesforceの準備

認証に必要な設定は大きく2種類あります。

  • IPアドレス制限
  • セキュリティトークン

今回はIPアドレス制限を使用しました。
設定 > ユーザー > プロファイルから、対象プロファイルを選択します。
「ログイン IP アドレスの制限」を指定すれば完了です。

simpleforceの準備

次にgo側の準備を行います。

mkdir simpleforce-study
cd ./simpleforce-study
go mod init simpleforce-study
go get github.com/simpleforce/simpleforce

main.goを作成します

package main

import (
	"fmt"
	"github.com/simpleforce/simpleforce"
)

/**
 * Salesforceの接続情報
 */
var (
	// https://xxxxx.my.salesforce.com
	sfURL      = "URL"
	// ユーザー名とメールアドレスは別物なので要注意
	sfUser     = "ユーザー名"
	sfPassword = "パスワード"
	// IPアドレス制限を利用した場合はトークン不要
	sfToken    = ""
)

/**
 * simpleforceを使ってSalesforceに接続
 */
func createClient() *simpleforce.Client {
	client := simpleforce.NewClient(sfURL, simpleforce.DefaultClientID, simpleforce.DefaultAPIVersion)
	if client == nil {
		return nil
	}
	err := client.LoginPassword(sfUser, sfPassword, sfToken)
	if err != nil {
		return nil
	}
	return client
}

/**
 * 取引先データを取得
 */
func getAccounts(client simpleforce.Client) *simpleforce.QueryResult {
	// SOQL文を実行
    accounts, err := client.Query("SELECT Id, Name FROM Account ORDER BY Name LIMIT 10")
	if err != nil {
		return nil
	}
	return accounts
}

/**
 * 取引先データを生成
 */
func createAccount(client simpleforce.Client, name string) *simpleforce.SObject {
	newAccount := client.SObject("Account").
		Set("Name", name).
		Create()
	return newAccount
}

/**
 * 取引先データを更新
 */
func updateAccount(client simpleforce.Client, id string, name string) *simpleforce.SObject {
	updateAccount := client.SObject("Account").
		Set("Id", id).
		Set("Name", name).
		Update()
	return updateAccount
}

func main() {
	client := createClient()

	fmt.Println("取引先データ取得")
	accounts := getAccounts(*client)
	for _, record := range accounts.Records {
		name := record.StringField("Name")
		fmt.Println(name)
	}

	fmt.Println("取引先データ生成")
	newAccount := createAccount(*client, "New Name")
	fmt.Println(newAccount)

	fmt.Println("取引先データ更新")
	updateAccount := updateAccount(*client, newAccount.ID(), "Changed Name")
	fmt.Println(updateAccount)
}

実行結果

Trailheadのハンズオン組織で実行しました。
実行前。

go run main.go
[simpleforce] User m.tsuchiya+simpleforce@v-standard.com authenticated.
取引先データ取得
Burlington Textiles Corp of America
Dickenson plc
Edge Communications
Express Logistics and Transport
GenePoint
Grand Hotels & Resorts Ltd
Pyramid Construction Inc.
Sample Account for Entitlements
sForce
United Oil & Gas Corp.
取引先データ生成
&map[Id:001GC00003jST6dYAG Name:New Name __client__:0x1400010abe0 attributes:{Account }]
取引先データ更新
&map[Id:001GC00003jST6dYAG Name:Changed Name __client__:0x140002b2000 attributes:{Account }]

無事にデータも生成できました。

シンプルに連携が実現できました。まさにsimpleforce!!
このほかUPSERTやファイルのダウンロード、Apexの実行もできるようなので欲しい機能は一通りありそうです。

ん?!疑問?!

ここまでやってきてふと疑問に思いました。
なぜID、パスワード、IP制限だけでアクセスできるの?
なんでこれで接続できちゃうの?!

公式では「接続アプリケーション」をつくって認証するようガイダンスされています。
https://developer.salesforce.com/docs/atlas.ja-jp.api_rest.meta/api_rest/intro_oauth_and_connected_apps.htm

なぜ接続アプリケーションなしで繋げられるのだろう...
なぜだろうと思いsimpleforceをみてみると...
https://github.com/simpleforce/simpleforce/blob/acf4ac67ef68eee62febf8e1afac93b55b0e6512/force.go#L143-L145

なんと最初の認証だけSOAP接続してセッション取得して、その後のデータアクセスはRESTを使用していました。たしかにRESTは接続アプリケーション認証だし、SOAPはWSDLファイル意識しなきゃいけないし。どちらもクセがあるんですがSOAPとRESTを組み合わせてsimpleを実現していたようです。アイデア面白い。

まとめ

なんだかんだSalesforceでSOAPは残りそうですがセキュリティ基準はどんどん上がってますのでいつか利用できなくなっちゃうかもしれませんが、シンプルにSalesforceにつなぐにはsimpleforce良さそうです。

Discussion