def index(request): global TOKEN, router_error, router_reply weixinlogger = logging.getLogger('weixin') conversationlogger = logging.getLogger('conversation') if request.method == 'GET': if 'signature' not in request.GET or 'timestamp' not in request.GET or 'nonce' not in request.GET or 'echostr' not in request.GET: return HttpResponse('bad request %s' % str(request.GET)) signature = request.GET['signature'] timestamp = request.GET['timestamp'] nonce = request.GET['nonce'] echostr = request.GET['echostr'] weixinlogger.info("receive one get message signature %s timestamp %s nonce %s echostr %s" % (signature, timestamp, nonce, echostr)) weixin = WeiXin.on_connect(TOKEN, timestamp, nonce, signature, echostr) if weixin.validate(): return HttpResponse(echostr, content_type="text/plain") else: return HttpResponse(None, content_type="text/plain") elif request.method == 'POST': try: weixin = WeiXin.on_message(smart_str(request.raw_post_data)) message = weixin.to_json() weixinlogger.info("receive one message %s" % str(message)) conversationlogger.info("receive one message %s" % str(message)) try: user = WeixinUser.objects.get(uid=message['FromUserName']) except: user = WeixinUser() user.src = message['ToUserName'] user.uid = message['FromUserName'] user.integral = 0 user.save() Router.get_instance().reply(message, _route_callback) if router_error is None and router_reply is not None: router_reply.platform = MessageBuilder.PLATFORM_WEIXIN if router_reply.type != MessageBuilder.TYPE_NO_RESPONSE: weixinlogger.info("reply success type %s platform %s data %s" % (router_reply.type, router_reply.platform, router_reply.data)) conversationlogger.info("reply success type %s platform %s data %s" % (router_reply.type, router_reply.platform, router_reply.data)) return HttpResponse(MessageBuilder.build(message, router_reply), content_type="application/xml") else: weixinlogger.info("%s", router_reply.data) conversationlogger.info("%s", router_reply.data) else: weixinlogger.info("router error %s router reply %s" % (str(router_error), str(router_reply))) conversationlogger.info("router error %s router reply %s" % (str(router_error), str(router_reply))) raise "not find games" return HttpResponse('<xml></xml>', content_type="application/xml") except: logger.error(traceback.format_exc()) reply_config = BuildConfig(MessageBuilder.TYPE_RAW_TEXT, MessageBuilder.PLATFORM_WEIXIN, u"非常抱歉,没能理解你的话") return HttpResponse(MessageBuilder.build(message, reply_config), content_type="application/xml")
def _build_weixin_game_collection(context, data): articles = [] articles.append({ 'title': u'游戏合集之' + data.title, 'description': u'游戏合集' + data.recommended_reason, 'pic_url': 'http://weixin.bestgames7.com/media/%s' % data.cover, 'url': 'http://weixin.bestgames7.com/collections/%d/preview' % data.id }) for game in data.games.all()[:3]: title = '%s - %s' % (game.brief_comment, game.name) url_pos = game.recommended_reason.find('http://') if url_pos != -1: description = game.recommended_reason[:url_pos] else: description = game.recommended_reason pic_url = 'http://weixin.bestgames7.com/media/%s' % game.icon url = 'http://weixin.bestgames7.com/games/%d/preview' % game.id articles.append({ 'title': title, 'description': description, 'pic_url': pic_url, 'url': url }) return WeiXin.to_news_xml(context.get('FromUserName', None), context.get('ToUserName', None), articles)
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 _build_weixin_games(context, data): articles = [] is_first = True for game in data: url_pos = game.recommended_reason.find('http://') if url_pos != -1: description = game.recommended_reason[:url_pos] else: description = game.recommended_reason if is_first: pic_url = 'http://weixin.bestgames7.com/media/%s' % game.screenshot_path_1 title = game.name is_first = False else: pic_url = 'http://weixin.bestgames7.com/media/%s' % game.icon title = '%s - %s' % (game.brief_comment.strip(), game.name) url = 'http://weixin.bestgames7.com/games/%d/preview' % game.id articles.append({ 'title': title, 'description': description, 'pic_url': pic_url, 'url': url }) resp = WeiXin.to_news_xml(context.get('FromUserName', None), context.get('ToUserName', None), articles) logger.debug("len %d %s" % (len(resp), resp)) return resp
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 _build_weixin_download_urls(context, data): content = '' for game in data: content = content + game.name + '\n' logger.debug("android %s iOS %s" % (game.android_download_url, game.iOS_download_url)) if game.android_download_url is not None and len(game.android_download_url) > 0: android_download_shorten_url = load_shorten_android_download_url(game) if android_download_shorten_url is not None: content = content + u'安卓下载地址' content = content + android_download_shorten_url + '\n' else: content = content + u'无安卓版\n' else: content = content + u'无安卓版\n' if game.iOS_download_url is not None and len(game.iOS_download_url) > 0: ios_download_shorted_url = load_shorten_ios_download_url(game) if ios_download_shorted_url is not None: content = content + u'苹果下载地址' content = content + ios_download_shorted_url + '\n' else: content = content + u'无苹果版\n' else: content = content + u'无苹果版\n' content = content + '\n' return WeiXin.to_text_xml(to_user_name=context.get('FromUserName', None), from_user_name=context.get('ToUserName', None), content=content, func_flag=0)
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_gen_signature(self): params = { 'token':'token', 'timestamp':'timestamp', 'nonce':'nonce', } gen_signature = WeiXin.gen_signature(params) self.assertEqual('6db4861c77e0633e0105672fcd41c9fc2766e26e', gen_signature)
def _build_weixin_gift_shop(context, data): articles = [] articles.append({ 'title': u'积分商城', 'description': u'使用积分在积分商城兑换您心仪的礼品。', 'pic_url': 'http://cow.bestgames7.com/static/img/giftshop.png', 'url': 'http://cow.bestgames7.com/weixin/gifts/%d' % data }) return WeiXin.to_news_xml(context.get('FromUserName', None), context.get('ToUserName', None), articles)
def _build_weixin_intro(context, data): articles = [] articles.append({ 'title': u'小每 - 您身边的手机游戏砖家', 'description': u'发现好玩的手机游戏,了解最新的手机游戏资讯,参与趣味答题赢积分换礼品。', 'pic_url': 'http://cow.bestgames7.com/static/img/weixin-intro.jpg', 'url': 'http://cow.bestgames7.com/weixin/intro' }) return WeiXin.to_news_xml(context.get('FromUserName', None), context.get('ToUserName', None), articles)
def _build_weixin_answer(context, data): articles = [] articles.append({ 'title': u'趣味答题', 'description': u'每天一道题,答对一题得5分,积分可以换奖品。', 'pic_url': 'http://cow.bestgames7.com/static/img/puzzle.png', 'url': 'http://cow.bestgames7.com/weixin/puzzles?user_id=%d' % data }) return WeiXin.to_news_xml(context.get('FromUserName', None), context.get('ToUserName', None), articles)
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))
def _build_weixin_game_collection(context, data): articles = [] articles.append({'title' : u'游戏合集之' + data.title, 'description' : u'游戏合集' + data.recommended_reason, 'pic_url' : 'http://weixin.bestgames7.com/media/%s' % data.cover, 'url' : 'http://weixin.bestgames7.com/collections/%d/preview' % data.id}) for game in data.games.all()[:3]: title = '%s - %s' % (game.brief_comment, game.name) url_pos = game.recommended_reason.find('http://') if url_pos != -1: description = game.recommended_reason[:url_pos] else: description = game.recommended_reason pic_url = 'http://weixin.bestgames7.com/media/%s' % game.icon url = 'http://weixin.bestgames7.com/games/%d/preview' % game.id articles.append({'title' : title, 'description' : description, 'pic_url' : pic_url, 'url' : url}) return WeiXin.to_news_xml(context.get('FromUserName', None), context.get('ToUserName', None), articles)
def _build_weixin_games(context, data): articles = [] is_first = True for game in data: url_pos = game.recommended_reason.find('http://') if url_pos != -1: description = game.recommended_reason[:url_pos] else: description = game.recommended_reason if is_first: pic_url = 'http://weixin.bestgames7.com/media/%s' % game.screenshot_path_1 title = game.name is_first = False else: pic_url = 'http://weixin.bestgames7.com/media/%s' % game.icon title = '%s - %s' % (game.brief_comment.strip(), game.name) url = 'http://weixin.bestgames7.com/games/%d/preview' % game.id articles.append({'title' : title, 'description' : description, 'pic_url' : pic_url, 'url' : url}) resp = WeiXin.to_news_xml(context.get('FromUserName', None), context.get('ToUserName', None), articles) logger.debug("len %d %s" % (len(resp), resp)) return resp
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 _build_weixin_download_urls(context, data): content = '' for game in data: content = content + game.name + '\n' logger.debug("android %s iOS %s" % (game.android_download_url, game.iOS_download_url)) if game.android_download_url is not None and len( game.android_download_url) > 0: android_download_shorten_url = load_shorten_android_download_url( game) if android_download_shorten_url is not None: content = content + u'安卓下载地址' content = content + android_download_shorten_url + '\n' else: content = content + u'无安卓版\n' else: content = content + u'无安卓版\n' if game.iOS_download_url is not None and len( game.iOS_download_url) > 0: ios_download_shorted_url = load_shorten_ios_download_url(game) if ios_download_shorted_url is not None: content = content + u'苹果下载地址' content = content + ios_download_shorted_url + '\n' else: content = content + u'无苹果版\n' else: content = content + u'无苹果版\n' content = content + '\n' return WeiXin.to_text_xml(to_user_name=context.get('FromUserName', None), from_user_name=context.get('ToUserName', None), content=content, func_flag=0)
def _build_weixin_answer(context, data): articles = [] articles.append({'title' : u'趣味答题', 'description' : u'每天一道题,答对一题得5分,积分可以换奖品。', 'pic_url' : 'http://cow.bestgames7.com/static/img/puzzle.png', 'url' : 'http://cow.bestgames7.com/weixin/puzzles?user_id=%d' % data}) return WeiXin.to_news_xml(context.get('FromUserName', None), context.get('ToUserName', None), articles)
def _build_weixin_gift_shop(context, data): articles = [] articles.append({'title' : u'积分商城', 'description' : u'使用积分在积分商城兑换您心仪的礼品。', 'pic_url' : 'http://cow.bestgames7.com/static/img/giftshop.png', 'url' : 'http://cow.bestgames7.com/weixin/gifts/%d' % data}) return WeiXin.to_news_xml(context.get('FromUserName', None), context.get('ToUserName', None), articles)
def _build_weixin_raw_text(context, data): # FIXME return WeiXin.to_text_xml(to_user_name=context.get('FromUserName', None), from_user_name=context.get('ToUserName', None), content=data, func_flag=0)
def _build_weixin_intro(context, data): articles = [] articles.append({'title' : u'小每 - 您身边的手机游戏砖家', 'description' : u'发现好玩的手机游戏,了解最新的手机游戏资讯,参与趣味答题赢积分换礼品。', 'pic_url' : 'http://cow.bestgames7.com/static/img/weixin-intro.jpg', 'url' : 'http://cow.bestgames7.com/weixin/intro'}) return WeiXin.to_news_xml(context.get('FromUserName', None), context.get('ToUserName', None), articles)
def index(request, wx): global router_error, router_reply wxlogger = logging.getLogger('weixin') r = redis.StrictRedis(host='localhost', port=6379, db=0) if request.method == 'GET': if 'signature' not in request.GET or 'timestamp' not in request.GET or 'nonce' not in request.GET or 'echostr' not in request.GET: return HttpResponse('bad request %s' % str(request.GET)) signature = request.GET['signature'] timestamp = request.GET['timestamp'] nonce = request.GET['nonce'] echostr = request.GET['echostr'] wxlogger.info("receive one get message signature %s timestamp %s nonce %s echostr %s" % (signature, timestamp, nonce, echostr)) token = cache.get('wx_%s_token' % wx) weixin = WeiXin.on_connect(token, timestamp, nonce, signature, echostr) if weixin.validate(): return HttpResponse(echostr, content_type="text/plain") else: return HttpResponse(None, content_type="text/plain") elif request.method == 'POST': try: weixin = WeiXin.on_message(smart_str(request.raw_post_data)) message = weixin.to_json() wx_account = WXAccount.objects.get(id=wx) wx_account.message_count += 1 wx_account.save() wxlogger.info("receive one message %s" % str(message)) if message['MsgType'] == 'event' and message['Event'] == 'subscribe': walluser, created = WallUser.objects.get_or_create(wx=wx_account, openid=message['FromUserName']) walluser.wall_item_id='0' walluser.save() r.rpush('userList', message['FromUserName']) wxlogger.info("我要订阅") if message['MsgType'] == 'text' or message['MsgType'] == 'image' or message['MsgType'] == 'voice': wxlogger.info("我想上墙") wxlogger.info(len(WallUser.objects.filter(wx=wx_account, openid=message['FromUserName']))) if not len(WallUser.objects.filter(wx=wx_account, openid=message['FromUserName']))==0: walluser = WallUser.objects.filter(wx=wx_account, openid=message['FromUserName'])[0] #wxlogger.info('walluser is %s' % message['FromUserName']) if not walluser.wall_item_id == '0':#说明上墙了 #对上墙活动的进行时间进行判断,有可能上墙了但活动已经结束了 wallitem = WallItem.objects.filter(id=walluser.wall_item_id) if len(wallitem) == 0: walluser.wall_item_id = '0' walluser.save() reply_str = "活动不存在" reply_config = BuildConfig(MessageBuilder.TYPE_RAW_TEXT, MessageBuilder.PLATFORM_WEIXIN, reply_str) return HttpResponse(MessageBuilder.build(message, reply_config), content_type="application/xml") else: wallitem = wallitem[0] #结束时间10分钟后的处理 #if (datetime.now()-wallitem.begin_time).seconds <= 600: if datetime.now()<wallitem.end_time:#说明在上墙时间内 if message['MsgType'] == 'text' or message['MsgType'] == 'voice': message_str = "" if message['MsgType'] == 'text': message_str = message['Content'] else: message_str = message['Recognition'] if not message_str == "退出": wxlogger.info('receive message %s' % message_str) WallMsg.objects.create(user=walluser, type='text', content=message_str, wall_item_id=walluser.wall_item_id) reply_str = "发送成功" wxlogger.info(datetime.now()) reply_config = BuildConfig(MessageBuilder.TYPE_RAW_TEXT, MessageBuilder.PLATFORM_WEIXIN, reply_str) return HttpResponse(MessageBuilder.build(message, reply_config), content_type="application/xml") else:#quit the wall walluser.wall_item_id = '0' walluser.save() reply_str = "退出成功" reply_config = BuildConfig(MessageBuilder.TYPE_RAW_TEXT, MessageBuilder.PLATFORM_WEIXIN, reply_str) return HttpResponse(MessageBuilder.build(message, reply_config), content_type="application/xml") else:#image WallMsg.objects.create(user=walluser, type=message['MsgType'], content=message['PicUrl'], wall_item_id=walluser.wall_item_id) reply_str = "发送成功" reply_config = BuildConfig(MessageBuilder.TYPE_RAW_TEXT, MessageBuilder.PLATFORM_WEIXIN, reply_str) return HttpResponse(MessageBuilder.build(message, reply_config), content_type="application/xml") if (datetime.now()-wallitem.end_time).seconds <= 600:#超出上墙时间不到10分钟 reply_str = "活动已结束,您将在10分钟之后自动退出该活动,您也可以回复“退出”直接退出该活动。" reply_config = BuildConfig(MessageBuilder.TYPE_RAW_TEXT, MessageBuilder.PLATFORM_WEIXIN, reply_str) return HttpResponse(MessageBuilder.build(message, reply_config), content_type="application/xml") else: walluser.wall_item_id = '0' walluser.save() wxlogger.info("活动已经结束超过10分钟,您已经被系统退出上墙。") reply_str = "活动已经结束超过10分钟,您已经被系统退出上墙。" reply_config = BuildConfig(MessageBuilder.TYPE_RAW_TEXT, MessageBuilder.PLATFORM_WEIXIN, reply_str) return HttpResponse(MessageBuilder.build(message, reply_config), content_type="application/xml") else:#说明没有上墙 if message['MsgType'] == 'text': wxlogger.info(message) wxlogger.info("说明没有上墙") if not len(WallItem.objects.filter(wx=wx_account)) == 0:#说明该微信号有微信墙活动 for wallitem in WallItem.objects.filter(wx=wx_account): if message['Content']==wallitem.keyword:#说明有上墙的关键字 reply_str = "" if datetime.now()<wallitem.begin_time:#没有开始 reply_str = "活动未开始,请在活动开始("+str(wallitem.begin_time)+")之后再发送消息。" elif datetime.now()>wallitem.end_time:#说明已经结束 reply_str = "活动已结束" else: wxlogger.info(wallitem.welcome) walluser.wall_item_id = wallitem.id walluser.save() if judge_symbol(wallitem.welcome): reply_str = wallitem.welcome+'回复“退出”则退出上墙。' else: reply_str = wallitem.welcome+','+'回复“退出”则退出上墙。' reply_config = BuildConfig(MessageBuilder.TYPE_RAW_TEXT, MessageBuilder.PLATFORM_WEIXIN, reply_str) return HttpResponse(MessageBuilder.build(message, reply_config), content_type="application/xml") Router.get_instance().reply(wx, message, _route_callback) if router_error is None and router_reply is not None: router_reply.platform = MessageBuilder.PLATFORM_WEIXIN if router_reply.type != MessageBuilder.TYPE_NO_RESPONSE: wxlogger.info("reply success type %s platform %s data %s" % (router_reply.type, router_reply.platform, router_reply.data)) return HttpResponse(MessageBuilder.build(message, router_reply), content_type="application/xml") else: wxlogger.info("%s", router_reply.data) else: wxlogger.info("router error %s router reply %s" % (str(router_error), str(router_reply))) reply_config = BuildConfig(MessageBuilder.TYPE_RAW_TEXT, MessageBuilder.PLATFORM_WEIXIN, u"抱歉,我不是很明白") return HttpResponse(MessageBuilder.build(message, reply_config), content_type="application/xml") #return HttpResponse('<xml></xml>', content_type="application/xml") except: wxlogger.error(traceback.format_exc()) reply_config = BuildConfig(MessageBuilder.TYPE_RAW_TEXT, MessageBuilder.PLATFORM_WEIXIN, u"抱歉,我不是很明白。") return HttpResponse(MessageBuilder.build(message, reply_config), content_type="application/xml")
def _build_webapp(context, data): articles = [] articles.append(data) return WeiXin.to_news_xml(context.get('FromUserName', None), context.get('ToUserName', None), articles)