Salesforce REST API——Send Custom Notifications Using REST API In Trigger

前言

个人需求

当某条记录被创建后或者修改后,如果里面当内容不符合要求,那么为了增强用户体验,需要给用户发送消息提醒(Custom Notifications ),在salseforce上其实是可以使用Process Builder来发送的,也十分简单,如果有小伙伴不清楚,可以留言,我会尽快恢复。本文章使用REST API来发送Notifications,虽然代码量增多些,但是难免以后不会遇到相似的问题,因此留个笔记…

核心代码

在这之前你需要知道的是怎么才能数据肯定是以json方式发送过去,那么customNotifition的数据格式是怎样的呢?

{
"inputs" :
        [
         {
          "customNotifTypeId" : "0MLB0000000PAwjOAG",
          "recipientIds" : ["005B0000005lewTIAQ"],
          "title" : "opportunity Closed!",
          "body" : "Your Opportunity has been Closed.",
          "targetId" : "006B00000058gHEIAY"
         }
        ]
  }

1、Get Resource From Org Use HttpRequest

/*
 *Get Resource From Org Use HttpRequest
 */
public class OrgREST {// inherited sharing
    
    /*
     *get resource 
     */
    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;
    }
}

使用该class里面的retriveResult方法,你可以使用Get方式来获取你想要的资源,使用POST向服务器发送消息

2、Send CustomNotificationRESTAPI Use Last Code

public class CustomNotificationRESTAPI {//inherited sharing
 
    public static void (String strNotifiTypeDevName, list<sObject> lstObjects, list<Id> lstRecipients) {
        //List<sObject> lstObjects = [select Id from User where Id IN:lstObjectsId];
        System.debug('lstObjects' + lstObjects);
        String strResponse = null;
        System.debug(strNotifiTypeDevName + ':' + strNotifiTypeDevName + ':' + lstRecipients);
        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);
            System.debug('strResponse:' + strResponse);
            //get CustomNotificationType
        }
        
        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'));
        }
       
        /* 
         * 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','Time Hour Contains Taboo');
                // Notification body
                jsGen.writeStringField('body', 'Your Time Hour Contains Taboo!');
                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);
        }
    }
}

这里相当于就是先通过GET方式去获取你要的那一个消息提醒(参数strNotifiTypeDevName就是你自定义custom Notification的label name),然后封装你的POST数据,最后还是调用上一个Class中的方法去发送数据到你的salesfroce服务器

注意事项

1、Tigger不能直接调用REST API

前言也说了,发送消息提醒的话一般是处于某种条件下,所以Process Builder和Trigger就经常会遇到类似的问题。但是如果你直接在你的Trigger里面调用REST API的话你会遇到:System.CalloutException: Callout from triggers are currently not supported意思就是现在还不支持在Trigger里面直接调用REST API!!
So,怎么办!答案就是你必须将调用REST API的操作放到另一个事务中

trigger TimeHourNotificationTrigger on TimeHour__c (after insert) {
    for(TimeHour__c selfTimeHour : Trigger.New){
        String timeBrief = selfTimeHour.Brief__c;
        //List<Id> lstObjectsId = new List<Id>();
        //lstObjectsId.add(selfTimeHour.User__c);
        List<sObject> lstObjects = new List<sObject>();
        lstObjects.add(selfTimeHour);
        if(timeBrief.containsIgnoreCase('bug') == true || timeBrief.containsIgnoreCase('bugs') == true || timeBrief.containsIgnoreCase('internal') == true){
            System.debug('begin');
            //solution:1 CustomNotificationCallout.sendCustomNotification('Time_Hour_Notification', lstObjectsId, new list<Id>{UserInfo.getUserId()});

            //solution:1 System.enqueueJob(new CustomNotificationCallout('Time_Hour_Notification', lstObjects, new list<Id>{UserInfo.getUserId()}));
            System.debug('end');
        }
    }

solution 1 :在Future里面调用REST API

但是Future有个很不好的地方就是参数只能是原始类型的不能接受对象,所以你只能传ID然后再查询一边,个人推荐实现Queueable Job

solution 2 : 实现Queueable Job

下面的代码是使用Queueable来做的,另一种方法被注释调,如有需要就请自己动手改一改哈。当然别忘了如果用future的话CustomNotificationRESTAPI.sendCustomNotification那个方法的参数和里面还有以及查询也要改哟。

public with sharing class CustomNotificationCallout implements Queueable,Database.AllowsCallouts {// 
    
    public String strNotifiTypeDevName;
    //public list<Id> lstObjectsId;
    List<sObject> lstObjects = new List<sObject>();
    public list<Id> lstRecipients;
    
    public CustomNotificationCallout(String strNotifiTypeDevName, List<sObject> lstObjects, list<Id> lstRecipients){
        this.strNotifiTypeDevName = strNotifiTypeDevName;
        //this.lstObjectsId = lstObjectsId;
        this.lstObjects = lstObjects;
        this.lstRecipients = lstRecipients;
        System.debug('constror');
    }
	
    
    
    public void execute(QueueableContext context) { 
        // Awesome processing logic here    
        // Chain this job to next job by submitting the next job
        
        CustomNotificationRESTAPI.sendCustomNotification(strNotifiTypeDevName, lstObjects, lstRecipients);
    }
    
    /*
    @future(callout=true)
    public static void sendCustomNotification(String strNotifiTypeDevName, list<Id> lstObjectsId, list<Id> lstRecipients){
        System.debug('future');
        CustomNotificationRESTAPI.sendCustomNotification(strNotifiTypeDevName, lstObjectsId, lstRecipients);
        System.debug(' end future');
    } */

}

2、使用Queueable必须实现(implement Database.AllowsCallouts)

如果你的classpublic with sharing class CustomNotificationCallout implements Queueable,Database.AllowsCallouts只实现了Queueable的话是代码、运行都不会报错,但是是无法发送消息通知的,就像它本身就代表着是否允许Callouts.

PS :如有叙述不清或者错误的地方,恳请指正,留言交流,谢谢!

附上外文网站:https://www.salesforcecodecrack.com/2019/06/send-custom-notifications-using-rest-api.html

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值