网站地图    收藏   

主页 > 后端 > 微信开发 >

大齐玩转微信公众账号系列(七): 微信公众账

来源:自学PHP网    时间:2015-04-14 12:58 作者: 阅读:

[导读] 此系列博文目录:如何申请微信公众帐号微信公众账号消息那些事儿服务号实现自定义菜单微信公众账号开发入门(原理)微信公众账号开发:URL 和 Tocken微信公众账号开发:消息原理微信...

 此系列博文目录:

如何申请微信公众帐号

微信公众账号消息那些事儿

服务号实现自定义菜单

微信公众账号开发入门(原理)

微信公众账号开发: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 方法;详细情况请看代码注释;

 

这篇博文就到此结束了,文字不多,对应开发人员来说,有图、有源码就足矣...

我们下篇就说说菜单设计了...

自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习

京ICP备14009008号-1@版权所有www.zixuephp.com

网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com

添加评论