jeudi 7 janvier 2016
·
4 minutes de lecture
Interacting with the Salesforce APIs can be tricky if your favorite language doesn't have modules or packages available to handle the complexity. Of course, you can build one from scratch. However, chances you'll hit a couple of roadblocks along the way.
A couple of weeks ago, I started working on a package to interact with the Salesforce APIs in Go, currently available on Github. My main motivations were to use it for my personal projects, to leverage existing packages such as golang.org/x/oauth2
(since all the other packages seem to rebuild this part of the logic) and to improve my understanding of both the Salesforce APIs and Go.
Here's a quick example on how to execute an SOQL query using the package.
First of, you will have to create an http client implementing the OAuth2 specification. To achieve this, github.com/jpmonette/force
is leveraging the oauth2
package built by Google.
conf := &oauth2.Config{
ClientID: "CLIENT-ID",
ClientSecret: "CLIENT-SECRET",
Endpoint: oauth2.Endpoint{
TokenURL: "TOKEN-URL",
},
}
token, \_ := conf.PasswordCredentialsToken(oauth2.NoContext, "USERNAME", "PASSWORD")
instanceUrl, \_ := token.Extra("instance_url").(string)
client := conf.Client(oauth2.NoContext, token)
Here are the steps to obtain a functional http client:
oauth2.Config
required to query an access_token
from Salesforce - details are provided when configuring a Connected App;access_token
using the Username-Password OAuth Flow;instance_url
from the reponse, required by the github.com/jpmonette/force
package to query the correct instance;Now that we have a functional http client, here's how to use it with the force
package:
c, \_ := force.NewClient(client, instanceUrl)
var data QueryReponse
c.Query("SELECT Id, Name FROM Account LIMIT 10", &data)
fmt.Println("Total size: "+data.TotalSize)
fmt.Println("First ID: "+data.Records[0].Id)
In the previous snippet, we are:
force
client;data
variable using the type QueryReponse
(defined later)func (c *Client) Query(query string, v interface{}) (err error)
function;At last, you have to define the QueryReponse
struct:
type QueryReponse struct {
TotalSize int `json:"totalSize"`
Records []struct {
ID string `json:"Id"`
Name string `json:"Name"`
Attributes struct {
Type string `json:"type"`
URL string `json:"url"`
} `json:"attributes"`
} `json:"records"`
}
Now, here's the whole example:
package main
import (
"os"
"fmt"
"github.com/jpmonette/force"
"golang.org/x/oauth2"
)
func main() {
conf := &oauth2.Config{
ClientID: os.Getenv("SFCLIENTID"),
ClientSecret: os.Getenv("SFCLIENTSECRET"),
Endpoint: oauth2.Endpoint{
TokenURL: os.Getenv("SFTOKENURL"),
},
}
token, _ := conf.PasswordCredentialsToken(oauth2.NoContext, os.Getenv("SFUSERNAME"), os.Getenv("SFPASSWORD"))
instanceUrl, _ := token.Extra("instance_url").(string)
client := conf.Client(oauth2.NoContext, token)
c, _ := force.NewClient(client, instanceUrl)
var data QueryReponse
c.Query("SELECT Id, Name FROM Account LIMIT 10", &data)
fmt.Println("Total size: " + data.TotalSize)
fmt.Println("First ID: " + data.Records[0].Id)
}
// QueryReponse is used to Unmarshal the SOQL query response
type QueryReponse struct {
TotalSize int `json:"totalSize"`
Records []struct {
ID string `json:"Id"`
Name string `json:"Name"`
Attributes struct {
Type string `json:"type"`
URL string `json:"url"`
} `json:"attributes"`
} `json:"records"`
}
Now - if you go get github.com/jpmonette/force
and go run main.go
, the console should output something similar to:
~ » go run main.go
Total size: 10
First ID: 001b000002T9ak4
Notes: For simplicity, error checking has been omitted in the example.
Please note that this package is inspired by the go-github package. Since it is a work in progress, you are more than welcomed to send pull requests to support additional features.