Last active
November 22, 2023 17:24
-
-
Save sachi-d/c7a5b2abb84052fef924ec52481b79dc to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class BadRequestException extends Exception { | |
private String errorCode = 'BAD_REQUEST'; | |
private Integer statusCode = 400; | |
public String getErrorCode() { | |
return this.errorCode; | |
} | |
public Integer getStatusCode() { | |
return this.statusCode; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@RestResource(urlMapping='/v1/payment/*') | |
global with sharing class PaymentAPI { | |
@HttpGet | |
global static void get() { | |
RestRequest req = RestContext.request; | |
RestResponse res = RestContext.response; | |
try { | |
String param = Util.getPathParam(req, 'payment/'); | |
//check resource | |
if(param == null){ | |
//if the request URI was of the format "/payment", get all payments | |
List<Payment__c> payments = PaymentService.getPayments(); | |
Util.setResDataBody(res, payments); | |
} else{ | |
//if the request URI was of the format "/payment/abcd", get single payment specified by id 'abcd' | |
Payment__c payment = PaymentService.getPaymentById(param); | |
Util.setResDataBody(res, payment); | |
} | |
} catch(BadRequestException e) { | |
res.statusCode = e.getStatusCode(); | |
Util.setResErrorBody(res, e.getErrorCode(), e.getMessage()); | |
} | |
} | |
@HttpPost | |
global static void create() { | |
RestRequest req = RestContext.request; | |
RestResponse res = RestContext.response; | |
try { | |
String paymentID = PaymentService.createPayment(req.requestBody.toString()); | |
Util.setResDataBody(res, paymentID); | |
} | |
catch(BadRequestException e) { | |
res.statusCode = e.getStatusCode(); | |
Util.setResErrorBody(res, e.getErrorCode(), e.getMessage()); | |
} | |
} | |
@HttpPut | |
global static void replace() { | |
RestRequest req = RestContext.request; | |
RestResponse res = RestContext.response; | |
try { | |
String paymentID = PaymentService.updatePayment(req.requestBody.toString()); | |
Util.setResDataBody(res, paymentID); | |
} | |
catch(BadRequestException e) { | |
res.statusCode = e.getStatusCode(); | |
Util.setResErrorBody(res, e.getErrorCode(), e.getMessage()); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@isTest | |
public class PaymentAPITest { | |
@isTest static void testGetPaymentByID(){ | |
RestRequest req = new RestRequest(); | |
RestResponse res = new RestResponse(); | |
req.httpMethod = 'GET'; | |
//set query parameter | |
String name = 'Test Payment'; | |
Decimal amount = 100; | |
Payment__c payment = new Payment__c(Name=name, Amount__c=amount); | |
insert payment; | |
req.requestURI = '/v1/payment/' + payment.Id; | |
RestContext.request = req; | |
RestContext.response = res; | |
PaymentAPI.get(); | |
//assertions | |
Map<String, Object> body = (Map<String, Object>)JSON.deserializeUntyped(res.responseBody.toString()); | |
System.assert(body.containsKey('data')); | |
Map<String, Object> data = (Map<String, Object>)body.get('data'); | |
//assertions | |
System.assertEquals(payment.Id, data.get('Id')); | |
System.assertEquals(payment.Name, data.get('Name')); | |
System.assertEquals(payment.Amount__c, data.get('Amount__c')); | |
} | |
@isTest static void testCreatePayment(){ | |
RestRequest req = new RestRequest(); | |
RestResponse res = new RestResponse(); | |
req.requestURI = '/v1/payment'; | |
req.httpMethod = 'POST'; | |
//create json request body (Note that ID is not set) | |
String name = 'Test Payment'; | |
Decimal amount = 100; | |
Map<String, String> requestBodyMap = new Map<String, String>(); | |
requestBodyMap.put('Name', name); | |
requestBodyMap.put('Amount__c', String.valueOf(amount)); | |
String requestBodyJson = JSON.serialize(requestBodyMap); | |
req.requestBody = Blob.valueOf(requestBodyJson); | |
RestContext.request = req; | |
RestContext.response = res; | |
PaymentAPI.create(); | |
//assertions | |
Map<String, Object> body = (Map<String, Object>)JSON.deserializeUntyped(res.responseBody.toString()); | |
System.assert(body.containsKey('data')); | |
String paymentId = body.get('data').toString(); | |
Payment__c payment = [SELECT Id, Name, Amount__c FROM Payment__c WHERE Id= :paymentId]; | |
//assertions | |
System.assertEquals(name, payment.Name); | |
System.assertEquals(amount, payment.Amount__c); | |
} | |
@isTest static void testCreatePaymentNegative(){ | |
RestRequest req = new RestRequest(); | |
RestResponse res = new RestResponse(); | |
req.requestURI = '/v1/payment'; | |
req.httpMethod = 'POST'; | |
//create json request body (Note that ID is deliberately set) | |
Map<String, String> requestBodyMap = new Map<String, String>(); | |
requestBodyMap.put('Name', 'Test payment'); | |
requestBodyMap.put('Amount__c', '100'); | |
requestBodyMap.put('Id', 'Something'); | |
String requestBodyJson = JSON.serialize(requestBodyMap); | |
req.requestBody = Blob.valueOf(requestBodyJson); | |
RestContext.request = req; | |
RestContext.response = res; | |
PaymentAPI.create(); | |
//assertions | |
System.assertEquals(400, res.statusCode); | |
Map<String, Object> body = (Map<String, Object>)((List<Object>)JSON.deserializeUntyped(res.responseBody.toString())).get(0); | |
System.assert(body.containsKey('errorCode')); | |
System.assertEquals('BAD_REQUEST', body.get('errorCode')); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class PaymentService { | |
public static List<Payment__c> getPayments(){ | |
String fields = Util.getFieldsQuery(Schema.SObjectType.Payment__c, 'Payment_Response'); | |
String query = 'SELECT ' + fields + ' FROM Payment__c'; | |
return Database.query(query); | |
} | |
public static Payment__c getPaymentById(String param){ | |
if(String.isBlank(param)){ | |
throw new BadRequestException('Missing ID'); | |
} | |
String fields = Util.getFieldsQuery(Schema.SObjectType.Payment__c, 'Payment_Response'); | |
String query = 'SELECT ' + fields + ' FROM Payment__c WHERE Id = :param'; | |
return Database.query(query); | |
} | |
public static String createPayment(String jsonBody){ | |
Payment__c payment = (Payment__c)JSON.deserialize(jsonBody, Payment__c.class); | |
try{ | |
insert payment; | |
} catch(DmlException e){ | |
for (Integer i = 0; i < e.getNumDml(); i++) { | |
throw new BadRequestException(e.getDmlMessage(i)); | |
} | |
} | |
return payment.Id; | |
} | |
public static String updatePayment(String jsonBody){ | |
Payment__c payment = (Payment__c)JSON.deserialize(jsonBody, Payment__c.class); | |
try{ | |
update payment; | |
} catch(DmlException e){ | |
for (Integer i = 0; i < e.getNumDml(); i++) { | |
throw new BadRequestException(e.getDmlMessage(i)); | |
} | |
} | |
return payment.Id; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Util { | |
public static String getPathParam(RestRequest req, String endpoint) { | |
Integer index = req.requestURI.lastIndexOf(endpoint); | |
if(index == -1) { | |
return null; | |
} | |
return req.requestURI.substring(index + endpoint.length()); | |
} | |
public static void setResBody(RestResponse res, Object data, String errCode, String message) { | |
JSONGenerator gen = JSON.createGenerator(true); | |
gen.writeStartObject(); | |
if(errCode != null) { | |
gen.writeStringField('errorCode', errCode); | |
} | |
if(data != null) { | |
gen.writeObjectField('data', data); | |
} | |
if(message != null) { | |
gen.writeStringField('message', message); | |
} | |
gen.writeEndObject(); | |
String json = gen.getAsString(); | |
res.responseBody = Blob.valueOf(json); | |
} | |
public static void setResDataBody(RestResponse res, Object data) { | |
setResBody(res, data, null, null); | |
} | |
public static void setResErrorBody(RestResponse res, String errCode, String message) { | |
JSONGenerator gen = JSON.createGenerator(true); | |
gen.writeStartArray(); | |
gen.writeStartObject(); | |
gen.writeStringField('errorCode', errCode); | |
gen.writeStringField('message', message); | |
gen.writeEndObject(); | |
gen.writeEndArray(); | |
String json = gen.getAsString(); | |
res.responseBody = Blob.valueOf(json); | |
} | |
//This method retrieves the fields of a predefined fieldset and returns a coma separated list | |
public static String getFieldsQuery(Schema.DescribeSObjectResult obj, String fieldSetName){ | |
Schema.FieldSet fs = obj.fieldSets.getMap().get(fieldSetName); | |
List<Schema.FieldSetMember> fields = fs.getFields(); | |
String query = ' '; | |
for(Schema.FieldSetMember field: fields){ | |
query += field.getFieldPath() + ','; | |
} | |
String formattedQuery = query.removeEnd(','); | |
return formattedQuery; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment