def set_cache(self, key, value): """添加微信Media相关redis""" res = self.redis_ctl.set(key, value) self.redis_ctl.expire(key, self._expire_media_token) logger.debug('【微信media缓存】setCache>>>key[' + key + '],value[' + value + ']') return res
def get_code_url(self, state): """获取code的url""" dict = {'redirect_uri': self.REDIRECT_URI} redirect_uri = urllib.parse.urlencode(dict) author_get_code_url = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&%s&response_type=code&scope=%s&state=%s#wechat_redirect' % ( WxConfig.AppID, redirect_uri, self.SCOPE, state) logger.debug('【微信网页授权】获取网页授权的code的url>>>>' + author_get_code_url) return author_get_code_url
def sign(self): string = '&'.join([ '%s=%s' % (key.lower(), self.ret[key]) for key in sorted(self.ret) ]) self.ret['signature'] = hashlib.sha1( string.encode('utf-8')).hexdigest() logger.debug('【微信JS-SDK】获取JS-SDK权限签名>>>>dict[' + str(self.ret) + ']') return self.ret
def get_cache(self, key): """获取redis""" try: v = (self.redis_ctl.get(key)).decode('utf-8') logger.debug(v) logger.debug('【微信token缓存】getCache>>>key[' + key + '],value[' + v + ']') return v except Exception: return None
def check_signature(self, signature, timestamp, nonce): """校验token是否正确""" token = 'binbinliu123' L = [timestamp, nonce, token] L.sort() s = L[0] + L[1] + L[2] sha1 = hashlib.sha1(s.encode('utf-8')).hexdigest() logger.debug('sha1=' + sha1 + '&signature=' + signature) return sha1 == signature
def add_kf_data(self): '''创建客服数据''' kf_data = { 'kf_account': 'bzw_lolface@gh_cacb86407b98', 'nickname': '小包' } KF_DATA = json.dumps(kf_data, ensure_ascii=False) logger.debug('【微信客服创建客服数据KF_DATA[' + str(KF_DATA) + ']') return KF_DATA
def check_signature(self, signature, timestamp, nonce): """校验token是否正µ确""" token = WxConfig.AppCustomToken L = [timestamp, nonce, token] L.sort() s = L[0] + L[1] + L[2] sha1 = hashlib.sha1(s.encode('utf-8')).hexdigest() logger.debug('sha1=' + sha1 + '&signature=' + signature) return sha1 == signature
def get_cache(self, key): """获取redis""" try: media_id = (self.redis_ctl.get(key)).decode('utf-8') logger.debug(media_id) logger.debug('【微信Meida缓存】getCache>>>key[' + key + '],value[' + media_id + ']') return media_id except Exception: return None
def get_userinfo(self, access_token, openid): """拉取用户信息""" url = self.get_userinfo_url + 'access_token=%s&openid=%s&lang=zh_CN' % ( access_token, openid) r = requests.get(url) logger.debug('【微信网页授权】拉取用户信息Response[' + str(r.status_code) + ']') if r.status_code == 200: res = r.text json_data = json.loads((res.encode('iso-8859-1')).decode('utf-8')) logger.debug('【微信网页授权】拉取用户信息>>>>' + str(json_data))
def create_menu_data(self): """创建菜单数据""" menu_data = {'button': []} # 大菜单 menu_Index0 = { 'type': 'view', 'name': '测试菜单1', 'url': self._wx_author_server.get_code_url('menuIndex0') } menu_data['button'].append(menu_Index0) MENU_DATA = json.dumps(menu_data, ensure_ascii=False) logger.debug('【微信自定义菜单】创建菜单数据MENU_DATA[' + str(MENU_DATA) + ']') return MENU_DATA
def post(self): body = self.request.body logger.debug('微信消息回复中心】收到用户消息' + str(body.decode('utf-8'))) data = ET.fromstring(body) ToUserName = data.find('ToUserName').text FromUserName = data.find('FromUserName').text MsgType = data.find('MsgType').text if MsgType == 'text' or MsgType == 'voice': '''文本消息 or 语音消息''' try: MsgId = data.find("MsgId").text if MsgType == 'text': Content = data.find('Content').text # 文本消息内容 elif MsgType == 'voice': Content = data.find('Recognition').text # 语音识别结果,UTF8编码 if Content == u'你好': MsgType = 'text' reply_content = '您好,请问有什么可以帮助您的吗?' else: # 接入多客服系统 MsgType = 'transfer_customer_service' reply_content = Content CreateTime = int(time.time()) out = self.reply_text(FromUserName, ToUserName, CreateTime, MsgType, reply_content) logger.debug(out) self.write(out) # 查找不到关键字,同时默认回复 MsgType = "text" reply_content = "客服接入中,稍后将为您服务" if reply_content: CreateTime = int(time.time()) out = self.reply_text(FromUserName, ToUserName, CreateTime, MsgType, reply_content) self.write(out) except Exception as e: logger.error(str(e)) elif MsgType == 'event': '''接收事件推送''' try: Event = data.find('Event').text if Event == 'subscribe': # 关注事件 CreateTime = int(time.time()) reply_content = self.sys_order_reply MsgType = 'text' out = self.reply_text(FromUserName, ToUserName, CreateTime, MsgType, reply_content) self.write(out) except: pass
def get_menu(self): """获取menu,如果没有menu则进行创建""" menu = WxMenuServer() try: data = menu.get_menu() logger.debug('微信获取menu' + str(data)) if data == 0: pass else: menu.create_menu() except Exception as e: logger.error('Exception:' + e)
def get_auth_access_token(self, code): """通过code换取网页授权access_token""" url = self.get_access_token_url + 'appid=%s&secret=%s&code=%s&grant_type=authorization_code' % ( WxConfig.AppID, WxConfig.AppSecret, code) r = requests.get(url) logger.debug('【微信网页授权】通过code换取网页授权access_token的Response[' + str(r.status_code) + ']') if r.status_code == 200: res = r.text logger.debug('【微信网页授权】通过code换取网页授权access_token>>>>' + res) json_res = json.loads(res) if 'access_token' in json_res.keys(): return json_res elif 'errcode' in json_res.keys(): errcode = json_res['errcode']
def get(self): try: signature = self.get_argument('signature') timestamp = self.get_argument('timestamp') nonce = self.get_argument('nonce') echostr = self.get_argument('echostr') result = self.check_signature(signature, timestamp, nonce) logger.debug('微信sign校验,signature=' + signature + ',×tamp=' + timestamp + '&nonce=' + nonce + '&echostr=' + echostr) if result: logger.debug('微信sign校验,返回echostr=' + echostr) self.write(echostr) else: logger.error('微信sign校验,---校验失败') except Exception as e: logger.error('微信sign校验,---Exception' + str(e))
def delete_menu(self): """自定义菜单删除接口""" access_token = self._token_cache.get_cache( self._token_cache.KEY_ACCESS_TOKEN) if access_token: url = WxConfig.menu_delete_url + access_token r = requests.get(url) logger.debug('【微信自定义菜单】自定义菜单删除接口Response[' + str(r.status_code) + ']') if r.status_code == 200: res = r.text logger.debug('【微信自定义菜单】自定义菜单删除接口' + res) json_res = json.loads(res) if 'errcode' in json_res.keys(): errcode = json_res['errcode'] return errcode else: logger.error('【微信自定义菜单】自定义菜单删除接口获取不到access_token')
def add_kf(self): access_token = self._token_cache.get_cache( self._token_cache.KEY_ACCESS_TOKEN) if access_token: url = WxConfig.add_kf + access_token data = self.add_kf_data() r = requests.post(url, data.encode('utf-8')) logger.debug('【微信多客服系统】Response' + str(r.status_code)) if r.status_code == 200: res = r.text logger.debug('[微信多客服系统]' + res) json_res = json.loads(res) if 'errcode' in json.loads(res): errcode = json_res['errcode'] return errcode else: logger.error('微信多客服系统获取不到access_token')
def post(self): body = self.request.body logger.debug('微信消息回复中心】收到用户消息' + str(body.decode('utf-8'))) data = ET.fromstring(body) ToUserName = data.find('ToUserName').text FromUserName = data.find('FromUserName').text MsgType = data.find('MsgType').text if MsgType == 'text' or MsgType == 'voice': '''文本消息 or 语音消息''' try: MsgId = data.find("MsgId").text if MsgType == 'text': Content = data.find('Content').text # 文本消息内容 elif MsgType == 'voice': Content = data.find('Recognition').text # 语音识别结果,UTF8编码 if Content == u'你好': reply_content = '您好,请问有什么可以帮助您的吗?' else: # 查找不到关键字,默认回复 reply_content = "客服小儿智商不够用啦~" if reply_content: CreateTime = int(time.time()) out = self.reply_text(FromUserName, ToUserName, CreateTime, reply_content) self.write(out) except: pass elif MsgType == 'event': '''接收事件推送''' try: Event = data.find('Event').text if Event == 'subscribe': # 关注事件 CreateTime = int(time.time()) reply_content = self.sys_order_reply out = self.reply_text(FromUserName, ToUserName, CreateTime, reply_content) self.write(out) except: pass
def invite_kf(self): access_token = self._token_cache.get_cache( self._token_cache.KEY_ACCESS_TOKEN) if access_token: url = WxConfig.invite_kf + access_token invite_data = { 'kf_account': 'bzw_lolface@gh_cacb86407b98', 'invite_wx': 'bzw_lolface' } r = requests.post( url, json.dumps(invite_data, ensure_ascii=False).encode('utf-8')) logger.debug('[微信多客服系统]Response' + str(r.status_code)) if r.status_code == 200: res = r.text logger.debug('[微信多客服系统]' + res) json_res = json.loads(res) if 'errcode' in json.loads(res): errcode = json_res('errcode') return errcode else: logger.error('[微信多客服系统获取不到access_token]')
def create_menu_data(self): """创建菜单数据""" menu_data = {'button': []} # 大菜单 menu_l1_1 = {'name': '最新优惠', 'sub_button': []} menu_l1_2 = {'name': '会员中心', 'sub_button': []} menu_l2_1 = { 'type': 'view', 'name': '会员享9折优惠', 'url': self._wx_author_server.get_code_url('menuIndex0') } menu_l2_2 = { 'type': 'view', 'name': '申请会员', 'url': self._wx_author_server.get_code_url('apply_vip') } menu_l1_1['sub_button'].append(menu_l2_1) menu_l1_2['sub_button'].append(menu_l2_2) menu_data['button'].append(menu_l1_1) menu_data['button'].append(menu_l1_2) MENU_DATA = json.dumps(menu_data, ensure_ascii=False) logger.debug('【微信自定义菜单】创建菜单数据MENU_DATA[' + str(MENU_DATA) + ']') return MENU_DATA
def post(self, flag): if flag == 'wxauthor': '''微信网页授权''' code = self.get_argument('code') state = self.get_argument('state') # 获取重定向的url redirect_url = self.wx_config.wx_menu_state_map[state] logger.debug('【微信网页授权】将要重定向的地址为:redirct_url[' + redirect_url + ']') logger.debug('【微信网页授权】用户同意授权,获取code>>>>code[' + code + ']state[' + state + ']') if code: # 通过code换取网页授权access_token data = self.wx_author_server.get_auth_access_token(code) openid = data['openid'] logger.debug('【微信网页授权】openid>>>>openid[' + openid + ']') if openid: # 跳到自己的业务界面 self.redirect(redirect_url) else: # 获取不到openid logger.debug('获取不到openid')
def set_access_cache(self, key, value): """添加微信access_token验证相关redis""" res = self.redis_ctl.set(key, value) self.redis_ctl.expire(key, self._expire_access_token) logger.debug('【微信token缓存】setCache>>>key[' + key + '],value[' + value + ']') return res
def post(self): body = self.request.body logger.debug('微信消息回复中心】收到用户消息' + str(body.decode('utf-8'))) data = ET.fromstring(body) ToUserName = data.find('ToUserName').text FromUserName = data.find('FromUserName').text self._from_name = FromUserName self._to_name = ToUserName MsgType = data.find('MsgType').text if MsgType == 'text' or MsgType == 'voice': '''文本消息 or 语音消息''' try: MsgId = data.find("MsgId").text if MsgType == 'text': Content = data.find('Content').text # 文本消息内容 results = self.pattern.search(Content) if results: # 找到了符合订单ID的内容 order_id = results.group() self._order_id = order_id http_client = tornado.httpclient.AsyncHTTPClient() token = self._token_cache.get_cache( self._token_cache.KEY_WD_ACCESS_TOKEN) params = {"order_id": order_id} public = { "access_token": token, "version": "1.0", "format": "json", "method": "vdian.order.get" } url = r'https://api.vdian.com/api?param={"order_id":"%s"}&public={"method":"vdian.order.get","access_token":"%s","version":"1.0","format":"json"}' % ( order_id, token) http_client.fetch(url, callback=self.on_response) else: reply_content = WxConfig.COMMON_COPYWRITE CreateTime = int(time.time()) out = self.reply_text(FromUserName, ToUserName, CreateTime, reply_content) self.write(out) self.finish() except Exception as e: logger.error(str(e)) self.finish() elif MsgType == 'event': '''接收事件推送''' try: CreateTime = int(time.time()) Event = data.find('Event').text if Event == 'subscribe': # 关注事件 out = self.reply_text(FromUserName, ToUserName, CreateTime, WxConfig.ATTENTION_INIT_COPYWRITE_1) self.write(out) self.send_service_message_text( WxConfig.ATTENTION_INIT_COPYWRITE_2) elif Event == 'CLICK': key = data.find('EventKey').text if key == 'reprint': # 转载 out = self.reply_text(FromUserName, ToUserName, CreateTime, WxConfig.REPRINT_COPYWRITE) self.write(out) except Exception as e: logger.error(str(e)) finally: self.finish() elif MsgType == 'image': try: CreateTime = int(time.time()) out = self.reply_text(FromUserName, ToUserName, CreateTime, WxConfig.PART_IN_GUESSGANME_WAITTING) self.write(out) except Exception as e: logger.error(str(e)) finally: self.finish()
def create_menu_data(self): """创建菜单数据""" menu_data = { "button": [{ "name": "精选内容", "sub_button": [{ "type": "view", "name": "精选文章", "url": "http://mp.weixin.qq.com/mp/homepage?__biz=MjM5Nzc5MDkwMQ==&hid=3&sn=70ce35abda6a8236f90a3a36e964dc2d" }, { "type": "view", "name": "影评剧评", "url": "http://mp.weixin.qq.com/mp/homepage?__biz=MjM5Nzc5MDkwMQ==&hid=4&sn=aeaee3a48324880d0c5e6ea335d5b9cc" }, { "type": "view", "name": "明星专访", "url": "http://mp.weixin.qq.com/mp/homepage?__biz=MjM5Nzc5MDkwMQ==&hid=5&sn=24c252b77d42b6d93bd021bbc4eaf67f" }] }, { "type": "view", "name": "李易峰专刊", "url": "https://weidian.com/s/209793342?ifr=shopdetail&wfr=c" }, { "name": "联系我们", "sub_button": [{ "type": "media_id", "name": "加入我们", "media_id": "b-Ij3Ifb-J_iT6cv09d5mOV7UvvCeEZ9fQqxIEqAXW0" }, { "type": "click", "name": "欢迎转载", "key": "reprint" }, { "type": "media_id", "name": "商务合作", "media_id": "b-Ij3Ifb-J_iT6cv09d5mKHcKOLuXzDAqMAT9ns8XWU" }] }] } MENU_DATA = json.dumps(menu_data, ensure_ascii=False) logger.debug('【微信自定义菜单】创建菜单数据MENU_DATA[' + str(MENU_DATA) + ']') return MENU_DATA