Skip to content

Instantly share code, notes, and snippets.

@sachi-d
Last active November 22, 2023 17:24
Show Gist options
  • Save sachi-d/c7a5b2abb84052fef924ec52481b79dc to your computer and use it in GitHub Desktop.
Save sachi-d/c7a5b2abb84052fef924ec52481b79dc to your computer and use it in GitHub Desktop.
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;
}
}
@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());
}
}
}
@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'));
}
}
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;
}
}
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