• 订阅号服务开发03-被动消息应答


    @

    前言

    在进行微信公众号服务开发,最重要的文档就是官方的技术文档,开发之前多阅读几遍!

    [info]微信公众平台技术文档:https://mp.weixin.qq.com/wiki

    何为被动消息应答?

    用户在微信公众号中输入内容或点击菜单后,开发者服务再根据接收到的消息进行应答,这种类型便是被动消息应答。

    被动消息类型

    先上一段代码,用于开发者服务端接收被动消息,打印出消息的类型。
    views.py

    from django.http import HttpResponse
    from django.views.decorators.csrf import csrf_exempt
    from wechatpy import parse_message
    from wechatpy.exceptions import InvalidSignatureException
    from wechatpy.utils import check_signature
    
    @csrf_exempt
    def wechat(request):
        # GET 方式用于微信公众平台绑定验证
        if request.method == 'GET':
            signature = request.GET.get('signature', "")
            timestamp = request.GET.get('timestamp', "")
            nonce = request.GET.get('nonce', "")
            echo_str = request.GET.get('echostr', "")
            token = 'MiltonGuan'
            try:
                check_signature(token, signature, timestamp, nonce)
                print("微信签名验证通过!")
            except InvalidSignatureException:
                print("微信签名验证失败!")
                echo_str = '微信签名验证失败'
            return HttpResponse(echo_str)
        # POST 方式用于接受被动消息
        if request.method == 'POST':
            # wechatpy 提供了一个便捷的函数 parse_message 来处理由微信服务器发送过来的 XML 消息并解析生成对应的消息类:
            msg = parse_message(request.body)
            print("开发者服务收到的消息:", msg)
    

    与前面的例子相比,修改的代码只有接收“POST”消息的这一块

    # POST 方式用于接受被动消息
    if request.method == 'POST':
        # wechatpy 提供了一个便捷的函数 parse_message 来处理由微信服务器发送过来的 XML 消息并解析生成对应的消息类:
        msg = parse_message(request.body)
        print("开发者服务收到的消息:", msg)
    

    文本消息 MsgType=="text"

    在公众号中,输入文本消息“测试文本消息”,则可以在pycharm的控制台中打印消息如下

    开发者服务收到的消息: TextMessage(OrderedDict([('ToUserName', 'gh_dd3ad8e3fb33'), ('FromUserName', 'oiQF0tzMZ5Md5HaAlKvrZo9OIGBw'), ('CreateTime', '1557045409'), ('MsgType', 'text'), ('Content', '测试文本消息'), ('MsgId', '22291530543511304')]))
    

    看过官方文档便知,实际上微信服务器向开发者服务器发送过来的是xml格式的内容,如

    <xml> 
     <ToUserName><![CDATA[gh_dd3ad8e3fb33]]></ToUserName>  
    <FromUserName><![CDATA[oiQF0tzMZ5Md5HaAlKvrZo9OIGBw]]></FromUserName>  <CreateTime>1557045409</CreateTime> 
     <MsgType><![CDATA[text]]></MsgType>
      <Content><![CDATA[测试文本消息]]></Content> 
     <MsgId>22291530543511304</MsgId></xml>
    
    
    参数 描述
    ToUserName 开发者微信号
    FromUserName 发送方帐号(一个OpenID)
    CreateTime 消息创建时间 (整型)
    MsgType 消息类型,文本为text
    Content 文本消息内容
    MsgId 消息id,64位整型

    上面例子这里打印的内容,已经被wechatpy 提供的一个便捷的函数 parse_message 将微信服务器发送过来的 XML 消息解析生成了对应的消息类。

    图片消息 MsgType=="image"

    在公众号中,发送一张图片,pycharm控制台输出如下

    开发者服务收到的消息: ImageMessage(OrderedDict([('ToUserName', 'gh_dd3ad8e3fb33'), ('FromUserName', 'oiQF0tzMZ5Md5HaAlKvrZo9OIGBw'), ('CreateTime', '1557046675'), ('MsgType', 'image'), ('PicUrl', 'http://mmbiz.qpic.cn/mmbiz_jpg/1GvjsQCjdzN4FwdiaetpjPyibOIibL6rnnC4dicibbibGh4hv0wO7YK6Yu4Rj2Q7QsZYczIX0jZvyoGianwwVB41ouKNA/0'), ('MsgId', '22291549457593467'), ('MediaId', 'cUlcX98uOYHkyxLf7XJmOkSbliTj2Zcups6mCZlSUF6yq94H_IVX-WFLtxK_1dT9')]))
    

    语音消息 MsgType=="voice"

    在公众号中,发送一段语音,pycharm控制台输出如下

    开发者服务收到的消息: VoiceMessage(OrderedDict([('ToUserName', 'gh_dd3ad8e3fb33'), ('FromUserName', 'oiQF0tzMZ5Md5HaAlKvrZo9OIGBw'), ('CreateTime', '1557046793'), ('MsgType', 'voice'), ('MediaId', 'RQ70i8ItrXzDCAIj4sZoiWjQFBn4a3_i5JlMnzhuaCMkJKnP5vshdz6nlrWCbDNx'), ('Format', 'amr'), ('MsgId', '22291547468076299'), ('Recognition', None)]))
    

    视频消息 MsgType=="video"

    在公众号中,发送一段视频,pycharm控制台输出如下

    开发者服务收到的消息: VideoMessage(OrderedDict([('ToUserName', 'gh_dd3ad8e3fb33'), ('FromUserName', 'oiQF0tzMZ5Md5HaAlKvrZo9OIGBw'), ('CreateTime', '1557046883'), ('MsgType', 'video'), ('MediaId', 'Cpr-ieJ7HH3ZQz9WzbvaCCN14TmF2TonpRRdDXT-TVNIldI2pidNe3r6HNhwOXOP'), ('ThumbMediaId', '2uMNUEopAJ49MLzLxnpltZ8y2LOuRwrVQsufHIJaGqShmQY7K7fbpmyeNU7E-_rx'), ('MsgId', '22291553506594661')]))
    

    地理位置消息 MsgType=="location"

    在公众号中,发送位置,pycharm控制台输出如下

    开发者服务收到的消息: LocationMessage(OrderedDict([('ToUserName', 'gh_dd3ad8e3fb33'), ('FromUserName', 'oiQF0tzMZ5Md5HaAlKvrZo9OIGBw'), ('CreateTime', '1557046957'), ('MsgType', 'location'), ('Location_X', '23.117962'), ('Location_Y', '113.321632'), ('Scale', '16'), ('Label', '富力中心(天河区珠江新城华夏路10号)'), ('MsgId', '22291551235258971')]))
    

    在公众号中,发送收藏中的一个链接,pycharm控制台输出如下

    开发者服务收到的消息: LinkMessage(OrderedDict([('ToUserName', 'gh_dd3ad8e3fb33'), ('FromUserName', 'oiQF0tzMZ5Md5HaAlKvrZo9OIGBw'), ('CreateTime', '1557047123'), ('MsgType', 'link'), ('Title', '官方网站-小鹏汽车'), ('Description', '小鹏汽车,致力于应用新的技术、工艺和商业模式,造年轻人喜爱的智能化电动汽车'), ('Url', 'https://www.xiaopeng.com/m/videos.html'), ('MsgId', '22291558059713663')]))
    

    事件消息 MsgType=="event"

    在微信用户和公众号产生交互的过程中,用户的某些操作会使得微信服务器通过事件推送的形式通知到开发者在开发者中心处设置的服务器地址,从而开发者可以获取到该信息。其中,某些事件推送在发生后,是允许开发者回复用户的,某些则不允许

    关注、取消事件 Event"subscribe",Event"unsubscribe"

    最常见的场景是当我们关注某个订阅号时,会收到一条欢迎信息,如
    在这里插入图片描述

    开发者服务收到的消息: SubscribeEvent(OrderedDict([('ToUserName', 'gh_dd3ad8e3fb33'), ('FromUserName', 'oiQF0tzMZ5Md5HaAlKvrZo9OIGBw'), ('CreateTime', '1557123164'), ('MsgType', 'event'), ('Event', 'subscribe'), ('EventKey', None)]))
    
    开发者服务收到的消息: UnsubscribeEvent(OrderedDict([('ToUserName', 'gh_dd3ad8e3fb33'), ('FromUserName', 'oiQF0tzMZ5Md5HaAlKvrZo9OIGBw'), ('CreateTime', '1557123120'), ('MsgType', 'event'), ('Event', 'unsubscribe'), ('EventKey', None)]))
    

    更多事件(略)...

    [info] 更多详细信息,可参考官方文档:
    https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140453
    https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140454

    被动消息应答类型

    根据前面的各种被动消息类型,开发者服务器作出相应的应答,先直接上代码如下
    views.py

    import os
    
    from django.http import HttpResponse
    from django.views.decorators.csrf import csrf_exempt
    from wechatpy import parse_message
    from wechatpy.client import WeChatClient
    from wechatpy.exceptions import InvalidSignatureException
    from wechatpy.utils import check_signature
    
    app = {
        "appid": "wx3a07084cc1a11915",
        "appsecret": "8f9a6bb1f66b59aa705ecd9938a3874c"
    }
    wx = WeChatClient(app.get("appid"), app.get("appsecret"))
    
    
    @csrf_exempt
    def wechat(request):
        # GET 方式用于微信公众平台绑定验证
        if request.method == 'GET':
            signature = request.GET.get('signature', "")
            timestamp = request.GET.get('timestamp', "")
            nonce = request.GET.get('nonce', "")
            echo_str = request.GET.get('echostr', "")
            token = 'MiltonGuan'
            try:
                check_signature(token, signature, timestamp, nonce)
                print("微信签名验证通过!")
            except InvalidSignatureException:
                print("微信签名验证失败!")
                echo_str = '微信签名验证失败'
            return HttpResponse(echo_str)
        # POST 方式用于接受被动消息
        if request.method == 'POST':
            # wechatpy 提供了一个便捷的函数 parse_message 来处理由微信服务器发送过来的 XML 消息并解析生成对应的消息类:
            msg = parse_message(request.body)
            print("开发者服务收到的消息:", msg)
    
            if msg.type == "text":
                # 回复文本消息
                from wechatpy.replies import TextReply
                reply = TextReply(message=msg)
                reply.content = msg.content
                return HttpResponse(reply.render(), content_type="application/xml")
    
            if msg.type == "image":
                # 回复图片消息
                from wechatpy.replies import ImageReply
                reply = ImageReply(message=msg)
                reply.media_id = msg.media_id
                return HttpResponse(reply.render(), content_type="application/xml")
    
            if msg.type == "voice":
                # 回复语音消息
                from wechatpy.replies import VoiceReply
                reply = VoiceReply(message=msg)
                reply.media_id = msg.media_id
                return HttpResponse(reply.render(), content_type="application/xml")
    
            if msg.type == "video":
                # 回复视频消息
                from wechatpy.replies import VideoReply
                reply = VideoReply(message=msg)
                reply.media_id = wx.media.upload("video", open(os.path.join(os.path.dirname(__file__), "hello.mp4"), "rb")).get("media_id")
                reply.title = "视频标题..."
                reply.description = "视频描述..."
                return HttpResponse(reply.render(), content_type="application/xml")
    
            if msg.type == "location":
                # 回复音乐消息
                from wechatpy.replies import MusicReply
                reply = MusicReply(message=msg)
                reply.thumb_media_id = wx.media.upload("thumb", open(os.path.join(os.path.dirname(__file__), "music.jpg"), "rb")).get("thumb_media_id")
                reply.music_url = "https://od.qingting.fm/m4a/5a8e82757cb89146f20a287b_8762416_64.m4a"
                reply.hq_music_url = "https://od.qingting.fm/m4a/5a8e82757cb89146f20a287b_8762416_64.m4a"
                reply.title = "梦想明月曲"
                reply.description = "崔子格"
                return HttpResponse(reply.render(), content_type="application/xml")
    
            if msg.type == "link":
                # 回复图文消息
                from wechatpy.replies import ArticlesReply
                reply = ArticlesReply(message=msg)
                # 当用户发送文本、图片、视频、图文、地理位置这五种消息时,开发者只能回复1条图文消息
                reply.add_article(article={
                    'title': '入门接口测试框架pytest',
                    'description': '掌握python中的测试框架,首选pytest!',
                    'url': 'https://mp.weixin.qq.com/s/4pLFQOdiB02DekTk-5RLbQ',
                    'image': 'https://mmbiz.qpic.cn/mmbiz_png/0QhkJiaDuoKSmrTs3KpjQLMwn14WUFOCS9Tq7ZqvFOL653WuowZZMYNNnm8FRbicmk8C8v31HxC4YibFRfOkSsuqQ/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1',
                })
                return HttpResponse(reply.render(), content_type="application/xml")
    
            if msg.type == "event":
                if msg.event == "subscribe":
                    # 订阅欢迎消息
                    from wechatpy.replies import TextReply
                    reply = TextReply(message=msg)
                    reply.content = "欢迎您的订阅,一起学习python!"
                    return HttpResponse(reply.render(), content_type="application/xml")
    

    回复文本消息,关键代码:

    from wechatpy.replies import TextReply
    reply = TextReply(message=msg)
    reply.content = msg.content
    return HttpResponse(reply.render(), content_type="application/xml")
    

    在这里插入图片描述

    回复图片消息,关键代码:

    from wechatpy.replies import ImageReply
    reply = ImageReply(message=msg)
    reply.media_id = msg.media_id
    return HttpResponse(reply.render(), content_type="application/xml")
    

    在这里插入图片描述

    回复语音消息,关键代码:

    from wechatpy.replies import VoiceReply
    reply = VoiceReply(message=msg)
    reply.media_id = msg.media_id
    return HttpResponse(reply.render(), content_type="application/xml")
    

    在这里插入图片描述

    回复视频消息,关键代码:

    from wechatpy.replies import VideoReply
    reply = VideoReply(message=msg)
    reply.media_id = wx.media.upload("video", open(os.path.join(os.path.dirname(__file__), "hello.mp4"), "rb")).get("media_id")
    reply.title = "视频标题..."
    reply.description = "视频描述..."
    return HttpResponse(reply.render(), content_type="application/xml")
    

    在这里插入图片描述

    回复音乐消息,关键代码:

    from wechatpy.replies import MusicReply
    reply = MusicReply(message=msg)
    reply.thumb_media_id = wx.media.upload("thumb", open(os.path.join(os.path.dirname(__file__), "music.jpg"), "rb")).get("thumb_media_id")
    reply.music_url = "https://od.qingting.fm/m4a/5a8e82757cb89146f20a287b_8762416_64.m4a"
    reply.hq_music_url = "https://od.qingting.fm/m4a/5a8e82757cb89146f20a287b_8762416_64.m4a"
    reply.title = "梦想明月曲"
    reply.description = "崔子格"
    return HttpResponse(reply.render(), content_type="application/xml")
    

    在这里插入图片描述

    回复图文消息,关键代码:

    from wechatpy.replies import ArticlesReply
    reply = ArticlesReply(message=msg)
    # 当用户发送文本、图片、视频、图文、地理位置这五种消息时,开发者只能回复1条图文消息
    reply.add_article(article={
        'title': '入门接口测试框架pytest',
        'description': '掌握python中的测试框架,首选pytest!',
        'url': 'https://mp.weixin.qq.com/s/4pLFQOdiB02DekTk-5RLbQ',
        'image': 'https://mmbiz.qpic.cn/mmbiz_png/0QhkJiaDuoKSmrTs3KpjQLMwn14WUFOCS9Tq7ZqvFOL653WuowZZMYNNnm8FRbicmk8C8v31HxC4YibFRfOkSsuqQ/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1',
    })
    return HttpResponse(reply.render(), content_type="application/xml")
    

    在这里插入图片描述


    :-:
    微信扫一扫,关注“python测试开发圈”,获取更多测试开发分享!

  • 相关阅读:
    05流程图和流程定义的操作
    04启动流程实例,任务的查询与完成
    03流程图的绘制与部署
    02数据库表的初始化方式
    01环境安装
    JavaScript基础和JavaScript内置对象:
    用手机、pid作为win电脑扩展屏
    H5新增特性之语义化标签
    盒模型
    CSS定位总结--static、relative、absolute、fixed
  • 原文地址:https://www.cnblogs.com/guanfuchang/p/10840969.html
Copyright © 2020-2023  润新知