1 进入微信公众号首页,页面底部找到”开发/基本配置“,得到AppID(开发者ID)和AppSecret(开发者密码),并增加到GeneralTools下的Contants.py文件中。
""" 微信相关常量 """ # 微信的token令牌 WECHAT_TOKEN = "tongheng" WECHAT_APPID = "" #隐藏 WECHAT_APPSECRET = "" 隐藏 # 微信服务器IP地址 SERVER_ID_ADDRESS = '' # 隐藏 SERVER_ID_PORT = '5379' # 缓存公众号access_token WECHATPY_ACCESS_TOKEN_CACHE = 'redis://:cgl139@' + SERVER_ID_ADDRESS + ':' + SERVER_ID_PORT + '/3'
2 新增一个名为Wechart的APP,并配置。
3 在Wechar/views目录下创建文件Method.py
import hashlib from wechatpy.oauth import WeChatOAuth from wechatpy.client import WeChatClient from wechatpy.session.redisstorage import RedisStorage from redis import Redis from GeneralTools import Constants def generate_signature(timestamp, nonce): """ 生成微信加密签名 :param timestamp: 时间戳 :param nonce: 随机数 :return: signature """ # 按照微信的流程进行计算签名 sortlist = [Constants.WECHAT_TOKEN, timestamp, nonce] # 排序 # 1)将token、timestamp、nonce三个参数进行字典序排序 sortlist.sort() # 拼接字符串 tmp_str = "".join(sortlist) # 进行sha1加密, 得到正确的签名值 # 2)将三个参数字符串拼接成一个字符串进行sha1加密 # signature = hashlib.sha1(tmp_str).hexdigest() sha = hashlib.sha1() sha.update(tmp_str.encode('utf-8')) signature = sha.hexdigest() return signature def get_WeChatOAuth(redirect_uri, state='123', scope='snsapi_userinfo'): """ 获取WeChatOAuth对象 :param redirect_uri: 授权后重定向的回调链接地址, 请使用 urlEncode 对链接进行处理 :param scope:应用授权作用域,snsapi_base,snsapi_userinfo :param state:重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节 :return: WeChatOAuth对象 """ return WeChatOAuth( app_id=Constants.WECHAT_APPID, secret=Constants.WECHAT_APPSECRET, redirect_uri=redirect_uri, scope=scope, state=state ) def get_WeChatClient(): """ 获取WeChatClient对象 :return:WeChatClient对象 """ redis_client = Redis.from_url(Constants.WECHATPY_ACCESS_TOKEN_CACHE) session_interface = RedisStorage( redis_client, prefix="wechatpy" ) return WeChatClient( Constants.WECHAT_APPID, Constants.WECHAT_APPSECRET, session=session_interface ) def get_authorize_url(redirect_uri, state): """ 获取授权跳转地址 :return: authorize_url """ wechatOAuth = get_WeChatOAuth(redirect_uri, state) return wechatOAuth.authorize_url
3 在Wechart/views目录下创建文件:Interface.py,内容如下:
from rest_framework import status import logging from django.http import HttpResponse import xmltodict import time from django.views.generic import View from .Method import generate_signature # 获取在配置文件中定义的logger,用来记录日志 logger = logging.getLogger('tongheng2') class Interface(View): """ 微信公众号开发服务器配置 """ @classmethod def get(cls, request): """ 【功能描述】微信服务器验证消息</br> :param request:GET请求携带参数(signature、timestamp、nonce、echostr)</br> :return:原样返回echostr参数</br> """ logger.info("body:%s" % request.body) # logger.info("path:%s" % request.path) # logger.info("method:%s" % request.method) logger.info("GET:%s" % request.GET) logger.info("POST:%s" % request.POST) # logger.info("META:%s" % request.META) # 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。 signature = request.GET.get('signature') # 时间戳 timestamp = request.GET.get('timestamp') # 随机数 nonce = request.GET.get('nonce') # 随机字符串 echostr = request.GET.get('echostr') logger.info("signature:%s" % signature) logger.info("timestamp:%s" % timestamp) logger.info("nonce:%s" % nonce) logger.info("echostr:%s" % echostr) # 校验参数 if not all([signature, timestamp, nonce, echostr]): # 请求参数错误 return HttpResponse(status.HTTP_400_BAD_REQUEST) # 进行sha1加密, 得到正确的签名值 sign = generate_signature(timestamp, nonce) logger.info("sign:%s" % sign) # 将自己计算的签名值与请求的签名参数进行对比,如果相同,则证明请求来自微信服务器 if signature != sign: # 微信签名错误 return HttpResponse(status.HTTP_403_FORBIDDEN) else: # return Response(data=echostr, status=status.HTTP_200_OK) return HttpResponse(echostr) # http://127.0.0.1:8000/ThirdParts/wechat/ # POST /ThirdParts/wechat/ @classmethod def post(cls, request): """ 【功能描述】当普通微信用户向公众账号发消息时,微信服务器将POST消息的XML数据包到开发者填写的URL上。 """ logger.info("body:%s" % request.body) # logger.info("path:%s" % request.path) # logger.info("method:%s" % request.method) logger.info("GET:%s" % request.GET) logger.info("POST:%s" % request.POST) # logger.info("META:%s" % request.META) xml_str = request.body if not xml_str: # 请求参数错误 return HttpResponse(status.HTTP_400_BAD_REQUEST) # 对xml字符串进行解析 xml_dict = xmltodict.parse(xml_str) xml_dict = xml_dict.get("xml") # 提取消息类型 msg_type = xml_dict.get("MsgType") if msg_type == "text": # 表示发送的是文本消息 # 构造返回值,经由微信服务器回复给用户的消息内容 resp_dict = { "xml": { "ToUserName": xml_dict.get("FromUserName"), "FromUserName": xml_dict.get("ToUserName"), "CreateTime": int(time.time()), "MsgType": "text", "Content": xml_dict.get("Content") } } else: resp_dict = { "xml": { "ToUserName": xml_dict.get("FromUserName"), "FromUserName": xml_dict.get("ToUserName"), "CreateTime": int(time.time()), "MsgType": "text", "Content": "i love u" } } # 将字典转换为xml字符串 resp_xml_str = xmltodict.unparse(resp_dict) # 返回消息数据给微信服务器 return HttpResponse(resp_xml_str)
4 配置url
from django.urls import path from .views import Interface urlpatterns = [ path('Interface/', Interface.Interface.as_view()), ]
5 发布到服务器