0027 微信开发(接收微信消息)

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

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

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

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

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

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

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

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

from wechatpy import parse_message

msg = parse_message(xml)

3 视图编写

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 Constents

# 获取在配置文件中定义的logger,用来记录日志
logger = logging.getLogger('tongheng2')

from wechatpy.replies import TextReply
from wechatpy import parse_message
from Applications.WeChart.utils import get_authorize_url


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=Constents.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):
        """
        当普通微信用户向公众账号发消息时,微信服务器将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(Constents.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":
            msg_content = '收到文本消息'
            print(msg.content)
        elif msg.type == 'image':
            msg_content = '收到图片消息'
            print('url地址:',msg.image)
        elif msg.type == 'voice':
            msg_content = '收到语音消息'
            print(msg.media_id)
        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':
                print('关注公众号')
            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 django.views.static import serve
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),
    re_path(r'(?P<path>.*)$', serve, {'document_root': settings.DOCUMENT_ROOT}),
]

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

7 测试公众号消息和事件

  

  

猜你喜欢

转载自www.cnblogs.com/dorian/p/12388570.html