コード例 #1
0
ファイル: utils.py プロジェクト: lyonyang/wechatpy_tornado
def rsa_decrypt(encrypted_data, pem, password=None):
    """
    rsa 解密
    :param encrypted_data: 待解密 bytes
    :param pem: RSA private key 内容/binary
    :param password: RSA private key pass phrase
    :return: 解密后的 binary
    """
    from cryptography.hazmat.backends import default_backend
    from cryptography.hazmat.primitives import serialization
    from cryptography.hazmat.primitives import hashes
    from cryptography.hazmat.primitives.asymmetric import padding

    encrypted_data = to_binary(encrypted_data)
    pem = to_binary(pem)
    private_key = serialization.load_pem_private_key(pem,
                                                     password,
                                                     backend=default_backend())
    data = private_key.decrypt(encrypted_data,
                               padding=padding.OAEP(
                                   mgf=padding.MGF1(hashes.SHA1()),
                                   algorithm=hashes.SHA1(),
                                   label=None,
                               ))
    return data
コード例 #2
0
ファイル: utils.py プロジェクト: lyonyang/wechatpy_tornado
def rsa_encrypt(data, pem, b64_encode=True):
    """
    rsa 加密
    :param data: 待加密字符串/binary
    :param pem: RSA public key 内容/binary
    :param b64_encode: 是否对输出进行 base64 encode
    :return: 如果 b64_encode=True 的话,返回加密并 base64 处理后的 string;否则返回加密后的 binary
    """
    from cryptography.hazmat.backends import default_backend
    from cryptography.hazmat.primitives import serialization
    from cryptography.hazmat.primitives import hashes
    from cryptography.hazmat.primitives.asymmetric import padding
    encoded_data = to_binary(data)
    pem = to_binary(pem)
    public_key = serialization.load_pem_public_key(pem,
                                                   backend=default_backend())
    encrypted_data = public_key.encrypt(encoded_data,
                                        padding=padding.OAEP(
                                            mgf=padding.MGF1(hashes.SHA1()),
                                            algorithm=hashes.SHA1(),
                                            label=None,
                                        ))
    if b64_encode:
        encrypted_data = base64.b64encode(encrypted_data).decode('utf-8')
    return encrypted_data
コード例 #3
0
ファイル: utils.py プロジェクト: lyonyang/wechatpy_tornado
def format_url(params, api_key=None):
    data = [
        to_binary('{0}={1}'.format(k, params[k])) for k in sorted(params)
        if params[k]
    ]
    if api_key:
        data.append(to_binary('key={0}'.format(api_key)))
    return b"&".join(data)
コード例 #4
0
    def _encrypt(self, text, _id):
        text = to_binary(text)
        tmp_list = []
        tmp_list.append(to_binary(self.get_random_string()))
        length = struct.pack(b'I', socket.htonl(len(text)))
        tmp_list.append(length)
        tmp_list.append(text)
        tmp_list.append(to_binary(_id))

        text = b''.join(tmp_list)
        text = PKCS7Encoder.encode(text)

        ciphertext = to_binary(self.cipher.encrypt(text))
        return base64.b64encode(ciphertext)
コード例 #5
0
    async def _fetch_access_token(self, url, params):
        """ The real fetch access token """
        logger.info('Fetching access token')

        params = urlencode(dict((k, to_binary(v)) for k, v in params.items()))
        url = '{0}?{1}'.format(url, params)

        req = HTTPRequest(url)
        res = await self._http.fetch(req)

        if res.error is not None:
            raise WeChatClientException(errcode=None,
                                        errmsg=None,
                                        client=self,
                                        request=req,
                                        response=res)

        result = self._decode_result(res)
        if 'errcode' in result and result['errcode'] != 0:
            raise WeChatClientException(result['errcode'],
                                        result['errmsg'],
                                        client=self,
                                        request=res.request,
                                        response=res)

        expires_in = 7200
        if 'expires_in' in result:
            expires_in = result['expires_in']
        self.session.set(self.access_token_key, result['access_token'],
                         expires_in)
        self.expires_at = int(time.time()) + expires_in
        return result
コード例 #6
0
ファイル: messages.py プロジェクト: lyonyang/wechatpy_tornado
 def __repr__(self):
     _repr = "{klass}({msg})".format(klass=self.__class__.__name__,
                                     msg=repr(self._data))
     if six.PY2:
         return to_binary(_repr)
     else:
         return to_text(_repr)
コード例 #7
0
 def encode(cls, text):
     length = len(text)
     padding_count = cls.block_size - length % cls.block_size
     if padding_count == 0:
         padding_count = cls.block_size
     padding = to_binary(chr(padding_count))
     return text + padding * padding_count
コード例 #8
0
 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)
コード例 #9
0
    async def _request(self, method, url_or_endpoint, **kwargs):
        if not url_or_endpoint.startswith(('http://', 'https://')):
            api_base_url = kwargs.pop('api_base_url', self.API_BASE_URL)
            url = '{base}{endpoint}'.format(base=api_base_url,
                                            endpoint=url_or_endpoint)
        else:
            url = url_or_endpoint

        params = kwargs.pop('params', {})

        if isinstance(kwargs['params'], dict) and \
                        'component_access_token' not in params:
            params['component_access_token'] = await self.access_token()

        params = urlencode(dict((k, to_binary(v)) for k, v in params.items()))
        url = '{0}?{1}'.format(url, params)

        data = kwargs.pop('data', {})

        if isinstance(data, dict):
            kwargs['body'] = json.dumps(data)

        req = HTTPRequest(url, method=method, **kwargs)
        res = await self._http.fetch(req)
        if res.error is not None:
            raise WeChatClientException(errcode=None,
                                        errmsg=None,
                                        client=self,
                                        request=req,
                                        response=res)

        return await self._handle_result(res, method, url, **kwargs)
コード例 #10
0
    async def _request(self, method, url_or_endpoint, **kwargs):
        if not url_or_endpoint.startswith(('http://', 'https://')):
            url = '{base}{endpoint}'.format(base=self.API_BASE_URL,
                                            endpoint=url_or_endpoint)
        else:
            url = url_or_endpoint

        params = kwargs.pop('params', {})
        params = urlencode(dict((k, to_binary(v)) for k, v in params.items()))
        url = '{0}?{1}'.format(url, params)

        data = kwargs.pop('data', {})

        if isinstance(data, dict):
            body = json.dumps(data, ensure_ascii=False)
            body = body.encode('utf-8')
            kwargs['body'] = body

        req = HTTPRequest(url, method=method, **kwargs)
        res = await self._http.fetch(req)

        if res.error is not None:
            raise WeChatOAuthException(errcode=None,
                                       errmsg=None,
                                       client=self,
                                       request=req,
                                       response=res)

        return await self._handle_result(res, method=method, url=url, **kwargs)
コード例 #11
0
 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)
コード例 #12
0
ファイル: __init__.py プロジェクト: lyonyang/wechatpy_tornado
    async def _request(self, method, url_or_endpoint, **kwargs):
        if not url_or_endpoint.startswith(('http://', 'https://')):
            api_base_url = kwargs.pop('api_base_url', self.API_BASE_URL)
            if self.sandbox:
                api_base_url = '{url}sandboxnew/'.format(url=api_base_url)
            url = '{base}{endpoint}'.format(
                base=api_base_url,
                endpoint=url_or_endpoint
            )
        else:
            url = url_or_endpoint

        params = kwargs.pop('params', {})
        params = urlencode(dict((k, to_binary(v)) for k, v in params.items()))
        url = '{0}?{1}'.format(url, params)

        data = kwargs.pop('data', {})

        if isinstance(data, dict):
            if 'mchid' not in data:
                data.setdefault('mch_id', self.mch_id)
            data.setdefault('sub_mch_id', self.sub_mch_id)
            data.setdefault('nonce_str', random_string(32))
            data = optionaldict(data)

            if data.get('sign_type', 'MD5') == 'HMAC-SHA256':
                sign = calculate_signature_hmac(data, await self.sandbox_api_key() if self.sandbox else self.api_key)
            else:
                sign = calculate_signature(data, await self.sandbox_api_key() if self.sandbox else self.api_key)
            body = dict_to_xml(data, sign)
            body = body.encode('utf-8')
            kwargs['body'] = body

        # 商户证书
        if self.mch_cert and self.mch_key:
            ssl_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
            ssl_ctx.load_cert_chain(self.mch_cert, self.mch_key)
            kwargs['ssl_options'] = ssl_ctx

        kwargs['request_timeout'] = kwargs.pop('timeout') if 'timeout' in kwargs else self.timeout
        logger.debug('Request to WeChat API: %s %s\n%s', method, url, kwargs)

        req = HTTPRequest(
            url,
            method=method,
            **kwargs
        )

        res = await self._http.fetch(req)
        if res.error is not None:
            raise WeChatPayException(
                return_code=None,
                client=self,
                request=req,
                response=res
            )

        return self._handle_result(res)
コード例 #13
0
ファイル: fields.py プロジェクト: lyonyang/wechatpy_tornado
 def __repr__(self):
     _repr = '{klass}({name})'.format(
         klass=self.__class__.__name__,
         name=repr(self.name)
     )
     if six.PY2:
         return to_binary(_repr)
     else:
         return to_text(_repr)
コード例 #14
0
 def __str__(self):
     _str = '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)
     if six.PY2:
         return to_binary(_str)
     else:
         return to_text(_str)
コード例 #15
0
 def _decrypt(self, text, _id, exception=None):
     text = to_binary(text)
     plain_text = self.cipher.decrypt(base64.b64decode(text))
     padding = byte2int(plain_text[-1])
     content = plain_text[16:-padding]
     xml_length = socket.ntohl(struct.unpack(b'I', content[:4])[0])
     xml_content = to_text(content[4:xml_length + 4])
     from_id = to_text(content[xml_length + 4:])
     if from_id != _id:
         exception = exception or Exception
         raise exception()
     return xml_content
コード例 #16
0
    async def delete_account(self, account):
        """
        删除客服账号
        详情请参考
        http://mp.weixin.qq.com/wiki/1/70a29afed17f56d537c833f89be979c9.html

        :param account: 完整客服账号,格式为:账号前缀@公众号微信号
        :return: 返回的 JSON 数据包
        """
        params_data = [
            'access_token={0}'.format(quote(await self.access_token())),
            'kf_account={0}'.format(quote(to_binary(account), safe=b'/@')),
        ]
        params = '&'.join(params_data)
        return await self._get(
            'https://api.weixin.qq.com/customservice/kfaccount/del',
            params=params)
コード例 #17
0
    async def update_account(self, account, nickname, password):
        """
        更新客服账号
        详情请参考
        http://mp.weixin.qq.com/wiki/1/70a29afed17f56d537c833f89be979c9.html

        :param account: 完整客服账号,格式为:账号前缀@公众号微信号
        :param nickname: 客服昵称,最长6个汉字或12个英文字符
        :param password: 客服账号登录密码
        :return: 返回的 JSON 数据包
        """
        password = to_binary(password)
        password = hashlib.md5(password).hexdigest()
        return await self._post(
            'https://api.weixin.qq.com/customservice/kfaccount/update',
            data={
                'kf_account': account,
                'nickname': nickname,
                'password': password
            })
コード例 #18
0
    async def _request(self, method, url_or_endpoint, **kwargs):
        if not url_or_endpoint.startswith(('http://', 'https://')):
            api_base_url = kwargs.pop('api_base_url', self.API_BASE_URL)
            url = '{base}{endpoint}'.format(base=api_base_url,
                                            endpoint=url_or_endpoint)
        else:
            url = url_or_endpoint

        params = kwargs.pop('params', {})
        if 'access_token' not in params:
            params['access_token'] = await self.access_token()

        params = urlencode(dict((k, to_binary(v)) for k, v in params.items()))
        url = '{0}?{1}'.format(url, params)

        data = kwargs.pop('data') if 'data' in kwargs else {}

        if isinstance(data, dict):
            body = json.dumps(data, ensure_ascii=False)
            body = body.encode('utf-8')
            kwargs['body'] = body

        kwargs['request_timeout'] = kwargs.pop('timeout', self.timeout)
        result_processor = kwargs.pop('result_processor', None)
        req = HTTPRequest(url, method=method, **kwargs)
        res = await self._http.fetch(req)

        if res.error is not None:
            raise WeChatClientException(errcode=None,
                                        errmsg=None,
                                        client=self,
                                        request=req,
                                        response=res)

        return self._handle_result(res, method, url, result_processor,
                                   **kwargs)
コード例 #19
0
 def _decrypt(self, text, exception=None):
     text = to_binary(text)
     plain_text = self.cipher.decrypt(base64.b64decode(text))
     padding = byte2int(plain_text[-1])
     content = plain_text[:-padding]
     return content
コード例 #20
0
    def _encrypt(self, text):
        text = to_binary(text)
        text = PKCS7Encoder.encode(text)

        ciphertext = to_binary(self.cipher.encrypt(text))
        return base64.b64encode(ciphertext)
コード例 #21
0
 def __init__(self, key):
     self.key = to_binary(hashlib.md5(to_binary(key)).hexdigest())
     assert len(self.key) == 32
コード例 #22
0
 def __init__(self, token, encoding_aes_key, _id):
     encoding_aes_key = to_binary(encoding_aes_key + '=')
     self.key = base64.b64decode(encoding_aes_key)
     assert len(self.key) == 32
     self.token = token
     self._id = _id
コード例 #23
0
ファイル: replies.py プロジェクト: lyonyang/wechatpy_tornado
 def __str__(self):
     if six.PY2:
         return to_binary(self.render())
     else:
         return to_text(self.render())
コード例 #24
0
ファイル: fields.py プロジェクト: lyonyang/wechatpy_tornado
 def __base64_decode(self, text):
     return to_text(base64.b64decode(to_binary(text)))