这一篇我们以图文消息为例,来给大家讲解在 Salesforce 中是如何发送和接收的。
首先我们在 Salesforce 中创建一个类用来保存用户发送过来的消息。这个类我们叫它 ReceiveMsg ,代码如下
public class ReceiveMsg
{
public String toUserName;
public String fromUserName;
public String msgType;
public String picURL;
public String mediaID;
public String locationX;
public String locationY;
public String URL;
public String content;
public String event;
public String eventKey;
public String recognition;
public ReceiveMsg(String tUN, String fUN, String mT, String pU, String mI, String lX, String lY, String u, String c, String e, String eK, String r)
{
this.toUserName = tUN;
this.fromUserName = fUN;
this.msgType = mT;
this.picURL = pU;
this.mediaID = mI;
this.locationX = lX;
this.locationY = lY;
this.URL = u;
this.content = c;
this.event = e;
this.eventKey = eK;
this.recognition = r;
}
}
这个类中有12个属性,包含了绝大部分消息类型的字段信息。
接下来我们创建一个回复图文消息的类,这个类我们叫它 ReplyMsg ,代码如下
public class ReplyMsg
{
public String title;
public String description;
public String picUrl;
public String url;
public ReplyMsg(String t, String d, String p, String u)
{
this.title = t;
this.description = d;
this.picUrl = p;
this.url = u;
}
}
这个类中定义了一条详细的新闻信息。
接下来我们重新构造 doPost 方法,并使它能够解析任何类型的 XML 内容。修改后代码如下
@HttpPost
global static void doPost()
{
//Receive message from user;
RestRequest req = RestContext.request;
RestResponse res = RestContext.response;
string strMsg = req.requestBody.toString();
XmlStreamReader reader = new XmlStreamReader(strMsg);
String toUserName = '';
String fromUserName = '';
String msgType = '';
String picURL = '';
String mediaID = '';
String locationX = '';
String locationY = '';
String URL = '';
String content = '';
String msgID = '';
String event = '';
String eventKey = '';
String recognition = '';
while(reader.hasNext())
{
if(reader.getLocalName() == 'ToUserName')
{
reader.next();
if(String.isNotBlank(reader.getText()))
{
toUserName = reader.getText();
}
}
else if(reader.getLocalName() == 'FromUserName')
{
reader.next();
if(String.isNotBlank(reader.getText()))
{
fromUserName = reader.getText();
}
}
else if(reader.getLocalName() == 'MsgType')
{
reader.next();
if(String.isNotBlank(reader.getText()))
{
msgType = reader.getText();
}
}
else if(reader.getLocalName() == 'PicURL')
{
reader.next();
if(String.isNotBlank(reader.getText()))
{
picURL = reader.getText();
}
}
else if(reader.getLocalName() == 'MediaId')
{
reader.next();
if(String.isNotBlank(reader.getText()))
{
mediaID = reader.getText();
}
}
else if(reader.getLocalName() == 'Location_X')
{
reader.next();
if(String.isNotBlank(reader.getText()))
{
locationX = reader.getText();
}
}
else if(reader.getLocalName() == 'Location_Y')
{
reader.next();
if(String.isNotBlank(reader.getText()))
{
locationY = reader.getText();
}
}
else if(reader.getLocalName() == 'Url')
{
reader.next();
if(String.isNotBlank(reader.getText()))
{
URL = reader.getText();
}
}
else if(reader.getLocalName() == 'MsgId')
{
reader.next();
if(String.isNotBlank(reader.getText()))
{
msgID = reader.getText();
}
}
else if(reader.getLocalName() == 'Content')
{
reader.next();
if(String.isNotBlank(reader.getText()))
{
content = reader.getText();
}
}
else if(reader.getLocalName() == 'Event')
{
reader.next();
if(String.isNotBlank(reader.getText()))
{
event = reader.getText();
}
}
else if(reader.getLocalName() == 'EventKey')
{
reader.next();
if(String.isNotBlank(reader.getText()))
{
eventKey = reader.getText();
}
}
else if(reader.getLocalName() == 'Recognition')
{
reader.next();
if(String.isNotBlank(reader.getText()))
{
recognition = reader.getText();
}
}
reader.next();
}
ReceiveMsg receiveMsg = new ReceiveMsg(toUserName, fromUserName, msgType, picURL, mediaID, locationX, locationY, URL, content, event, eventKey, recognition );
}
该方法里,我们对所有微信消息类型的 XML 进行了解析,并通过解析回来的值初始化了 ReceiveMsg 对象,接下来,我们将通过传递这个对象调用不同的方法完成各种任务。最后我们在 doPost 方法的结尾加上以下代码:
String rtnMsg = '';
//回复消息
if(msgType.equals('text')){
rtnMsg = handleText(receiveMsg);
}
RestContext.response.addHeader('Content-Type', 'text/plain');
RestContext.response.responseBody = Blob.valueOf(rtnMsg);
这段代码里首先定义了一个返回 XML 的 String 字符串,接着判断如果用户发来的消息类型是文本类型,则调用一个 handleText 的方法来处理回复信息,这里传递给 handleText 方法的对象正是我们前面定义的 ReceiveMsg 对象,在这个方法中我们可以定制我们需要的功能,随后通过 RestContext 即可将 XML 消息返回给微信,最后返回给发送消息的用户。
接下来我们对 handleText 方法进行详解。代码如下
private static String handleText(ReceiveMsg msg)
{
String keyword = msg.content;
String strReply;
String strResult;
if(keyword.equals('文本'))
{
strReply = '这是个文本消息';
strResult = composeTextReply(msg, strReply);
}
else if(keyword.equals('图文'))
{
ReplyMsg news = new ReplyMsg('Meginfo Blog', 'Salesforce Force.com Site 集成微信公众平台 (四) 图文消息处理', 'https://secure.sfdcstatic.com/common/assets/img/logo-tag-company.png', 'http://blog.meginfo.com/');
List<ReplyMsg> newsList = new List<ReplyMsg>();
newsList.add(news);
strResult = composeNewsReply(msg, newsList);
}
return strResult;
}
首先我们来看第一个 if 语句,如果用户发送过来的信息是"文本",将满足这个条件,并把 strReply 的值传到 composeTextReply 方法中完成XML构建。如果用户发过来的信息是"图文",那么将进入else if语句,并返回给用户单图文信息,这里先构造了一个 ReplyMsg 数组,当然数组里只有一个 ReplyMsg 对象,将这个数组交给 composeNewsReply 来完成最终的XML ;下面是 composeTextReply 和 composeNewsReply 方法的代码。
private static String composeTextReply(ReceiveMsg msg, String strReply)
{
Datetime dt = System.now();
String returnDT = dt.format('EEEE, MMMM d, yyyy');
String replyMSG = '<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>' + returnDT + '</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[{2}]]></Content></xml>';
String[] arguments = new String[]{msg.fromUserName, msg.toUserName, strReply};
return String.format(replyMSG, arguments);
}
private static String composeNewsReply(ReceiveMsg msg, List<ReplyMsg> newsList)
{
String strNews = '';
String newsTpl = '<item><Title><![CDATA[{0}]]></Title><Description><![CDATA[{1}]]></Description><PicUrl><![CDATA[{2}]]></PicUrl><Url><![CDATA[{3}]]></Url></item>';
for(ReplyMsg news : newsList){
String[] arguments = new String[]{news.title, news.description, news.picUrl, news.url};
strNews += String.format(newsTpl, arguments);
}
String strTmp = '<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>1234567890</CreateTime><MsgType><![CDATA[news]]></MsgType><ArticleCount><![CDATA[{2}]]></ArticleCount><Articles>' + strNews + '</Articles></xml>';
String[] arguments = new String[]{msg.fromUserName, msg.toUserName, String.valueOf(newsList.size())};
String results = String.format(strTmp, arguments);
return results;
}
演示结果如下