Django对接微信公众号以实现消息自动回复

前言

  本篇博客使用Django框架,搭配uWsgi和Nginx,结合着Postman API调试工具,实现了微信公众号用户消息自动回复的功能,并成功部署到腾讯云服务器上。

  在上篇博客中,我们已经配置好了腾讯云服务器,并能够进行简单的交互。

1. 配置微信公众号

在这里插入图片描述

  • 点击右侧的修改配置,填写相应的信息
	URL:	http://服务器公网IP/wx
	Token:	自己设置一条字符串
	EncodingAESKey:	随机生成就可
	消息加解密方式:	为方便调试,暂时选择明文模式

在这里插入图片描述

2. 验证信息来源

  上述信息填写完后,选择提交会触发一个GET请求来验证Token,验证的逻辑图如下:

在这里插入图片描述
  下面我们在项目目录中的views.py文件中来实现这个逻辑,代码如下:

	from django.http import HttpResponse
	import hashlib
	
	
	# Create your views here.
	def TencentView(request):
	    if request.method == 'GET':
	        # 解析参数
	        data = request.GET
	        # Flask	from flask import request
	        # data = request.args
	        if len(data) == 0:
	            return HttpResponse(content="hello, this is WeChat view")
	        signature = data.get(key='signature', default='')
	        timestamp = data.get(key='timestamp', default='')
	        nonce = data.get(key='nonce', default='')
	        echostr = data.get(key='echostr', default='')
	        # 请按照公众平台官网\基本配置中信息填写
	        token = "xxxxxxxxxxxxxxxxxx"
	
	        list_para = [token, timestamp, nonce]
	        list_para.sort()
	        list_str = ''.join(list_para).encode('utf-8')
	
	        sha1 = hashlib.sha1()
	        sha1.update(list_str)
	        # map(sha1.update, list_para)
	        # 加密
	        hashcode = sha1.hexdigest()
	
	        print("/GET func: hashcode: {0}, signature: {1}".format(hashcode, signature))
	
	        if hashcode == signature:
	            return HttpResponse(content=echostr)
	        else:
	            return HttpResponse(content='验证失败')
	
	    elif request.method == 'POST':
	    	pass

  这里有一个坑,官方给的示例使用Python2写的,但Python2的hashlib加密与Python3中的不一样,Python3需要先进行utf-8编码。

  上述配置无误后,再次提交就会验证成功,如果仍未成功,请检查一下加密结果是否出错了,若token验证成功,会自动返回基本配置的主页面,点击启动按钮。

3. 消息接收-回复测试

  粉丝给公众号发送文本消息:“hello”,在开发者后台,收到公众平台发送的xml如下:

	<xml>
		 <ToUserName><![CDATA[公众号]]></ToUserName>
		 <FromUserName><![CDATA[粉丝号]]></FromUserName>
		 <CreateTime>1460537339</CreateTime>
		 <MsgType><![CDATA[text]]></MsgType>
		 <Content><![CDATA[hello]]></Content>
		 <MsgId>6272960105994287618</MsgId>
	</xml>

  字段说明如下:

字段作用
ToUserName公众号
FromUserName粉丝号
CreateTime微信公众平台记录粉丝发送该消息的具体时间
MsgType消息类型,有textimagevoice
Content消息内容
MsgId公众平台为记录识别该消息的一个标记数值,微信后台系统自动产生

  公众号想回复给粉丝一条文本消息,内容为“test”, 那么开发者发送给公众平台后台的xml内容如下:

	<xml>
		 <ToUserName><![CDATA[粉丝号]]></ToUserName>
		 <FromUserName><![CDATA[公众号]]></FromUserName>
		 <CreateTime>1460541339</CreateTime>
		 <MsgType><![CDATA[text]]></MsgType>
		 <Content><![CDATA[test]]></Content>
	</xml>

  假如服务器无法保证在五秒内处理回复,则必须回复“success”或者“”(空串),否则微信后台会提示“该公众号暂时无法提供服务,请稍后再试”。

  消息接收-回复流程图如下:

在这里插入图片描述
  下面我们继续在项目目录中的views.py文件中来实现这个流程,增添代码如下:

from xml.etree import ElementTree
import time


class ParseXmlMsg(object):
    def __init__(self, xmlData):
        self.ToUserName = xmlData.find('ToUserName').text
        self.FromUserName = xmlData.find('FromUserName').text
        self.CreateTime = xmlData.find('CreateTime').text
        self.MsgType = xmlData.find('MsgType').text
        self.MsgId = xmlData.find('MsgId').text

        if self.MsgType == 'text':
            self.Content = xmlData.find('Content').text.encode('utf-8')
        elif self.MsgType == 'image':
            self.PicUrl = xmlData.find('PicUrl').text
            self.MediaId = xmlData.find('MediaId').text


class TextMsg(object):
    def __init__(self, toUserName, fromUserName, content):
        # 私有对象,禁止外部访问
        self.__dict = dict()
        self.__dict['ToUserName'] = toUserName
        self.__dict['FromUserName'] = fromUserName
        self.__dict['CreateTime'] = int(time.time())
        self.__dict['Content'] = content

    def send(self):
        XmlForm = """
            <xml>
                <ToUserName><![CDATA[{ToUserName}]]></ToUserName>
                <FromUserName><![CDATA[{FromUserName}]]></FromUserName>
                <CreateTime>{CreateTime}</CreateTime>
                <MsgType><![CDATA[text]]></MsgType>
                <Content><![CDATA[{Content}]]></Content>
            </xml>
            """
        return XmlForm.format(**self.__dict)


class ImageMsg(object):
    def __init__(self, toUserName, fromUserName, mediaId):
        self.__dict = dict()
        self.__dict['ToUserName'] = toUserName
        self.__dict['FromUserName'] = fromUserName
        self.__dict['CreateTime'] = int(time.time())
        self.__dict['MediaId'] = mediaId

    def send(self):
        XmlForm = """
            <xml>
                <ToUserName><![CDATA[{ToUserName}]]></ToUserName>
                <FromUserName><![CDATA[{FromUserName}]]></FromUserName>
                <CreateTime>{CreateTime}</CreateTime>
                <MsgType><![CDATA[image]]></MsgType>
                <Image>
                <MediaId><![CDATA[{MediaId}]]></MediaId>
                </Image>
            </xml>
            """
        return XmlForm.format(**self.__dict)

  另外还需要在elif语句中增加以下代码:

	elif request.method == 'POST':
        # 解析发送过来的body
        webData = request.body
        # Flask
        # if request.content_type.startswith('application/json'):
        #     webData = request.json
        # elif request.content_type.startswith('multipart/form-data'):
        #     webData = request.form
        # elif request.content_type.startswith('application/x-www-form-urlencoded'):
        #     webData = request.values
        # else:
        #     webData = request.get_data()
        # print("Post webdata is ", webData)
        xmlData = ElementTree.fromstring(webData)
        recMsg = ParseXmlMsg(xmlData)

        if recMsg.MsgType == 'text':
            toUser = recMsg.FromUserName
            fromUser = recMsg.ToUserName
            content = 'test'

            replyMsg = TextMsg(toUser, fromUser, content)
            return HttpResponse(content=replyMsg.send())
        elif recMsg.MsgType == 'image':
            print('暂时不做处理')
            return HttpResponse(content='success')

4. Postman 调试

  为了调试方便,我们可以在本地启动项目,然后通过Postman来发送-接收xml消息,调试完毕无误后再上传到服务器。

  • 首先在本地启动项目
	# 在启动之前,先注释掉settings.py文件中的一行代码,关闭CSRF验证
	# 否则POST时会触发CSRF验证失败
	# 'django.middleware.csrf.CsrfViewMiddleware'
	python manage.py runserver

在这里插入图片描述

  • 打开Postman,使用POST请求,在Body菜单栏中填入我们需要发送的xml消息,具体·配置信息如下图所示

在这里插入图片描述

  • 填写完后,点击Send发送,在下方响应信息栏中我们就会收到返回的信息

在这里插入图片描述
  发送的消息为“hello”,收到的信息为“test”,说明很OK,然后将代码上传到服务器。

  上传服务器后记得重启一下uWsgiNginx哦!

5. 官方接口调试

  微信公众平台提供了一个在线测试平台,通过这个平台可以模拟粉丝与公众号的互动。

在这里插入图片描述

  FromUserName 在配置微信公众号时,基本配置菜单栏那里可以看到。

  配置无误后,点击下方检查问题按钮,不出意外的话,你会得到以下信息:

在这里插入图片描述
  向微信公众号发送信息,貌似表情包也是text类型:

在这里插入图片描述

  OK!很nice!!!

在这里插入图片描述

  • 6
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
下面是一个简单的 Django 对接微信小程序的接口示例代码。 首先在你的 Django 项目的 settings.py 中添加以下的配置: ```python WECHAT_APPID = 'your_appid' WECHAT_APPSECRET = 'your_appsecret' WECHAT_TOKEN = 'your_token' WECHAT_AES_KEY = 'your_aes_key' ``` 然后在你的 Django 项目中创建一个 views.py 文件,并添加以下代码: ```python import hashlib import xml.etree.ElementTree as ET from django.http import HttpResponse from django.views.decorators.csrf import csrf_exempt from django.conf import settings @csrf_exempt def wechat(request): if request.method == 'GET': # 微信接入时需要进行验证 signature = request.GET.get('signature', '') timestamp = request.GET.get('timestamp', '') nonce = request.GET.get('nonce', '') echostr = request.GET.get('echostr', '') token = settings.WECHAT_TOKEN # 将 token、timestamp、nonce 三个参数进行字典序排序 tmp_list = [token, timestamp, nonce] tmp_list.sort() # 将三个参数字符串拼接成一个字符串进行 sha1 加密 tmp_str = ''.join(tmp_list) sha1 = hashlib.sha1(tmp_str.encode('utf-8')).hexdigest() # 如果是来自微信的请求,则返回 echostr if sha1 == signature: return HttpResponse(echostr) elif request.method == 'POST': # 处理微信小程序的消息 xml_str = request.body root = ET.fromstring(xml_str) # 读取 xml 中的 ToUserName、FromUserName、CreateTime、MsgType 和 Content to_user_name = root.findtext('ToUserName') from_user_name = root.findtext('FromUserName') create_time = root.findtext('CreateTime') msg_type = root.findtext('MsgType') content = root.findtext('Content') # 构造返回的 xml xml = """ <xml> <ToUserName><![CDATA[%s]]></ToUserName> <FromUserName><![CDATA[%s]]></FromUserName> <CreateTime>%s</CreateTime> <MsgType><![CDATA[%s]]></MsgType> <Content><![CDATA[%s]]></Content> </xml> """ % (from_user_name, to_user_name, create_time, msg_type, content) return HttpResponse(xml, content_type='application/xml') ``` 上述代码实现了一个简单的微信小程序对接接口,能够处理 GET 请求中的微信接入验证以及 POST 请求中的消息推送。 在你的 Django 项目的 urls.py 中添加以下的路由配置: ```python from django.urls import path from . import views urlpatterns = [ path('wechat', views.wechat), ] ``` 这样,你就可以通过访问 `http://yourdomain.com/wechat` 来访问你的微信小程序对接接口了。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏小悠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值