用Django搭建微信公众号后端

Posted 小鱼牌豆腐饼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用Django搭建微信公众号后端相关的知识,希望对你有一定的参考价值。

用Django搭建微信公众号后端

微信TOKEN验证

  进入微信公众平台,基本设置会有这样一个服务器配置选项。如果开启就是进入了开发者模式,微信公众平台上自动回复和自定义菜单的功能就会失效。

创建项目与APP

  我们创建一个Django项目(我这边用的叫blogproject),创建一个叫'wechat'的app。(关于怎么创建参考Django的菜鸟教程(http://www.runoob.com/django/django-tutorial.html))。
  将我们自己创建的APP名称加进去,顺便改一下默认的模板文件夹

 
   
   
 
  1. # blogproject/setting.py

  2. INSTALLED_APPS = [

  3.    'django.contrib.admin',

  4.    # ...

  5.    # my app

  6.    'wechat',

  7. ]

  8. TEMPLATES = [

  9.    {

  10.        'BACKEND': 'django.template.backends.django.DjangoTemplates',

  11.        'DIRS': [os.path.join(BASE_DIR, 'templates')],# 修改此处

  12.        'APP_DIRS': True,

  13.        # ...

  14.    },

  15. ]

编辑views.py

  来看一下微信的官方文档(https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1445241432),第1.4小节,有一个案例,可以看到服务器接受signature,timestamp,nonce,echostr这四个参数。
  我是看了自强学堂(http://code.ziqiangxuetang.com/django/python-django-weixin.html)的例子,有了下面的代码

 
   
   
 
  1. # wechat/views.py

  2. # 省略头部引用和声明

  3. TOKEN = '********' # 自己改一下

  4. @csrf_exempt # 关闭csrf验证

  5. def wechat(request):

  6.    if request.method == 'GET':

  7.        # 获得参数signature nonce token timestamp echostr

  8.        signature = request.GET.get('signature', '')

  9.        timestamp = request.GET.get('timestamp', '')

  10.        nonce = request.GET.get('nonce', '')

  11.        echostr = request.GET.get('echostr', '')

  12.        token = TOKEN

  13.        # 将token、timestamp、nonce字段进行字典顺序排序

  14.        # 然后拼接成一个字符串进行sha1加密

  15.        # 加密后的字符串和signature进行比较,相同则返回echostr。

  16.        tmp_list = [token, timestamp, nonce]

  17.        tmp_list.sort()

  18.        hashstr = "%s%s%s" % tuple(tmp_list)

  19.        hashstr = hashlib.sha1(hashstr.encode('utf-8')).hexdigest()

  20.        # sha = hashlib.sha1()

  21.        # hashstr = sha.update("".join(tmp_list)).hexdigest()

  22.        if hashstr == signature:

  23.            return HttpResponse(echostr)

  24.        # 这个else的作用就是普通的网页打开显示'wx_index',看看是不是能成功路由(调用)

  25.        else:

  26.            return HttpResponse('weixin_index')

路由

  光写了函数来处理我们的数据,也不够啊。我总需要去调用他。所以我们需要路由。我们这边的路由分两步进行,先路由到我们的APP,再路由到各个函数。

 
   
   
 
  1. # blogproject/url.py

  2. urlpatterns = [

  3.    url(r'^admin/', admin.site.urls),

  4.    # 添加这一行

  5.    url(r'', include('wechat.urls'))

  6. ]

  然后我们就路由到了我们wechat的APP。接下来在wechat的文件夹下创建一个url.py的文件。

 
   
   
 
  1. # wechat/url.py

  2. from django.conf.urls import url

  3. from . import views

  4. app_name = 'wechat'

  5. urlpatterns = [

  6.    url(r'^wechat/index$', views.wechat, name='wechat'),# 这是我们所需要的功能函数

  7.    url(r'^wechat/index1$', views.index1, name='index1'),# 这是测试函数

  8. ]

上传服务器

用Django搭建微信公众号后端

消息回复

  有人会疑惑为什么不用微信官方给的自动回复呢?
  我想了几个答案:第一呢,用自己的回复更有极(就)客(要)精(装)神(逼)。第二,大家应该都知道一个APP叫SimiSimi,就是那个会聊天的小黄鸡,我要实现这个功能。第三,实现一些查询功能,比如天气,火车票,历史上的今天等等。后两个待添加。这次就完成重复你说话。

消息模板

  我们先来微信回过来的信息,它是一个XML数据包。微信官方文档(https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140453)

 
   
   
 
  1. <xml>

  2.    <ToUserName><![CDATA[toUser]]></ToUserName>

  3.    <FromUserName><![CDATA[fromUser]]></FromUserName>

  4.    <CreateTime>1348831860</CreateTime>

  5.    <MsgType><![CDATA[text]]></MsgType>

  6.    <Content><![CDATA[this is a test]]></Content>

  7.    <MsgId>1234567890123456</MsgId>

  8. </xml>

  微信也给了每个参数的解释

参数 描述
ToUserName 开发者微信号
FromUserName 发送方帐号(一个OpenID)
CreateTime 消息创建时间 (整型)
MsgType text
Content 文本消息内容
MsgId 消息id,64位整型

注:还有别的类型的xml数据,有需要可以看看官方文档。

转化数据

  我接受XML数据,然后将数据转化为Django能处理的数据。

 
   
   
 
  1. data = smart_str(request.body)

  2. xml = etree.fromstring(data)

提取数据,并处理做

  我们将各个数据内容提取出来

 
   
   
 
  1. ToUserName = xml.find('ToUserName').text

  2. FromUserName = xml.find('FromUserName').text

  3. CreateTime = xml.find('CreateTime').text

  4. MsgType = xml.find('MsgType').text

  5. Content = xml.find('Content').text

  6. MsgId = xml.find('MsgId').text

  我们要考虑这样一个逻辑:

  1. 用户发给我们的服务器什么消息,就回给用户什么信息。Content不变

  2. 用户发给我们的消息类型text,我们也不变。

  3. 时间不是23:59:59的这种类型,而是一个字符串类型的整型数值。

 
   
   
 
  1. time_stamp = str(int(time.time()))

  2. reply_content = {

  3.    'ToUserName': FromUserName,

  4.    'FromUserName': ToUserName,

  5.    'time': time_stamp,

  6.    'Content': Content,

  7. }

创建信息模板

  然后我们创建一个信息模板,叫做'wechat_reply.xml',放在'templates/wechat'下。当然'templates'与'wechat'文件夹小自己创建。
  这边的templates文件夹就是在settings.py里修改的目的!

 
   
   
 
  1. <xml>

  2.    <ToUserName>

  3.        <![CDATA[{{ ToUserName }}]]>

  4.    </ToUserName>

  5.    <FromUserName>

  6.        <![CDATA[{{ FromUserName }}]]>

  7.    </FromUserName>

  8.    <CreateTime>{{ time }}</CreateTime>

  9.    <MsgType>

  10.        <![CDATA[text]]>

  11.    </MsgType>

  12.    <Content>

  13.        <![CDATA[{{ Content }}]]>

  14.    </Content>

  15. </xml>

  我们用rendertostring()函数渲染模板信息,并将数据返回给微信。

  最后的代码就是这样:

 
   
   
 
  1.    if request.method == 'POST':

  2.        data = smart_str(request.body)

  3.        xml = etree.fromstring(data)

  4.        # 在控制台输出一下挑调试信息

  5.        # print('收到的XML数据')

  6.        # print(data)

  7.        ToUserName = xml.find('ToUserName').text

  8.        FromUserName = xml.find('FromUserName').text

  9.        CreateTime = xml.find('CreateTime').text

  10.        MsgType = xml.find('MsgType').text

  11.        Content = xml.find('Content').text

  12.        MsgId = xml.find('MsgId').text

  13.        time_stamp = str(int(time.time()))

  14.        reply_content = {

  15.            'ToUserName': FromUserName,

  16.            'FromUserName': ToUserName,

  17.            'time': time_stamp,

  18.            'Content': Content,

  19.        }

  20.        response_xml = render_to_string('wechat/wechat_reply.xml', context=reply_content)

  21.        return HttpResponse(response_xml)

大功告成!

  提交给我们的服务器,就可以测试啦!

END


以上是关于用Django搭建微信公众号后端的主要内容,如果未能解决你的问题,请参考以下文章

js处理微信分享配置

Payment:微信支付配置文件设置说明

Django+wechatpy接入微信公众平台以及授权登录

微信公众平台接口调试工具怎么用

接入微信公众平台开发之用户关注(取消)事件触发后台自定义消息体通知给用户的实现过程

用数据分析头部微信公众号到底有多牛