在开发微信公众号平台时,若上层或自己要求实现自动化的消息回复模块功能测试,则需要用代码模拟用户向微信公众号发消息,具体的实现是利用python的urllib库往对应的url发送post消息,再接受redirect或render后的结果,对其进行解析即可。
微信服务器接受用户输入后,向第三方发送的数据为XML格式,详情可见微信公众平台-接受消息-接送普通消息。
根据官方文档的说明,我们可以构造相应的获取XML格式文本消息和菜单点击事件数据的函数。若需要修改发送的其他信息,可以自行修改接口。
# 获取文本消息数据,data为发送的文本消息,open_id为用户的open_id
def get_message_text(data, open_id='1'):
result = b'''<xml><ToUserName><![CDATA[gh_4d853060485f]]></ToUserName>
<FromUserName><![CDATA[''' + open_id.encode() + b''']]></FromUserName>
<CreateTime>1508031926</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[''' + data.encode() + b''']]></Content>
<MsgId>6476947803910477524</MsgId>
</xml>'''
return result
# 获取菜单点击事件数据,event_key为该菜单对应的EventKey,open_id为用户的open_id
def get_message_event_click(event_key, open_id='1'):
result = b'''<xml><ToUserName><![CDATA[gh_4d853060485f]]></ToUserName>
<FromUserName><![CDATA[''' + open_id.encode() + b''']]></FromUserName>
<CreateTime>1508031926</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[CLICK]]></Event>
<EventKey><![CDATA[''' + event_key.encode() + b''']]></EventKey>
<MsgId>6476947803910477524</MsgId>
</xml>'''
return result
获得要发送的数据后,需要向自己的服务器发出text/xml类型的post请求,其中url为要测试的服务器地址+/wechat?access_token=自己的access_token,关于access_token,下面使用框架已封装好的函数,若你的框架没有该接口,实现方式详见我的另一篇文章:Python3: Django开发微信公众平台功能测试之获取access_token。
首先,导入函数用到的python库。
import urllib.request
然后,实现发送消息的函数。
# 向自己的服务器发送XML数据,url_local为服务器地址,data为XML二进制数据
def send_message(url_local, data):
lib = CustomWeChatView.lib
url = url_local + '/wechat?access_token=%s' % (
lib.get_wechat_access_token()
)
req = urllib.request.Request(
url=url, data=data, headers={'Content-Type':'text/xml'}
)
res_data = urllib.request.urlopen(req)
res = res_data.read().decode()
return res
有了这三个函数,就能轻松的模拟微信服务器向自己服务器发消息并得到结果的过程了,具体使用方式如下:
from django.contrib.staticfiles.testing import StaticLiveServerTestCase
class CalculatorHandlerTest(StaticLiveServerTestCase):
def test_express_right(self):
# 向有计算功能的服务器发送表达式
result = send_message(self.live_server_url, get_message_text('99 * 99 + 1'))
# 返回的数据为XML类型,结果只是其中的一部分
self.assertIn("9802", result)
菜单点击事件采用以下发送方式:
result = send_message(self.live_server_url, get_message_event_click('TEST_SEND_MENU_CLICK'))