def dict_to_xml(d, sign): xml = ['<xml>\n'] for k in sorted(d): # use sorted to avoid test error on Py3k v = d[k] if isinstance(v, six.integer_types) or v.isdigit(): xml.append('<{0}>{1}</{0}>\n'.format(to_text(k), to_text(v))) else: xml.append('<{0}><![CDATA[{1}]]></{0}>\n'.format( to_text(k), to_text(v))) xml.append('<sign><![CDATA[{0}]]></sign>\n</xml>'.format(to_text(sign))) return ''.join(xml)
def __str__(self): if six.PY2: return to_binary('{code}: {msg}'.format(code=self.errcode, msg=self.errmsg)) else: return to_text('{code}: {msg}'.format(code=self.errcode, msg=self.errmsg))
def _encrypt_message(self, msg, nonce, timestamp=None): """将公众号回复用户的消息加密打包 :param msg: 待回复用户的消息,xml格式的字符串 :param nonce: 随机串,可以自己生成,也可以用URL参数的nonce :param timestamp: 时间戳,可以自己生成,也可以用URL参数的timestamp,如为None则自动用当前时间 :return: 加密后的可以直接回复用户的密文,包括msg_signature, timestamp, nonce, encrypt的xml格式的字符串 """ xml = """<xml> <Encrypt><![CDATA[{encrypt}]]></Encrypt> <MsgSignature><![CDATA[{signature}]]></MsgSignature> <TimeStamp>{timestamp}</TimeStamp> <Nonce><![CDATA[{nonce}]]></Nonce> </xml>""" nonce = to_binary(nonce) timestamp = to_binary(timestamp) or to_binary(int(time.time())) encrypt = self.__pc.encrypt(msg, self.__id) # 生成安全签名 signature = get_sha1_signature(self.__token, timestamp, nonce, encrypt) return to_text(xml.format( encrypt=encrypt, signature=signature, timestamp=timestamp, nonce=nonce ))
def __str__(self): _repr = 'Error code: {code}, message: {msg}'.format(code=self.errcode, msg=self.errmsg) if six.PY2: return to_binary(_repr) else: return to_text(_repr)
def __repr__(self): _repr = '{klass}({code}, {msg})'.format(klass=self.__class__.__name__, code=self.errcode, msg=self.errmsg) if six.PY2: return to_binary(_repr) else: return to_text(_repr)
def __str__(self): if six.PY2: return to_binary( 'Error code: {code}, message: {msg}. Pay Error code: {pay_code}, message: {pay_msg}' .format(code=self.return_code, msg=self.return_msg, pay_code=self.errcode, pay_msg=self.errmsg)) else: return to_text( 'Error code: {code}, message: {msg}. Pay Error code: {pay_code}, message: {pay_msg}' .format(code=self.return_code, msg=self.return_msg, pay_code=self.errcode, pay_msg=self.errmsg))
def get_jsapi_signature(self, prepay_id, timestamp=None, nonce_str=None): """ 获取 JSAPI 签名 :param prepay_id: 统一下单接口返回的 prepay_id 参数值 :param timestamp: 可选,时间戳,默认为当前时间戳 :param nonce_str: 可选,随机字符串,默认自动生成 :return: 签名 """ data = { 'appId': self.appid, 'timeStamp': timestamp or to_text(int(time.time())), 'nonceStr': nonce_str or random_string(32), 'signType': 'MD5', 'package': 'prepay_id={0}'.format(prepay_id), } return calculate_signature(data, self._client.api_key)
def get_appapi_params(self, prepay_id, timestamp=None, nonce_str=None): """ 获取 APP 支付参数 :param prepay_id: 统一下单接口返回的 prepay_id 参数值 :param timestamp: 可选,时间戳,默认为当前时间戳 :param nonce_str: 可选,随机字符串,默认自动生成 :return: 签名 """ data = { 'appid': self.appid, 'partnerid': self.mch_id, 'prepayid': prepay_id, 'package': 'Sign=WXPay', 'timestamp': timestamp or to_text(int(time.time())), 'noncestr': nonce_str or random_string(32) } sign = calculate_signature(data, self._client.api_key) data['sign'] = sign return data
def _decrypt_message(self, msg, msg_signature, timestamp, nonce): """检验消息的真实性,并且获取解密后的明文 :param msg: 密文,对应POST请求的数据 :param msg_signature: 签名串,对应URL参数的msg_signature :param timestamp: 时间戳,对应URL参数的timestamp :param nonce: 随机串,对应URL参数的nonce :return: 解密后的原文 """ timestamp = to_binary(timestamp) nonce = to_binary(nonce) try: msg = xmltodict.parse(to_text(msg))['xml'] except Exception as e: raise ParseError(e) encrypt = msg['Encrypt'] signature = get_sha1_signature(self.__token, timestamp, nonce, encrypt) if signature != msg_signature: raise ValidateSignatureError() return self.__pc.decrypt(encrypt, self.__id)
def _decrypt_message(self, msg, msg_signature, timestamp, nonce): """检验消息的真实性,并且获取解密后的明文 :param msg: 密文,对应POST请求的数据 :param msg_signature: 签名串,对应URL参数的msg_signature :param timestamp: 时间戳,对应URL参数的timestamp :param nonce: 随机串,对应URL参数的nonce :return: 解密后的原文 """ timestamp = to_binary(timestamp) nonce = to_binary(nonce) if isinstance(msg, six.string_types): try: msg = xmltodict.parse(to_text(msg))['xml'] except Exception as e: raise ParseError(e) encrypt = msg['Encrypt'] signature = get_sha1_signature(self.__token, timestamp, nonce, encrypt) if signature != msg_signature: raise ValidateSignatureError() return self.__pc.decrypt(encrypt, self.__id)
def _encrypt_message(self, msg, nonce, timestamp=None): """将公众号回复用户的消息加密打包 :param msg: 待回复用户的消息,xml格式的字符串 :param nonce: 随机串,可以自己生成,也可以用URL参数的nonce :param timestamp: 时间戳,可以自己生成,也可以用URL参数的timestamp,如为None则自动用当前时间 :return: 加密后的可以直接回复用户的密文,包括msg_signature, timestamp, nonce, encrypt的xml格式的字符串 """ xml = """<xml> <Encrypt><![CDATA[{encrypt}]]></Encrypt> <MsgSignature><![CDATA[{signature}]]></MsgSignature> <TimeStamp>{timestamp}</TimeStamp> <Nonce><![CDATA[{nonce}]]></Nonce> </xml>""" nonce = to_binary(nonce) timestamp = to_binary(timestamp) or to_binary(int(time.time())) encrypt = self.__pc.encrypt(msg, self.__id) # 生成安全签名 signature = get_sha1_signature(self.__token, timestamp, nonce, encrypt) return to_text( xml.format(encrypt=encrypt, signature=signature, timestamp=timestamp, nonce=nonce))
def __str__(self): if six.PY2: return to_binary(self.message) else: return to_text(self.message)
def calculate_signature(params, api_key): url = format_url(params, api_key) return to_text(hashlib.md5(url).hexdigest().upper())