Giter Site home page Giter Site logo

salesforce's Introduction

Salesforce

This is an up to date wrapper for the Salesforce.com REST API. I initially found working with the API to be a bit frustrating and hopefully this wrapper will make everything easy for you.

More information about the Salesforce REST API can be found at

http://www.salesforce.com/us/developer/docs/api_rest/

Build

Clojars Project

CircleCI

Usage

We first need to set up some authentication information as a Clojure map. All the information can be found in your Salesforce account.

In order to get an auth token and information about your account we call the auth! function like this

(use 'salesforce.core)

(def config
  {:client-id ""
   :client-secret ""
   :username ""
   :password ""
   :security-token ""})

(def auth-info (auth! config))

You can optionally pass in :login-host if you want to use test.salesforce.com or my.salesforce.com addresses

This returns a map of information about your account including an authorization token that will allow you to make requests to the REST API.

The response looks something like this

{:id "https://login.salesforce.com/id/1234",
 :issued_at "1367488271359",
 :instance_url "https://na15.salesforce.com",
 :signature "1234",
 :access_token "1234"}

Now you can use your auth-config to make requests to the API.

(resources auth-info)

Setting the API version

There are multiple versions of the Salesforce API so you need to decare the version you want to use.

You can easily get the latest API version with the following function

(latest-version) ;; => "39.0"

You can set a version in several ways.

Globally

(set-version! "39.0")

Inside a macro

(with-version "39.0"
  ;; Do stuff here )

Or just using the latest version (this is slow as it needs to make an additional http request)

(with-latest-version
  ;; Do stuff here)

SObjects

The following methods are available

  • so->all
  • so->get
  • so->create
  • so->update
  • so->delete
  • so->describe

Get all sobjects

(so->objects auth-info)

Get all records

(so->all "Account" auth-info)

Get recently created items

(so->recent "Account" auth-info)

Get a single record

;; Fetch all the info
(so->get "Account" "001i0000007nAs3" auth-info)
;; Fetch only the name and website attributes
(so->get "Account" "001i0000007nAs3" ["Name" "Website"] auth-info))

Create a record

(so->create "Account" {:Name "My Account"} auth-info)

Update a record

(so->update "Account" "001i0000007nAs3" {:Name "My New Account Name"} auth-info)

Delete a record

(so->delete "Account" "001i0000008Ge2OAAS" auth-info)

Describe an record

(so->describe "Account" auth-info)

Salesforce Object Query Language

Salesforce provides a query language called SOQL that lets you run custom queries on the API.

(soql "SELECT name from Account" auth-info)

Salesforce provides a search language called SOSL that lets you run custom searches on the API.

(sosl "FIND {Joe Smith} IN Name Fields RETURNING lead" auth-info)

A sample session

This final example shows an example REPL session using the API

(def config
  {:client-id ""
   :client-secret ""
   :username ""
   :password ""
   :security-token ""})

;; Get auth info needed to make http requests
(def auth (auth! config))

;; Get and then set the latest API version globally
(set-version! (latest-version))

;; Now we are all set to access the salesforce API
(so->objects auth)

;; Get all information from accounts
(so->all "Account" auth)

;; Fetch a single account
(so->get "Account" "001i0000008Ge2TAAS" auth)

;; Create a new account
(so->create "Account" {:Name "My new account"} auth)

;; Update the account
(so->update "Account" "001i0000008JTPpAAO" {:Name "My Updated Account Name"} auth)


;; Delete the account we just created
(so->delete "Account" "001i0000008JTPpAAO" auth)

;; Finally use SOQL to find account information
(:records (soql "SELECT name from Account" auth))

;; You can also pass a clojure java.jdbc array to the soql query
;; The classes on the array will be serialized following the SOQLable protocol, which can be extended in your program.
(soql ["select * from fruits where name = ? and price >= ? and created = ?" "apple" 9/5 (java.time.LocalDate/of 2020 10 10)] auth)

Contributors

  • Owain Lewis
  • Rod Pugh
  • Lucas Severo

License

Distributed under the Eclipse Public License, the same as Clojure.

salesforce's People

Contributors

kenrestivo-stem avatar kubrack avatar owainlewis avatar rodnaph avatar sgeop avatar tuddman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

salesforce's Issues

NullPointerException on SFDC API errors.

Currently salesforce.core/request doesn't handle properly the case when SFDC API returns error.
There is try/catch around clj-http.client/request but then parse-limit-info crashes with NullPointerException due to absence [:headers "sforce-limit-info"] in the resp.

Even when pass through the parse-limit-info, the salesforce.core/request returns nil instead of SFDC error message since exception's :body is already extracted.

Please consider the diff:

--- a/src/salesforce/core.clj
+++ b/src/salesforce/core.clj
@@ -1,6 +1,5 @@
 (ns salesforce.core
   (:require
-   [clojure.string :as str]
    [cheshire.core :as json]
    [clj-http.client :as http]
    [clojure.string :as str]
@@ -71,10 +70,10 @@
                           {:method method
                            :url full-url
                            :headers {"Authorization" (str "Bearer " (:access_token token))}}))
-                  (catch Exception e (:body (ex-data e))))]
-    (-> (get-in resp [:headers "sforce-limit-info"]) ;; Record limit info in atom
-        (parse-limit-info)
-        ((partial reset! limit-info)))
+                  (catch Exception e (ex-data e)))]
+    (some-> (get-in resp [:headers "sforce-limit-info"]) ;; Record limit info in atom
+            (parse-limit-info)
+            ((partial reset! limit-info)))
     (-> resp
         :body
         (json/decode true))))

BEFORE

=> (sf/so->objects auth)
Execution error (NullPointerException) at (REPL:1).
null

AFTER

=> (sf/so->objects auth)
({:message "The REST API is not enabled for this Organization.", :errorCode "API_DISABLED_FOR_ORG"})

Execution error (MalformedURLException) at java.net.URL/<init>

Hi
While trying to setup a connection with Salesforce I ran into the following issue:

Execution error (MalformedURLException) at java.net.URL/ (URL.java:672).
no protocol: /services/data/v51.0/sobjects/Account

This is code that I used, and I got a warning and exception while loading it into the REPL

Connecting to local nREPL server...
nREPL server started on port 56447 on host localhost - nrepl://localhost:56447
Clojure 1.10.1
(ns mytest.core )
=> nil
(use 'salesforce.core)
WARNING: update already refers to: #'clojure.core/update in namespace: clj-http.client, being replaced by: #'clj-http.client/update
=> nil
(def config
  {:client-id "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
   :client-secret "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
   :username "[email protected]"
   :password "XXXXX"
   :security-token ""  
   :login-host "test.salesforce.com"})
=> #'mytest.core/config

(def auth-info (auth! config))
Execution error (ExceptionInfo) at slingshot.support/stack-trace (support.clj:194).
clj-http: status 400

(set-version! (latest-version))
=> "51.0"

(defn foo
  "I don't do a whole lot."
  []
  (println "My First Salesforce connection!")
  (so->all "Account" auth-info))
=> #'mytest.core/foo

(foo)
My First Salesforce connection!
Execution error (MalformedURLException) at java.net.URL/<init> (URL.java:672).
no protocol: /services/data/v51.0/sobjects/Account

Any thoughts on how I can resolve this?

Need to specify hostname in config

I have been told we need to use stempowered.my.salesforce.com not login.salesforce.com

Need to be able to pass in a hostname explicitly.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.