Ejemplo n.º 1
0
    def _encrypt_message(self,
                         msg,
                         nonce,
                         timestamp=None,
                         crypto_class=None):
        from wechatpy_tornado.replies import BaseReply

        xml = """<xml>
<Encrypt><![CDATA[{encrypt}]]></Encrypt>
<MsgSignature><![CDATA[{signature}]]></MsgSignature>
<TimeStamp>{timestamp}</TimeStamp>
<Nonce><![CDATA[{nonce}]]></Nonce>
</xml>"""
        if isinstance(msg, BaseReply):
            msg = msg.render()
        timestamp = timestamp or to_text(int(time.time()))
        pc = crypto_class(self.key)
        encrypt = to_text(pc.encrypt(msg, self._id))
        signature = _get_signature(self.token, timestamp, nonce, encrypt)
        return to_text(xml.format(
            encrypt=encrypt,
            signature=signature,
            timestamp=timestamp,
            nonce=nonce
        ))
Ejemplo n.º 2
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
Ejemplo n.º 3
0
    def _decrypt_message(self, msg, appid, mch_id, crypto_class=None):
        import xmltodict
        if not isinstance(msg, dict):
            msg = xmltodict.parse(to_text(msg))['xml']

        req_info = msg['req_info']
        if msg['appid'] != appid:
            raise InvalidAppIdException()
        if msg['mch_id'] != mch_id:
            raise InvalidMchIdException()
        pc = crypto_class(self.key)
        ret = pc.decrypt(req_info)
        return xmltodict.parse(to_text(ret))['root']
Ejemplo n.º 4
0
    async def update(self, group_id, name):
        """
        修改分组名

        详情请参考
        http://mp.weixin.qq.com/wiki/0/56d992c605a97245eb7e617854b169fc.html

        :param group_id: 分组id,由微信分配
        :param name: 分组名字(30个字符以内)
        :return: 返回的 JSON 数据包

        使用示例::

            from wechatpy_tornado import WeChatClient

            client = WeChatClient('appid', 'secret')
            res = client.group.update(1234, 'New Name')

        """
        name = to_text(name)
        return await self._post(
            'groups/update',
            data={
                'group': {
                    'id': int(group_id),
                    'name': name
                }
            }
        )
Ejemplo n.º 5
0
 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)
Ejemplo n.º 6
0
    async def get_jsapi_params(self,
                               prepay_id,
                               timestamp=None,
                               nonce_str=None,
                               jssdk=False):
        """
        获取 JSAPI 参数

        :param prepay_id: 统一下单接口返回的 prepay_id 参数值
        :param timestamp: 可选,时间戳,默认为当前时间戳
        :param nonce_str: 可选,随机字符串,默认自动生成
        :param jssdk: 前端调用方式,默认使用 WeixinJSBridge
                      使用 jssdk 调起支付的话,timestamp 的 s 为小写
                      使用 WeixinJSBridge 调起支付的话,timeStamp 的 S 为大写
        :return: 参数
        """
        data = {
            'appId': self.sub_appid or 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),
        }
        sign = calculate_signature(
            data, self._client.api_key if not self._client.sandbox else await
            self._client.sandbox_api_key())
        logger.debug('JSAPI payment parameters: data = %s, sign = %s', data,
                     sign)
        data['paySign'] = sign
        if jssdk:
            data['timestamp'] = data.pop('timeStamp')
        return data
Ejemplo n.º 7
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)
Ejemplo n.º 8
0
def parse_message(xml):
    """
    解析微信服务器推送的 XML 消息

    :param xml: XML 消息
    :return: 解析成功返回对应的消息或事件,否则返回 ``UnknownMessage``
    """
    if not xml:
        return
    message = xmltodict.parse(to_text(xml))['xml']
    message_type = message['MsgType'].lower()
    event_type = None
    if message_type == 'event' or message_type.startswith('device_'):
        if 'Event' in message:
            event_type = message['Event'].lower()
        # special event type for device_event
        if event_type is None and message_type.startswith('device_'):
            event_type = message_type
        elif message_type.startswith('device_'):
            event_type = 'device_{event}'.format(event=event_type)

        if event_type == 'subscribe' and message.get('EventKey'):
            event_key = message['EventKey']
            if event_key.startswith(('scanbarcode|', 'scanimage|')):
                event_type = 'subscribe_scan_product'
                message['Event'] = event_type
            elif event_key.startswith('qrscene_'):
                # Scan to subscribe with scene id event
                event_type = 'subscribe_scan'
                message['Event'] = event_type
                message['EventKey'] = event_key[len('qrscene_'):]
        message_class = EVENT_TYPES.get(event_type, UnknownMessage)
    else:
        message_class = MESSAGE_TYPES.get(message_type, UnknownMessage)
    return message_class(message)
Ejemplo n.º 9
0
 def decrypt_message(self, msg):
     raw_data = base64.b64decode(msg)
     decrypted = self.cipher.decrypt(raw_data)
     plaintext = PKCS7Encoder.decode(decrypted)
     decrypted_msg = json.loads(to_text(plaintext))
     if decrypted_msg['watermark']['appid'] != self.app_id:
         raise InvalidAppIdException()
     return decrypted_msg
Ejemplo n.º 10
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)
Ejemplo n.º 11
0
 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)
Ejemplo n.º 12
0
def dict_to_xml(d, sign=None):
    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 (isinstance(v, six.string_types)
                                             and 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)))
    if sign:
        xml.append('<sign><![CDATA[{0}]]></sign>\n</xml>'.format(
            to_text(sign)))
    else:
        xml.append('</xml>')
    return ''.join(xml)
Ejemplo n.º 13
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)
Ejemplo n.º 14
0
def parse_message(xml):
    if not xml:
        return
    message = xmltodict.parse(to_text(xml))['xml']
    message_type = message['MsgType'].lower()
    if message_type == 'event':
        event_type = message['Event'].lower()
        message_class = EVENT_TYPES.get(event_type, UnknownMessage)
    else:
        message_class = MESSAGE_TYPES.get(message_type, UnknownMessage)
    return message_class(message)
Ejemplo n.º 15
0
    async def create(self, name):
        """
        创建标签

        :param name: 标签名(30个字符以内)
        :return: 返回的 JSON 数据包

        """
        name = to_text(name)
        return await self._post('tags/create',
                                data={'tag': {
                                    'name': name
                                }},
                                result_processor=lambda x: x['tag'])
Ejemplo n.º 16
0
    async def update(self, tag_id, name):
        """
        编辑标签

        :param tag_id: 标签id,由微信分配
        :param name: 标签名字(30个字符以内)
        :return: 返回的 JSON 数据包

        """
        name = to_text(name)
        return await self._post(
            'tags/update', data={'tag': {
                'id': int(tag_id),
                'name': name
            }})
Ejemplo n.º 17
0
    def get_unauthorized(self, msg, signature, timestamp, nonce):
        """
        处理取消授权通知

        :params msg: 加密内容
        :params signature: 消息签名
        :params timestamp: 时间戳
        :params nonce: 随机数
        """
        warnings.warn(
            '`get_unauthorized` method of `WeChatComponent` is deprecated,'
            'Use `parse_message` instead',
            DeprecationWarning,
            stacklevel=2)
        content = self.crypto.decrypt_message(msg, signature, timestamp, nonce)
        message = xmltodict.parse(to_text(content))['xml']
        return ComponentUnauthorizedMessage(message)
Ejemplo n.º 18
0
    def _decrypt_message(self,
                         msg,
                         signature,
                         timestamp,
                         nonce,
                         crypto_class=None):
        if not isinstance(msg, dict):
            import xmltodict

            msg = xmltodict.parse(to_text(msg))['xml']

        encrypt = msg['Encrypt']
        _signature = _get_signature(self.token, timestamp, nonce, encrypt)
        if _signature != signature:
            raise InvalidSignatureException()
        pc = crypto_class(self.key)
        return pc.decrypt(encrypt, self._id)
Ejemplo n.º 19
0
    def cache_component_verify_ticket(self, msg, signature, timestamp, nonce):
        """
        处理 wechat server 推送的 component_verify_ticket消息

        :params msg: 加密内容
        :params signature: 消息签名
        :params timestamp: 时间戳
        :params nonce: 随机数
        """
        warnings.warn(
            '`cache_component_verify_ticket` method of `WeChatComponent` is deprecated,'
            'Use `parse_message` instead',
            DeprecationWarning,
            stacklevel=2)
        content = self.crypto.decrypt_message(msg, signature, timestamp, nonce)
        message = xmltodict.parse(to_text(content))['xml']
        o = ComponentVerifyTicketMessage(message)
        self.session.set(o.type, o.verify_ticket)
Ejemplo n.º 20
0
    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
Ejemplo n.º 21
0
    async 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.sub_appid or 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 if not self._client.sandbox else await
            self._client.sandbox_api_key())
Ejemplo n.º 22
0
    async def parse_message(self, msg, msg_signature, timestamp, nonce):
        """
        处理 wechat server 推送消息

        :params msg: 加密内容
        :params msg_signature: 消息签名
        :params timestamp: 时间戳
        :params nonce: 随机数
        """
        content = self.crypto.decrypt_message(msg, msg_signature, timestamp,
                                              nonce)
        message = xmltodict.parse(to_text(content))['xml']
        message_type = message['InfoType'].lower()
        message_class = COMPONENT_MESSAGE_TYPES.get(message_type,
                                                    ComponentUnknownMessage)
        msg = message_class(message)
        if msg.type == 'component_verify_ticket':
            self.session.set(msg.type, msg.verify_ticket)
        elif msg.type in ('authorized', 'updateauthorized'):
            msg.query_auth_result = await self.query_auth(
                msg.authorization_code)
        return msg
Ejemplo n.º 23
0
    async def create(self, name):
        """
        创建分组

        详情请参考
        http://mp.weixin.qq.com/wiki/0/56d992c605a97245eb7e617854b169fc.html

        :param name: 分组名字(30个字符以内)
        :return: 返回的 JSON 数据包

        使用示例::

            from wechatpy_tornado import WeChatClient

            client = WeChatClient('appid', 'secret')
            res = client.group.create('New Group')

        """
        name = to_text(name)
        return await self._post(
            'groups/create',
            data={'group': {'name': name}}
        )
Ejemplo n.º 24
0
 def __str__(self):
     if six.PY2:
         return to_binary(self.render())
     else:
         return to_text(self.render())
Ejemplo n.º 25
0
 def __base64_decode(self, text):
     return to_text(base64.b64decode(to_binary(text)))
Ejemplo n.º 26
0
def calculate_signature_hmac(params, api_key):
    url = format_url(params, api_key)
    sign = to_text(
        hmac.new(api_key.encode(), msg=url,
                 digestmod=hashlib.sha256).hexdigest().upper())
    return sign
Ejemplo n.º 27
0
def calculate_signature(params, api_key):
    url = format_url(params, api_key)
    logger.debug("Calculate Signature URL: %s", url)
    return to_text(hashlib.md5(url).hexdigest().upper())
Ejemplo n.º 28
0
 def get(self, key, default=None):
     key = self.key_name(key)
     value = self.mc.get(key)
     if value is None:
         return default
     return json.loads(to_text(value))
Ejemplo n.º 29
0
 def __to_text(self, value):
     return to_text(value)