本文已参与「新人创作礼」活动,一起开启掘金创作之路。
【实战篇】:使用apex web service实现带附件上传的web-to-lead功能
@RestResource(urlMapping='/SyncLeadToSF')
global with sharing class SyncLeadToSF {
// request parameters
global class ParameterData {
// lead data
public String AccountType;
public String Name;
public String Email;
public String InvestmentAmount;
public String BirthDate;// Date string format: 2018-06-01
public String TaxResidenceCountry;
public String PrimaryPhone;
public String SecondaryPhone;
public String Country;// Must specific a country before specific a state or province, if the country is China, you must match the provice using the picklist value.
public String State;
public String City;
public String Street;
public String PostalCode;
public String ExperienceLevel;// Beginner, Intermediate, Advanced
public String OwnerEntity;
public List<AttachData> attachList;
}
public class AttachData {
//file data
public String FileName;
public String ContentData;// base64 of the file body
public String ContentType;
}
// response result
global class SyncReturnResult {
public String Message;
public String Code;// 0: success; -1: failure
}
@HttpPost
global static SyncReturnResult doPost() {
SyncReturnResult result = new SyncReturnResult();
result.Code = '0';
result.Message = 'success';
RestRequest req = RestContext.request;
//Convert the requestBody into a string
String bodyStr = req.requestBody.toString();
System.debug('bodyStr: ' + bodyStr);
ParameterData param = new ParameterData();
//Deserialize the received Json data to the Apex object
param = (ParameterData)JSON.deserialize(bodyStr, ParameterData.class);
System.debug('param: ' + param);
Savepoint sp = Database.setSavepoint();
try{
Lead ld = new Lead();
// Must: Company | Lead Status | Last Name
if(String.isNotEmpty(param.AccountType)) ld.Account_TypeA__c = param.AccountType;
if(String.isNotEmpty(param.Name)) ld.LastName = param.Name;
if(String.isNotEmpty(param.Email)) ld.Email = param.Email;
if(String.isNotEmpty(param.InvestmentAmount)) ld.Investment_Amount__c = Decimal.valueOf(param.InvestmentAmount);
if(String.isNotEmpty(param.BirthDate)) ld.Date_of_Birth__c = Date.valueOf(param.BirthDate);
if(String.isNotEmpty(param.TaxResidenceCountry)) ld.Tax_Residence_Country__c = param.TaxResidenceCountry;
if(String.isNotEmpty(param.PrimaryPhone)) ld.Phone = param.PrimaryPhone;
if(String.isNotEmpty(param.SecondaryPhone)) ld.MobilePhone = param.SecondaryPhone;
if(String.isNotEmpty(param.Country)) ld.Country = param.Country;
if(String.isNotEmpty(param.State)) ld.State = param.State;
if(String.isNotEmpty(param.City)) ld.City = param.City;
if(String.isNotEmpty(param.Street)) ld.Street = param.Street;
if(String.isNotEmpty(param.PostalCode)) ld.PostalCode = param.PostalCode;
if(String.isNotEmpty(param.ExperienceLevel)) ld.Experience_Level__c = param.ExperienceLevel;
if(String.isNotEmpty(param.OwnerEntity)) ld.Owner_Entity__c = param.OwnerEntity;
ld.LeadSource = '';
ld.Status = 'New';
ld.Company = '[not provided]';
insert ld;
if(param.attachList.size() > 0) {
List<Attachment> atts = new List<Attachment>();
for(AttachData attach : param.attachList) {
Attachment att = new Attachment();
att.ParentId = ld.Id;
att.Name = attach.FileName;
att.ContentType = attach.ContentType;
att.Body = EncodingUtil.base64Decode(attach.ContentData);
atts.add(att);
}
// insert Attachment
insert atts;
}
}catch(Exception e) {
system.debug('exception : ' + e.getMessage() + datetime.now().format('yyyy-MM-dd HH:mm:ss') + ' Line Number = ' + e.getLineNumber());
result.Message = '[Error Line Number]: ' + e.getLineNumber() + ', [Error Message]: ' + e.getMessage();
result.Code = '-1';
Database.rollback(sp);
}
RestResponse resp = RestContext.response;
String respJson = json.serialize(result);
system.debug('json string ------------>' + respJson);
String respBody = EncodingUtil.urlDecode(respJson, 'utf-8');
resp.responseBody = Blob.valueof(respBody);
return result;
}
}
Test Class:
@isTest
private class SyncLeadToSFTest {
static testMethod void testMethod1() {
SyncLeadToSF.AttachData attach1 = new SyncLeadToSF.AttachData();
attach1.FileName = 'application.pdf';
attach1.ContentType = 'application/pdf';
attach1.ContentData = 'JVBERi0xLjcNCiW1tbW1DQoxIDAgb2JqDQo8PC9UeXBlL0NhdGFsb2cvUGFnZXMgMiAwIFIvTGFuZyh6aC1DTikgL1N0cnVjdFRyZWVSb290IDEwIDAgUi9NYXJrSW5mbzw8L01hcmtlZCB0cnVlPj4vTWV0YWRhdGEgMjQgMCBSL1ZpZXdlclByZWZlcmVuY2VzIDI1IDAgUj4+DQplbmRvYmoNCjIgMCBvYmoNCjw8L1R5cGUvUGFnZXMvQ291bnQgMS9LaWRzWyAzIDAgUl0gPj4NCmVuZG9iag0KMyAwIG9iag0KPDwvVHlwZS9QYWdlL1BhcmVudCAyIDAgUi9SZXNvdXJjZXM8PC9Gb250PDwvRjEgNSAwIFI+Pi9FeHRHU3RhdGU8PC9HUzcgNyAwIFIvR1M4IDggMCBSPj4vUHJvY1NldFsvUERGL1RleHQvSW1hZ2VCL0ltYWdlQy9JbWFnZUldID4+L01lZGlhQm94WyAwIDAgNTk1LjMyIDg0MS45Ml0gL0NvbnRlbnRzIDQgMCBSL0dyb3VwPDwvVHlwZS9Hcm91cC9TL1RyYW5zcGFyZW5jeS9DUy9EZXZpY2VSR0I+Pi9UYWJzL1MvU3RydWN0UGFyZW50cyAwPj4NCmVuZG9iag0KNCAwIG9iag0KPDwvRmlsdGVyL0ZsYXRlRGVjb2RlL0xlbmd0aCAyMDY+Pg0Kc3RyZWFtDQp4nLXQOwvCMBQF4D2Q/3DGVjDNTV8JFAdbLYqC0oiDOHSonSy+/j+2UgRBcerdDhwOHxdecSkbJIm3ThcZpLcqmxpO1Yx3hTuZYJqluHImhexO65ggEZpQ+Ao6IGEUbhVn+xEazqaWM29OICnCCPbEWdeWIJh2QAWIQwN7bkt5EaO+t7uoX0n3Kefs4Fh3HDjV/eEeYZeczdrVLWeYrVPgk0sDcUlqEak396XscfivUkOpiISvv6o2buxk3dvm/3n+UDxlfvG+Pe0JFKCCJQ0KZW5kc3RyZWFtDQplbmRvYmoNCjUgMCBvYmoNCjw8L1R5cGUvRm9udC9TdWJ0eXBlL1RydWVUeXBlL05hbWUvRjEvQmFzZUZvbnQvQkNERUVFK0RlbmdYaWFuL0VuY29kaW5nL1dpbkFuc2lFbmNvZGluZy9Gb250RGVzY3JpcHRvciA2IDAgUi9GaXJzdENoYXIg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Zb6Gar2ERn8XLXKOkM6EnQxXEzlJEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEAT5t8FGw5VFvmLPkqX/12OhiJrJPvrkPnY+74X4/O08fho51DOP70/8/zf98xuIhQ8hZf/Teuxe0soZiIZdSSL/N/0jCIL8AQzh4CLEk/DECE9f4gMpLAklw0kWGU3ySBGxkkaHA/KUPdLKSL3DUbvuTgkt3YUhJ0yrWbZ0yQOLWxY1L1wwf97c++fMnjWzqbGhfkZdbU111fRplVMryq1lllJzyZTJk+6bOMFkHD+uuKgwP2/smNGjRubmZI/IGqDwkbqHM20e0gx1hlUaEU7apB4Q9IgIZ+ziDLtESLSP1SnthnyjamSBMXO4XKUyydUqu8HOazLpZS6zWboyTNAE1IK60MTIQvXI/AlGZaatRMiElKI7Ys78pO48V8jOZhQZ7Vk6iPWIjxDi3dHsu7JzurLVSjvJs9nK2gingXSDvI0RAqKMlSaYiUltL9WpVWqjFcq2uRFPVVFJBoQ8u0KMcgS0qOzwIaVwWcarOxhXaILRriwpN2VDacJq7MJfYQeJV892hkvsSotSaRdr1KV5RpvKzpSo5a54gREsxpjlNpVapTSZOhyHQmhptQraYkl6m5pZnt9mYJYXTjDu84EtsbzI2M4ybEZJuqmtP+QZ9ylhzYVUlqbSRBpR0ggZycDKtLNuQnn5PgMhzUIuLyQIcQvMQkhz60pjiKWDdab5ODvSCh0ZYJtaOnhnjqGrNA9pbs60ZiFNAOwAtjdIRQY3g7vB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OjAyOjE5KzA4OjAwPC94bXA6Q3JlYXRlRGF0ZT48eG1wOk1vZGlmeURhdGU+MjAxOC0wNy0xOFQxNTowMjoxOSswODowMDwveG1wOk1vZGlmeURhdGU+PC9yZGY6RGVzY3JpcHRpb24+CjxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiICB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyI+Cjx4bXBNTTpEb2N1bWVudElEPnV1aWQ6OTFBMDMzNEUtMTNBNi00NDc4LUI5OTAtNTVCNUNGODVBNzcyPC94bXBNTTpEb2N1bWVudElEPjx4bXBNTTpJbnN0YW5jZUlEPnV1aWQ6OTFBMDMzNEUtMTNBNi00NDc4LUI5OTAtNTVCNUNGODVBNzcyPC94bXBNTTpJbnN0YW5jZUlEPjwvcmRmOkRlc2NyaXB0aW9uPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKPC9yZGY6UkRGPjwveDp4bXBtZXRhPjw/eHBhY2tldCBlbmQ9InciPz4NCmVuZHN0cmVhbQ0KZW5kb2JqDQoyNSAwIG9iag0KPDwvRGlzcGxheURvY1RpdGxlIHRydWU+Pg0KZW5kb2JqDQoyNiAwIG9iag0KPDwvVHlwZS9YUmVmL1NpemUgMjYvV1sgMSA0IDJdIC9Sb290IDEgMCBSL0luZm8gOSAwIFIvSURbPDRFMzNBMDkxQTYxMzc4NDRCOTkwNTVCNUNGODVBNzcyPjw0RTMzQTA5MUE2MTM3ODQ0Qjk5MDU1QjVDRjg1QTc3Mj5dIC9GaWx0ZXIvRmxhdGVEZWNvZGUvTGVuZ3RoIDk4Pj4NCnN0cmVhbQ0KeJw1zbsNgDAMBNDLjwQ62IUBmC4SO9DSMQAj0DIAEj07BMcHLvx0sk4GZEoxsnugspJLMY/iPNkUv5BTCRGwUhjQkEgSaUkgnnyFrtbvPxliiZNb3PVDmpUxK9MBvLB9C9oNCmVuZHN0cmVhbQ0KZW5kb2JqDQp4cmVmDQowIDI3DQowMDAwMDAwMDEwIDY1NTM1IGYNCjAwMDAwMDAwMTcgMDAwMDAgbg0KMDAwMDAwMDE2NiAwMDAwMCBuDQowMDAwMDAwMjIyIDAwMDAwIG4NCjAwMDAwMDA0OTIgMDAwMDAgbg0KMDAwMDAwMDc3MiAwMDAwMCBuDQowMDAwMDAwOTQxIDAwMDAwIG4NCjAwMDAwMDExODEgMDAwMDAgbg0KMDAwMDAwMTIzNCAwMDAwMCBuDQowMDAwMDAxMjg3IDAwMDAwIG4NCjAwMDAwMDAwMTEgNjU1MzUgZg0KMDAwMDAwMDAxMiA2NTUzNSBmDQowMDAwMDAwMDEzIDY1NTM1IGYNCjAwMDAwMDAwMTQgNjU1MzUgZg0KMDAwMDAwMDAxNSA2NTUzNSBmDQowMDAwMDAwMDE2IDY1NTM1IGYNCjAwMDAwMDAwMTcgNjU1MzUgZg0KMDAwMDAwMDAxOCA2NTUzNSBmDQowMDAwMDAwMDE5IDY1NTM1IGYNCjAwMDAwMDAwMjAgNjU1MzUgZg0KMDAwMDAwMDAyMSA2NTUzNSBmDQowMDAwMDAwMDAwIDY1NTM1IGYNCjAwMDAwMDE5NzcgMDAwMDAgbg0KMDAwMDAwMjE4NiAwMDAwMCBuDQowMDAwMDEzNzAzIDAwMDAwIG4NCjAwMDAwMTY4NDEgMDAwMDAgbg0KMDAwMDAxNjg4NiAwMDAwMCBuDQp0cmFpbGVyDQo8PC9TaXplIDI3L1Jvb3QgMSAwIFIvSW5mbyA5IDAgUi9JRFs8NEUzM0EwOTFBNjEzNzg0NEI5OTA1NUI1Q0Y4NUE3NzI+PDRFMzNBMDkxQTYxMzc4NDRCOTkwNTVCNUNGODVBNzcyPl0gPj4NCnN0YXJ0eHJlZg0KMTcxODMNCiUlRU9GDQp4cmVmDQowIDANCnRyYWlsZXINCjw8L1NpemUgMjcvUm9vdCAxIDAgUi9JbmZvIDkgMCBSL0lEWzw0RTMzQTA5MUE2MTM3ODQ0Qjk5MDU1QjVDRjg1QTc3Mj48NEUzM0EwOTFBNjEzNzg0NEI5OTA1NUI1Q0Y4NUE3NzI+XSAvUHJldiAxNzE4My9YUmVmU3RtIDE2ODg2Pj4NCnN0YXJ0eHJlZg0KMTc4NzkNCiUlRU9G';
SyncLeadToSF.AttachData attach2 = new SyncLeadToSF.AttachData();
attach2.FileName = 'test.pdf';
attach2.ContentType = 'application/pdf';
attach2.ContentData = 'JVBERi0xLjcNCiW1tbW1DQoxIDAgb2JqDQo8PC9UeXBlL0NhdGFsb2cvUGFnZXMgMiAwIFIvTGFuZyh6aC1DTikgL1N0cnVjdFRyZWVSb290IDEwIDAgUi9NYXJrSW5mbzw8L01hcmtlZCB0cnVlPj4vTWV0YWRhdGEgMjQgMCBSL1ZpZXdlclByZWZlcmVuY2VzIDI1IDAgUj4+DQplbmRvYmoNCjIgMCBvYmoNCjw8L1R5cGUvUGFnZXMvQ291bnQgMS9LaWRzWyAzIDAgUl0gPj4NCmVuZG9iag0KMyAwIG9iag0KPDwvVHlwZS9QYWdlL1BhcmVudCAyIDAgUi9SZXNvdXJjZXM8PC9Gb250PDwvRjEgNSAwIFI+Pi9FeHRHU3RhdGU8PC9HUzcgNyAwIFIvR1M4IDggMCBSPj4vUHJvY1NldFsvUERGL1RleHQvSW1hZ2VCL0ltYWdlQy9JbWFnZUldID4+L01lZGlhQm94WyAwIDAgNTk1LjMyIDg0MS45Ml0gL0NvbnRlbnRzIDQgMCBSL0dyb3VwPDwvVHlwZS9Hcm91cC9TL1RyYW5zcGFyZW5jeS9DUy9EZXZpY2VSR0I+Pi9UYWJzL1MvU3RydWN0UGFyZW50cyAwPj4NCmVuZG9iag0KNCAwIG9iag0KPDwvRmlsdGVyL0ZsYXRlRGVjb2RlL0xlbmd0aCAyMDY+Pg0Kc3RyZWFtDQp4nLXQOwvCMBQF4D2Q/3DGVjDNTV8JFAdbLYqC0oiDOHSonSy+/j+2UgRBcerdDhwOHxdecSkbJIm3ThcZpLcqmxpO1Yx3hTuZYJqluHImhexO65ggEZpQ+Ao6IGEUbhVn+xEazqaWM29OICnCCPbEWdeWIJh2QAWIQwN7bkt5EaO+t7uoX0n3Kefs4Fh3HDjV/eEeYZeczdrVLWeYrVPgk0sDcUlqEak396XscfivUkOpiISvv6o2buxk3dvm/3n+UDxlfvG+Pe0JFKCCJQ0KZW5kc3RyZWFtDQplbmRvYmoNCjUgMCBvYmoNCjw8L1R5cGUvRm9udC9TdWJ0eXBlL1RydWVUeXBlL05hbWUvRjEvQmFzZUZvbnQvQkNERUVFK0RlbmdYaWFuL0VuY29kaW5nL1dpbkFuc2lFbmNvZGluZy9Gb250RGVzY3JpcHRvciA2IDAgUi9GaXJzdENoYXIg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Zb6Gar2ERn8XLXKOkM6EnQxXEzlJEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEAT5t8FGw5VFvmLPkqX/12OhiJrJPvrkPnY+74X4/O08fho51DOP70/8/zf98xuIhQ8hZf/Teuxe0soZiIZdSSL/N/0jCIL8AQzh4CLEk/DECE9f4gMpLAklw0kWGU3ySBGxkkaHA/KUPdLKSL3DUbvuTgkt3YUhJ0yrWbZ0yQOLWxY1L1wwf97c++fMnjWzqbGhfkZdbU111fRplVMryq1lllJzyZTJk+6bOMFkHD+uuKgwP2/smNGjRubmZI/IGqDwkbqHM20e0gx1hlUaEU7apB4Q9IgIZ+ziDLtESLSP1SnthnyjamSBMXO4XKUyydUqu8HOazLpZS6zWboyTNAE1IK60MTIQvXI/AlGZaatRMiElKI7Ys78pO48V8jOZhQZ7Vk6iPWIjxDi3dHsu7JzurLVSjvJs9nK2gingXSDvI0RAqKMlSaYiUltL9WpVWqjFcq2uRFPVVFJBoQ8u0KMcgS0qOzwIaVwWcarOxhXaILRriwpN2VDacJq7MJfYQeJV892hkvsSotSaRdr1KV5RpvKzpSo5a54gREsxpjlNpVapTSZOhyHQmhptQraYkl6m5pZnt9mYJYXTjDu84EtsbzI2M4ybEZJuqmtP+QZ9ylhzYVUlqbSRBpR0ggZycDKtLNuQnn5PgMhzUIuLyQIcQvMQkhz60pjiKWDdab5ODvSCh0ZYJtaOnhnjqGrNA9pbs60ZiFNAOwAtjdIRQY3g7vB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OjAyOjE5KzA4OjAwPC94bXA6Q3JlYXRlRGF0ZT48eG1wOk1vZGlmeURhdGU+MjAxOC0wNy0xOFQxNTowMjoxOSswODowMDwveG1wOk1vZGlmeURhdGU+PC9yZGY6RGVzY3JpcHRpb24+CjxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiICB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyI+Cjx4bXBNTTpEb2N1bWVudElEPnV1aWQ6OTFBMDMzNEUtMTNBNi00NDc4LUI5OTAtNTVCNUNGODVBNzcyPC94bXBNTTpEb2N1bWVudElEPjx4bXBNTTpJbnN0YW5jZUlEPnV1aWQ6OTFBMDMzNEUtMTNBNi00NDc4LUI5OTAtNTVCNUNGODVBNzcyPC94bXBNTTpJbnN0YW5jZUlEPjwvcmRmOkRlc2NyaXB0aW9uPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKPC9yZGY6UkRGPjwveDp4bXBtZXRhPjw/eHBhY2tldCBlbmQ9InciPz4NCmVuZHN0cmVhbQ0KZW5kb2JqDQoyNSAwIG9iag0KPDwvRGlzcGxheURvY1RpdGxlIHRydWU+Pg0KZW5kb2JqDQoyNiAwIG9iag0KPDwvVHlwZS9YUmVmL1NpemUgMjYvV1sgMSA0IDJdIC9Sb290IDEgMCBSL0luZm8gOSAwIFIvSURbPDRFMzNBMDkxQTYxMzc4NDRCOTkwNTVCNUNGODVBNzcyPjw0RTMzQTA5MUE2MTM3ODQ0Qjk5MDU1QjVDRjg1QTc3Mj5dIC9GaWx0ZXIvRmxhdGVEZWNvZGUvTGVuZ3RoIDk4Pj4NCnN0cmVhbQ0KeJw1zbsNgDAMBNDLjwQ62IUBmC4SO9DSMQAj0DIAEj07BMcHLvx0sk4GZEoxsnugspJLMY/iPNkUv5BTCRGwUhjQkEgSaUkgnnyFrtbvPxliiZNb3PVDmpUxK9MBvLB9C9oNCmVuZHN0cmVhbQ0KZW5kb2JqDQp4cmVmDQowIDI3DQowMDAwMDAwMDEwIDY1NTM1IGYNCjAwMDAwMDAwMTcgMDAwMDAgbg0KMDAwMDAwMDE2NiAwMDAwMCBuDQowMDAwMDAwMjIyIDAwMDAwIG4NCjAwMDAwMDA0OTIgMDAwMDAgbg0KMDAwMDAwMDc3MiAwMDAwMCBuDQowMDAwMDAwOTQxIDAwMDAwIG4NCjAwMDAwMDExODEgMDAwMDAgbg0KMDAwMDAwMTIzNCAwMDAwMCBuDQowMDAwMDAxMjg3IDAwMDAwIG4NCjAwMDAwMDAwMTEgNjU1MzUgZg0KMDAwMDAwMDAxMiA2NTUzNSBmDQowMDAwMDAwMDEzIDY1NTM1IGYNCjAwMDAwMDAwMTQgNjU1MzUgZg0KMDAwMDAwMDAxNSA2NTUzNSBmDQowMDAwMDAwMDE2IDY1NTM1IGYNCjAwMDAwMDAwMTcgNjU1MzUgZg0KMDAwMDAwMDAxOCA2NTUzNSBmDQowMDAwMDAwMDE5IDY1NTM1IGYNCjAwMDAwMDAwMjAgNjU1MzUgZg0KMDAwMDAwMDAyMSA2NTUzNSBmDQowMDAwMDAwMDAwIDY1NTM1IGYNCjAwMDAwMDE5NzcgMDAwMDAgbg0KMDAwMDAwMjE4NiAwMDAwMCBuDQowMDAwMDEzNzAzIDAwMDAwIG4NCjAwMDAwMTY4NDEgMDAwMDAgbg0KMDAwMDAxNjg4NiAwMDAwMCBuDQp0cmFpbGVyDQo8PC9TaXplIDI3L1Jvb3QgMSAwIFIvSW5mbyA5IDAgUi9JRFs8NEUzM0EwOTFBNjEzNzg0NEI5OTA1NUI1Q0Y4NUE3NzI+PDRFMzNBMDkxQTYxMzc4NDRCOTkwNTVCNUNGODVBNzcyPl0gPj4NCnN0YXJ0eHJlZg0KMTcxODMNCiUlRU9GDQp4cmVmDQowIDANCnRyYWlsZXINCjw8L1NpemUgMjcvUm9vdCAxIDAgUi9JbmZvIDkgMCBSL0lEWzw0RTMzQTA5MUE2MTM3ODQ0Qjk5MDU1QjVDRjg1QTc3Mj48NEUzM0EwOTFBNjEzNzg0NEI5OTA1NUI1Q0Y4NUE3NzI+XSAvUHJldiAxNzE4My9YUmVmU3RtIDE2ODg2Pj4NCnN0YXJ0eHJlZg0KMTc4NzkNCiUlRU9G';
List<SyncLeadToSF.AttachData> attaList = new List<SyncLeadToSF.AttachData>{attach1, attach2};
SyncLeadToSF.ParameterData req = new SyncLeadToSF.ParameterData();
req.AccountType = 'Individual Client';
req.Name = 'Wilson Xu';
req.Email = 'wilson@ibs.com';
req.InvestmentAmount = '5000000';
req.BirthDate = '2018-07-19';
req.TaxResidenceCountry = 'China';
req.PrimaryPhone = '18788888888';
req.SecondaryPhone = '18688888888';
req.Country = 'China';
req.State = 'Guangdong';
req.City = 'GuangZhou';
req.Street = 'HaiZhu New City';
req.PostalCode = '500000';
req.ExperienceLevel = 'Advanced';
req.OwnerEntity = 'MEX Australia Pty Ltd.';
req.attachList = attaList;
Test.startTest();
// set up a test request
RestRequest request = new RestRequest();
RestResponse response = new RestResponse();
request.requestUri = 'https://ims-mex.cs57.force.com/services/apexrest/SyncLeadToSF';
request.httpMethod = 'POST';
request.addHeader('Content-Type', 'application/json');
request.requestBody = Blob.valueOf(JSON.serialize(req));
RestContext.request = request;
RestContext.response= response;
SyncLeadToSF.SyncReturnResult result = new SyncLeadToSF.SyncReturnResult();
result = SyncLeadToSF.doPost();
Test.stopTest();
}
}
【Expose your apex class as a web service】:
你可以将你的Apex类的方法公开成一个REST或者SOAP的web service。通过使你的方法能够通过网络访问,你的外部应用程序就可以和Salesforce集成来执行各种漂亮的操作。
Exp:如果你的公司的呼叫中心正在使用一个内部系统来管理on-premises的资源。而你的agent也想使用这个应用来处理他们日常的工作,包括在Salesforce内管理case记录。通过使用一个接口,agent就能够查看和更新case,并且访问内部资源。这个应用调用Apex web service类来管理Salesforce数据。
【Expose a class as a rest service】:
把类定义成global并把方法定义成global static。给类和方法加注释。例如,这个例子的Apex REST类用了一个方法。getRecord方法是一个REST API call。因为使用了@HttpGet,所以他会被一个GET请求唤醒。
@RestResource(urlMapping='/Account/*')
global with sharing class MyRestResource {
@HttpGet
global static Account getRecord() {
// add you code
}
}
@RestResource(urlMapping='/Account/): Apex REST的base endpoint是yourInstance.salesforce.com/services/ap… mapping是追加到这个base endpoint里,组成你的REST服务。例如,在这个例子里,REST endpoint是yourInstance.salesforce.com/services/ap…
URL mapping是大小写敏感的,并且可以包含一个通配符()。
给每一个要暴露的方法定义成global static,并且给加一个注释把他和一个HTTP方法关联起来。下面是有效的注释。在每一个Apex类里,一个注释只能用一次。
编辑
【Expose class as a soap service】:
把你的Apex类公开成一个SOAP web service,就和REST一样简单。把你的类定义成global。加上webservice关键字以及把方法定义成static的。webservice关键字就是给这个方法提供global式的访问。
Exp:这个样例方法getRecord是一个返回Account记录的SOAP API call。
global with sharing class MySOAPWebService {
webservice static Account getRecord() {
// add your code
}
}
外部应用程序可以通过消耗WSDL文件来call你的web service方法。在class的详细页面为你的class创建WSDL。
因为平台安全是Salesforce最重要的事,所以你的web service需要认证。除了Apex class WSDL外,外部应用程序必须使用Enterprise WSDL或者Partner WSDL。
【Apex rest walkthrough】:
先创建一个被公开成REST service的Apex类。然后你试着访问另一个系统的方法。最后写测试。
你的Apex类是管理case记录的。这个类包含了五个方法,并且每一个方法都对应一个 HTTP方法。例如,如果客户应用程序为GET HTTP方法唤醒了一个REST call,那getCaseById就会被唤醒。
因为这个类的URL mapping被定义成/Cases/*,任何以yourInstance.salesforce.com/services/ap… service。
根据下面的代码创建一个Apex REST类。
@RestResource(urlMapping='/Cases/*')
global with sharing class CaseManager {
@HttpGet
global static Case getCaseById() {
RestRequest request = RestContext.request;
// grap the caseId from the end of the URL
String caseId = request.requestURI.substring(request.requestURI.lastIndexOf('/') + 1);
Case result = [SELECT CaseNumber, Subject, Origin, Priority
FROM Case
WHERE Id = :caseId];
return result;
}
@HttpPost
global static ID createCase(String subject, String status, String origin, String priority) {
Case thisCase = new Case(
Subject = subject,
Status = status,
Origin = origin,
Priority = priority
);
insert thisCase;
return thisCase.Id;
}
@HttpDelete
global static void deleteCase() {
RestRequest request = RestContext.request;
String caseId = request.requestURI.substring(request.requestURI.lastIndexOf('/') + 1);
Case thisCase = [SELECT Id FROM Case WHERE Id = :caseId];
delete thisCase;
}
@HttpPut
global static ID upsertCase(String subject, String status, String origin, String priority, String id) {
Case thisCase = new Case(
Id = id,
Subject = subject,
Status = status,
Origin = origin,
Priority = priority
);
// Match case by id, if present. Otherwise, create new case.
upsert thisCase;
// return the case ID.
return thisCase.Id;
}
@HttpPatch
global static ID updateCaseFields() {
RestRequest request = RestContext.request;
String caseId = request.requestURI.substring(request.requestURI.lastIndexOf('/') + 1);
Case thisCase = [SELECT Id FROM Case WHERE Id = :caseId];
// Deserialize the JSON string into name-value pairs
Map<String, Object> paras = (Map<String, Object>)JSON.deserializeUntyped(request.requestBody.tostring());
// Iterate through each parameter field and value
for(String fieldName : paras.keySet()) {
thisCase.put(fieldName, paras.get(fieldName));
}
update thisCase;
return thisCase.Id;
}
}
【Create a Record with a POST Method】:
我们先调用POST方法来创建一个Case。
为了唤醒你的REST service,你需要用一个REST client!几乎所有的REST client你都可以用,比如你自己的API client,cURL command-line tool,或者curl library for PHP。我们可以使用Workbench工具作为我们的REST client应用程序,但是稍后我们会简单介绍下cURL。
Apex REST支持两种资源的表现格式:JSON和XML。在一个request和response的body里,JSON默认就是被传递的,并且它是通过在HTTP header里的Content-Type属性来指定的。因为JSON比XML易于阅读和理解,这一章我们就介绍JSON。下面,我们来发送一个JSON格式的case记录。
Apex REST支持OAuth 2.0和session认证机制。这意味着我们用了专业的标准来保证我们应用和数据的安全性。幸运的是,你可以使用Workbench来让测试变的简单。通过Force.com APIs,Workbench是为管理员和开发人员提供与org交互的功能强大且基于WEB的一组套件。
通过Workbench,当你用用户名和密码登陆Salesforce时,你可以使用session认证。这样,你也是在用REST Explorer来调用你的REST service。
1)进入workbench.developerforce.com/login.php网站…
Environment:Production
2)登陆后,选择utilities | REST Explorer | POST
URI :/services/apexrest/Cases/
3)request body中输入下面的JSON串
{
"subject": "Bigfoot Sighting!",
"status": "New",
"origin": "Phone",
"priority": "Low"
}
然后点执行。这个执行会调用被绑定在POST HTTP方法上的方法,也就是createCase。
注释:此post方法直接接收参数的,request body的key大小写必须严格遵循入参申明的变量。
4)点击Show Raw Response查看返回结果。返回结果里包含新创建的记录的ID。
编辑
【Retrieve Data with a Custom GET Method】:
我们用相似的方法用Workbench来唤醒GET HTTP方法。
1)在Workbench里选择GET
2)URI :/services/apexrest/Cases/(用在上一步中获得的ID)。
3)点击执行。这个执行会唤醒被绑定在GET HTTP方法上的方法,也就是getCaseById。
4)点击Show Raw Response查看返回结果。
Raw Response
HTTP/1.1 200 OK
Date: Sun, 15 Jul 2018 02:33:14 GMT
Strict-Transport-Security: max-age=31536002; includeSubDomains
Public-Key-Pins-Report-Only: pin-sha256="9n0izTnSRF+W4W4JTq51avSXkWhQB8duS2bxVLfzXsY="; pin-sha256="5kJvNEMw0KjrCAu7eXY5HZdvyCS13BbA0VJG1RSP91w="; pin-sha256="njN4rRG+22dNXAi+yb8e3UMypgzPUPHlv4+foULwl1g="; max-age=86400; includeSubDomains; report-uri="https://calm-dawn-26291.herokuapp.com/hpkp-report/00D28000000bNDIm";
Expect-CT: max-age=0; report-uri="https://calm-dawn-26291.herokuapp.com/Expect-CT-report/00D28000000bNDIm";
X-Robots-Tag: none
Cache-Control: no-cache,must-revalidate,max-age=0,no-store,private
Set-Cookie: BrowserId=V22uytLFTpiPbSaO__15eQ;Path=/;Domain=.salesforce.com;Expires=Thu, 13-Sep-2018 02:33:14 GMT;Max-Age=5184000
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Content-Type: application/json;charset=UTF-8
Vary: Accept-Encoding
Content-Encoding: gzip
Transfer-Encoding: chunked
{
"attributes" : {
"type" : "Case",
"url" : "/services/data/v38.0/sobjects/Case/5000K00001HiY4xQAF"
},
"CaseNumber" : "00001042",
"Subject" : "Bigfoot Sighting!",
"Status" : "New",
"Origin" : "Phone",
"Priority" : "Low",
"Id" : "5000K00001HiY4xQAF"
}
【Retrieve Data Using cURL】:
cURL是通过使用URL语法来获取和发送文件的命令行工具。他在处理REST endpoints时非常方便。不用Workbench来处理Apex REST service,而使用cURL来唤醒GET HTTP方法。每次你“cURL”你的REST endpoint时,你也会传递session ID来获得认证。你已经被Workbench宠坏了,因为在你登录后他会为你传递session ID。
为了获得一个session ID,你首先需要在你的Salesforce的org里创建一个连接app并且启用OAuth。参考developer.salesforce.com/docs/atlas.… ID的consumer key和consumer secret。
【Update Data with a Custom PUT or PATCH Method】:
你可以用PUT或者PATCH HTTP方法更新记录。如果记录存在就更新,不存在就新建。PUT是一个upsert方法。PATCH方法只能用于更新已经存在的记录。在Apex里,update operation只更新指定的字段,不覆盖整个记录。我们会写一些代码来指定我们的方法是update还是upsert。
【Update Data with the PUT Method】:
加到CaseManager类里的upsertCase方法用了PUT action。这个方法用了built-in的upsert(Apex DML方法),通过匹配ID来创建或更新记录。
@HttpPut
global static ID upsertCase(String subject, String status, String origin, String priority, String id) {
Case thisCase = new Case(
Id = id,
Subject = subject,
Status = status,
Origin = origin,
Priority = priority
);
// Match case by id, if present. Otherwise, create new case.
upsert thisCase;
// return the case ID.
return thisCase.Id;
}
唤醒这个PUT方法:
1)在Workbench REST Explorer,选择PUT。
2)URI:/services/apexrest/Cases/
3)upsertCase方法需要在请求的body里得到字段的值。在请求的body里输入下面的内容,换成刚才我们创建的Case的ID。
{
"id": "<Record_ID>",
"status": "Working",
"subject": "Bigfoot Sighting!",
"priority": "Medium"
}
注意:这个ID是可选的,如果要想创建一个Case,就不用传这个字段。我们这个例子是想更新一个Case,所以传了ID。
4)点击执行。这个请求唤醒了你REST service的upsertCase方法。Status,Subject和Priority字段被更新。尽管subject的值和旧值一样,他还是会被更新。同样,因为这个请求的body不包含Case Origin字段的值,所以这个值在upsertCase方法里是Null,结果就是这个字段的值会被更新成空。
注释:此post方法直接接收参数的,request body的key大小写必须严格遵循入参申明的变量。
【Update Data with the PATCH Method】:
作为PUT方法的替代者,可以使用PATCH方法来更新记录。你可以用不同的方式实施PATCH方法。一种方法就是在方法里为每一个要更新的字段定义参数。例如,你可以定义一个只更新priority字段的方法:updateCasePriority(String priority)。可以列出多个参数来更新多个字段。
另一个更复杂的方法用请求body里的JSON的name/value对来传递。这样,这个方法就可以接受任意数量的参数,并且参数不需要在方法参数中定义。这个方法的另外一个优点就是不会因为没有传递某个字段的值而清空这个字段的内容。
你加到CaseManager类里的updateCaseFields方法就是用的这种方法。这个方法将请求body里的JSON串解析成name/value的map,然后使用sObject的PUT方法给字段设置值。
@HttpPatch
global static ID updateCaseFields() {
RestRequest request = RestContext.request;
String caseId = request.requestURI.substring(request.requestURI.lastIndexOf('/') + 1);
Case thisCase = [SELECT Id FROM Case WHERE Id = :caseId];
// Deserialize the JSON string into name-value pairs
Map<String, Object> paras = (Map<String, Object>)JSON.deserializeUntyped(request.requestBody.tostring());
// Iterate through each parameter field and value
for(String fieldName : paras.keySet()) {
thisCase.put(fieldName, paras.get(fieldName));
}
update thisCase;
return thisCase.Id;
}
唤醒PATCH方法:
1)在Workbench REST Explorer,点击PATCH 。
2)URI:/services/apexrest/Cases/。在请求的Body中输入下列的JSON串。
{
"status": "Escalated",
"priority": "High"
}
3)点击执行。这个请求唤醒了REST service的updateCaseFields方法。Status和Priority字段的值被更新。
【Test Your Apex REST Class】:
测试Apex REST和测试其他的Apex类类似。
// Set up a test request
RestRequest request = new RestRequest();
// Set request properties
request.requestUri = 'https://yourInstance.salesforce.com/services/apexrest/Cases/' + recordId;
request.setMethod = 'GET';
// Set other properties, such as parameters
request.params.put('status', 'Working');
// more awesome code here...
// Finally, assign the request to RestContext if used.
RequestCobtext.request = request;
If the method you’re testing accesses request values through RestContext, assign the request to RestContext to populate it (RestContext.request = request;).
下面是测试类的全部代码。
@isTest
private class CaseManagerTest {
static testMethod void testGetCaseById() {
Id recordId = createTestRecord();
// set up a test request
RestRequest request = new RestRequest();
request.requestUri = 'https://yourInstance.salesforce.com/service/apexrest/Cases/' + recordId;
request.httpMethod = 'Get';
RestContext.request = request;
// call the method to test
Case thisCase = CaseManager.getCaseById();
// verify results
System.assert(thisCase != null);
System.assertEquals("Test records", thisCase.Subject);
}
@isTest static void testCreateCase() {
// Call the method to test
ID thisCaseId = CaseManager.createCase("Ferocious chipmunk", "New", "Phone", "Low");
// verify results
System.assert(thisCaseId != null);
Case thisCase = [SElECT Id FROM Case WHERE Id = :thisCaseId];
System.assert(thisCase != null);
System.assertEquals(thisCase.Subject, "Ferocious chipmunk");
}
static testMethod void testDeleteCase() {
Id recordId = createTestRecord();
// set up a test request
RestRequest request = new RestRequest();
request.requestUri = 'https://yourInstance.salesforce.com/service/apexrest/Cases/' + recordId;
// Notice no delete method
request.httpMethod = "Get";
RestContext.request = request;
// call the method to test
CaseManager.deleteCase();
// verify record is deleted
List<Case> cases = [SELECT Id FROM Case WHERE Id = :recordId];
System.assert(cases.size() == 0);
}
static testMethod testUpsertCase() {
// 1. insert new case
ID case1Id = CaseManager.upsertCase("Ferocious chipmunk", "New", "Phone", "Low", null);
// verify new record was created
System.assert(case1Id != null);
Case case1 = [SELECT Id FROM Case WHERE Id = :case1Id];
System.assert(case1 != null);
System.assertEquals(case1.Subject, "Ferocious chipmunk");
// 2. update status of existing record to Working
ID case2Id = CaseManager.upsertCase("Ferocious chipmunk", "Working", "Phone", "Low", case1Id);
System.assert(case2Id != null);
Case case2 = [SELECT Id, Status FROM Case WHERE Id = :case2Id];
System.assert(case2 != null);
System.assertEquals(case2.Status, "Working");
}
@isTest static void testUpdateCaseFields() {
Id recordId = createTestRecord();
// set up a test request
RestRequest request = new RestRequest();
request.requestUri = 'https://yourInstance.salesforce.com/service/apexrest/Cases/' + recordId;
// Notice no delete method
request.httpMethod = "PATCH";
request.addHeader("Content-Type", "application/json");
request.requestBody = Blob.valueOf({"status": "Working"});
RestContext.request = request;
// update status of existing record to Working
ID thisCaseId = CaseManager.updateCaseFields();
// verify record was updated
System.assert(thisCaseId != null);
Case thisCase = [SELECT Id, Status FROM Case WHERE Id = :thisCaseId];
System.assert(thisCase != null);
System.assertEquals(thisCase.Status, "Working");
}
// helper method
static Id createTestRecord() {
// create case record
Case caseTest = new Case(
Subject = "Test record",
Status = "New",
Origin = "Phone",
Priority = "Medium"
);
insert caseTest;
return caseTest;
}
}
【Tell me more... 】:
1. Supported Data Types for Apex REST
Apex REST支持一下数据类型的参数和返回值。
-Apex primitives(excluding sObject and Blob)
-sObjects
-Lists or maps of Apex primitives or sObjects (only maps with String keys are supported)
-User-defined types that contain member variables of the types listed above.
2. Namespaces in Apex REST Endpoints
Apex REST可以被用在被管理的或没被管理的packages。当调用被包含在一个背管理的packages的 Apex REST时,你需要在调用URL的REST里包含这个package的命名空间。例如,如果这个类被包含在一个叫做packageNamespace的被管理的package里,并且Apex REST方法用了一个/MyMethod/*的URL mapping,通过REST来调用这些方法的URL应该是下面这样的格式:instance.salesforce.com/services/ap…
3. Custom Apex Web Services and Salesforce APIs
除了用Apex代码写REST和SOAP services,外部应用程序可以通过使用Salesforce的 REST和SOAP APIs来和Salesforce集成。这些APIs让你create,update和delete记录。然而,使用Apex web services的优点是Apex方法可以封装复杂的逻辑。这些逻辑对外界是不可见的。并且,Apex类的操作要比单独做API calls快的多。在一个Apex web service call里,只会发送一个请求,并且这些方法里的所有操作都是在server端进行的。
4. Security Considerations for Apex Web Services
The security context under which Apex web service methods run differs from the security context of Salesforce APIs. Unlike Salesforce APIs, Apex web service methods run with system privileges and don’t respect the user’s object and field permissions. However, Apex web service methods enforce sharing rules when declared with the with sharing keyword.