如何在Salesforce中创建一个新的铅使用TwilioForce APEX图书馆

问题描述:

早安所有,如何在Salesforce中创建一个新的铅使用TwilioForce APEX图书馆

首先,在Force.com IDE和Salesforce对我来说是一个新的技能。我试图利用TwilioForce APEX Library:https://www.twilio.com/docs/salesforce/install

为我客户的Twilio帐户上的每个来电创建新的Salesforce潜在客户。我已经尽可能在Eclipse中创建一个新的Force.com项目,将Twilioforce组件,类和页面复制到项目中,但需要一些关于如何编写逻辑以创建主导的指导。

我有问题: 1.您是否可以提供指向参考资料的链接,演示如何以编程方式在Salesforce中创建新的潜在客户? 2.我如何测试TwilioForce组件,尤其是那些已更改为反映我客户的Twilio电话号码和令牌的组件?这些可从Eclipse的Force.com项目中调用,还是必须从我的developer.org帐户调用? 3.一旦我找出如何从传入的Twilio调用中完成上述创建,如何将我创建的代码库部署到我的客户端?

感谢, 希德

编辑: EYESCREAM,你的样品是一个巨大的帮助。下面是与TwilioForce代码库传来TwilioRestResponse类:

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'); 
} 

我需要从TwilioRestResponse或CallXmlParser类中读入电话号码和CallerID名称,并插入新Lead中的相应字段。 在我的新潜在客户中引用CallObject.PhoneNumberSid的适当语法是什么?或者,解析出TwilioRestResponse是否更好?如果是这样,我将如何从GetResponseText中选择电话号码和CallerID名称?再次

感谢, 希德

回答更新,请向下滚动

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='[email protected]', 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://*.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('[email protected]', leads[0].Email); 
    } 
} 

这里的时候,你会在Eclipse中运行它的结果:http://dl.dropbox.com/u/709568/*/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>PN</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

不幸的是,我得到关于(CallsXmlParser.Call C:callxml1.ListRecords)行编译错误{ 陈述期待右花括号 – SidC 2010-12-16 21:36:03

+0

我刚刚创建了我的组织从Twilio库2类:TestCallsXmlParser和CallsXmlParser。无论是在最新版本的trunk中,它运行都没有问题......也许你在类名中犯了一个错字?内部类是否称为公共类?也许你的eclipse/force.com插件的版本是旧的?我在插件版本Summer '10(19.0.0),我的完整代码库在这里供参考:http://dl.dropbox.com/u/709568/*/Sid%20-%20my%20Dev%20Edition。 zip – eyescream 2010-12-17 06:11:17

+0

我的不好:)我在文件的最后缺少了一个右括号。现在已经创建好了,我该如何在我的developerforce帐户上运行它?非常感谢!! – SidC 2010-12-17 17:56:16

如果有人在部署twilio库时遇到问题,可以在这里提供好的细节,这些细节完成大部分任务。一些如何,如果它可以帮助http://redcurrantscloud.blogspot.in/

谢谢。