def handle(t): if not self.check_signature( request.query.timestamp, request.query.nonce, request.query.signature ): return abort(403) body = request.body.read() message_dict = parse_xml(body) if "Encrypt" in message_dict: xml = self.crypto.decrypt_message( timestamp=request.query.timestamp, nonce=request.query.nonce, msg_signature=request.query.msg_signature, encrypt_msg=message_dict["Encrypt"] ) message_dict = parse_xml(xml) message = process_message(message_dict) logging.info("Receive message %s" % message) reply = self.get_reply(message) if not reply: self.logger.warning("No handler responded message %s" % message) return '' response.content_type = 'application/xml' if self.use_encryption: return self.crypto.encrypt_message(reply) else: return reply.render()
def test_django(): os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_test.settings") sys.path.append( os.path.join( os.path.abspath(os.path.dirname(__file__)), 'django_test_env' ) ) from django.test.utils import setup_test_environment setup_test_environment() from django.test.client import Client from werobot.parser import parse_xml, process_message import django django.setup() client = Client() token = 'TestDjango' timestamp = str(time.time()) nonce = str(random.randint(0, 10000)) signature = get_signature(token, timestamp, nonce) echostr = generate_token() response = client.get( '/robot/', { 'signature': signature, 'timestamp': timestamp, 'nonce': nonce, 'echostr': echostr } ) assert response.status_code == 200 assert response.content.decode('utf-8') == echostr xml = """ <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>""" params = "?timestamp=%s&nonce=%s&signature=%s" % \ (timestamp, nonce, signature) url = '/robot/' response = client.post(url, data=xml, content_type="text/xml") assert response.status_code == 403 assert response.content.decode('utf-8') == u'喵' url += params response = client.post(url, data=xml, content_type="text/xml") assert response.status_code == 200 response = process_message(parse_xml(response.content)) assert response.content == 'hello' response = client.options(url) assert response.status_code == 405
def parse_message(self, body, timestamp=None, nonce=None, msg_signature=None): """ 解析获取到的 Raw XML ,如果需要的话进行解密,返回 WeRoBot Message。 :param body: 微信服务器发来的请求中的 Body。 :return: WeRoBot Message """ message_dict = parse_xml(body) if "Encrypt" in message_dict: xml = self.crypto.decrypt_message( timestamp=timestamp, nonce=nonce, msg_signature=msg_signature, encrypt_msg=message_dict["Encrypt"] ) message_dict = parse_xml(xml) return process_message(message_dict)
def parse_message( self, body, timestamp=None, nonce=None, msg_signature=None ): """ 解析获取到的 Raw XML ,如果需要的话进行解密,返回 WeRoBot Message。 :param body: 微信服务器发来的请求中的 Body。 :return: WeRoBot Message """ message_dict = parse_xml(body) if "Encrypt" in message_dict: xml = self.crypto.decrypt_message( timestamp=timestamp, nonce=nonce, msg_signature=msg_signature, encrypt_msg=message_dict["Encrypt"] ) message_dict = parse_xml(xml) return process_message(message_dict)
def test_tornado(self): token = self.token timestamp = str(time.time()) nonce = str(random.randint(0, 10000)) signature = get_signature(token, timestamp, nonce) echostr = generate_token() params = "?timestamp=%s&nonce=%s&signature=%s&echostr=%s" % ( timestamp, nonce, signature, echostr ) response = self.fetch(path=self.endpoint + params) assert response.code == 200 assert response.body.decode('utf-8') == echostr response = self.fetch(path=self.endpoint, ) assert response.code == 403 assert response.body.decode('utf-8') == u'喵' xml = """ <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>""" response = self.fetch( path=self.endpoint + params, method='POST', body=xml, headers={'Content-Type': 'text/xml'} ) self.assertEqual(response.code, 200) self.assertEqual( process_message(parse_xml(response.body)).content, 'hello' ) response = self.fetch( path=self.endpoint, method='POST', body=xml, headers={'Content-Type': 'text/xml'} ) self.assertEqual(response.code, 403)
def tester(app, token, endpoint): test_app = webtest.TestApp(app) response = test_app.get(endpoint, expect_errors=True) assert response.status_code == 403 timestamp = str(time.time()) nonce = str(random.randint(0, 10000)) signature = get_signature(token, timestamp, nonce) echostr = generate_token() params = "?timestamp=%s&nonce=%s&signature=%s&echostr=%s" % ( timestamp, nonce, signature, echostr ) response = test_app.get(endpoint + params) assert response.status_code == 200 assert response.body.decode('utf-8') == echostr response = test_app.get(endpoint, expect_errors=True) assert response.status_code == 403 assert response.body.decode('utf-8') == u'喵' xml = """ <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> """ with pytest.raises(AppError): # WebTest will raise an AppError # if the status_code is not >= 200 and < 400. test_app.post(endpoint, xml, content_type="text/xml") response = test_app.post( endpoint + params, xml, content_type="text/xml" ) assert response.status_code == 200 response = process_message(parse_xml(response.body)) assert response.content == 'hello'
def test_message_crypt(): encoding_aes_key = generate_token(32) + generate_token(11) token = generate_token() timestamp = to_text(int(time.time())) nonce = generate_token(5) app_id = generate_token(18) crypt = MessageCrypt(token=token, encoding_aes_key=encoding_aes_key, app_id=app_id) message = crypt.encrypt_message('hello', timestamp, nonce) assert message is not None message = parse_xml(message) assert message is not None message = crypt.decrypt_message(message['TimeStamp'], message['Nonce'], message['MsgSignature'], message['Encrypt']) assert message == to_binary('hello')
def test_message_crypt(): encoding_aes_key = generate_token(32) + generate_token(11) token = generate_token() timestamp = to_text(int(time.time())) nonce = generate_token(5) app_id = generate_token(18) crypt = MessageCrypt( token=token, encoding_aes_key=encoding_aes_key, app_id=app_id ) message = crypt.encrypt_message('hello', timestamp, nonce) assert message is not None message = parse_xml(message) assert message is not None message = crypt.decrypt_message( message['TimeStamp'], message['Nonce'], message['MsgSignature'], message['Encrypt'] ) assert message == to_binary('hello')