# -*- 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過幾天補上