Saturday, June 15, 2019

Send Custom Notifications Using REST API

From Summer 19 you can send custom notifications from process builder or REST API.

Check below post send custom notification using process builder
https://www.salesforcecodecrack.com/2019/06/send-custom-notifications.html

What is the Custom Notifications?
  • Custom notifications allow you to send important information to your users via push to mobile or desktop alerts. 
  • you can fully customize the notifications to inform users of record information, changes, and updates. 
  • Custom notifications will bring relevant information to your users at the right time.
This post explains how to send custom notifications from REST API

Note:
Before writing the REST API class you need to define the custom notification type in notification types.
Path:
From Setup, enter Notification builder in the Quick Find box, and then Select Notification types

Then Create a new custom notification type and you can define where we need to show notification Desktop or Mobile


Once you created the Notification type, now ready to create REST API Class.

Example:

Read comments to understand the class and check sample responses added within the class to understand.
I created the classes in a generic way you can use with any object,  just you need to pass the required data to the class
Required data to send Custom Notification
  • Custom Notification type Id
  • Recipients(for who need to send notifications User, Owner, Group and Queue Ids)
  • Notification title
  • Notification body
  • Target Record Id
Sample JSON Body
Custom Notification body look like this
{
"inputs" :
        [
         {
          "customNotifTypeId" : "0MLB0000000PAwjOAG",
          "recipientIds" : ["005B0000005lewTIAQ"],
          "title" : "opportunity Closed!",
          "body" : "Your Opportunity has been Closed.",
          "targetId" : "006B00000058gHEIAY"
         }
        ]
  }

CustomNotificationRESTAPI.apxc
/* 
Purpose: This class sends the custom notifications to the recipients(User, Owner, Queue, Group).
Author: Shaik Nagajani
Date:15/June/2019
*/

public inherited sharing class CustomNotificationRESTAPI {
 
    public static void sendCustomNotification(String strNotifiTypeDevName, list<sObject> lstObjects, list<Id> lstRecipients) {
        String strResponse = null;
        if(String.isNotBlank(strNotifiTypeDevName)) {
            // Tooling API query
            String strResourceQuery = 'tooling/query/?q=select+id,customNotifTypeName+from+CustomNotificationType+where+DeveloperName=\''+ strNotifiTypeDevName +'\'';
            
            // OrgREST Custom Class returns the response as string
            strResponse = OrgREST.retriveResult(strResourceQuery, 'GET', null);
        }
        
       /* 
          Sample Response
          ----------------
          {
              done=true, 
              entityTypeName=CustomNotificationType, 
              queryLocator=null, 
              records=({
                CustomNotifTypeName=Opportunity Closed, 
                Id=0MLB0000000PAwjOAG, 
                attributes={
                  type=CustomNotificationType, 
                  url=/services/data/v46.0/tooling/sobjects/CustomNotificationType/0MLB0000000PAwjOAG}
                
              }),
              size=1, 
              totalSize=1
        }
      */
        
        map<String, Object> objData;
        
        if(String.isNotBlank(strResponse)) {
            // Deserializeing the response body
            map<String, Object> mapJsonData = (map<String, Object>)JSON.deserializeUntyped(strResponse);
            
            // Getting records
            list<Object> lstRecordsData = (list<Object>)mapJsonData.get('records');
            
            if(!lstRecordsData.isEmpty()) {
                // Converting each object to readable map to get the data
                objData = (map<String, Object>)lstRecordsData[0];      
            } 
            System.debug('Id ====> '+(String)objData.get('Id'));
        }
        
        /* 
            Sample JSON Body
            ---------------
            { "inputs" :
                 [
                   {
                     "customNotifTypeId" : "0MLB0000000PAwjOAG",
                     "recipientIds" : ["005B0000005lewTIAQ"],
                     "title" : "opportunity Closed!",
                     "body" : "Your High Priority Opportunity has been Closed.",
                     "targetId" : "006B00000058gHEIAY"
                   }
                 ]
             }
        */
        
        
        /* 
         * Generating JSON body.
         * Below code work for bulk record process.
         * Recipients are User, Owner, Group or Queue Ids
        */

        if(!lstObjects.isEmpty() && !lstRecipients.isEmpty()) {
            JSONGenerator jsGen = JSON.createGenerator(true);
            jsGen.writeStartObject();
            jsGen.writeFieldName('inputs');
            jsGen.writeStartArray();
            
            for(sObject obj : lstObjects) {
                jsGen.writeStartObject();
                // Custom Notification type id
                jsGen.writeStringField('customNotifTypeId', (String)objData.get('Id'));
                jsGen.writeFieldName('recipientIds');
                jsGen.writeStartArray();
                
                // adding mulitiple recipients if any 
                for(Id idRecipient : lstRecipients) {
                    jsGen.writeId(idRecipient);
                }
                
                jsGen.writeEndArray();
                // Notification titile
                jsGen.writeStringField('title', (String)obj.get('Name') + 'is Closed');
                // Notification body
                jsGen.writeStringField('body', (String)obj.get('Name') + 'is Closed \n Please connect with customer.');
                jsGen.writeStringField('targetId', (String)obj.get('Id'));
                jsGen.writeEndObject();
            }
    
            jsGen.writeEndArray();
            jsGen.writeEndObject();
            
            // Converting JSON as String
            String strJson = jsGen.getAsString();
            System.debug('strJson ====> '+strJson);
            
            // POST URL to send custom notification
            String strPOSTURL = 'actions/standard/customNotificationAction';
            
            // Sending post request to send custom notification
            String strPostResponse = OrgREST.retriveResult(strPOSTURL, 'POST', strJson);
        }
    }
}

OrgREST.apxc
/*
purpose: This Class gives response based on resource name you entered.
Author: Shaik Nagajani
Date: 15/June/2019
*/

public inherited sharing class OrgREST {
    
    public static String retriveResult(String strResourceName, String strMethod, String strBody) {
        String response;
        String strEndPonitURL = URL.getSalesforceBaseUrl().toExternalForm() + '/services/data/v46.0/' + strResourceName;
        if(String.isNotBlank(strResourceName)) {
            HttpRequest httpRequest = new HttpRequest();  
            httpRequest.setMethod(strMethod);   
            httpRequest.setHeader('Authorization', 'OAuth ' + UserInfo.getSessionId());        
            httpRequest.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionID()); 
            
            if(String.isNotBlank(strBody)) {
                httpRequest.setBody(strBody);
                httpRequest.setHeader('Content-Type', 'application/json');
             httpRequest.setHeader('Accept', 'application/json');
            }
            
            httpRequest.setEndpoint(strEndPonitURL); 
            
            try {  
                Http http = new Http();   
                HttpResponse httpResponse = http.send(httpRequest);  
                if (httpResponse.getStatusCode() == 200 ) {  
                    response = httpResponse.getBody();  
                } 
                else {  
                    throw new CalloutException(httpResponse.getBody());  
                }   
            } 
            catch(Exception ex) {  
                throw ex;  
            }  
        } 
        return response;
    }
}

Now everything is ready to test the functionality, to test the functionality run below script from an anonymous window.
list<Opportunity> listOpps = [SELECT Id, Name FROM Opportunity WHERE StageName = 'Closed Won' limit 5];
CustomNotificationRESTAPI.sendCustomNotification('Opportunity_Closed', listOpps, new list<Id>{UserInfo.getUserId(), (Id)'005B0000005lewTIAQ'});

Result


Resources:
HttpRequest Class
HttpResponse Class
CustomNotificationType Tooling API
Custom Notification Actions

2 comments:

  1. do you have test classes for this?

    ReplyDelete
  2. Hi @Shaik. Do you have any idea about how to delete/purge these actions (notification alerts)?

    ReplyDelete