(转载)微信

# -*- coding: utf8
# Author: twinsant@gmail.com
import hashlib
import xml.etree.ElementTree as ET

class WeiXin(object):
    def __init__(self, token=None, timestamp=None, nonce=None, signature=None, echostr=None, xml_body=None):
        self.token = token
        self.timestamp = timestamp
        self.nonce = nonce
        self.signature = signature
        self.echostr = echostr

        self.xml_body = xml_body

    @classmethod
    def on_connect(self, token=None, timestamp=None, nonce=None, signature=None, echostr=None):
        obj = WeiXin(token=token,
            timestamp=timestamp,
            nonce=nonce,
            signature=signature,
            echostr=echostr)
        return obj

    @classmethod
    def on_message(self, xml_body):
        obj = WeiXin(xml_body=xml_body)
        return obj

    def to_json(self):
        '''http://docs.python.org/2/library/xml.etree.elementtree.html#xml.etree.ElementTree.XML
        '''
        j = {}
        root = ET.fromstring(self.xml_body)
        for child in root:
            if child.tag == 'CreateTime':
                value = long(child.text)
            else:
                value = child.text
            j[child.tag] = value
        return j

    def _to_tag(self, k):
        return ''.join([w.capitalize() for w in k.split('_')])

    def _cdata(self, data):
        '''http://stackoverflow.com/questions/174890/how-to-output-cdata-using-elementtree
        '''
        if type(data) is str:
            return '<![CDATA[%s]]>' % data.replace(']]>', ']]]]><![CDATA[>')
        return data

    def to_xml(self, **kwargs):
        xml = '<xml>'
        def cmp(x, y):
            ''' WeiXin need ordered elements?
            '''
            orderd = ['to_user_name', 'from_user_name', 'create_time', 'msg_type', 'content', 'func_flag']
            try:
                ix = orderd.index(x)
            except ValueError:
                return 1
            try:
                iy = orderd.index(y)
            except ValueError:
                return -1
            return ix - iy
        for k in sorted(kwargs.iterkeys(), cmp):
            v = kwargs[k]
            tag = self._to_tag(k)
            xml += '<%s>%s</%s>' % (tag, self._cdata(v), tag)
        xml += '</xml>'
        return xml

    def validate(self):
        params = {}
        params['token'] = self.token
        params['timestamp'] = self.timestamp
        params['nonce'] = self.nonce

        signature = self.signature
        echostr = self.echostr

        if echostr is not None and self.is_not_none(params):
            _signature = self._signature(params)
            if _signature == signature:
                return True
        return False

    def is_not_none(self, params):
        for k, v in params.items():
            if v is None:
                return False
        return True

    def _signature(self, params):
        '''http://docs.python.org/2/library/hashlib.html
        '''
        a = sorted([v for k, v in params.items()])
        s = ''.join(a)
        return hashlib.sha1(s).hexdigest()

import unittest
class WeiXinTestCase(unittest.TestCase):
    def test_on_connect_validate(self):
        weixin = WeiXin.on_connect(token='token',
            timestamp='timestamp',
            nonce='nonce',
            signature='6db4861c77e0633e0105672fcd41c9fc2766e26e',
            echostr='echostr')
        self.assertEqual(weixin.validate(), True)

    def test_on_connect_validate_false(self):
        weixin = WeiXin.on_connect(token='token',
            timestamp='timestamp',
            nonce='nonce_false',
            signature='6db4861c77e0633e0105672fcd41c9fc2766e26e',
            echostr='echostr')
        self.assertEqual(weixin.validate(), False)

    def test_on_message_text(self):
        body = '''
        <xml>
            <ToUserName><![CDATA[toUser]]></ToUserName>
            <FromUserName><![CDATA[fromUser]]></FromUserName> 
            <CreateTime>1348831860</CreateTime>
            <MsgType><![CDATA[text]]></MsgType>
            <Content><![CDATA[this is a test]]></Content>
            <MsgId>1234567890123456</MsgId>
       </xml>
        '''
        weixin = WeiXin.on_message(body)
        j = weixin.to_json()
        def assertParam(name, value):
            self.assertEqual(name in j, True)
            self.assertEqual(j[name], value)
        assertParam('ToUserName', 'toUser')
        assertParam('FromUserName', 'fromUser')
        assertParam('CreateTime', 1348831860)
        assertParam('MsgType', 'text')
        assertParam('Content', 'this is a test')
        assertParam('MsgId', '1234567890123456')

    def test_on_message_image(self):
        body = '''
        <xml>
        <ToUserName><![CDATA[toUser]]></ToUserName>
        <FromUserName><![CDATA[fromUser]]></FromUserName>
        <CreateTime>1348831860</CreateTime>
        <MsgType><![CDATA[image]]></MsgType>
        <PicUrl><![CDATA[this is a url]]></PicUrl>
        <MsgId>1234567890123456</MsgId>
        </xml>
        '''
        weixin = WeiXin.on_message(body)
        j = weixin.to_json()
        def assertParam(name, value):
            self.assertEqual(name in j, True)
            self.assertEqual(j[name], value)
        assertParam('ToUserName', 'toUser')
        assertParam('FromUserName', 'fromUser')
        assertParam('CreateTime', 1348831860)
        assertParam('MsgType', 'image')
        assertParam('PicUrl', 'this is a url')
        assertParam('MsgId', '1234567890123456')

    def test_on_message_location(self):
        body = '''
        <xml>
        <ToUserName><![CDATA[toUser]]></ToUserName>
        <FromUserName><![CDATA[fromUser]]></FromUserName>
        <CreateTime>1351776360</CreateTime>
        <MsgType><![CDATA[location]]></MsgType>
        <Location_X>23.134521</Location_X>
        <Location_Y>113.358803</Location_Y>
        <Scale>20</Scale>
        <Label><![CDATA[位置信息]]></Label>
        <MsgId>1234567890123456</MsgId>
        </xml> 
        '''
        weixin = WeiXin.on_message(body)
        j = weixin.to_json()
        def assertParam(name, value):
            self.assertEqual(name in j, True)
            self.assertEqual(j[name], value)
        assertParam('ToUserName', 'toUser')
        assertParam('FromUserName', 'fromUser')
        assertParam('CreateTime', 1351776360)
        assertParam('MsgType', 'location')
        assertParam('Location_X', '23.134521')
        assertParam('Location_Y', '113.358803')
        assertParam('Scale', '20')
        assertParam('Label', u'位置信息')
        assertParam('MsgId', '1234567890123456')

    def test_on_message_link(self):
        body = '''
        <xml>
        <ToUserName><![CDATA[toUser]]></ToUserName>
        <FromUserName><![CDATA[fromUser]]></FromUserName>
        <CreateTime>1351776360</CreateTime>
        <MsgType><![CDATA[link]]></MsgType>
        <Title><![CDATA[公众平台官网链接]]></Title>
        <Description><![CDATA[公众平台官网链接]]></Description>
        <Url><![CDATA[url]]></Url>
        <MsgId>1234567890123456</MsgId>
        </xml>
        '''
        weixin = WeiXin.on_message(body)
        j = weixin.to_json()
        def assertParam(name, value):
            self.assertEqual(name in j, True)
            self.assertEqual(j[name], value)
        assertParam('ToUserName', 'toUser')
        assertParam('FromUserName', 'fromUser')
        assertParam('CreateTime', 1351776360)
        assertParam('MsgType', 'link')
        assertParam('Title', u'公众平台官网链接')
        assertParam('Description', u'公众平台官网链接')
        assertParam('Url', 'url')
        assertParam('MsgId', '1234567890123456')

    def test_to_xml_text(self):
        xml = '''
        <xml>
        <ToUserName><![CDATA[toUser]]></ToUserName>
        <FromUserName><![CDATA[fromUser]]></FromUserName>
        <CreateTime>12345678</CreateTime>
        <MsgType><![CDATA[text]]></MsgType>
        <Content><![CDATA[content]]></Content>
        <FuncFlag>0</FuncFlag>
        </xml>
        '''
        weixin = WeiXin()
        to_user_name = 'toUser'
        from_user_name = 'fromUser'
        create_time = 12345678
        msg_type = 'text'
        content = 'content'
        func_flag = 0
        self.assertEqual(xml.replace('\n', '').replace(' ', '').strip(), weixin.to_xml(to_user_name=to_user_name,
            from_user_name=from_user_name,
            create_time=create_time,
            msg_type=msg_type,
            content=content,
            func_flag=func_flag))

if __name__ == '__main__':
    unittest.main()

 

posted @ 2013-02-25 10:40  hhhyde  阅读(376)  评论(0编辑  收藏  举报