The following article demonstrates exposing the apex class as a REST web service for creating a lead record in Salesforce. It is designed to handle HTTP POST requests containing lead data in JSON format.
The class queries the Salesforce database to check if a lead already exists with the same email address. If an existing lead is found, the method updates the lead with the new information provided in the request, but only if the corresponding field in the existing lead is blank. If no existing lead is found, a new lead record is created with the information provided in the request.
An expected JSON request.
{
"FirstName": "John",
"LastName": "Doe",
"Street": "123 Main St",
"City": "Anytown",
"State": "California",
"Country": "United States",
"Zip": "12345",
"Phone": "555-555-5555",
"Email": "[email protected]",
"Company": "John Doe"
}
The apex class is annotated with @RestResource(urlMapping='/ProcessLeadInfo')
. So the endpoint for Apex REST is https://yourInstance.my.salesforce.com/services/apexrest/ProcessLeadInfo
@RestResource(urlMapping='/ProcessLeadInfo')
global class ProcessLeadInfoController{
@HttpPost
global static void ProcessData() {
try{
//Returns the RestRequest object for our Apex REST method.
RestRequest request = RestContext.request;
//Returns the RestResponse for our Apex REST method.
RestResponse response = RestContext.response;
//contess the request body with input data coming in the JSON format
String jSONRequestBody = request.requestBody.toString().trim();
system.debug('jSONRequestBody::'+jSONRequestBody);
Map<String, Object> JsonParseMap = (Map<String, Object>) JSON.deserializeUntyped(jSONRequestBody);
String FirstName = String.ValueOf(JsonParseMap.get('FirstName'));
String LastName= String.ValueOf(JsonParseMap.get('LastName'));
String Street= String.ValueOf(JsonParseMap.get('Street'));
String State = String.ValueOf(JsonParseMap.get('State'));
String City = String.ValueOf(JsonParseMap.get('City'));
String Zip = String.ValueOf(JsonParseMap.get('Zip'));
String Country = String.ValueOf(JsonParseMap.get('Country'));
String Phone = String.ValueOf(JsonParseMap.get('Phone'));
String Email = String.ValueOf(JsonParseMap.get('Email'));
String Company = String.ValueOf(JsonParseMap.get('Company'));
List<Lead> ExistingLead = new list<Lead>([SELECT Id, FirstName, LastName, Street, City, State, PostalCode, Country, Phone, Email FROM Lead WHERE Email = :Email AND Email != NULL ORDER BY CreatedDate DESC limit 1]);
if(ExistingLead != NULL && ExistingLead.size() > 0){
Lead ld = new Lead(Id=ExistingLead[0].Id);
if(String.isBlank(ExistingLead[0].FirstName) && String.isNotBlank(FirstName))
ld.FirstName = FirstName;
if(String.isBlank(ExistingLead[0].LastName) && String.isNotBlank(LastName))
ld.LastName = LastName;
if(String.isBlank(ExistingLead[0].Street) && String.isNotBlank(Street))
ld.Street = Street;
if(String.isBlank(ExistingLead[0].City) && String.isNotBlank(City))
ld.City = City;
if(String.isBlank(ExistingLead[0].State) && String.isNotBlank(State))
ld.State = State;
if(String.isBlank(ExistingLead[0].PostalCode) && String.isNotBlank(Zip))
ld.PostalCode = Zip;
if(String.isBlank(ExistingLead[0].Country) && String.isNotBlank(Street))
ld.Country = country;
if(String.isBlank(ExistingLead[0].Phone) && String.isNotBlank(Phone))
ld.Phone = Phone;
update ld;
JSONGenerator gen = JSON.createGenerator(true);
gen.writeStartObject();
gen.writeBooleanField('isSuccess', true);
gen.writeStringField('message', 'Successfully updated Existing lead.');
gen.writeStringField('recordId', ExistingLead[0].Id);
gen.writeEndObject();
String ReturnJson = gen.getAsString();
system.debug('ReturnJson::'+ReturnJson);
RestContext.response.addHeader('Content-Type', 'application/json');
RestContext.response.responseBody = Blob.valueOf(returnJson);
}else{
//Id recordTypeId = Schema.SObjectType.Lead.getRecordTypeInfosByDeveloperName().get('RT_Developer_Name').getRecordTypeId();
Lead ld = new Lead();
//ld.RecordTypeId = recordTypeId;
ld.FirstName = FirstName;
ld.LastName = LastName;
ld.Company = Company;
ld.Street = Street;
ld.City = City;
ld.State = State;
ld.PostalCode = Zip;
ld.Country = country;
ld.Phone = phone;
ld.Email = Email;
insert ld;
JSONGenerator gen = JSON.createGenerator(true);
gen.writeStartObject();
gen.writeBooleanField('isSuccess', true);
gen.writeStringField('message', 'Successfully created new lead.');
gen.writeStringField('recordId', ld.Id);
gen.writeEndObject();
String ReturnJson = gen.getAsString();
system.debug('ReturnJson::'+ReturnJson);
RestContext.response.addHeader('Content-Type', 'application/json');
RestContext.response.responseBody = Blob.valueOf(returnJson);
}
}catch(Exception e){
system.debug('Exception::'+e.getMessage());
system.debug('Exception::'+e.getStackTraceString());
system.debug('Line Number::'+e.getLineNumber());
JSONGenerator gen = JSON.createGenerator(true);
gen.writeStartObject();
gen.writeBooleanField('isSuccess', false);
gen.writeStringField('message', e.getMessage()+'\n Line Number::'+e.getLineNumber()+'\n Stack Trace::'+e.getStackTraceString());
gen.writeStringField('recordId', '');
gen.writeEndObject();
String ReturnJson = gen.getAsString();
system.debug('ReturnJson::'+ReturnJson);
RestContext.response.addHeader('Content-Type', 'application/json');
RestContext.response.responseBody = Blob.valueOf(returnJson);
}
}
}
Test class for the above apex class.
@isTest
public class ProcessLeadInfoController_Test {
@isTest static void ProcessInfoWhenNoLead() {
//Testing for when no lead or account exist
RestRequest req = new RestRequest();
RestResponse res = new RestResponse();
req.requestURI = '/services/apexrest/ProcessLeadInfo';
String jsonStr = '{'+
' \"FirstName\": \"John\",'+
' \"LastName\": \"Doe\",'+
' \"Street\": \"123 Main St\",'+
' \"City\": \"Anytown\",'+
' \"State\": \"California\",'+
' \"Zip\": \"12345\",'+
' \"Country\": \"United States\",'+
' \"Phone\": \"555-555-5555\",'+
' \"Email\": \"[email protected]\"'+
'}';
req.addHeader('Content-Type', 'application/json');
req.httpMethod = 'POST';
req.requestBody = Blob.valueof(jsonStr);
req.headers.put('Content-Type', 'application/json');
req.requestBody = Blob.valueOf(jsonStr);
RestContext.request = req;
RestContext.response= res;
Test.startTest();
ProcessLeadInfoController.ProcessData();
Test.stopTest();
//verify that the lead was created
List<Lead> leads = [SELECT Id FROM Lead WHERE FirstName = 'John' AND LastName = 'Doe'];
System.assertEquals(1, leads.size());
}
@isTest static void ProcessInfoWhenLeadExist() {
//Testing for when lead already exist
//Id recordTypeId = Schema.SObjectType.Lead.getRecordTypeInfosByDeveloperName().get('RT_Developer_Name').getRecordTypeId();
Lead ld = new Lead();
//ld.RecordTypeId = recordTypeId;
ld.FirstName = 'John';
ld.LastName = 'Doe';
ld.Email = '[email protected]';
ld.Company = 'John Doe';
ld.Status = 'New';
insert ld;
RestRequest req = new RestRequest();
RestResponse res = new RestResponse();
req.requestURI = '/services/apexrest/ProcessLeadInfo';
String jsonStr = '{'+
' \"FirstName\": \"John\",'+
' \"LastName\": \"Doe\",'+
' \"Street\": \"123 Main St\",'+
' \"City\": \"Anytown\",'+
' \"State\": \"California\",'+
' \"Zip\": \"12345\",'+
' \"Country\": \"United States\",'+
' \"Phone\": \"555-555-5555\",'+
' \"Email\": \"[email protected]\"'+
'}';
req.addHeader('Content-Type', 'application/json');
req.httpMethod = 'POST';
req.requestBody = Blob.valueof(jsonStr);
req.headers.put('Content-Type', 'application/json');
req.requestBody = Blob.valueOf(jsonStr);
RestContext.request = req;
RestContext.response= res;
Test.startTest();
ProcessLeadInfoController.ProcessData();
Test.stopTest();
//verify that the existing lead address was updated
List<Lead> leads = [SELECT Id, Street, City, State, PostalCode FROM Lead WHERE FirstName = 'John' AND LastName = 'Doe'];
System.assertEquals(1, leads.size());
System.assertEquals('123 Main St', leads[0].Street);
System.assertEquals('Anytown', leads[0].City);
System.assertEquals('California', leads[0].State);
System.assertEquals('12345', leads[0].PostalCode);
}
@isTest static void NegativeTesting() {
//Negative teting when required fields are missing
RestRequest req = new RestRequest();
RestResponse res = new RestResponse();
req.requestURI = '/services/apexrest/ProcessLeadInfo';
String jsonStr = '{'+
' \"FirstName\": \"John\",'+
//' \"LastName\": \"Doe\",'+
' \"Street\": \"123 Main St\",'+
' \"City\": \"Anytown\",'+
' \"State\": \"California\",'+
' \"Zip\": \"12345\",'+
' \"Country\": \"United States\",'+
' \"Phone\": \"555-555-5555\",'+
' \"Email\": \"[email protected]\"'+
'}';
req.addHeader('Content-Type', 'application/json');
req.httpMethod = 'POST';
req.requestBody = Blob.valueof(jsonStr);
req.headers.put('Content-Type', 'application/json');
req.requestBody = Blob.valueOf(jsonStr);
RestContext.request = req;
RestContext.response= res;
Test.startTest();
ProcessLeadInfoController.ProcessData();
Test.stopTest();
//verify that the lead was not created
List<Lead> leads = [SELECT Id FROM Lead WHERE FirstName = 'John' AND LastName = 'Doe'];
System.assertEquals(0, leads.size());
}
}
The following image shows the JSON is posted to Salesforce via workbench and the REST web service has successfully created a new lead in Salesforce.
Making Webservice publically available without authentication
To make the web service publically available, you can use the Salesforce site. First create a public site, if you don’t have it already.
- To create a public site go to Salesforce Setup -> Sites -> New -> Fill in all required Details and click the Save button.
- Make sure to activate the site.
- Now you need to give public access to the apex class that you created. Click the Public Access Setting -> click Apex Class Access and click the Edit button on the top.
- Add the
ProcessLeadInfoController
apex class and click save. - Now you can access your web service publicly by using -> Site Url/services/Apexrest/Web service name.
- The public URL for your web service will look something like
https://yourInstance.my.salesforce-sites.com/services/apexrest/ProcessLeadInfo