本系列属作者原创,请尊重作者的劳动成果,转载请注明出处 , 谢谢!
我的博客地址:http://blog.csdn.net/qicong7
此系列博文目录:
如何申请微信公众帐号
微信公众账号消息那些事儿
服务号实现自定义菜单
微信公众账号开发入门(原理)
微信公众账号开发:URL 和 Tocken
微信公众账号开发:消息原理
微信公众账号开发:消息设计、源码
微信公众账号开发:菜单原理、设计、源码
微信公众账号开发:JS接口
微信公众账号开发:Auth2.0认证原理、设计、源码
上篇博文主要介绍了微信公众账号消息的原理,如果你已经详细阅读了上篇博文,我想对于公众账号开发者的消息设计,你心中已经有个大概了;
所以不啰嗦了,直奔主题吧,我用的开发语言是python(是我使用众多语言中最棒的,没有之一),下面是逻辑流程图以及源码(源码只贴主要的部分);
消息设计流程图
这个流程图是很简单的了,微信公众账号的消息本身就不复杂,说的简单点就是:输入、处理、输出;
源码
@csrf_exempt def wx_valid(request):#提供给微信公众平台的url,微信公众平台请求url时,会执行此方法 ‘‘‘微信开发者验证,是GET请求;GET 和 POST 区分是认证还是发送消息(发送消息的时候是POST)‘‘‘ if request.method == ‘GET‘: tocken=‘zainanjing6tocken‘#提供给微信公众平台的tocken,可以保持在数据库、文件或者直接硬编码到代码中; if tocken: timestamp = request.GET[‘timestamp‘] nonce = request.GET[‘nonce‘] signature = request.GET[‘signature‘] echostr = request.GET[‘echostr‘] arr = [tocken,timestamp,nonce] arr.sort() data = ‘‘ for s in arr : data += s sha1 = hashlib.sha1() #或hashlib.md5() sha1.update(data) _signature = sha1.hexdigest() #生成40位(sha1)或32位(md5)的十六进制字符串 if _signature == signature : return HttpResponse(echostr)#返回 echostr return HttpResponse(‘error‘)#返回 error else:#POST请求,也就是微信公众平台转发用户消息给开发者服务器 ‘‘‘ 如果是POST 请求,那么表示的是用户发送消息,或者点击菜单发送事件消息; 通过同一个URL进行处理;只是请求的方法不一样, ‘‘‘ xml = request.POST.keys()[0]#post的数据,其他语言取法可能有不同,django是这么取的,也可能有其他方法?有朋友知道的可以分享下 if xml: q_obj = get_request_obj(xml.encode(‘UTF-8‘))#获取请求对象dict rep_xml = get_response_obj(q_obj)#根据account分发处理业务 if rep_xml: return HttpResponse(rep_xml) return HttpResponse(‘error‘) ‘‘‘ 转换请求的xml数据成 req_obj (dict类型) XmlUtil类,没有贴出源代码,很简单,就是解析xml对象 ‘‘‘ def get_request_obj(xml): q_obj = {} root = XmlUtil.getRootNode(xml) msgType = XmlUtil.getSingleNodeValue(root,‘MsgType‘) if msgType == MsgType.TEXT: q_obj[‘Content‘] = XmlUtil.getSingleNodeValue(root,‘Content‘) elif msgType == MsgType.IMAGE: q_obj[‘PicUrl‘] = XmlUtil.getSingleNodeValue(root,‘PicUrl‘) elif msgType == MsgType.LOCATION: q_obj[‘Location_X‘] = XmlUtil.getSingleNodeValue(root,‘Location_X‘) q_obj[‘Location_Y‘] = XmlUtil.getSingleNodeValue(root,‘Location_Y‘) q_obj[‘Scale‘] = XmlUtil.getSingleNodeValue(root,‘Scale‘) q_obj[‘Label‘] = XmlUtil.getSingleNodeValue(root,‘Label‘) else: q_obj[‘Event‘] = XmlUtil.getSingleNodeValue(root,‘Event‘) q_obj[‘EventKey‘] = XmlUtil.getSingleNodeValue(root,‘EventKey‘) q_obj[‘ToUserName‘] = XmlUtil.getSingleNodeValue(root,‘ToUserName‘) q_obj[‘FromUserName‘] = XmlUtil.getSingleNodeValue(root,‘FromUserName‘) q_obj[‘CreateTime‘] = XmlUtil.getSingleNodeValue(root,‘CreateTime‘) q_obj[‘MsgType‘] = XmlUtil.getSingleNodeValue(root,‘MsgType‘) q_obj[‘MsgId‘] = XmlUtil.getSingleNodeValue(root,‘MsgId‘) return q_obj ‘‘‘ 转换rep_obj 成发送的xml的形式 ‘‘‘ def get_response_obj(q_obj): msg_type = q_obj[‘MsgType‘] p_obj = None ‘‘‘ 根据自己的业务处理,获取对象 msg_obj , 封装的 msg_obj 如果是文本消息,需要有 content,createTime 等; 如果是图文消息,我们使用的是list,如果size=1,单图文消息;如果size>1 ,多图文消息 其他类型,不多做解释,和文本类似 ‘‘‘ if msg_obj: if msg_obj[‘MsgType‘] == ‘text‘:#文本消息 return get_response_text(q_obj,p_obj) elif msg_obj[‘MsgType‘] == ‘news‘:#图文消息 return get_response_news(q_obj,p_obj) return None ‘‘‘ 获取response_text ‘‘‘ def get_response_text(q_obj,text): rep_xml = u‘‘‘<xml> <ToUserName><![CDATA[%s]]></ToUserName> <FromUserName><![CDATA[%s]]></FromUserName> <CreateTime>%s</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[%s]]></Content> </xml>‘‘‘ %(q_obj[‘FromUserName‘],q_obj[‘ToUserName‘],TimeUtil.getIntTime(),text.content) return rep_xml.encode(‘UTF-8‘) ‘‘‘ 回复新闻消息 ‘‘‘ def get_response_news(q_obj,news_list): rep_xml = u‘‘‘<xml> <ToUserName><![CDATA[%s]]></ToUserName> <FromUserName><![CDATA[%s]]></FromUserName> <CreateTime>%s</CreateTime> <MsgType><![CDATA[news]]></MsgType> <ArticleCount>%d</ArticleCount> <Articles>‘‘‘ %(q_obj[‘FromUserName‘],q_obj[‘ToUserName‘],TimeUtil.getIntTime(),len(news_list)) for new in news_list: rep_xml += u‘‘‘<item> <Title><![CDATA[%s]]></Title> <Description><![CDATA[%s]]></Description> <PicUrl><![CDATA[%s]]></PicUrl> <Url><![CDATA[%s]]></Url> </item>‘‘‘ %(new.title,new.brief,new.picUrl,new.url)#这里使用简介 rep_xml += ‘</Articles></xml>‘ return rep_xml.encode(‘UTF-8‘)
代码中:
@csrf_exempt
def wx_valid(request):
和URL 、Tocken 设计那篇博文中用的是同一个方法,也就是提供给微信公众平台服务器的URL 对应的方法,只是请求的方式不一样,URL验证的时候是 GET 方法,发送消息的时候是POST 方法;详细情况请看代码注释;
这篇博文就到此结束了,文字不多,对应开发人员来说,有图、有源码就足矣...
我们下篇就说说菜单设计了...