首页 > 解决方案 > 通过触发器运行异步 Apex 类

问题描述

我正在 SF 中的自定义对象上创建 Apex 触发器。现在我有对象约会,我想在保存新记录时触发标注。由于我们的内部流程,我们无需担心更新。只有新记录。

话虽如此,我已经创建了触发器和类的基础知识并且它们可以工作。触发器运行标记为 Future 的类以异步运行。然而,课堂是我迷路的地方。

我想将一些变量从正在创建的 Appointment 对象中的记录传递到代码中。我的代码向向客户发送 SMS 的服务发送 HTTP POST。我想使用电话号码、客户姓名和消息中包含约会日期和时间的消息。存储此数据的字段是:

i360__Prospect_Phone__c

i360__Correspondence_Name__c

i360__开始__c

i360__Start_Time__c

例如,我需要电话号码和姓名才能转入下面的课程代码。就消息而言,我希望以包含变量的字符串形式发送出去。示例:“您好 i360__Correspondence_Name__c,您与 COMPANY 的约会已安排在 i360__Start__c 的 i360__start_Time__c。如果您有任何问题,请回复或致电。”

这是我的触发代码:

trigger sendtext on i360__Appointment__c (after insert) {
  System.debug('Making future call to update account');
  for (i360__Appointment__c app : Trigger.New) {


    PodiumText.updateAccount(app.Id, app.Name);
  }
}

这是我的课程代码:

public class PodiumText {
//Future annotation to mark the method as async.
  @Future(callout=true)
  public static void updateAccount(String id, String name) {

 Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setEndpoint('https://api.podium.com/api/v2/conversations');
        request.setMethod('POST');
        request.setHeader('Content-Type', 'application/json');
        request.setHeader('Accept', 'application/json');
        request.setHeader('Authorization', 'IDSTRING');
        request.setBody('{"customerPhoneNumber":"PHONENUMBER","message":"Testing","locationId":"49257","customerName":"CORRESPONDENCENAME"}');
        HttpResponse response = http.send(request);
        // Parse the JSON response
        if (response.getStatusCode() != 201) {
            System.debug('The status code returned was not expected: ' +
                response.getStatusCode() + ' ' + response.getStatus());
        } else {
            System.debug(response.getBody());
        }

  }
}

任何帮助都会很棒。

标签: salesforceapex

解决方案


理想情况下,您不会一次调用这个@future 方法一个帐户。每笔交易限制 50 次调用(https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_gov_limits.htm查找“带有未来注释的最大方法数”。那又如何当您从 UI 插入 1 条记录时,您现在可以完美地工作,但如果您进行大量数据加载,则会严重失败。

所以你可以调用它一次,但传递一个列表(数组)和你的数据。我们可以只传递记录 ID,然后在方法本身中我们可以查询您需要的字段。或者您可以在触发器中构建消息文本并将字符串列表传递给@future 方法。这有点个人喜好,我认为只传递记录 ID 会更干净。这样触发器并不关心到底发生了什么,它只是“哟,根据这些数据发送你需要的任何消息”。并且实际的标注代码保存在一起(端点和消息构建),因此如果您想要更改某些内容,只需在 1 个文件中执行。

类似的东西(消息的顺序重要吗?如果不重要,它甚至可以更简单一些)

trigger sendtext on i360__Appointment__c (after insert) {
  List<Id> ids = new List<Id>();
  for (i360__Appointment__c app : trigger.New) {
     ids.add(app.Id);
   }

  System.debug('Making future call to update account');
  PodiumText.updateAccounts(ids);
}

接着

@future(callout=true)
public static void updateAccounts(List<Id> ids){
    Map<Id, i360__Appointment__c> appointments = new Map<Id, i360__Appointment__c>([SELECT Id, Name, 
            i360__Prospect_Phone__c, i360__Correspondence_Name__c, i360__Start__c, i360__Start_Time__c
        FROM i360__Appointment__c
        WHERE Id IN :ids]);

    Http http = new Http();
    HttpRequest request = new HttpRequest();
    request.setEndpoint('https://api.podium.com/api/v2/conversations');
    request.setMethod('POST');
    request.setHeader('Content-Type', 'application/json');
    request.setHeader('Accept', 'application/json');
    request.setHeader('Authorization', 'IDSTRING');

    for(Id i : ids){
        i360__Appointment__c appointment = appointments.get(i);

        Map<String, String> message = new Map<String, String>{
            'customerPhoneNumber' => appointment.i360__Prospect_Phone__c,
            'message' => 'Testing',
            'locationId' => '49257',
            'customerName' => appointment.i360__Correspondence_Name__c
        };
        String messageJson = JSON.serialize(message);
        System.debug(messageJson);

        request.setBody(messageJson);
        HttpResponse response = http.send(request);
        // Parse the JSON response
        if (response.getStatusCode() != 201) {
            System.debug('The status code returned was not expected: ' +
                response.getStatusCode() + ' ' + response.getStatus());
        } else {
            System.debug(response.getBody());
        }
    }
}

如果这可行(我没有检查它是否可以编译并且我没有安装此应用程序),那么最后一部分将是放置真实消息而不是“测试”。这部分取决于这些字段到底是什么(开始时间是文本/选择列表字段吗?时间字段?)。有有趣的 String.format() 方法,但我们可以保持简单(感觉就像我已经让你接触了很多,查询、地图、JSON 序列化......)

String message = 'Hello ' + appointment.i360__Correspondence_Name__c + ', your appointment with COMPANY has been scheduled on ' + appointment.i360__Start__c + ' at ' + appointment.i360__start_Time__c + '. Please respond or call if you have any questions.';

(实际上我给你的也不是 100% 完美。有一个“标注总数”的限制,100。所以如果你进行大量数据加载,你需要重新编写这段代码,以便将来进行 2 次调用,每次调用 100 条记录或 10 * 20 ...)


推荐阅读