1. 程式人生 > >使用Django進行微信公眾號開發

使用Django進行微信公眾號開發

一、微信公眾號的準備:

1. 註冊

訪問地址:https://mp.weixin.qq.com/
按照提示註冊即可
注意:本文樣例使用個人公眾號,由於個人公眾號沒有介面許可權,自定義選單無法進行開發,同學們不要註冊錯!
這裡寫圖片描述

2. 配置

需要準備好自己的伺服器地址,可以使用騰訊雲阿里雲京東雲等等皆可,沒有域名用IP也可以。
在公眾平臺官網的開發-基本設定頁面,勾選協議成為開發者,點選“修改配置”按鈕,填寫伺服器地址(URL)、Token和EncodingAESKey,其中URL是開發者用來接收微信訊息和事件的介面URL。Token可由開發者可以任意填寫,用作生成簽名(該Token會和介面URL中包含的Token進行比對,從而驗證安全性)。EncodingAESKey由開發者手動填寫或隨機生成,將用作訊息體加解密金鑰。
詳細配置文件:

https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421135319
這裡寫圖片描述

3. 連線

伺服器配置提交後,微信伺服器傳送GET請求到填寫的伺服器地址URL上,GET請求攜帶引數包括signature、timestamp、nonce、echostr,服務端程式通過檢驗signature對請求進行校驗(下面有校驗方式)。若確認此次GET請求來自微信伺服器,請原樣返回echostr引數內容給微信伺服器確認後接入生效。加密/校驗流程如下,下文中有程式碼具體實現:
1)將token、timestamp、nonce三個引數進行字典序排序
2)將三個引數字串拼接成一個字串進行sha1加密
3)開發者獲得加密後的字串可與signature對比,標識該請求來源於微信

二、基於Django開發微信公眾號後臺的步驟:

1.準備工作

  1. 新建 django project,專案名暫定devnav
django-admin.py startproject devnav
  1. 新建 app
    進入專案目錄下,cd project_wechat 然後執行下面的命令
python manage.py startapp wechat

django-admin.py startapp wechat
  1. 修改settings.py加入剛才建立的wechat應用
INSTALLED_APPS = (
    'django.contrib.admin'
, 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'wechat', )
  1. 修改專案同名app內的urls.py,新增新的app wechat的路由解析跳轉
urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^wx/', include('wechat.urls',namespace="wechat")),
   ]

2.編寫wechat應用的urls.py

修改app wechat內的urls.py,新增針對檢視函式的解析,預設訪問指向檢視函式的weixin_main方法,若有其他方法可參考註釋中的startmymenu方法來編寫

app_name = 'wechat'

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^$', views.weixin_main, name='weixin_main'),
    #url(r'^startmymenu$', views.startmymenu, name='startmymenu'),
    ]

3.編寫wechat應用的views.py

get方法做校驗,post方法傳xml資料,解析和拼湊xml資料實現自動回覆功能

# Create your views here.
# -*- coding: utf-8 -*-

import hashlib
import json
from django.utils.encoding import smart_str
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse

#django預設開啟csrf防護,這裡使用@csrf_exempt去掉防護
@csrf_exempt
def weixin_main(request):
    if request.method == "GET":
        #接收微信伺服器get請求發過來的引數
        signature = request.GET.get('signature', None)
        timestamp = request.GET.get('timestamp', None)
        nonce = request.GET.get('nonce', None)
        echostr = request.GET.get('echostr', None)
        #伺服器配置中的token
        token = '寫你的token在這裡'
        #把引數放到list中排序後合成一個字串,再用sha1加密得到新的字串與微信發來的signature對比,如果相同就返回echostr給伺服器,校驗通過
        hashlist = [token, timestamp, nonce]
        hashlist.sort()
        hashstr = ''.join([s for s in hashlist])
        hashstr = hashlib.sha1(hashstr).hexdigest()
        if hashstr == signature:
          return HttpResponse(echostr)
        else:
          return HttpResponse("field")
    else:
        othercontent = autoreply(request)
        return HttpResponse(othercontent)

#微信伺服器推送訊息是xml的,根據利用ElementTree來解析出的不同xml內容返回不同的回覆資訊,就實現了基本的自動回覆功能了,也可以按照需求用其他的XML解析方法
import xml.etree.ElementTree as ET
def autoreply(request):
    try:
        webData = request.body
        xmlData = ET.fromstring(webData)

        msg_type = xmlData.find('MsgType').text
        ToUserName = xmlData.find('ToUserName').text
        FromUserName = xmlData.find('FromUserName').text
        CreateTime = xmlData.find('CreateTime').text
        MsgType = xmlData.find('MsgType').text
        MsgId = xmlData.find('MsgId').text

        toUser = FromUserName
        fromUser = ToUserName

        if msg_type == 'text':
            content = "您好,歡迎來到Python大學習!希望我們可以一起進步!"
            replyMsg = TextMsg(toUser, fromUser, content)
            print "成功了!!!!!!!!!!!!!!!!!!!"
            print replyMsg
            return replyMsg.send()

        elif msg_type == 'image':
            content = "圖片已收到,謝謝"
            replyMsg = TextMsg(toUser, fromUser, content)
            return replyMsg.send()
        elif msg_type == 'voice':
            content = "語音已收到,謝謝"
            replyMsg = TextMsg(toUser, fromUser, content)
            return replyMsg.send()
        elif msg_type == 'video':
            content = "視訊已收到,謝謝"
            replyMsg = TextMsg(toUser, fromUser, content)
            return replyMsg.send()
        elif msg_type == 'shortvideo':
            content = "小視訊已收到,謝謝"
            replyMsg = TextMsg(toUser, fromUser, content)
            return replyMsg.send()
        elif msg_type == 'location':
            content = "位置已收到,謝謝"
            replyMsg = TextMsg(toUser, fromUser, content)
            return replyMsg.send()
        else:
            msg_type == 'link'
            content = "連結已收到,謝謝"
            replyMsg = TextMsg(toUser, fromUser, content)
            return replyMsg.send()

    except Exception, Argment:
        return Argment

class Msg(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

import time
class TextMsg(Msg):
    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)

4.效果展示

這裡寫圖片描述

5.進一步的功能擴充套件