杂项Django:Django接入微信公众平台

目录

前言

微信公众平台接入文档链接

原web.py框架下代码

1 main.py

2 handle.py(验证服务器配置)

3 handle.py(正式)

4 receive.py

5 reply.py

改造项目之前的解析

改造代码

1 建立django项目和app

2 项目路径

3 修改项目文件

#4 关于验证服务器使用的加密设置


前言

能有这篇文章纯属我的无聊之举。微信公众平台的接入文档里采用的是python的web.py框架(一个很小很轻量级的web框架,但是网上的资料和官网的资料都太少了),本文在接入文档的代码里稍作改动,使其成为一个django项目便于运行。

微信公众平台接入文档链接

关于微信平台转发的xml消息的结构等其他问题在这里都有很详尽的解释:

1开启公众号开发者模式 | 微信开放文档

原web.py框架下代码

1 main.py

# -*- coding: utf-8 -*-

# filename: main.py

import web

from handle import Handle

urls = (

    '/wx', 'Handle',

)

if __name__ == '__main__':

    app = web.application(urls, globals())

    app.run()

2 handle.py(验证服务器配置)

# -*- coding: utf-8 -*-

# filename: handle.py

import hashlib

import web

class Handle(object):

    def GET(self):

        try:

            data = web.input()

            if len(data) == 0:

                return "hello, this is handle view"

            signature = data.signature

            timestamp = data.timestamp

            nonce = data.nonce

            echostr = data.echostr

            token = "xxxx" #请按照公众平台官网\基本配置中信息填写

            list = [token, timestamp, nonce]

            list.sort()

            sha1 = hashlib.sha1()

            map(sha1.update, list)

            hashcode = sha1.hexdigest()

            print "handle/GET func: hashcode, signature: ", hashcode, signature

            if hashcode == signature:

                return echostr

            else:

                return ""

        except Exception, Argument:

            return Argument

3 handle.py(正式)

# -*- coding: utf-8 -*-# 

# filename: handle.py

import hashlib

import reply

import receive

import web

class Handle(object):

    def POST(self):

        try:

            webData = web.data()

            print "Handle Post webdata is ", webData

            #后台打日志

            recMsg = receive.parse_xml(webData)

            if isinstance(recMsg, receive.Msg) and recMsg.MsgType == 'text':

                toUser = recMsg.FromUserName

                fromUser = recMsg.ToUserName

                content = "test"

                replyMsg = reply.TextMsg(toUser, fromUser, content)

                return replyMsg.send()

            else:

                print "暂且不处理"

                return "success"

        except Exception, Argment:

            return Argment

4 receive.py

# -*- coding: utf-8 -*-#

# filename: receive.py

import xml.etree.ElementTree as ET

def parse_xml(web_data):

    if len(web_data) == 0:

        return None

    xmlData = ET.fromstring(web_data)

    msg_type = xmlData.find('MsgType').text

    if msg_type == 'text':

        return TextMsg(xmlData)

    elif msg_type == 'image':

        return ImageMsg(xmlData)

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

class TextMsg(Msg):

    def __init__(self, xmlData):

        Msg.__init__(self, xmlData)

        self.Content = xmlData.find('Content').text.encode("utf-8")

class ImageMsg(Msg):

    def __init__(self, xmlData):

        Msg.__init__(self, xmlData)

        self.PicUrl = xmlData.find('PicUrl').text

        self.MediaId = xmlData.find('MediaId').text

5 reply.py

# -*- coding: utf-8 -*-#

# filename: reply.py

import time

class Msg(object):

    def __init__(self):

        pass

    def send(self):

        return "success"

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)

class ImageMsg(Msg):

    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)

改造项目之前的解析

首先,django项目并不需要main.py文件,所以我们可以将其删去。main.py里的路径映射移到django项目目录下的urls.py就可以。

handle.py在web.py中承担了接受数据和返回视图的作用,而django项目中承担此功能的部分是app目录下的views.py。

receive.py与reply.py作为处理微信公众平台转发的xml数据的部分本身不需要更改,但由于我们可能把项目转接到一个大的django项目下,为防止重名且明晰用途,我们将这两个文件重命名为wxRecieve.py与wxReply.py。

改造代码

1 建立django项目和app

这一步骤我不详讲,网上的教程可以说一搜一大把,或者也可以去看看笔者写的django教程。

在本文中,我们默认读者已经知道django是如何运作的,至少基本上能够看懂python。

记得在settings.py中加上你的app。

2 项目路径

我们设定django项目名为djagowx,app名为wxrun,则整个目录的结构如下:

 
 

djangowx

│  db.sqlite3

│  manage.py

├─djangowx

│  │  asgi.py

│  │  settings.py

│  │  urls.py

│  │  wsgi.py

│  │  __init__.py

│  │

│  └─__pycache__

│          /

└─wxrun

    │  admin.py

    │  apps.py

    │  models.py

    │  tests.py

    │  urls.py

    │  views.py

    │  __init__.py

    │

    ├─migrations

    │  │  __init__.py

    │  │

    │  └─__pycache__

    │          /

    │

    └─__pycache__

            /

3 修改项目文件

其余文件不做改动,我们在项目文件夹下新建两个文件wxRecieve.py与wxReply.py,内容复制于接入文档里的receive.py、reply.py,负责读取与生成xml消息。

修改app目录下的views.py:

import hashlib

from django.http import HttpResponse

import wxReceive as receive

import wxReply as reply

from django.views.decorators.csrf import csrf_exempt

@csrf_exempt

def token(request):

    if(request.method=='GET'):

        signature=request.GET['signature']

        timestamp=request.GET['timestamp']

        nonce=request.GET['nonce']

        echostr=request.GET['echostr']

        token="mytheodorwx20200923"

        list = [token, timestamp, nonce]

        list.sort()

        sha1 = hashlib.sha1()

        map(sha1.update, list)

        hashcode = sha1.hexdigest()

        print("handle/GET func: hashcode, signature: ", hashcode, signature)

        if hashcode == signature:

            return HttpResponse(echostr)

        else:

            return HttpResponse("Error Response")

    else:

        Recxml=receive.parsexml(request.body) #读取信息,至于为什么不是POST,是因为这不是字典也不是表单

        if(isinstance(Recxml,receive.Msg) and Recxml.MsgType=="text"):

            toUser = Recxml.FromUserName

            fromUser = Recxml.ToUserName

            '''

            你的逻辑判断和返回模块(拿文字内容和文字返回内容举例)

            content="你要返回的数据"

            '''

            replyMsg = reply.TextMsg(toUser, fromUser, content)

            return HttpResponse(reply.send())

修改项目文件夹下的urls.py:

from django.urls import path

from wxrun import views

urlpatterns=[

    path('你的url路径',views.token),

]

#4 关于验证服务器使用的加密设置

不知道是不是我的操作有问题,按照接入文档进行排序然后sha1加密生成的hashcode并不等于signature。由于token和服务器网址都在后台填写,并且验证服务器只需要返回echostr,本质上没有特别大的安全风险,所以我将views.py的代码进行了部分删减,如果有同样问题的可以使用如下代码:

import hashlib

from django.http import HttpResponse

import wxReceive as receive

import wxReply as reply

from django.views.decorators.csrf import csrf_exempt

@csrf_exempt

def token(request):

    if(request.method=='GET'):

        echostr=request.GET['echostr']

        return HttpResponse(echostr)

    else:

        Recxml=receive.parsexml(request.body) #读取信息,至于为什么不是POST,是因为这不是字典也不是表单

        if(isinstance(Recxml,receive.Msg) and Recxml.MsgType=="text"):

            toUser = Recxml.FromUserName

            fromUser = Recxml.ToUserName

            '''

            你的逻辑判断和返回模块(拿文字内容和文字返回内容举例)

            content="你要返回的数据"

            '''

            replyMsg = reply.TextMsg(toUser, fromUser, content)

            return HttpResponse(reply.send())

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值