0012 微信开发(微信接入)

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 发布到服务器

猜你喜欢

转载自www.cnblogs.com/dorian/p/12355246.html