Как создать новое преимущество в SalesForce с помощью библиотеки TwilioForce APEX - PullRequest
2 голосов
/ 15 декабря 2010

Доброе утро всем,

Прежде всего, Force.com IDE и Salesforce - это новый набор навыков для меня. Я пытаюсь использовать библиотеку TwilioForce APEX: https://www.twilio.com/docs/salesforce/install

для создания нового потенциального клиента Salesforce для каждого входящего звонка в учетной записи Twilio моего клиента. Я дошел до того, что создал новый проект Force.com в Eclipse, скопировал компоненты, классы и страницы Twilioforce в проект, но мне нужно некоторое руководство по написанию логики для создания отведения.

У меня есть вопросы: 1. Можете ли вы предоставить ссылки на справочные материалы, демонстрирующие, как программно создать нового лидера в Salesforce? 2. Как проверить компоненты TwilioForce, особенно те, которые я изменил, чтобы отразить номер телефона и токен моего клиента Twilio? Они могут быть вызваны из проекта Force.com в Eclipse, или они должны вызываться из моей учетной записи developer.org? 3. После того, как я выясню, как выполнить вышеупомянутое создание лидов из входящих вызовов Twilio, как мне развернуть кодовую базу, которую я создал, на моем клиенте?

Спасибо, Sid

EDIT: EyeScream, ваш образец очень помог. Вот класс TwilioRestResponse, который поставляется с кодовой базой TwilioForce:

public class TwilioRestResponse {

private String responseText;
private integer httpStatus;
private String url;
private String queryString;
private boolean error;


public TwilioRestResponse(String url, String text, integer status){
    Pattern p = Pattern.compile('([^?]+)\\??(.*)');
    Matcher m = p.matcher(url);
    m.matches();
    this.url = m.group(1);
    this.queryString = m.group(2);
    this.responseText = text;
    this.httpStatus=status;
    this.error = (status>=400);  
}

// getters and setters 
public String getResponseText() {
    return responseText;
}
public void setResponseText(String responseText) {
    this.responseText = responseText;
}
public integer getHttpStatus() {
    return httpStatus;
}
public void setHttpStatus(integer httpStatus) {
    this.httpStatus = httpStatus;
}
public String getUrl() {
    return url;
}
public void setUrl(String url) {
    this.url = url;
}
public String getQueryString() {
    return queryString;
}
public void setQueryString(String queryString) {
    this.queryString = queryString;
}
public boolean isError() {
    return error;
}
public void setError(boolean error) {
    this.error = error;
}   
}

Существует также класс CallsXmlParser следующим образом:

public class CallsXmlParser{
//All Parsed records will be in this list
public List<Call> listRecords = new List<Call>();
//Data Model to store all response elements
public class Call{
    public string Sid{get;set;}
    public string DateCreated{get;set;}
    public string DateUpdated{get;set;}
    public string CallSegmentSid{get;set;}
    public string AccountSid{get;set;}
    public string Called{get;set;}
    public string Caller{get;set;}
    public string PhoneNumberSid{get;set;}
    public string Status{get;set;}
    public string StartTime{get;set;}
    public string EndTime{get;set;}
    public string Duration{get;set;}
    public string Price{get;set;}
    public string Flags{get;set;}
    public string Annotation{get;set;}
}
public CallsXmlParser(){

}
public CallsXmlParser(string data){
    XmlStreamReader xsr = new XmlStreamReader(data);
    listRecords = parse(xsr);
}
public Call[] parse(XmlStreamReader reader) {
    Call[] members = new Call[0];
    while(reader.hasNext()) {
        if (reader.getEventType() == XmlTag.START_ELEMENT) {
           if ('Call' == reader.getLocalName()) {                 
                Call member = parseMember(reader);
                members.add(member);
            }
         }
        reader.next();
    }
    return members;
}
//Parsing Each Call Tag and its nested tags
public Call parseMember(XmlStreamReader reader){
    Call callObject = new Call();
    while(reader.hasNext()) {

       if ('Call' == reader.getLocalName() && reader.getEventType() == XmlTag.END_ELEMENT) {
           break;
        }
        else if('Sid' == reader.getLocalName() && reader.getEventType() == XmlTag.START_ELEMENT){
          reader.next();                   
          if(reader.getEventType() == XmlTag.CHARACTERS) { 
            callObject.Sid = reader.getText(); 
          }
        }else if('DateCreated' == reader.getLocalName() && reader.getEventType() == XmlTag.START_ELEMENT){
          reader.next();                   
          if(reader.getEventType() == XmlTag.CHARACTERS) { 
            callObject.DateCreated= reader.getText(); 
          }
        }else if('DateUpdated' == reader.getLocalName() && reader.getEventType() == XmlTag.START_ELEMENT){
          reader.next();                   
          if(reader.getEventType() == XmlTag.CHARACTERS) { 
            callObject.DateUpdated= reader.getText(); 
          }
        }else if('CallSegmentSid' == reader.getLocalName() && reader.getEventType() == XmlTag.START_ELEMENT){
          reader.next();                   
          if(reader.getEventType() == XmlTag.CHARACTERS) { 
            callObject.CallSegmentSid= reader.getText(); 
          }
        }else if('AccountSid' == reader.getLocalName() && reader.getEventType() == XmlTag.START_ELEMENT){
          reader.next();                   
          if(reader.getEventType() == XmlTag.CHARACTERS) { 
            callObject.AccountSid= reader.getText(); 
          }
        }else if('Called' == reader.getLocalName() && reader.getEventType() == XmlTag.START_ELEMENT){
          reader.next();                   
          if(reader.getEventType() == XmlTag.CHARACTERS) { 
            callObject.Called= reader.getText(); 
          }
        }else if('Caller' == reader.getLocalName() && reader.getEventType() == XmlTag.START_ELEMENT){
          reader.next();                   
          if(reader.getEventType() == XmlTag.CHARACTERS) { 
            callObject.Caller= reader.getText(); 
          }
        }else if('PhoneNumberSid' == reader.getLocalName() && reader.getEventType() == XmlTag.START_ELEMENT){
          reader.next();                   
          if(reader.getEventType() == XmlTag.CHARACTERS) { 
            callObject.PhoneNumberSid= reader.getText(); 
          }
        }else if('Status' == reader.getLocalName() && reader.getEventType() == XmlTag.START_ELEMENT){
          reader.next();                   
          if(reader.getEventType() == XmlTag.CHARACTERS) { 
            callObject.Status = reader.getText(); 
          }
        }else if('StartTime' == reader.getLocalName() && reader.getEventType() == XmlTag.START_ELEMENT){
          reader.next();                   
          if(reader.getEventType() == XmlTag.CHARACTERS) { 
            callObject.StartTime = reader.getText(); 
          }
        }else if('EndTime' == reader.getLocalName() && reader.getEventType() == XmlTag.START_ELEMENT){
          reader.next();                   
          if(reader.getEventType() == XmlTag.CHARACTERS) { 
            callObject.EndTime = reader.getText(); 
          }
        }else if('Duration' == reader.getLocalName() && reader.getEventType() == XmlTag.START_ELEMENT){
          reader.next();                   
          if(reader.getEventType() == XmlTag.CHARACTERS) { 
            callObject.Duration = reader.getText(); 
          }
        }else if('Price' == reader.getLocalName() && reader.getEventType() == XmlTag.START_ELEMENT){
          reader.next();                   
          if(reader.getEventType() == XmlTag.CHARACTERS) { 
            callObject.Price = reader.getText(); 
          }
        }else if('Flags' == reader.getLocalName() && reader.getEventType() == XmlTag.START_ELEMENT){
          reader.next();                   
          if(reader.getEventType() == XmlTag.CHARACTERS) { 
            callObject.Flags = reader.getText(); 
          }
        }else if('Annotation' == reader.getLocalName() && reader.getEventType() == XmlTag.START_ELEMENT){
          reader.next();                   
          if(reader.getEventType() == XmlTag.CHARACTERS) { 
            callObject.Annotation = reader.getText(); 
          }
        }

       reader.next();
   }
   return callObject;
} 
}

Мой базовый класс insertLead выглядит следующим образом:

public with sharing class insertLead {
Lead1 = new Lead(Phone='TwilioRestResponse.GetResponseText');
}

Мне нужно прочитать номер телефона и имя CallerID из классов TwilioRestResponse или CallXmlParser и вставить в соответствующие поля в новом отведении. Каков подходящий синтаксис для ссылки на CallObject.PhoneNumberSid в моем новом сообщении? Или лучше разобрать TwilioRestResponse? Если да, то как мне выбрать только номер телефона и имя CallerID из GetResponseText?

Еще раз спасибо, Sid

Ответы [ 2 ]

4 голосов
/ 15 декабря 2010

Ответ обновлен, пожалуйста, прокрутите вниз

public class SidTest {

    //  1. How to create a new Lead programatically on Force.com (in Apex)
    /* This method is marked as test method, meaning that you can use it to run tests but in the end no data will be saved
        (transaction rollback). You'll need similar code in a class that intercepts messages from Twilio.
    */
    public static testMethod void insertLead(){
        Lead l = new Lead(FirstName='Test', LastName='Lead', Email='example@example.com', Company='test', NumberofEmployees=7);
        insert l;

        // 2. How do I test the TwilioForce components, especially those I've changed to reflect my client's Twilio phone number and token?
    /*  Not sure what do you mean, but most likely by writing test classes like this one and checking their test code coverage.
        See also http://stackoverflow.com/questions/4372202/how-to-unit-test-works-in-salesforce/4381941
        Below sample test that checks if our insert above succeeded.
        You can run it from Eclipse (preferred) or Salesforce GUI in Setup->Develop->Apex classes.
    */
        Lead[] leads = [SELECT Name, Email FROM Lead WHERE Name = 'Test Lead'];

        System.debug(leads);    // if you want to see results in detailed debug log
        System.assertEquals(1, leads.size());
        System.assertEquals('example@example.com', leads[0].Email);
    }
}

Вот результат, когда вы запустите его в Eclipse: http://dl.dropbox.com/u/709568/stackoverflow/Sid.png

Что касается последнего вопроса: когда вы будете довольны функциональностью, протестированной в вашей Developer Edition, вы должны попросить клиента предоставить вам доступ к «Песочнице» его организации. Вы можете создать в Eclipse новый проект, указывающий на эту изолированную программную среду, и просто создать в нем все классы, выполнить тесты с подмножеством реальных данных и т. Д. Наконец, вы или кто-либо со стороны клиента выполните развертывание в «рабочей» среде, где такие вещи, как код охват в автоматизированных тестах начнет иметь значение.

В качестве альтернативы вы можете создать пакет с вашим кодом и продавать его в AppExchange, как плагин для Salesforce, который любой может загрузить в свою организацию. Вы можете взимать плату за это, конечно. Но сейчас это выглядит как слишком большой прыжок ...

Надеюсь, это поможет вам начать.


Обновление: Вот быстрый и грязный класс, основанный на TestCallsXmlParser, который включен в пакет кода, который вы используете:

public class TestCallsXmlParser{
    @isTest
    public static void TestCallsXmlParserMethod1(){
        CallsXmlParser callxml = new CallsXmlParser();
        String xmlData = '<TwilioResponse> <Calls page=\"0\" numpages=\"1\" pagesize=\"50\" total=\"38\" start=\"0\" end=\"37\"> <Call> <Sid>CA42ed11f93dc08b952027ffbc406d0868</Sid> <DateCreated>Sat, 07 Feb 2009 13:15:19 -0800</DateCreated><DateUpdated>Sat, 07 Feb 2009 13:15:19 -0800</DateUpdated><CallSegmentSid/>';
        xmlData = xmlData + '<AccountSid>AC309475e5fede1b49e100272a8640f438</AccountSid><Called>4159633717</Called><Caller>4156767925</Caller><PhoneNumberSid>PN01234567890123456789012345678900</PhoneNumberSid><Status>2</Status><StartTime>Thu, 03 Apr 2008 04:36:33 -0400</StartTime><EndTime>Thu, 03 Apr 2008 04:36:47 -0400</EndTime>';
        xmlData = xmlData + '<Duration>14</Duration><Price/><Flags>1</Flags></Call>';
        xmlData = xmlData + '<Call><Sid>CA751e8fa0a0105cf26a0d7a9775fb4bfb</Sid><DateCreated>Sat, 07 Feb 2009 13:15:19 -0800</DateCreated><DateUpdated>Sat, 07 Feb 2009 13:15:19 -0800</DateUpdated><CallSegmentSid/>';
        xmlData = xmlData + '<AccountSid>AC309475e5fede1b49e100272a8640f438</AccountSid><Called>2064287985</Called><Caller>4156767925</Caller><PhoneNumberSid>PNd59c2ba27ef48264773edb90476d1674</PhoneNumberSid><Status>2</Status>';
        xmlData = xmlData + '<StartTime>Thu, 03 Apr 2008 01:37:05 -0400</StartTime><EndTime>Thu, 03 Apr 2008 01:37:40 -0400</EndTime><Duration>35</Duration><Price/> <Flags>1</Flags> </Call></Calls></TwilioResponse> ';
        CallsXmlParser callxml1 = new CallsXmlParser(xmlData);

        // eyescream's modification starts here

        // list to store our leads and bulk save them in blocks up to 100 records at 1 insert
        List<Lead> leads = new List<Lead>();

        for(CallsXmlParser.Call c : callxml1.listRecords) {
            System.debug('2 new Leads will be created from phone numbers: ' + c.Caller + ', ' + c.Called);
            leads.add(new Lead(MobilePhone = c.Caller, Company='x', LastName='x')); // Company & Last Name are mandatory fields
            leads.add(new Lead(MobilePhone = c.Called, Company='y', LastName='y')); // without them insert will fail.

            if(leads.size() == 100) { // 100 is the limit of records saved at once. Inserting in batches speeds up execution.
                insert leads;
                leads.clear();
            }
        }

        // If we have any leftovers, we'll insert them too.
        if(leads.size() > 0) {
            insert leads;
            leads.clear();
        }
    }
}

Конечно, вы можете улучшить его, проверить наличие дубликатов, заполнить реальными именами и т. Д. ... но это примерно то, как вы можете использовать проанализированные результаты. Я не думаю, что анализ XML сам по себе был бы хорошим вариантом ... Ваш вопрос предполагает, что в XML будет добавлено больше полей (или существующие будут использоваться для хранения различных данных), но, вероятно, вы сможете расширить парсер соответственно.

0 голосов
/ 26 июля 2013

Если у кого-то есть проблемы с развертыванием библиотеки twilio, здесь приведены подробные сведения, которые выполняют большинство задач. Как-то, если бы это могло помочь http://redcurrantscloud.blogspot.in/

Спасибо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...