Salesforce SOAP方式、REST方式

引用：https://www.cnblogs.com/zero-zyq/p/5599632.html
本篇参考Trail教程：

https://developer.salesforce.com/trailhead/force_com_dev_intermediate/apex_integration_services/apex_integration_rest_callouts

有的时候我们需要在salesforce中引入外部的方法或者数据，这样就需要访问外部的Services，目前常用的访问方式有两种：

1.SOAP方式：Web Service通过XML方式调用SOAP Web服务器;

2.REST方式：Http通过JSON使用REST方式调用服务器。

 这两种Callouts使用原理类似，简单的可以理解像服务器发送一个请求，然后服务器返回一个响应。基于WSDL的callouts适用于SOAP方式，HTTP方式可以使用任何的HTTP service，SOAP或者REST都可以。

这两种方式能选择Http方式尽量选择Http方式。

下面来了解一下REST方式获取外部Service数据以及其他Service访问Salesforce数据操作。

一.REST方式获取外部Service数据

REST方式主要原理如下图所示。使用REST方式主要步骤如下：

 



salesforce通过REST方式访问外界站点步骤如下：

1.将Web Service的授权端点地址添加到Remote Site中：setup->Administer->Security Site Settings->Remote Site Settings。

salesforce提供了两个测试URL，将两个测试的URL添加到Remote Site中。两个URL分别为：

http:https://ap2.salesforce.com/0rp28000000TSqv

soap:https://ap2.salesforce.com/0rp28000000TSr0



2.代码进行访问

通过HTTP方式可以使用以下方法进行相关操作的访问



https://th-apex-http-callout.herokuapp.com/animals远程站点JSON内容如下{"animals":["majestic badger","fluffy bunny","scary bear","chicken"]}

在Eclipse中使用匿名块编写代码实现访问：window->show view->Other->Execute Anonymous即可打开匿名块。
GET方式获取数据：

复制代码
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint('https://th-apex-http-callout.herokuapp.com/animals');
request.setMethod('GET');
HttpResponse response = http.send(request);
// If the request is successful, parse the JSON response.
if (response.getStatusCode() == 200) {
    // Deserialize the JSON string into collections of primitive data types.
    Map<String, Object> results = (Map<String, Object>) JSON.deserializeUntyped(response.getBody());
    // Cast the values in the 'animals' key as a list
    List<Object> animals = (List<Object>) results.get('animals');
    System.debug('Received the following animals:');
    for (Object animal: animals) {
        System.debug(animal);
    }
}
复制代码
输出的结果如下：



其他方式自行测试。

二.Salesforce作为REST Service供java访问（可以供其它语言访问，这里只对java展示，因为我只会java）

 有的时候我们需要在其他平台上获取sfdc端的数据，比如做android项目需要访问sfdc数据，那样就需要Salesforce作为Service，java端通过http获取并对数据进行相关操作。步骤如下：

1)新建一个App，然后创建Connected App:

setup->Build->Create->Apps.先new一个app，正常new完以后new一个Connected App，设置Enable OAuth Settings为true，截图如下所示：



java访问sfdc 的Service的时候需要用到Consumer Key以及Consumer Secret这两项。

2）sfdc端rest service构建：这里我们以Goods__c进行操作，主要方法有添加一条Goods，通过Id获取Goods，通过PageNumber获取指定条数开始的Goods数据，修改一条Goods以及删除一条Goods。

这里对常用的注解进行解释：

　　1.@RestResource:曝光此类作为REST资源;

　　2.@HttpGet:曝光方法作为REST资源，当有Http get请求发送时，此注解对应的方法会被执行;

　　3.@HttpPost:Http post 请求发送时，此注解对应的方法会被执行;

　　4.@HttpDelete:当有Http delete请求发送时，此注解对应的方法会被执行;

　　5.@HttpPut:当有Http put请求发送时，此注解对应的方法会被执行;

　　6.@HttpPatch:当有Http patch请求发送时，此注解对应的方法会被执行。

因为http有请求时按照请求方式来对应相关方法，所以一个类中上述标签只能存在一个，即不能存在两个方法标注@HttpRequest等。

复制代码
 1 /*
 2 * 使用salesforce通过REST方式作为webservice，需要以下几点：
 3 * 1.类和方法需要global，方法需要静态
 4 * 2.类需要通过RestResource（UrlMapping='/page/*'）注解声明
 5 * 3.@HttpGet和@HttpDelete不能有形参，可以通过URL?param或者URL/param方式传过来参数
 6 */
 7 @RestResource(UrlMapping='/Goods/*')
 8 global class GoodsRESTController {
 9     global static final Integer PAGE_SIZE = 20;
10     @HttpGet
11     global static List<Goods__c> getGoodsByIdOrGoodsList() {
12         RestRequest request = RestContext.request;
13         // grab the goodsId from the end of the URL
14         String currentPage = request.params.get('currentPage') != null ? request.params.get('currentPage') : '0';
15         Integer offsetNumber = Integer.valueOf(currentPage) * PAGE_SIZE;
16         String goodsId = request.params.get('goodsId');
17         String fetchSql;
18         if(goodsId != null) {
19             fetchSql = 'SELECT CreatedById, CreatedDate, IsDeleted, Name,' +
20             ' GoodsBrand__c, GoodsCostPrice__c, GoodsDescribe__c, GoodsName__c,' +
21             ' GoodsPrice__c, GoodsProfit__c, LastActivityDate, LastModifiedById,' +
22             ' LastModifiedDate, No__c, OwnerId, Id FROM Goods__c' +
23             ' where Id = :goodsId';
24         } else {
25             fetchSql = 'SELECT CreatedById, CreatedDate, IsDeleted, Name,' +
26             ' GoodsBrand__c, GoodsCostPrice__c, GoodsDescribe__c, GoodsName__c,' +
27             ' GoodsPrice__c, GoodsProfit__c, LastActivityDate, LastModifiedById,' +
28             ' LastModifiedDate, No__c, OwnerId, Id FROM Goods__c limit :PAGE_SIZE offset :offsetNumber';
29         }
30         List<Goods__c> goodsList = Database.query(fetchSql);
31         return goodsList;
32     }
33     
34     
35     @HttpPost
36     global static Id insertGoods(String goodsName,String goodsBrand,String goodsPrice,String goodsCostPrice,String goodsDescribe) {
37         System.debug('---------goodsName-------------' + goodsName);
38         Goods__c goods = new Goods__c();
39         if(goodsPrice != null && goodsPrice.isNumeric()) {
40             goods.GoodsPrice__c = Double.valueOf(goodsPrice);
41         }
42         if(goodsCostPrice != null && goodsCostPrice.isNumeric()) {
43             goods.GoodsCostPrice__c = Double.valueOf(goodsCostPrice);
44         }
45         goods.GoodsName__c = goodsName;
46         goods.GoodsDescribe__c = goodsDescribe;
47         insert goods;
48         return goods.Id;
49     }
50     
51     @HttpDelete
52     global static void deleteGoods() {
53         RestRequest request = RestContext.request;
54         String goodsId = request.requestURI.substring(
55             request.requestURI.lastIndexOf('/')+1);
56         Goods__c needDeleteGoods = [select Id from Goods__c where Id = :goodsId];
57         if(needDeleteGoods != null) {
58             delete needDeleteGoods;
59         }
60     }
61     
62     @HttpPut
63     global static ID upsertGoods(String id,String goodsName,String goodsBrand,String goodsPrice,String goodsCostPrice,String goodsDescribe) {
64         Goods__c goods = new Goods__c();
65         goods.Id = id;
66         goods.GoodsName__c = goodsName;
67         goods.GoodsBrand__c = goodsBrand;
68         goods.GoodsDescribe__c = goodsDescribe;
69         if(goodsPrice != null && goodsPrice.isNumeric()) {
70             goods.GoodsPrice__c = Double.valueOf(goodsPrice);
71         }
72         if(goodsCostPrice != null && goodsCostPrice.isNumeric()) {
73             goods.GoodsCostPrice__c = Double.valueOf(goodsCostPrice);
74         }
75         upsert goods;
76         return goods.Id;
77     }
78 
79     @HttpPatch
80     global static ID updateGoods() {
81         RestRequest request = RestContext.request;
82         String goodsId = request.requestURI.substring(
83             request.requestURI.lastIndexOf('/')+1);
84         Goods__c goods = [select Id from Goods__c where Id= :goodsId];
85         // Deserialize the JSON string into name-value pairs
86         Map<String, Object> params = (Map<String, Object>)JSON.deserializeUntyped(request.requestbody.tostring());
87         // Iterate through each parameter field and value
88         goods.GoodsName__c = String.valueOf(params.get('GoodsName__c'));
89         goods.GoodsPrice__c = Double.valueOf(params.get('GoodsPrice__c'));
90         goods.GoodsCostPrice__c = Double.valueOf(params.get('GoodsCostPrice__c'));
91         update goods;
92         return goods.Id;
93     } 
94     
95     
96     
97 }
复制代码
测试自己写的方法可以在workbench中查看，使用salesforce账号登录workbench，https://workbench.developerforce.com/login.php.在这里可以测试一下getGoodsByIdOrGoodsList方法，想要测试其他方法可以参看最上面的链接自行测试。如下图所示：

 

3）java端访问sfdc的REST Service

java端访问sfdc的REST Service之前需要做两部分，第一部分是下载Http client的jar包，第二部分是下载json的jar包。

1.Http client jar包下载：访问http://hc.apache.org/downloads.cgi 选择最新的jar包进行下载，下载后解压，在lib目录下位所需要的http client的jar包。



2.下载json的jar包：http://mvnrepository.com/artifact/org.json/json。可以选择下载最新的json下载后将json的jar和http client的jar放在一个文件夹下，比如我们现在放在桌面的jars文件夹下。



接下来打开eclipse，jars目录下的jar包全都放在java项目里，然后开始代码访问阶段。

复制代码
  1  
  2 import java.io.IOException;
  3 import java.util.ArrayList;
  4 import java.util.List;
  5 import org.apache.http.Header;
  6 import org.apache.http.HttpResponse;
  7 import org.apache.http.HttpStatus;
  8 import org.apache.http.client.ClientProtocolException;
  9 import org.apache.http.client.HttpClient;
 10 import org.apache.http.client.methods.HttpDelete;
 11 import org.apache.http.client.methods.HttpGet;
 12 import org.apache.http.client.methods.HttpPost;
 13 import org.apache.http.entity.StringEntity;
 14 import org.apache.http.impl.client.HttpClientBuilder;
 15 import org.apache.http.message.BasicHeader;
 16 import org.apache.http.util.EntityUtils;
 17 import org.json.JSONArray;
 18 import org.json.JSONException;
 19 import org.json.JSONObject;
 20 import org.json.JSONTokener;
 21  
 22 public class InvokeGoodsByRestViaSFDC {
 23  
 24     static final String USERNAME     = "你的salesforce账号";
 25     static final String PASSWORD     = "你的salesforce密码+security token(如果有security token)";
 26     static final String LOGINURL     = "https://login.salesforce.com";
 27     static final String GRANTSERVICE = "/services/oauth2/token?grant_type=password";
 28     static final String CLIENTID     = "3MVG9ZL0ppGP5UrBiKUS3jtHfmfz4eBCBEnuY0tIDByXVdtBJWeY6olTn1iLDNvP68EmfVtWE3IDzHOsMuDww";//上图中Consumer Key
 29     static final String CLIENTSECRET = "723866328398987848";//上图中的Consumer Secret
 30     private static String REST_ENDPOINT = "/services/apexrest" ;
 31     private static String baseUri;
 32     private static Header oauthHeader;
 33     private static Header prettyPrintHeader = new BasicHeader("X-PrettyPrint", "1");
 34     
 35     /**
 36      * 判断是否可以访问sfdc
 37      * return：可以访问sfdc的rest则返回true，否则返回false
 38      * */
 39     private static boolean isAccessable() {
 40         HttpClient httpclient = HttpClientBuilder.create().build();
 41          
 42         // Assemble the login request URL
 43         String loginURL = LOGINURL +
 44                           GRANTSERVICE +
 45                           "&client_id=" + CLIENTID +
 46                           "&client_secret=" + CLIENTSECRET +
 47                           "&username=" + USERNAME +
 48                           "&password=" + PASSWORD;
 49  
 50         // Login requests must be POSTs
 51         HttpPost httpPost = new HttpPost(loginURL);
 52         HttpResponse response = null;
 53         try {
 54             // Execute the login POST request
 55             response = httpclient.execute(httpPost);
 56         } catch (ClientProtocolException cpException) {
 57             cpException.printStackTrace();
 58         } catch (IOException ioException) {
 59             ioException.printStackTrace();
 60         }
 61         // verify response is HTTP OK
 62         final int statusCode = response.getStatusLine().getStatusCode();
 63         if (statusCode != HttpStatus.SC_OK) {
 64             System.out.println("Error authenticating to Force.com: "+statusCode);
 65             return false;
 66         }
 67  
 68         String getResult = null;
 69         try {
 70             getResult = EntityUtils.toString(response.getEntity());
 71         } catch (IOException ioException) {
 72             ioException.printStackTrace();
 73         }
 74  
 75         JSONObject jsonObject = null;
 76         String loginAccessToken = null;
 77         String loginInstanceUrl = null;
 78  
 79         try {
 80             jsonObject = (JSONObject) new JSONTokener(getResult).nextValue();
 81             loginAccessToken = jsonObject.getString("access_token");
 82             loginInstanceUrl = jsonObject.getString("instance_url");
 83         } catch (JSONException jsonException) {
 84             jsonException.printStackTrace();
 85         }
 86  
 87         baseUri = loginInstanceUrl + REST_ENDPOINT + "/Goods";
 88         oauthHeader = new BasicHeader("Authorization", "OAuth " + loginAccessToken) ;
 89         System.out.println("oauthHeader1: " + oauthHeader);
 90         System.out.println(response.getStatusLine());
 91         System.out.println("Successful login");
 92         System.out.println("instance URL: "+loginInstanceUrl);
 93         System.out.println("access token/session ID: "+loginAccessToken);
 94         System.out.println("baseUri: "+ baseUri);        
 95         return true;
 96     }
 97     
 98     
 99     public static void main(String[] args) {
100         createGoods("小米4","小米","2500","2000","测试商品描述信息：小米");
101         //deleteGoods("a052800000880mlAAA");
102         Goods getGoods = getGoodsById("a0528000008811qAAA");
103         if(getGoods != null) {
104             System.out.println("goods Name :" + getGoods.getGoodsName());
105             System.out.println("goods Price : " + getGoods.getGoodsPrice());
106             System.out.println("goods cost price :" +getGoods.getGoodsCostPrice());
107             System.out.println("goods brand : " + getGoods.getGoodsBrand());
108         }
109         List<Goods> goodsList = getGoodsList(0);
110         System.out.println(goodsList.toString());
111         
112         Goods updateGoods = new Goods();
113         updateGoods.setGoodsId("a0528000008811qAAA");
114         updateGoods.setGoodsName("test goods Name");
115         updateGoods.setGoodsPrice("10000");
116         updateGoods.setGoodsCostPrice("8000");
117         updateGoods(updateGoods);
118     }
119     
120     
121     
122     
123     // Create Goods using REST HttpPost
124     public static void createGoods(String goodsName,String goodsBrand,String goodsPrice,String goodsCostPrice,String goodsDescribe) {
125         try {
126             if(isAccessable()) {
127                 String uri = baseUri + "/createGoods";
128                 JSONObject goods = new JSONObject();
129                 goods.put("goodsName", goodsName);
130                 goods.put("goodsBrand", goodsBrand);
131                 goods.put("goodsPrice", goodsPrice);
132                 goods.put("goodsCostPrice",goodsCostPrice);
133                 goods.put("goodsDescribe", goodsDescribe);
134      
135                 System.out.println("JSON for goods record to be inserted:\n" + goods.toString(1));
136                 //Construct the objects needed for the request
137                 HttpClient httpClient = HttpClientBuilder.create().build();
138                 System.out.println("oauthHeader" + oauthHeader);
139                 HttpPost httpPost = new HttpPost(uri);
140                 httpPost.addHeader(oauthHeader);
141                 httpPost.addHeader(prettyPrintHeader);
142                 httpPost.addHeader("encoding", "UTF-8");
143                 // The message we are going to post
144                 StringEntity body = new StringEntity(goods.toString(1));
145                 body.setContentType("application/json");
146                 httpPost.setEntity(body);
147      
148                 //Make the request
149                 HttpResponse response = httpClient.execute(httpPost);
150                 System.out.print("response : " + response.toString());
151                 //Process the results
152                 int statusCode = response.getStatusLine().getStatusCode();
153                 System.out.println("status code : " + statusCode);
154                 if (statusCode == HttpStatus.SC_OK) {
155                     String response_string = EntityUtils.toString(response.getEntity());
156                     if(response_string != null ) {
157                         System.out.println("New Goods id from response: " + response_string);
158                     }
159                 } else {
160                     System.out.println("Insertion unsuccessful. Status code returned is " + statusCode);
161                 }
162                 httpPost.releaseConnection();
163             }
164         } catch (JSONException e) {
165             System.out.println("Issue creating JSON or processing results");
166             e.printStackTrace();
167         } catch (IOException ioe) {
168             ioe.printStackTrace();
169         } catch (NullPointerException npe) {
170             npe.printStackTrace();
171         }
172     }
173 
174     public static void deleteGoods(String goodsId) {
175         try {
176             if(isAccessable()) {
177                 String uri = baseUri + "/deleteGoods" + "/" + goodsId;
178                 HttpClient httpClient = HttpClientBuilder.create().build();
179                  
180                 HttpDelete httpDelete = new HttpDelete(uri);
181                 httpDelete.addHeader(oauthHeader);
182                 httpDelete.addHeader(prettyPrintHeader);
183      
184                 //Make the request
185                 HttpResponse response = httpClient.execute(httpDelete);
186      
187                 //Process the response
188                 int statusCode = response.getStatusLine().getStatusCode();
189                 if (statusCode == HttpStatus.SC_OK) {
190                     System.out.println("Deleted the goods successfully.");
191                 } else {
192                     System.out.println("goods delete NOT successful. Status code is " + statusCode);
193                 }
194                 httpDelete.releaseConnection();
195             }
196         } catch (JSONException e) {
197             System.out.println("Issue creating JSON or processing results");
198             e.printStackTrace();
199         } catch (IOException ioe) {
200             ioe.printStackTrace();
201         } catch (NullPointerException npe) {
202             npe.printStackTrace();
203         }
204     }
205     
206     public static List<Goods> getGoodsList(Integer pageNumber) {
207         try {
208             if(isAccessable()) {
209                 String uri = baseUri + "/getGoodsByIdOrGoodsList" + "？currentPage=" + pageNumber;
210                 HttpClient httpClient = HttpClientBuilder.create().build(); 
211                 HttpGet httpGet = new HttpGet(uri);
212                 httpGet.addHeader(oauthHeader);
213                 httpGet.addHeader(prettyPrintHeader);
214                 //Make the request
215                 HttpResponse response = httpClient.execute(httpGet);
216                 //Process the response
217                 int statusCode = response.getStatusLine().getStatusCode();
218                 if (statusCode == HttpStatus.SC_OK) {
219                     List<Goods> goodsList = new ArrayList<Goods>();
220                     String response_string = EntityUtils.toString(response.getEntity());
221                     System.out.println("response_string : " + response_string);
222                     JSONArray jsonArray = new JSONArray(response_string);
223                     JSONObject jsonObject = null;
224                     for(int i=0;i<jsonArray.length();i++) {
225                         jsonObject = jsonArray.getJSONObject(i);
226                         Goods goods = new Goods();
227                         if(jsonObject != null) {
228                             goods.setGoodsName(jsonObject.getString("GoodsName__c"));
229                             goods.setGoodsPrice(String.valueOf(jsonObject.getDouble("GoodsPrice__c")));
230                             goods.setGoodsCostPrice(String.valueOf(jsonObject.getDouble("GoodsCostPrice__c")));
231                             goods.setGoodsDescribe(jsonObject.getString("GoodsDescribe__c"));
232                             goodsList.add(goods);
233                         }
234                     }
235                     return goodsList;
236             } else {
237                 return null;
238             }
239             }
240         }catch (JSONException e) {
241             System.out.println("Issue creating JSON or processing results");
242             e.printStackTrace();
243         } catch (IOException ioe) {
244             ioe.printStackTrace();
245         } catch (NullPointerException npe) {
246             npe.printStackTrace();
247         }
248         return null;
249     }
250     
251     public static Goods  getGoodsById(String goodsId) {
252         try {
253             if(isAccessable()) {
254                 String uri = baseUri + "/getGoodsByIdOrGoodsList" + "？goodsId=" + goodsId;
255                 HttpClient httpClient = HttpClientBuilder.create().build();
256                  
257                 HttpGet httpGet = new HttpGet(uri);
258                 httpGet.addHeader(oauthHeader);
259                 httpGet.addHeader(prettyPrintHeader);
260      
261                 //Make the request
262                 HttpResponse response = httpClient.execute(httpGet);
263      
264                 //Process the response
265                 int statusCode = response.getStatusLine().getStatusCode();
266                 if (statusCode == HttpStatus.SC_OK) {
267                     String response_string = EntityUtils.toString(response.getEntity());
268                     System.out.println("response_string : " + response_string);
269                     JSONArray jsonArray = new JSONArray(response_string);
270                     JSONObject jsonObject = null;
271                     if(jsonArray.length() > 0) {
272                         jsonObject = jsonArray.getJSONObject(0);
273                     }
274                     
275                     Goods goods = new Goods();
276                     if(jsonObject != null) {
277                         goods.setGoodsName(jsonObject.getString("GoodsName__c"));
278                         goods.setGoodsPrice(String.valueOf(jsonObject.getDouble("GoodsPrice__c")));
279                         goods.setGoodsCostPrice(String.valueOf(jsonObject.getDouble("GoodsCostPrice__c")));
280                         goods.setGoodsDescribe(jsonObject.getString("GoodsDescribe__c"));
281                     }
282                     //goods.setGoodsBrand(jsonObject.getString("GoodsBrand__c"));
283                     return goods;
284                 } else {
285                     return null;
286                 }
287             }
288         } catch (JSONException e) {
289             System.out.println("Issue creating JSON or processing results");
290             e.printStackTrace();
291         } catch (IOException ioe) {
292             ioe.printStackTrace();
293         } catch (NullPointerException npe) {
294             npe.printStackTrace();
295         }
296         return null;
297     }
298     
299     public static void updateGoods(Goods updateGoods) {
300         try {
301             if(isAccessable()) {
302                 String uri = baseUri + "/updateGoods/"+updateGoods.getGoodsId();
303                 JSONObject goods = new JSONObject();
304                 goods.put("GoodsName__c", updateGoods.getGoodsName());
305                 goods.put("GoodsPrice__c", updateGoods.getGoodsPrice());
306                 goods.put("GoodsCostPrice__c", updateGoods.getGoodsCostPrice());
307                 org.apache.http.client.methods.HttpPatch httpPatch = new org.apache.http.client.methods.HttpPatch(uri);
308                 HttpClient httpClient = HttpClientBuilder.create().build();
309                 httpPatch.addHeader(oauthHeader);
310                 httpPatch.addHeader(prettyPrintHeader);
311                 StringEntity body = new StringEntity(goods.toString(1));
312                 body.setContentType("application/json");
313                 httpPatch.setEntity(body);
314      
315                 //Make the request
316                 HttpResponse response = httpClient.execute(httpPatch);
317      
318                 //Process the response
319                 int statusCode = response.getStatusLine().getStatusCode();
320                 if (statusCode == HttpStatus.SC_OK) {
321                     System.out.println("Updated the goods successfully.");
322                 } else {
323                     System.out.println("Goods update NOT successfully. Status code is " + statusCode);
324                 }
325             }
326         }catch (JSONException e) {
327             System.out.println("Issue creating JSON or processing results");
328             e.printStackTrace();
329         } catch (IOException ioe) {
330             ioe.printStackTrace();
331         } catch (NullPointerException npe) {
332             npe.printStackTrace();
333         }
334     }
335     
336     
337 }
复制代码
我们只对getGoodsById方法进行测试，下图为显示结果。



java访问sfdc的rest service需要OAuth身份认证，通过用户名密码，以及custom key 和custom password以及访问的apexrest链接即可以访问相应的rest service资源。

总结：本篇描述的主要是sfdc如何通过rest方式获取外部平台的资源以及sfdc如何作为rest service供外部平台调用，每个人的账号密码，以及custom key 和custom password不相同，copy代码后修改这几处地方，如果restResource以及相应注解对应的方法不同，也需要修改相应的方法。此篇文章的缺点为没有考虑中文内容的问题，通过insert等方法存储到服务器会导致中文乱码现象，有需要的可以自行对数据进行编码解码处理。