Salesforce Force.com Site 集成微信公众平台 (二) 文本消息处理

我们在上一篇 Salesforce Force.com Site 集成微信公众平台 (一) 后台配置 给大家介绍了如何通过 Salesforce 中的 Force.com Site 来连接微信公众平台。这次我们来介绍 Salesforce 怎样接收从微信公众平台发送过来的文本消息,同时做一个简单的自动回复。

首先我们来介绍一下信息的发送流程。当用户向微信发送信息时,微信公众平台服务器接收到消息后,检查当前公众帐号是否开启了开发者模式。如果开发者模式打开了,微信服务器会以 POST 的方式将 XML 数据包发送到我们在微信后台配置的 URL 上,也就是 Salesforce 系统中,这样我们就可以在 Apex 代码中处理这些消息了。

微信的消息类型有文本信息、图片信息、语音信息、视频信息、地理位置信息和链接信息,下面介绍如果处理最基本的文本消息。

文本消息的XML数据包

<xml>  
 <ToUserName><![CDATA[toUser]]></ToUserName>
 <FromUserName><![CDATA[fromUser]]></FromUserName> 
 <CreateTime>1348831860</CreateTime>
 <MsgType><![CDATA[text]]></MsgType>
 <Content><![CDATA[this is a test]]></Content>
 <MsgId>1234567890123456</MsgId>
</xml>  

数据包结构说明

Apex 中处理文本消息

分析了上面的数据结果后,在 WeChatRestController 类中添加 doPost 方法来处理微信的请求。

@HttpPost
global static void doPost()  
{
    // 存储XML各节点数据变量
    String toUserName = '';
    String fromUserName = '';
    String msgType = '';
    String content = '';

    // 获取XML数据包
    RestRequest req = RestContext.request;
    RestResponse res = RestContext.response;
    string strMsg = req.requestBody.toString();

    XmlStreamReader reader = new XmlStreamReader(strMsg);
    // 解析XML数据包,Force.com这块的处理能力并不强,简单的结构也需要较多代码来解析
     while(reader.hasNext())
     {
        if(parseXML(reader, 'ToUserName') != null)
        {
            toUserName = parseXML(reader, 'ToUserName');
        } 
        else if(parseXML(reader, 'FromUserName') != null)
        {
            fromUserName = parseXML(reader, 'FromUserName');
        }
        else if(parseXML(reader, 'MsgType') != null)
        {
            msgType = parseXML(reader, 'MsgType');
        }
        else if(parseXML(reader, 'Content') != null)
        {
            content = parseXML(reader, 'Content');
            System.debug('@@@' + reader.getText());
        }
        reader.next();
    }
}

private static String parseXML(XmlStreamReader reader, String node)  
{
    if(reader.getLocalName() == node)
    {
        reader.next();
        if(String.isNotBlank(reader.getText()))
        {
            return reader.getText();   
        }
    }
    return null;
}

查看测试结果

为了更容易看到结果,我在上面的代码中加入了 System.debug 方法。打开 Debug Logs (Setup->Monitor->Logs->Debug Logs) 页面,添加一个要跟踪的 User, 需要找到上一篇中创建 Site 对应的 Guest User,并设置跟踪时间。如下图所示:

在微信客户端输入了 “你是在发信息到Salesforce吗?” 测试消息内容。发送完成后,在 Salesfore 的打开 Debug log, 在 Log 中我们可以看到从微信端发过来的消息,说明接收成功。Debug Log 如下图所示:

自动回复信息

当我们成功接收消息后,就可以针对消息做相应的逻辑处理了,这里我们做一个简单的自动回复。

回复的数据也是XML结构,和发送过来的文本消息基本一致。添加了一个新的方法,代码如下:

private static void replyMsg(RestResponse res, String fromUserName, String toUserName, String rtnMsg)  
{
    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[]{fromUserName, toUserName, rtnMsg};
    String formattedReplyMSG = String.format(replyMSG, arguments);
    res.addHeader('Content-Type', 'text/plain');
    res.responseBody = Blob.valueOf(formattedReplyMSG);
}

之后添加 replyMsg(res, fromUserName, toUserName, 'Yes') 这行代码到我们的 doPost 方法中。

else if(parseXML(reader, 'Content') != null)  
{
    content = parseXML(reader, 'Content');
    System.debug('@@@' + content);
    // 自动回复 Yes 给微信用户
    replyMsg(res, fromUserName, toUserName, 'Yes');
}

当再次在微信客户端发送 “你是在发信息到Salesforce吗?” 的时候,系统将自动回复"Yes"。如下图如示:

到此文本消息已经讲完了,后续我们将继续推出其它类型的信息处理。希望大家继续关注。

Samba

Read more posts by this author.