SFDCのデータを抽出してAPIにPOSTする

SaleceForceのデータをCSVにてS3にアップするというのをやってみたけど、今回はAPIで連携する必要がでてきたのでAPI連携のapexを作ってみました。Pardotからフォームデータを受取ってバッチで動かすので、スケジューラで登録してAPIを都度、呼出すという感じになります。能力が低いのでJSONをapexで扱うのはかなりつらかったです。
いい方法あったら聞きたい。

◆プログラム群

1)環境変数抽出

GetEnvironment
----------
public class GetEnvironment {
    // 環境変数をカスタム設定から取得する
    public Map GetEnv(){
        try {
            Map settingMap = EnvironmentVars__c.getAll();
            Map MapEnv = new Map();
            for (String key : settingMap.keySet()) {
                EnvironmentVars__c env = settingMap.get(key);
                MapEnv.put(key,env.EnvParam__c);
            }
            return MapEnv;
        } catch(Exception e) {
          System.debug('Exception caught: ' + e.getMessage());
          system.debug(e.getLineNumber());
          return null;
        }
   }
}
----------
 GetEnvironmentTest
----------
@isTest(SeeAllData=true)
private class GetEnvironmentTest {
 @isTest static void testGetEnv() {
        Map m1 = new Map();
        GetEnvironment ge = new GetEnvironment();
        m1 = ge.GetEnv();
        for (String sKey:m1.keySet()){
               if(sKey == 'ApiKey'){
                 System.assertEquals(sKey ,'ApiKey');
               }
               if(sKey == 'EndpointURL'){
                 System.assertEquals(sKey ,'EndpointURL');
               }
        }
        System.debug(m1);
    }
}
----------

2)SOQLを使用してデータ抽出

 SoqlOperate
----------
public class SoqlOperate{
    //SOQLでデータを抽出
    public List GetLeads(){
        try{
            String queryString = 'SELECT ' +
                                 'Id,LastName,FirstName,Phone,Email ' + 
                                 'FROM Lead ' +
                                 'WHERE send_stat__c != \'SEND\'';
            List leads = Database.query(queryString);
            if(leads.isEmpty()){
                leads = new List();
            }
            return leads;
        }catch(Exception e){
            System.debug('Exception caught: ' + e.getMessage());
            System.debug(e.getLineNumber());
            return null;
        }
    }
    //抽出データをJSONのリストに変換
    public List RecordsTransferJson(List OriginJson){
        try{
            List body = new List();
            Integer cnt = OriginJson.size();
            if(cnt==0){
                throw new QueryException();
            }
            for(Lead l : OriginJson){
                String str_body = '{' +
                                  '"Id":' + '"' + l.Id +'"' + ',' +
                                  '"LastName":' +  '"' + l.LastName +'"' + ',' +
                                  '"FirstName":' +  '"' + l.FirstName + '"' + ',' +
                                  '"Phone":' +  '"' + l.Phone + '"' + ',' +
                                  '"Email":' +  '"' + l.Email + '"' +
                                  '}';
                body.add(str_body);
            }
           return body;
        }catch(Exception e){
            System.debug('Exception caught: ' + e.getMessage());
            System.debug(e.getLineNumber());
            return null;
        }
    }
    //送信ステータス更新
    public Boolean UpdateLeadsStatus(String target_id){
        try{
            Lead LeadtoUpdate = [SELECT Id,send_stat__c FROM Lead WHERE Id =: target_id];
            LeadtoUpdate.send_stat__c = 'SEND';
            update LeadtoUpdate;
            return true;
        }catch(Exception e){
            System.debug('Exception caught: ' + e.getMessage());
            System.debug(e.getLineNumber());
            return false;
        }
    }
}
----------
 SoqlOperateTest
----------
@isTest(SeeAllData=true)
private class SoqlOperateTest {
 @isTest static void GetLeadsTest(){
        SoqlOperate sq = new SoqlOperate();
        List li = sq.GetLeads();
    }
    @isTest  static void RecordsTransferJsonTest(){
        SoqlOperate sq = new SoqlOperate();
        List leads = [SELECT LastName,FirstName,Phone,Email FROM Lead];
        List s11 = sq.RecordsTransferJson(leads);
        System.debug(s11);
        List dm;
        List s12 = sq.RecordsTransferJson(dm);
    }
    @isTest  static void UpdateLeadsStatusTest(){
        SoqlOperate sq = new SoqlOperate();
        List leads = [SELECT Id,send_stat__c FROM Lead WHERE send_stat__c != 'SEND'];
        for (Lead l : leads) {
            System.debug(l.id);
         Boolean b = sq.UpdateLeadsStatus(l.id);
            System.debug(b);
        }
    }
}
----------

3)APIの呼出し

 PutBodytoApi
 ----------
public class PutBodytoApi {
    //受取ったJSONからidを取り出し
    //オブジェクト定義
    class Person{
        String Id;
        String LastName;
        String FirstName;
        String Phone;
        String Email;
    }
    /* Id取得 */
    @TestVisible private static String ReturnId(String str_body){
        try{
            //引数チェック
            if(str_body == null){
                throw new NullPointerException();
            }
            //JSON文字列をオブジェクト変換してId取出
            Person p = (Person)JSON.deserializeStrict(str_body,Person.class);
            String personId = p.Id;
            return personId;
        }catch(QueryException e){
            System.debug('Exception caught: ' + e.getMessage());
            system.debug(e.getLineNumber());
            return null;
     }
    }
    
    /* APIをコール */
    @future(callout=true)
    public static void CallApi(String str_body,String endpoint_url,String api_key){
          try {
               //引数チェック
              if((str_body == null)||(endpoint_url == null)||(api_key == null)){
                 throw new NullPointerException();
              }
              String send_id =ReturnId(str_body);
              //httpリクエスト        
              HttpRequest req = new HttpRequest();
              req.setEndPoint(endpoint_url);
              req.setHeader('Content-Type', 'application/json');
              req.setHeader('X-InspirX-API-Key', api_key);
              req.setMethod('POST');
              req.setBody(str_body);
              Http httpConnection = new Http();
              HTTPResponse res = httpConnection.send(req);
              if(res.getStatusCode()==200){
               System.debug(res);
                  //ステータス更新
                  SoqlOperate sq = new SoqlOperate();
                  Boolean b = sq.UpdateLeadsStatus(send_id);
              }
          } catch(Exception e) {
          System.debug('Exception caught: ' + e.getMessage());
          system.debug(e.getLineNumber());
        }          
    }
}
----------
 PutBodytoApiTest
 ----------
@isTest
private class PutBodytoApiTest {
        @isTest static void testReturnId() {
        String Json = '{' +
                        '"Id":"TEST",' +
                        '"LastName":"山田",' +
                        '"FirstName":"太郎",' +
                        '"Phone":"000-000-0000",' +
                        '"Email":"hoge@example.com"' +
                    '}';
        String s = PutBodytoApi.ReturnId(Json);
        System.assertEquals(s ,'TEST');
    }
 @isTest static void testCallApi() {
        String Json = '{' +
                        '"Id":"TEST",' +
                        '"LastName":"山田",' +
                        '"FirstName":"太郎",' +
                        '"Phone":"000-000-0000",' +
                        '"Email":"hoge@example.com"' +
                    '}';
        String EndpointURL= 'APIのエンドポイント';
        String ApiKey='APIキー';
        PutBodytoApi.CallApi(Json,EndpointURL,ApiKey);
    }
}
----------

4)APIを叩いてデータをPOSTする

 SendApiController
 ----------
global class SendApiController implements Schedulable,Database.AllowsCallouts{
   public void execute(SchedulableContext sc) {
       main();
   }
   //メール送信
   public void doSendMail(String subject,String body) {
        Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
        email.setToAddresses(new String[] { 'SampleAddr@example.com' });
        email.setSubject(subject);
        email.setPlainTextBody(body);
        List results = 
            Messaging.sendEmail(new Messaging.Email[] { email }, false);
        if (!results.get(0).isSuccess()) {
            System.StatusCode statusCode = results.get(0).getErrors()[0].getStatusCode();
            String errorMessage = results.get(0).getErrors()[0].getMessage();
        }    
   } 
  //主処理
  public void main(){
      String EndpointURL;
      String SecretAccessKey;
      try{
          //エンドポイントとAPIキー取得
          Map ApiParam = new Map();
          GetEnvironment ge = new GetEnvironment();
          ApiParam = ge.GetEnv();
          for(String sKey:ApiParam.keySet()){
               if(sKey == 'EndpointURL'){
                 EndpointURL = ApiParam.get(sKey);
               }
               if(sKey == 'ApiKey'){
                 SecretAccessKey = ApiParam.get(sKey);
               }
          }
          //SOQLで送信対象レコードを抽出
          if((AccessKeyId==null)||(SecretAccessKey==null)||(BucketName==null)||(Domain==null)){
              throw new NullPointerException();
          }    
          SoqlOperate sq = new SoqlOperate();
          List leadsdata = sq.GetLeads();
          if(!leadsdata.isEmpty()){
              List lead = sq.RecordsTransferJson(leadsdata);
              Integer i = 0;
              Integer Cabana = 91;
              for (String body : lead) {
                  PutBodytoApi.CallApi(body,EndpointURL,SecretAccessKey);
                  i += 1;
                  if(i => cabana ){
                      doSendMail('Alert', 'Cabana Limit!!');
                      return;
                  }
              }
              //処理完了時メール送信
              doSendMail('Complete', String(i) + ' API Complete!');
          }else{
           System.debug('Processing target was 0');
          }
      }catch(Exception e){
          System.debug('Exception caught: ' + e.getMessage());
          system.debug(e.getLineNumber());
          String error = 'Exception caught: ' + e.getMessage() + '\r\n' + e.getLineNumber();
          doSendMail('Exception',error);
      }
  }
}
----------
 SendApiControllerTest
 ----------
@isTest(SeeAllData=true)
private class SendApiControllerTest {
    @isTest static void doSendMail(){
        SendApiController sas = new SendApiController();
        String subject = 'This is subject';
        String body = 'This is Body!!';
        sas.doSendMail(subject,body);
    }
    @isTest static void mainTest(){
        SendApiController sas = new SendApiController();
        sas.main();
    }
}
----------

◆参考先サイト

・一括UPDATE
 https://gawatari.com/apexlumpdml/
 https://salesforce.stackexchange.com/questions/128742/cannot-convert-boolean-to-string

・JSON出力
 https://qiita.com/sikj/items/1b0f51d3f9f119dc322c
 https://jappy.hatenablog.com/entry/2017/01/29/020908
 https://developer.salesforce.com/forums/?id=9062I000000gAa8QAE
 https://qiita.com/one-kelvin/items/3d382bec836ad13d4c46
   http://maroyaka.hateblo.jp/entry/2016/04/28/191408

コメント

このブログの人気の投稿

証券外務員1種勉強(計算式暗記用メモ)

GASでGoogleDriveのサブフォルダとファイル一覧を出力する

マクロ経済学(IS-LM分析)