# coding=utf-8 import uuid import os import requests import json import xmltodict import time from hashlib import md5 from django.conf import settings from utils.exceptions import CustomError class WechatTenantPay(): def __init__(self, appid, mch_id, partner_trade_no, openid, amount, merchant_key, cert, key): self.params = { 'mch_appid': appid, # 申请商户号的appid或商户号绑定的appid 'mchid': mch_id, # 微信支付分配的商户号 'nonce_str': generate_nonce_str(), # 随机字符串,不长于32位 'partner_trade_no': partner_trade_no, # 商户订单号,需保持唯一性 'openid': openid, # 商户appid下,某用户的openid 'check_name': 'NO_CHECK', # 校验用户姓名选项 'amount': amount, # 金额 企业付款金额 单位为分 'desc': u'佣金', # 企业付款备注 } self.params['sign'] = generate_sign(self.params, merchant_key) self.url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers' self.cert_file = cert self.cert_key = key def pay(self): result = send_cert_request(self.url, self.params, self.cert_file, self.cert_key) return result class PayQuery(): def __init__(self, partner_trade_no, mch_id, appid, merchant_key, cert, key): self.url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo' self.cert_file = cert self.cert_key = key self.params = { 'nonce_str': generate_nonce_str(), 'partner_trade_no': partner_trade_no, 'mch_id': mch_id, 'appid': appid, } self.params['sign'] = generate_sign(self.params, merchant_key) def query(self): result = send_cert_request(self.url, self.params, self.cert_file, self.cert_key) return result def send_cert_request(url, param, cert_file, cert_key): ''' 发送携带证书的xml请求 ''' xml = xmltodict.unparse({'root': param}) response = requests.post(url, data=xml.encode('utf-8'), headers={'Content-Type': 'text/xml'}, cert=(cert_file, cert_key), verify=False) xmlmsg = json.loads(json.dumps(xmltodict.parse(response.content)))['xml'] print(xmlmsg) return xmlmsg def generate_nonce_str(): """ 生成随机字符串 """ return str(uuid.uuid4()).replace('-', '') def generate_sign(params, merchant_key): """ 生成md5签名的参数 """ if 'sign' in params: params.pop('sign') src = '&'.join(['%s=%s' % (k, v) for k, v in sorted(params.items())]) + '&key=%s' % merchant_key return md5(src.encode('utf-8')).hexdigest().upper() def validate_sign(resp_dict, merchant_key): """ 验证微信返回的签名 """ if 'sign' not in resp_dict: return False wx_sign = resp_dict['sign'] sign = generate_sign(resp_dict, merchant_key) if sign == wx_sign: return True return False def generate_response_data(resp_dict): """ 字典转xml """ return xmltodict.unparse({'xml': resp_dict}, pretty=True, full_document=False).encode('utf-8')