Ejemplo n.º 1
0
    def _encrypt_message(self,
                         msg,
                         nonce,
                         timestamp=None,
                         crypto_class=None):
        from wechatpy.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_binary(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 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 (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))
            )
    xml.append('<sign><![CDATA[{0}]]></sign>\n</xml>'.format(to_text(sign)))
    return ''.join(xml)
Ejemplo n.º 4
0
    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 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.º 5
0
    def test_base64decode_field_to_xml(self):
        from wechatpy.fields import Base64DecodeField

        content = to_text(base64.b64encode(b"test"))
        field = Base64DecodeField("Content")
        expected = "<Content><![CDATA[test]]></Content>"
        self.assertEqual(expected, field.to_xml(content))
Ejemplo n.º 6
0
    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 import WeChatClient

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

        """
        name = to_text(name)
        return self._post(
            'groups/update',
            data={
                'group': {
                    'id': int(group_id),
                    'name': name
                }
            }
        )
Ejemplo n.º 7
0
    def test_base64encode_field_to_xml(self):
        from wechatpy.fields import Base64EncodeField

        content = b"test"
        field = Base64EncodeField("Content")
        expected = "<Content><![CDATA[{content}]]></Content>".format(content=to_text(base64.b64encode(content)))
        self.assertEqual(expected, field.to_xml(content))
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()
    if message_type in ('event', 'device_event'):
        event_type = message['Event'].lower()
        # special event type for device_event
        if message_type == 'device_event':
            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
            else:
                # Scan to subscribe with scene id event
                event_type = 'subscribe_scan'
                message['Event'] = event_type
            message['EventKey'] = event_key.replace('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 get(self, key):
     key = self.key_name(key)
     value = self.mc.get(key)
     if not value:
         return None
     try:
         return json.loads(to_text(value))
     except ValueError:
         return value
Ejemplo n.º 10
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.º 11
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.º 12
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.º 13
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.º 14
0
    def get_jssdk_config(self, request, debug=None):
        import time
        from wechatpy.utils import random_string, to_text
        from wechatpy.client.api import WeChatJSAPI
        jsapi = WeChatJSAPI(self.get_wechat_client())
        ticket = jsapi.get_jsapi_ticket()
        nonce_str = random_string(32)
        timestamp = to_text(int(time.time()))
        url = request.META.get('HTTP_REFERER')
        signature = jsapi.get_jsapi_signature(nonce_str, ticket, timestamp, url)
        debug = bool(request.GET.get('debug')) if debug is None else debug

        return dict(
            debug=debug,
            appId=self.app_id,
            timestamp=timestamp,
            nonceStr=nonce_str,
            signature=signature,
            jsApiList=[
                'checkJsApi',
                'onMenuShareTimeline',
                'onMenuShareAppMessage',
                'onMenuShareQQ',
                'onMenuShareWeibo',
                'hideMenuItems',
                'showMenuItems',
                'hideAllNonBaseMenuItem',
                'showAllNonBaseMenuItem',
                'translateVoice',
                'startRecord',
                'stopRecord',
                'onRecordEnd',
                'playVoice',
                'pauseVoice',
                'stopVoice',
                'uploadVoice',
                'downloadVoice',
                'chooseImage',
                'previewImage',
                'uploadImage',
                'downloadImage',
                'getNetworkType',
                'openLocation',
                'getLocation',
                'hideOptionMenu',
                'showOptionMenu',
                'closeWindow',
                'scanQRCode',
                'chooseWXPay',
                'openProductSpecificView',
                'addCard',
                'chooseCard',
                'openCard'
            ],
        )
Ejemplo n.º 15
0
 def get_jsapi_params(self, prepay_id):
     """ 返回 jsapi 的付款对象 """
     import time
     from wechatpy.pay import api
     from wechatpy.utils import random_string, to_text
     jsapi = api.WeChatJSAPI(self.wechat_pay())
     return jsapi.get_jsapi_params(
         prepay_id=prepay_id,
         nonce_str=random_string(32),
         timestamp=to_text(int(time.time())),
     )
Ejemplo n.º 16
0
 def __str__(self):
     if six.PY2:
         return to_binary('Error code: {code}, message: {msg}'.format(
             code=self.return_code,
             msg=self.return_msg
         ))
     else:
         return to_text('Error code: {code}, message: {msg}'.format(
             code=self.return_code,
             msg=self.return_msg
         ))
Ejemplo n.º 17
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.º 18
0
    def get_component_verify_ticket(self, msg, signature, timestamp, nonce):
        """
        处理 wechat server 推送的 component_verify_ticket消息

        :params msg: 加密内容
        :params signature: 消息签名
        :params timestamp: 时间戳
        :params nonce: 随机数
        """
        content = self.crypto.decrypt_message(msg, signature, timestamp, nonce)
        message = xmltodict.parse(to_text(content))['xml']
        return ComponentVerifyTicketMessage(message)
Ejemplo n.º 19
0
    def get_unauthorized(self, msg, signature, timestamp, nonce):
        """
        处理取消授权通知

        :params msg: 加密内容
        :params signature: 消息签名
        :params timestamp: 时间戳
        :params nonce: 随机数
        """
        content = self.crypto.decrypt_message(msg, signature, timestamp, nonce)
        message = xmltodict.parse(to_text(content))['xml']
        return ComponentUnauthorizedMessage(message)
Ejemplo n.º 20
0
    def create(self, name):
        """
        创建标签

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

        """
        name = to_text(name)
        return self._post(
            'tags/create',
            data={'tag': {'name': name}},
            result_processor=lambda x: x['tag']
        )
Ejemplo n.º 21
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.º 22
0
 def preprocess_message(self, request):
     component = get_component()
     content = component.crypto.decrypt_message(
         request.body,
         request.query_params['msg_signature'],
         int(request.query_params['timestamp']),
         int(request.query_params['nonce'])
     )
     message = xmltodict.parse(to_text(content))['xml']
     cc = json.loads(json.dumps(message))
     cc['CreateTime'] = int(cc['CreateTime'])
     cc['CreateTime'] = datetime.fromtimestamp(cc['CreateTime'])
     if 'MsgId' in cc:
         cc['MsgId'] = int(cc['MsgId'])
     return cc
Ejemplo n.º 23
0
    def create(self, name):
        """
        创建分组
        详情请参考
        http://mp.weixin.qq.com/wiki/13/be5272dc4930300ba561d927aead2569.html

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

        """
        name = to_text(name)
        return self._post(
            'groups/create',
            data={'group': {'name': name}}
        )
Ejemplo n.º 24
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.º 25
0
    def create(self, name):
        """
        创建分组

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

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

        """
        name = to_text(name)
        return self._post(
            'groups/create',
            data={'group': {'name': name}}
        )
Ejemplo n.º 26
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.º 27
0
    def get_qrcode_url(self, ticket, data=None):
        """
        通过 ticket 换取二维码地址
        详情请参考
        http://iot.weixin.qq.com/wiki/new/index.html?page=3-4-4

        :param ticket: 二维码 ticket
        :param data: 额外数据
        :return: 二维码地址
        """
        url = 'http://we.qq.com/d/{ticket}'.format(ticket=ticket)
        if data:
            if isinstance(data, (dict, tuple, list)):
                data = urllib.urlencode(data)
            data = to_text(base64.b64encode(to_binary(data)))
            url = '{base}#{data}'.format(base=url, data=data)
        return url
Ejemplo n.º 28
0
    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)
Ejemplo n.º 29
0
    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 = self.query_auth(msg.authorization_code)
        return msg
Ejemplo n.º 30
0
    def update(self, tag_id, name):
        """
        编辑标签

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

        """
        name = to_text(name)
        return self._post(
            'tags/update',
            data={
                'tag': {
                    'id': int(tag_id),
                    'name': name
                }
            }
        )
Ejemplo n.º 31
0
    def get_jssdk_config(self, request, debug=None, version='1.0.0'):
        import time
        from wechatpy.utils import random_string, to_text
        from wechatpy.client.api import WeChatJSAPI
        jsapi = WeChatJSAPI(self.get_wechat_client())
        ticket = jsapi.get_jsapi_ticket()
        nonce_str = random_string(32)
        timestamp = to_text(int(time.time()))
        url = request.META.get('HTTP_REFERER')
        signature = jsapi.get_jsapi_signature(nonce_str, ticket, timestamp,
                                              url)
        debug = bool(request.GET.get('debug')) if debug is None else debug

        api_list = dict(
            checkJsApi=dict(minv='1.0.0', maxv='^'),
            onMenuShareTimeline=dict(minv='1.0.0', maxv='^'),
            onMenuShareAppMessage=dict(minv='1.0.0', maxv='^'),
            onMenuShareQQ=dict(minv='1.0.0', maxv='^'),
            onMenuShareWeibo=dict(minv='1.0.0', maxv='^'),
            hideMenuItems=dict(minv='1.0.0', maxv='^'),
            showMenuItems=dict(minv='1.0.0', maxv='^'),
            hideAllNonBaseMenuItem=dict(minv='1.0.0', maxv='^'),
            showAllNonBaseMenuItem=dict(minv='1.0.0', maxv='^'),
            translateVoice=dict(minv='1.0.0', maxv='^'),
            startRecord=dict(minv='1.0.0', maxv='^'),
            stopRecord=dict(minv='1.0.0', maxv='^'),
            onRecordEnd=dict(minv='1.0.0', maxv='^'),
            playVoice=dict(minv='1.0.0', maxv='^'),
            pauseVoice=dict(minv='1.0.0', maxv='^'),
            stopVoice=dict(minv='1.0.0', maxv='^'),
            uploadVoice=dict(minv='1.0.0', maxv='^'),
            downloadVoice=dict(minv='1.0.0', maxv='^'),
            chooseImage=dict(minv='1.0.0', maxv='^'),
            previewImage=dict(minv='1.0.0', maxv='^'),
            uploadImage=dict(minv='1.0.0', maxv='^'),
            downloadImage=dict(minv='1.0.0', maxv='^'),
            getNetworkType=dict(minv='1.0.0', maxv='^'),
            openLocation=dict(minv='1.0.0', maxv='^'),
            getLocation=dict(minv='1.0.0', maxv='^'),
            hideOptionMenu=dict(minv='1.0.0', maxv='^'),
            showOptionMenu=dict(minv='1.0.0', maxv='^'),
            closeWindow=dict(minv='1.0.0', maxv='^'),
            scanQRCode=dict(minv='1.0.0', maxv='^'),
            chooseWXPay=dict(minv='1.0.0', maxv='^'),
            openProductSpecificView=dict(minv='1.0.0', maxv='^'),
            addCard=dict(minv='1.0.0', maxv='^'),
            chooseCard=dict(minv='1.0.0', maxv='^'),
            openCard=dict(minv='1.0.0', maxv='^'),
            # 1.4.0 added
            updateAppMessageShareData=dict(minv='1.4.0', maxv='^'),
            updateTimelineShareData=dict(minv='1.4.0', maxv='^'),
            onMenuShareQZone=dict(minv='1.4.0', maxv='^'),
            onVoiceRecordEnd=dict(minv='1.4.0', maxv='^'),
            onVoicePlayEnd=dict(minv='1.4.0', maxv='^'),
        )

        return dict(
            debug=debug,
            appId=self.app_id,
            timestamp=timestamp,
            nonceStr=nonce_str,
            signature=signature,
            jsApiList=[
                k for k, v in api_list.items()
                if v['minv'] <= version < v['maxv']
            ],
        )
Ejemplo n.º 32
0
 def __str__(self):
     if six.PY2:
         return to_binary(self.render())
     else:
         return to_text(self.render())
Ejemplo n.º 33
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.º 34
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.º 35
0
 def __base64_decode(self, text):
     return to_text(base64.b64decode(to_binary(text)))
Ejemplo n.º 36
0
 def __to_text(self, value):
     return to_text(value)
Ejemplo n.º 37
0
 def get(self, key, default=None):
     key = self.key_name(key)
     value = self.redis.get(key)
     if value is None:
         return default
     return json.loads(to_text(value))
Ejemplo n.º 38
0
def calculate_signature(params, api_key):
    url = format_url(params, api_key)
    return to_text(hashlib.md5(url).hexdigest().upper())