def wechat_handler(): try: token = current_app.config['WECHAT_TOEKN'] signature = request.args.get('signature') timestamp = request.args.get('timestamp') nonce = request.args.get('nonce') check_signature(token, signature, timestamp, nonce) current_app.logger.info('wechat_handler begin') body = request.get_data() current_app.logger.info('wechat_handler body %s' % body) msg = parse_message(body) if msg.type == 'text': return reply_msg(msg) elif msg.type == 'event' and msg.event == 'click' and msg.key == 'V2003_SignIn': return sign_in(msg) elif msg.type == 'event' and msg.event in ['subscribe_scan', 'scan'] and msg.scene_id == '123': binding(msg) if msg.event == 'subscribe_scan': return welcome_article(msg) elif msg.type == 'event' and msg.event == 'unsubscribe': unsubscribe_unbinding(msg) elif msg.type == 'event' and msg.event == 'subscribe': return welcome_article(msg) reply = EmptyReply() return reply.render() except InvalidSignatureException: abort(404) except Exception as e: current_app.logger.exception('wechat_handler %s' % e) reply = EmptyReply() return reply.render()
def get_resp_message(request, source_msg, mode=None): request_msg = parse_message(source_msg) request_msg_type = request_msg.type log.info('>>> body[{}],request_msg_type[{}],request_msg[{}]'.format( request.body, request_msg_type, request_msg)) # 根据消息类型解析 if request_msg_type == 'text': reply = TextReply(content='{}'.format( get_text_reply(request, request_msg.content)), message=request_msg) elif request_msg_type == 'image': reply = TextReply(content=howold(request_msg.image), message=request_msg) elif request_msg_type == 'voice': if not request_msg.recognition: reply = TextReply(content='没听清楚啊,再说一遍,亲', message=request_msg) else: content = get_text_reply(request, request_msg.recognition) # tts = gTTS(text=content, lang='zh-cn') # tmpfd, tempfilename = tempfile.mkstemp() # tts.save(tempfilename) # with open(tempfilename, mode='rb') as f: # client = WeChatClient(config.WECHAT_APPID, config.WECHAT_SECRET) # res = WeChatMedia(client=client).upload('voice', f.read()) # print('>>>', res) # media_id = json.loads(res).get('media_id') # if not media_id: # reply = VideoReply(message=request_msg) # reply.media_id = media_id # else: # reply = TextReply(content='{}'.format(content), message=request_msg) reply = TextReply(content='{}'.format(content), message=request_msg) elif request_msg_type == 'event': request_msg_event = request_msg.event if request_msg_event == 'subscribe': reply = TextReply(content=config.WELCOME_MSG, message=request_msg) elif request_msg_event == 'unsubscribe': reply = TextReply(content='多谢关注!', message=request_msg) else: reply = EmptyReply() else: reply = EmptyReply() # 返回xml报文 xml = reply.render() if mode == 'aes': # get var timestamp = request.raw_args.get('timestamp', '') nonce = request.raw_args.get('nonce', '') crypto = WeChatCrypto(config.WECHAT_TOKEN, config.WECHAT_ENCODING_AES_KEY, config.WECHAT_APPID) encrypted_xml = crypto.encrypt_message(xml, nonce, timestamp) return encrypted_xml else: return xml
def wechat_handler(): msg = request.wechat_msg reply = EmptyReply() if msg.type == 'text': if msg.content == '课表': schedule_year = '2015-2016' schedule_term = '2' schedule_data = school.schedule(schedule_year, schedule_term) if type(schedule_data) == dict and schedule_data.get('error'): reply = TextReply(content=schedule_data['error'], message=msg) else: data = assemble_schedule(schedule_data) reply = create_reply(data, message=msg) elif msg.content == '成绩': score_year = '2015-2016' score_term = '2' score_data = school.score(score_year, score_term) if type(score_data) == dict and score_data.get('error'): reply = TextReply(content=schedule_data['error'], message=msg) else: data = assemble_score(score_year, score_term, score_data) reply = create_reply(data, message=msg) elif msg.content == '绑定': content = '<a >点击绑定</a>' content = '<a href="https://weixin.gxgk.cc/">点击绑定</a>' reply = TextReply(content=content, message=msg) else: reply = TextReply(content=msg.content, message=msg) return reply
class Event(object): ''' 事件基类 ''' reply = None expected_type = None msg_reply = None id = 0 type = 'unknown' # 消息的类型 source = None # 消息的来源用户,即发送消息的用户 target = None # 消息的目标用户 create_time = None # 消息的发送时间,UNIX 时间戳 time = None def __init__(self, msg): if not isinstance(msg, self.expected_type): raise TypeError("Expected " + str(self.expected_type)) self.msg = msg self.id = self.msg.id self.type = self.msg.type self.source = self.msg.source self.target = self.msg.target self.create_time = self.msg.create_time self.time = self.msg.time def on_take(self): ''' 推送消息-主动调用该方法 :return: ''' print('TextMessageBase', self.id) print('TextMessageBase', self.type) print('TextMessageBase', self.source) print('TextMessageBase', self.target) print('TextMessageBase', self.create_time) print('TextMessageBase', self.time) context = self.get_reply_body() if not context: self.msg_reply = EmptyReply() print('EmptyReply', type(self.msg_reply)) return context_send = {'message': self.msg, **context} self.msg_reply = self.reply(**context_send) def get_reply_body(self, context=None): ''' 微信公众号消息回复内容构建 :param context: :return: ''' return context def render(self): return self.msg_reply.render()
def deserialize_reply(xml, update_time=False): """反序列化被动回复 :param xml: 待反序列化的xml :param update_time: 是否用当前时间替换xml中的时间 :raises ValueError: 不能辨识的reply xml :rtype: wechatpy.replies.BaseReply """ if not xml: return EmptyReply() try: reply_dict = xmltodict.parse(xml)["xml"] msg_type = reply_dict["MsgType"] except: raise ValueError("bad reply xml") if msg_type not in REPLY_TYPES: raise ValueError("unknown reply type") cls = REPLY_TYPES[msg_type] kwargs = dict() for attr, field in cls._fields.items(): if field.name in reply_dict: str_value = reply_dict[field.name] kwargs[attr] = field.from_xml(str_value) if update_time: kwargs["time"] = time.time() return cls(**kwargs)
def _reply(self, msg): """处理消息 """ for h in self.handlers: reply = h.handle(msg) if isinstance(reply, BaseReply): return reply return EmptyReply()
def reply_msg(msg): rs = get_match_bloginfo(msg.content) record_msg(msg, rs['is_match']) if rs['is_match']: data = [rs] client = get_wechat_client() client.message.send_articles(msg.source, data) reply = EmptyReply() else: rs = get_sougou_result(msg.content) if rs['is_match']: client = get_wechat_client() client.message.send_articles(msg.source, [rs]) reply = EmptyReply() else: reply = TextReply(content=u'抱歉,关键词:{keyword} 还未收录。'.format( keyword=msg.content), message=msg) return reply.render()
def on_take(self): ''' 推送消息-主动调用该方法 :return: ''' print('TextMessageBase', self.id) print('TextMessageBase', self.type) print('TextMessageBase', self.source) print('TextMessageBase', self.target) print('TextMessageBase', self.create_time) print('TextMessageBase', self.time) context = self.get_reply_body() if not context: self.msg_reply = EmptyReply() print('EmptyReply', type(self.msg_reply)) return context_send = {'message': self.msg, **context} self.msg_reply = self.reply(**context_send)
def get_resp_message(source_msg): """构造微信公众号返回消息""" request_msg = parse_message(source_msg) request_msg_type = request_msg.type openid = request.args.get('openid', '') print('>>> request_msg_type[{}],request_msg[{}]'.format(request_msg_type, request_msg)) # 根据消息类型解析 if request_msg_type == 'text': reply = TextReply(content='{}'.format(request_msg.content), message=request_msg) elif request_msg_type == 'image': reply = TextReply(content='{}'.format('hello'), message=request_msg) elif request_msg_type == 'voice': if not request_msg.recognition: reply = TextReply(content='没听清楚啊,再说一遍,亲', message=request_msg) else: reply = TextReply(content='{}'.format(request_msg.recognition), message=request_msg) elif request_msg_type == 'event': request_msg_event = request_msg.event if request_msg_event == 'subscribe': # 用户关注后,登记用户信息 try: client = WeChatClient(WECHAT_APPID, WECHAT_SECRET) user_json = client.user.get(openid) except: print('>>>', '获取用户信息失败') else: save_wechat_user(user_json) reply = TextReply(content=WECHAT_WELCOME_MSG, message=request_msg) elif request_msg_event == 'unsubscribe': reply = TextReply(content='多谢关注!', message=request_msg) elif request_msg_event == 'CLICK': reply = EmptyReply() else: reply = EmptyReply() else: reply = EmptyReply() # 返回xml报文 return reply.render()
def _reply(self, msg): """处理消息的核心方法 """ for handler in self.handlers: # 每个消息处理器会判断 msg 的数据类型 # 如果不符合,直接返回 None # 如果符合,返回处理之后的 BaseReply 实例 reply = handler.handle(msg) if isinstance(reply, BaseReply): return reply # 如果微信公众号发来的消息不符合任何一个消息处理器的处理规则 # 返回 EmptyReply 这个类的实例 return EmptyReply()
def wxUrlTest(request): if request.method == 'GET': token = request.GET.get('token', '') timestamp = request.GET.get('timestamp', '') nonce = request.GET.get('nonce', '') echostr = request.GET.get('echostr', '') return HttpResponse(echostr) elif request.method == 'POST': # 回复空消息 msg = parse_message(request.body) if msg.type == 'text': print(msg) client.message.send_text(msg.source, '客服消息测试') return HttpResponse(EmptyReply().render())
def serve(request): timestamp = request.GET.get('timestamp', '') nonce = request.GET.get('nonce', '') if request.method == 'GET': signature = request.GET.get('signature', '') echo_str = request.GET.get('echostr', '') try: check_signature(settings.WECHAT_TOKEN, signature, timestamp, nonce) logger.info('Wechat signature validated.') return HttpResponse(echo_str) except InvalidSignatureException: logger.warning('Invalid wechat signature.') return HttpResponseBadRequest() elif request.method == 'POST': signature = request.GET.get('msg_signature', '') try: decrypted_xml = crypto.decrypt_message(request.body, signature, timestamp, nonce) except (InvalidAppIdException, InvalidSignatureException): logger.warning('Invalid wechat message signature.') return HttpResponseBadRequest() msg = parse_message(decrypted_xml) reply = None if msg.type == 'text': reply = process_text(request, msg) elif msg.type == 'event': if msg.event == 'subscribe': reply = actions.subscribe(msg) elif msg.event == 'unsubscribe': reply = actions.unsubscribe(msg) if reply is None: return HttpResponse(EmptyReply().render()) else: xml = reply.render() encrypted_xml = crypto.encrypt_message(xml, nonce, timestamp) return HttpResponse(encrypted_xml) else: return HttpResponseBadRequest()
def test_empty_reply(self): from wechatpy.replies import EmptyReply reply = EmptyReply() self.assertEqual('', reply.render())
def api(request): # 从 request 中提取基本信息 (signature, timestamp, nonce, xml) signature = request.GET.get('msg_signature') timestamp = request.GET.get('timestamp') nonce = request.GET.get('nonce') # 解析本次请求的 XML 数据 crypto = WeChatCrypto(settings.TOKEN, settings.ENCODINGAESKEY, settings.CORPID) if request.method == 'GET': # 检验合法性 echo_str = request.GET.get('echostr', '') try: echo_str = crypto.check_signature(signature, timestamp, nonce, echo_str) except InvalidSignatureException: # 处理异常情况或忽略 return HttpResponseBadRequest('Verify Failed') return HttpResponse(echo_str, content_type="text/plain") try: decrypted_xml = crypto.decrypt_message( request.body, signature, timestamp, nonce ) except (InvalidCorpIdException, InvalidSignatureException): # 处理异常或忽略 return HttpResponseBadRequest('Failed') msg = parse_message(decrypted_xml) response = EmptyReply() if msg.type == 'text': text = msg.content if text == 'info': userinfo = wechat_client.user.get(msg.source) response = TextReply(content=str(userinfo), message=msg) else: reply = Wechatkeyword.objects.extra(where=['%s SIMILAR TO keyword'], params=[text]).first() if reply: response = TextReply(content=u'%s' % reply.data, message=msg) elif msg.type == 'event': if msg.event == 'subscribe': # 关注事件 response = EmptyReply() elif msg.event == 'unsubscribe': logger.info('wechat user %s unsubscribe' % msg.source) user = User.objects.get(openid=msg.source) user.checkinaccountabnormal = True user.save() elif msg.event == 'location': nowtime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) try: user = User.objects.get(openid=msg.source) except User.DoesNotExist: pass else: user.latitude = msg.latitude user.longitude = msg.longitude user.accuracy = msg.precision user.lastpositiontime = nowtime user.save() elif msg.event == 'click': if msg.key == '1200': response = TextReply(content=u'地址:%s\n学生默认帐号:学号/身份证号\n教师默认帐号:职工号/职工号' % settings.DOMAIN, message=msg) xml = response.render() encrypted_xml = crypto.encrypt_message(xml, nonce, timestamp) return HttpResponse(encrypted_xml, content_type="application/xml")