第一句子网 - 唯美句子、句子迷、好句子大全
第一句子网 > Django实现微信公众号简单自动回复

Django实现微信公众号简单自动回复

时间:2018-12-04 07:47:01

相关推荐

Django实现微信公众号简单自动回复

在上篇博客阿里云部署django实现公网访问已经实现了了django在阿里云上的部署,接下来记录django实现微信公众号简单回复的开发过程,以方便日后查看

内容概要:

(1)微信公众号声请

(2)微信公众号开发者配置

(3)文本回复实现

(4)图片回复实现

1. 微信公众号声请

微信公众号的申请就不作介绍了,参考微信公众平台开发者文档中的入门指引

2.微信公众号开发者配置

开发者配置是微信公众号开发的第一步,显得极其重要

公众平台官网登录之后,找到“基本配置”菜单栏,如下图:

重点说明URL(服务器地址的配置),即与微信服务器直接通讯的服务器地址,我这里设置的是http://外网ip/wx/

同时django中的配置如下:(说明:我的django工程为mysite,微信应用为wechat)

(1)mysite目录下的urls.py配置如下

#from django.contrib import admin#from django.urls import path#from django.conf.urls import include,urlfrom django.conf.urls import url, includefrom django.contrib import adminurlpatterns = [url(r'^admin/', admin.site.urls),url(r'^blog/', include(('blog.urls',"blog"),namespace="blog")),url(r'^account/', include(('account.urls','account'),namespace='account')),url(r'^wx/', include(('wechat.urls','wechat'),namespace='wechat')),]

(2)wechat目录下的urls.py配置如下

from django.conf.urls import urlfrom .views import WeChaturlpatterns = [url(r'^$', WeChat.as_view())]

注:第一次我的URL配置为http://外网ip/wx,但在进行微信回复时提示"You called this URL via POST, but the URL doesn't end in a slash and you have APPEND_SL.....",百度后将修改settings:APPEND_SLASH=False也没有成功,后将配置改为http://外网ip/wx/成功了,若大家遇到同样的问题,可以多做尝试,主要原因还是因为表单的提交要将from的action地址改为/结尾

(3)token验证

token验证流程如下图:

代码实现:

# Create your views here.# -*- coding: utf-8 -*-from django.shortcuts import renderfrom django.http import HttpResponsefrom django.views.decorators.csrf import csrf_exemptfrom django.views.generic.base import Viewfrom django.template import loader, Contextfrom xml.etree import ElementTree as ETimport timeimport hashlibfrom .analysis import Analysisfrom django.utils.encoding import smart_strclass WeChat(View):#这里我当时写成了防止跨站请求伪造,其实不是这样的,恰恰相反。因为django默认是开启了csrf防护中间件的#所以这里使用@csrf_exempt是单独为这个函数去掉这个防护功能。@csrf_exemptdef dispatch(self, *args, **kwargs):return super(WeChat, self).dispatch(*args, **kwargs)#微信的介入验证是GET方法#微信正常的收发消息是POST方法@csrf_exemptdef get(self, request):print("welcome wx")#下面这四个参数是在接入时,微信的服务器发送过来的参数signature = request.GET.get('signature', None)#print(signature)timestamp = request.GET.get('timestamp', None)nonce = request.GET.get('nonce', None)echostr = request.GET.get('echostr', None)#这个token是我们自己来定义的,并且这个要填写在开发文档中的Token的位置token = 'fateli'#把token,timestamp, nonce放在一个序列中,并且按字符排序hashlist = [token, timestamp, nonce]hashlist.sort()#将上面的序列合成一个字符串hashstr = ''.join([s for s in hashlist])#通过python标准库中的sha1加密算法,处理上面的字符串,形成新的字符串。s1 = hashlib.sha1()s1.update(hashstr.encode("utf8")) hashstr = s1.hexdigest()#print(hashstr)#把我们生成的字符串和微信服务器发送过来的字符串比较,#如果相同,就把服务器发过来的echostr字符串返回去if hashstr == signature:return HttpResponse(echostr)else:return HttpResponse("field")

配置成功后就可以开始后续的消息回复工作了。若出现为问题,一定要仔细阅读开发者文档说明。

3.文本回复实现

回复的实现主要是要清除协议,其后就很简单了。

(1)接受文本格式

<xml><ToUserName><![CDATA[公众号]]></ToUserName><FromUserName><![CDATA[粉丝号]]></FromUserName><CreateTime>1460537339</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[欢迎开启公众号开发者模式]]></Content><MsgId>6272960105994287618</MsgId></xml>

(2)回复文本格式

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

(3)代码实现

新建analysis.py

from xml.etree import ElementTree as ETimport timeclass Analysis:def __init__(self, xmlData):print("接收到的数据:" + xmlData)def prase(self, xmlText):xmlData = ET.fromstring(xmlText)msgType = xmlData.find("MsgType").texttoUserName = xmlData.find("ToUserName").textfromUserName= xmlData.find("FromUserName").textif msgType == 'text':content = xmlData.find("Content").textTextMsgObj = TextMsg(toUserName, fromUserName, content)return TextMsgObj.structReply()elif msgType == 'image':mediaId = xmlData.find("MediaId").textImageMsgObj = ImageMsg(toUserName,fromUserName,mediaId)return ImageMsgObj.structReply()class TextMsg:def __init__(self,toUser,fromUser,recvMsg):self._toUser = toUserself._fromUser = fromUserself._recvMsg = recvMsgself._nowTime = int(time.time())def structReply(self):content = self._recvMsgtext = """<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>{2}</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[{3}]]></Content></xml>""".format(self._fromUser, self._toUser,self._nowTime,content) #前面两个参数的顺序需要特别注意return text

POST代码如下:

@csrf_exemptdef post(self, request):print("POST请求")analysisObj = Analysis(smart_str(request.body))toWxData = analysisObj.prase(smart_str(request.body))print(toWxData)return HttpResponse(smart_str(toWxData))

4.图片回复实现

实现了文本回复后图片恢复也就很简单了,过程一样,只是协议字段有区别

(1)接受文本格式

<xml><ToUserName><![CDATA[公众号]]></ToUserName><FromUserName><![CDATA[粉丝号]]></FromUserName><CreateTime>1460536575</CreateTime><MsgType><![CDATA[image]]></MsgType><PicUrl><![CDATA[/xxxxxx /0]]></PicUrl><MsgId>6272956824639273066</MsgId><MediaId><![CDATA[gyci5a-xxxxx-OL]]></MediaId></xml>

(2)回复文本格式

<xml><ToUserName><![CDATA[粉丝号]]></ToUserName><FromUserName><![CDATA[公众号]]></FromUserName><CreateTime>1460536576</CreateTime><MsgType><![CDATA[image]]></MsgType><Image><MediaId><![CDATA[gyci5oxxxxxxv3cOL]]></MediaId></Image></xml>

注意回复文本格式中只有MediaId,后续博客进行说明

(3)代码实现

class ImageMsg:def __init__(self,toUser,fromUser,mediaId):self._toUser = toUserself._fromUser = fromUserself._rediaId = mediaIdself._nowTime = int(time.time())self._mediaId = mediaIddef structReply(self):text = """<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>{2}</CreateTime><MsgType><![CDATA[image]]></MsgType><Image><MediaId><![CDATA[{3}]]></MediaId></Image></xml>""".format(self._fromUser, self._toUser,self._nowTime,self._mediaId) #前面两个参数的顺序需要特别注意return text

在开发过程中遇到问题,可以使用微信公众平台提供的在线接口调试工具。

原计划是继续进行菜单项的开发,但由于是个人订阅号,无法卡通认证,也就无法获取API开发权限,目前只能到此。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。