微信支付V2.0-python

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

"""
@author: Mr_zhang
@software: PyCharm
@file: wechat_pay.py
@time: 2021/1/29 下午9:46
"""

import hashlib
import requests
from random import Random


class WeChatPay:
    """
    微信支付
    """
    def __init__(self):
        self.APP_ID = "appid"  # appid
        self.MCH_ID = "mchid"  # 商户号
        self.API_KEY = "apikey"
        self.TRADE_TYPE = "MWEB"  # 支付类型
        self.notify_url = "https://xx.com/callback/"  # 支付成功回调接口
        self.pay_url = "https://api.mch.weixin.qq.com/pay/unifiedorder"  # 下单接口
        self.CREATE_IP = "服务器ip"

    @staticmethod
    def random_str(max_length=8):
        """
        生成随机字符串
        :param max_length: 字符串长度
        :return:
        """
        _ = ''
        chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789'
        length = len(chars) - 1
        random = Random()
        for i in range(max_length):
            _ += chars[random.randint(0, length)]
        return _

    @staticmethod
    def get_sign(data_dict, key):
        """
        签名函数
        :param data_dict: 需要签名的参数,格式为字典
        :param key: 密钥 ,即上面的API_KEY
        :return: 字符串
        """
        params_list = sorted(data_dict.items(), key=lambda e: e[0], reverse=False)  # 参数字典倒排序为列表
        params_str = "&".join(u"{}={}".format(k, v) for k, v in params_list) + '&key=' + key
        # 组织参数字符串并在末尾添加商户交易密钥
        md5 = hashlib.md5()  # 使用MD5加密模式
        md5.update(params_str.encode('utf-8'))  # 将参数字符串传入
        sign = md5.hexdigest().upper()  # 完成加密并转为大写
        return sign

    @staticmethod
    def trans_dict_to_xml(data_dict):
        """
        定义字典转XML的函数
        :param data_dict:
        :return:
        """
        data_xml = []
        for k in sorted(data_dict.keys()):  # 遍历字典排序后的key
            v = data_dict.get(k)  # 取出字典中key对应的value
            if k == 'detail' and not v.startswith('<![CDATA['):  # 添加XML标记
                v = '<![CDATA[{}]]>'.format(v)
            data_xml.append('<{key}>{value}</{key}>'.format(key=k, value=v))
        return '<xml>{}</xml>'.format(''.join(data_xml))  # 返回XML

    @staticmethod
    def trans_xml_to_dict(data_xml):
        """
        定义XML转字典的函数
        :param data_xml:
        :return:
        """
        data_dict = {}
        try:
            import xml.etree.cElementTree as ET
        except ImportError:
            import xml.etree.ElementTree as ET
        root = ET.fromstring(data_xml)
        for child in root:
            data_dict[child.tag] = child.text
        return data_dict

    def wx_pay(self, order_no, order_name, order_price_detail, order_total_price):
        nonce_str = self.random_str()  # 拼接出随机的字符串即可,我这里是用  时间+随机数字+5个随机字母
        total_fee = int(float(order_total_price) * 100)  # 付款金额,单位是分,必须是整数
        params = {
            'appid': self.APP_ID,  # APPID
            'mch_id': self.MCH_ID,  # 商户号
            'nonce_str': nonce_str,  # 随机字符串
            'out_trade_no': order_no,  # 订单编号,可自定义
            'total_fee': total_fee,  # 订单总金额
            'spbill_create_ip': self.CREATE_IP,  # 自己服务器的IP地址
            'notify_url': self.notify_url,  # 回调地址,微信支付成功后会回调这个url,告知商户支付结果
            'body': order_name,  # 商品描述
            'detail': order_price_detail,  # 商品描述
            'trade_type': self.TRADE_TYPE,  # 扫码支付类型
        }

        sign = self.get_sign(params, self.API_KEY)  # 获取签名
        params['sign'] = sign  # 添加签名到参数字典
        xml = self.trans_dict_to_xml(params)  # 转换字典为XML
        response = requests.post(url=self.pay_url, data=xml.encode())  # 以POST方式向微信公众平台服务器发起请求
        data_dict = self.trans_xml_to_dict(response.content)  # 将请求返回的数据转为字典
        return data_dict


wx_pay = WeChatPay()

 V3.0过几天补上

有更好的了: https://developers.weixin.qq.com/community/develop/article/doc/00062c08da8e4888eafb08c535b813

社区:https://developers.weixin.qq.com/community/pay/doc/00022e47830e90adbd2c507c951801

 

posted @ 2021-01-30 12:31  前方、有光  阅读(163)  评论(1编辑  收藏  举报