• 0033 微信公众平台开发(02 接收微信消息和事件)


      有了测试账号之后,我们该做什么呢?当然是接收来自于微信的消息和事件。

      公众号接收用户消息分为七类,包括文本消息、图片消息、语音消息、视频消息、小视频消息、地理位置消息、链接消息。

      公众号接收用户事件分为五类,包括关注事件、取消事件、扫描带参数二维码事件、上报地理位置事件、自定义菜单事件。

      当公众号接收到来自微信的消息时,需要做以下几步处理:

    1 验证消息是否来源于微信

      这个方法在上一节已学习过。

    2 解析来自于微信的消息和事件

      微信的消息正文是一个XML,我们收到这个XML需要进行解析,wechatpy提供了一个解析XML的方法parse_message,传入XML,返回解析后的对象。我们可以从解析后的对象中获取消息的内容。

    from wechatpy import parse_message
    
    msg = parse_message(xml)

    3 视图编写

      视图中的GET方法,上一节已经写好了,这一节主要是POST方法。POST方法主要是判断用户的消息和事件,至于收到这些消息,如何回复,在后面的章节中会讲到。

      这里需要注意的一点是用户关注公众号的时候,可以获取到用户的openid。在登录流程中会用到,比如:用户关注公众号的时候,获取用户的openid,保存在数据库中,而用户在登录注册输入手机的页面,再获取一次openid,并在数据库中找到这个Openid,并更新用户的手机号。同时,数据库中保存了Openid,可以随时根据Openid获取用户的其它资料。

    from django.views.generic import View
    from rest_framework import status
    import logging
    from django.http import HttpResponse
    from wechatpy.utils import check_signature
    from wechatpy.exceptions import InvalidSignatureException
    from GeneralTools import Constants
    from wechatpy import parse_message
    
    # 获取在配置文件中定义的logger,用来记录日志
    logger = logging.getLogger('wec_info')
    
    
    # from . import Replies
    
    
    class WechatInterface(View):
        """
        微信公众号开发服务器配置
        """
    
        @classmethod
        def get(cls, request):
            """
            微信服务器验证消息
            :param request:GET请求携带参数(signature、timestamp、nonce、echostr)
            :return:原样返回echostr参数
            """
    
            # logger.info("body:%s" % request.body)
            # logger.info("GET:%s" % request.GET)
            # logger.info("POST:%s" % request.POST)
    
            # 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
            signature = request.GET.get('signature')
            # 时间戳
            timestamp = request.GET.get('timestamp')
            # 随机数
            nonce = request.GET.get('nonce')
            # 随机字符串
            echostr = request.GET.get('echostr')
    
            logger.info("signature:%s" % signature)
            logger.info("timestamp:%s" % timestamp)
            logger.info("nonce:%s" % nonce)
            logger.info("echostr:%s" % echostr)
    
            # 校验参数
            if not all([signature, timestamp, nonce, echostr]):
                # 请求参数错误
                return HttpResponse(status.HTTP_400_BAD_REQUEST)
    
            try:
                check_signature(
                    token=Constants.WECHAT_TOKEN,  # 开发者在公众号配置中配置的令牌
                    signature=signature,  # 微信加密签名
                    timestamp=timestamp,  # 时间戳
                    nonce=nonce  # 随机数
                )
            except InvalidSignatureException as e:
                # 处理异常情况或忽略
                logger.error(e)
                # 微信签名错误
                return HttpResponse(status.HTTP_403_FORBIDDEN)
    
            # 验证成功时,应原样返回 echostr 参数值
            return HttpResponse(echostr)
    
        @classmethod
        def post(cls, request):
            print('===============>访问到了,')
            """
            当普通微信用户向公众账号发消息时,微信服务器将POST消息的XML数据包到开发者填写的URL上。
            """
            # logger.info("body:%s" % request.body)
            # logger.info("GET:%s" % request.GET)
            # logger.info("POST:%s" % request.POST)
    
            # 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
            signature = request.GET.get('signature')
            # 时间戳
            timestamp = request.GET.get('timestamp')
            # 随机数
            nonce = request.GET.get('nonce')
            # openid
            openid = request.GET.get('openid')
    
            # logger.info("signature:%s" % signature)
            # logger.info("timestamp:%s" % timestamp)
            # logger.info("nonce:%s" % nonce)
            # openid:o-dlPwDD8x_tKgeinvgj9CY9sfSI
            # logger.info("openid:%s" % openid)
    
            # 校验参数
            if not all([signature, timestamp, nonce, openid]):
                # 请求参数错误
                return HttpResponse(status.HTTP_400_BAD_REQUEST)
    
            try:
                check_signature(Constants.WECHAT_TOKEN, signature, timestamp, nonce)
            except InvalidSignatureException as e:
                # 处理异常情况或忽略
                logger.error(e)
                # 微信签名错误
                return HttpResponse(status.HTTP_403_FORBIDDEN)
    
            xml = request.body
            logger.info("xml:%s" % xml)
            if not xml:
                # 请求参数错误
                return HttpResponse(status.HTTP_400_BAD_REQUEST)
    
            msg = parse_message(xml)
            # logger.info("msg type:%s" % type(msg))
            # logger.info("msg_type:%s" % msg_type)
    
            msg_content = None
            if msg.type == "text":
                print('====================>')
                msg_content = '收到文本信息'
            elif msg.type == 'image':
                msg_content = '收到图片信息'
            elif msg.type == 'voice':
                msg_content = '收到语音信息'
            elif msg.type == 'video':
                msg_content = '收到视频消息'
                print(msg.media_id)
            elif msg.type == 'shortvideo':
                msg_content = '收到小视频消息'
                print(msg.media_id)
            elif msg.type == 'location':
                msg_content = '收到地理位置消息'
                print(msg.label)
            elif msg.type == 'link':
                msg_content = '收到链接消息'
                print(msg.link)
            elif msg.type == 'event':
                if msg.event == 'subscribe':
                    # 在用户关注公众号的时候,获取用户的openid,保存在数据库中,而当用户在注册的时候,
                    # 从注册页面再获取一次openid,同时把用户的手机号和openid,并根据该openid更新该用户的手机号。
                    print('============================>获取用户openid')
                    print(msg.source)
                    print('============================>')
                    msg_content = '用户关注'
                elif msg.event == 'unsubscribe':
                    print('取消关注公众号')  # 取消关注公众号后,不能向用户发送消息,但可以对用户资料进行处理。
                elif msg.event == 'subscribe_scan':
                    msg_content = '未关注用户扫描带参二维码事件'
                elif msg.event == 'scan':
                    msg_content = '已关注用户扫描带参二维码事件'
                elif msg.event == 'location':
                    msg_content = '上报地理信息事件'
                elif msg.event == 'click':
                    msg_content = '点击自定义菜单'
                elif msg.event == 'view':
                    msg_content = '点击菜单跳转事件'
            else:
                msg_content = '其它消息'
            print(msg_content)
            return HttpResponse('')

    4 配置Wechat分路由

    from django.urls import path
    from .views.WechartInterface import WeChatInterface
    urlpatterns = [
        path('WechatInterface/', WeChatInterface.as_view()),
    ]
    

    5 配置工程总路由

      把Wechat分路由加到总路由中

    from django.contrib import admin
    from django.urls import path, include, re_path
    from rest_framework.documentation import include_docs_urls
    from TongHeng2 import settings
    
    from rest_framework_jwt.views import obtain_jwt_token
    
    DESCRIPTION = """
            包括仝恒绩效云所有接口文档。包括以下应用:
            1 GeneralTools:常用工具APP
            2 Organizations: 组织机构(包含组织下的人员)APP
            3 Examples:示例APP,用于新知识的测试案例
    """
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('Examples/', include('Applications.Examples.urls')),
        path('Organizations/', include('Applications.Organizations.urls')),
        path('Wechat/', include('Applications.WeChat.urls')),
        path('docs/', include_docs_urls(title='API接口文档', description=DESCRIPTION)),
        path('authorizations/', obtain_jwt_token)
    ]
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

    6 把工程发布到指定IP的服务器上

    7 测试公众号消息和事件

      

      

  • 相关阅读:
    Java Web系统经常使用的第三方接口
    Direct UI
    Python 分析Twitter用户喜爱的推文
    数据挖掘十大经典算法(9) 朴素贝叶斯分类器 Naive Bayes
    利用Excel批量高速发送电子邮件
    普林斯顿大学数学系的崛起
    Node.js学习
    映射 SQL 和 Java 类型
    Nutch配置
    OGNL
  • 原文地址:https://www.cnblogs.com/dorian/p/12388570.html
Copyright © 2020-2023  润新知