def refresh_token(): # 通过com_access_token刷新公众号/小程序接口调用凭据/令牌 # 刷新刷新令 com_access_token = dao_wxapi.read_data("com_access_token") appid = config.WXAPPID user_info_list = dao_wxapi.read_info() for user_info in user_info_list: authorizer_appid = user_info["appid"] authorizer_refresh_token = user_info.get("authorizer_refresh_token") data = { "component_appid": appid, "authorizer_appid": authorizer_appid, "authorizer_refresh_token": authorizer_refresh_token } url_refresh_token = config.URL_REFRESH_TOKEN.format(com_access_token) dict_data = request("POST", url_refresh_token, data) if "authorizer_access_token" in dict_data: authorizer_access_token = dict_data["authorizer_access_token"] dao_wxapi.save("authorizer_access_token", authorizer_access_token) authorizer_refresh_token = dict_data["authorizer_refresh_token"] dao_wxapi.save("authorizer_refresh_token", authorizer_refresh_token) user_info_dict = {} user_info_dict["authorizer_access_token"] = authorizer_access_token user_info_dict[ "authorizer_refresh_token"] = authorizer_refresh_token user_info_dict["expires_ts"] = int(time.time()) + int( dict_data["expires_in"]) - 11 * 60 dao_wxapi.update_access_token(authorizer_appid, user_info_dict) else: log_error("refresh_token error: {}".format(str(user_info))) logger.info("refresh_token Done")
def auth(_from=None): # 授权入口 # 需appid, pre_auth_code, redirect_url # 选填 auth_type(1/2/3), biz_appid log_info('', request) inputs = {} fail = [] inputs["app_id"] = request.args.get("app_id") appid = config.WXAPPID pre_auth_code = authorization.pre_auth_code() pre_auth_code_save = dao_wxapi.read_data("pre_auth_code") if pre_auth_code != pre_auth_code_save: log_error( "pre_auth_code Error: pre_auth_code_new: {}, pre_auth_code_save: {}" .format(pre_auth_code, pre_auth_code_save)) redirect_url = config.URL_REDIRECT + '?pre_auth_code=' + pre_auth_code url_wxauth = config.URL_WXAUTH url_auth = url_wxauth.format(appid, pre_auth_code, redirect_url, 3) # 1 仅允许公众号 2 小程序 3 小程序&公众号 if not fail: inputs["pre_auth_code"] = pre_auth_code fail, sv_rsp = do_auth(inputs) """ if _from == "wx_service": rsp = {"url_auth": url_auth, "pre_auth_code": pre_auth_code} """ if sv_rsp.get("sign"): return render_template("index.html", url=url_auth) return "check and try again."
def com_access_token(): # 通过ticket 获取第三方接口调用凭据 ticket = dao_wxapi.read_data("ticket") data = { "component_appid": appid, "component_appsecret": appsecret, "component_verify_ticket": ticket } url_com_access_token = config.URL_COM_ACCESS_TOKEN dict_data = request("POST", url_com_access_token, data) com_access_token = dict_data["component_access_token"] dao_wxapi.save("com_access_token", com_access_token)
def pre_auth_code(): # 通过com_access_token获取预授权码 com_access_token = dao_wxapi.read_data("com_access_token") data = {"component_appid": appid} url_pre_auth_code = config.URL_PRE_AUTH_CODE.format(com_access_token) dict_data = request("POST", url_pre_auth_code, data) pre_auth_code = dict_data.get("pre_auth_code") or '' if not pre_auth_code: log_error( "pre_auth_code get failed: appid: {}, com_access_token: {}".format( appid, com_access_token)) dao_wxapi.save("pre_auth_code", pre_auth_code) return pre_auth_code
def do_authorization(data_dict): """授权事件处理""" if "AppId" in data_dict: try: appid = data_dict.get("AppId") # 第三方平台Appid authorizer_appid = data_dict.get("AuthorizerAppid") # 公众号appid pre_auth_code = data_dict.get("PreAuthCode") authorization_code = data_dict.get("AuthorizationCode") dao_wxapi.save("auth_code", authorization_code) dao_wxapi.save(authorization_code, pre_auth_code) com_access_token = dao_wxapi.read_data("com_access_token") if not com_access_token: send_log("com_access_token error", err=True) if data_dict.get("InfoType") != "component_verify_ticket": WechatOffAccPlatformMonitor.authorization_event( data_dict.get("InfoType"), data_dict) if data_dict.get("InfoType") == "authorized": # 授权成功 send_log("AuthorizedInfo: " + str(data_dict)) rsp_dict = authorization.authorizer_access_token( authorization_code) if rsp_dict.get("sign"): rsp_dict["msg"] = "授权成功" else: rsp_dict["msg"] = "授权失败" log_error("授权失败|授权信息: {}".format(str(data_dict))) elif data_dict.get("InfoType") == "unauthorized": # 取消授权 send_log("UnauthorizedInfo: " + str(data_dict)) # server_account_info 和 appid_map 中状态置0。 rsp_dict = authorization.unauthorized(authorizer_appid) if rsp_dict["sign"]: rsp_dict["msg"] = "已取消授权" elif data_dict.get("InfoType") == "updateauthorized": # 更新授权 send_log("UpdateauthorizedInfo: " + str(data_dict)) rsp_dict = authorization.authorizer_access_token( authorization_code, False) if rsp_dict["sign"]: update_list = authorization.refresh_info() except Exception as e: send_log(e.__class__.__name__ + '|' + str(e), err=True) return 1
def refresh_info(): appid = config.WXAPPID user_info_list = dao_wxapi.read_info() update_list = [] for user_info in user_info_list: # 循环获取授权方基本信息 com_access_token = dao_wxapi.read_data("com_access_token") url_getinfo = config.URL_GETINFO.format(com_access_token) authorizer_appid = user_info["appid"] data_info = { "component_appid": appid, "authorizer_appid": authorizer_appid } info_dict_data = request("POST", url_getinfo, data_info) rsp_dict = do_refresh_info(info_dict_data, user_info) update_list.append({user_info["nick_name"]: rsp_dict}) return update_list
def authorizer_access_token(auth_code, set_map=True): # 通过com_access_token获取公众号/小程序接口调用凭据/令牌 # 以及刷新凭据/刷新令牌 rsp_dict = {"sign": 0, "msg": ''} com_access_token = dao_wxapi.read_data("com_access_token") auth_code = auth_code # dao_wxapi.read_data("auth_code") data = {"component_appid": appid, "authorization_code": auth_code} url_authorizer_access_token = config.URL_AUTHORIZER_ACCESS_TOKEN.format( com_access_token) dict_data = request("POST", url_authorizer_access_token, data) send_log("AuthorizationAccountInfo:" + str(dict_data)) auth_info_all = '' if "authorization_info" in dict_data: # 授权信息 rsp_dict = do_authorizer_access_token(dict_data, auth_code, set_map=set_map) else: rsp_dict["msg"] = "微信服务器故障: authorizer_info not in response" return rsp_dict
def authorization_event(event_name, data): """授权事件监控, 公众号授权给第三方平台""" data = data app_id = '' nick_name = '' monitor_data = {} if event_name == "authorized": # 授权 data["event_name"] = f'{data.get("AuthorizerAppid")}授权予《大陆魔法学校》.' app_id = dao_wxapi.read_data(data.get("PreAuthCode") or '') or '' elif event_name == "unauthorized": # 取消授权 data[ "event_name"] = f'{data.get("AuthorizerAppid")}取消对于《大陆魔法学校》的授权.' nick_name = dao_wxservice.get_nick_name_by_wechat_id( data.get("AuthorizerAppid") or '') elif event_name == "updateauthorized": # 更新授权 data[ "event_name"] = f'{data.get("AuthorizerAppid")}更新对于《大陆魔法学校》的授权内容.' app_id = dao_wxservice.get_app_id_by_wechat_id( data.get("AuthorizerAppid") or '') else: # 异常操作? data["event_name"] = f'{data.get("AuthorizerAppid")}授权行为异常.' if app_id: # 授予 更新 权限 monitor_data["see_detail_url"] = ( 'http://wx.zuasdhakqcheg.com/wx_service/get_auth_info?app_id=' + app_id) elif nick_name: # 取消授权 monitor_data["nick_name"] = nick_name monitor_data["event_name"] = data["event_name"] WechatOffAccPlatformMonitor.make_wrarning( monitor_data, "*****@*****.**")
def do_authorizer_access_token(dict_data: dict, auth_code: str, set_map: bool = True, test_data: dict = {}) -> dict: rsp_dict = {"sign": 0, "msg": ''} com_access_token = dao_wxapi.read_data("com_access_token") authorizer_appid = dict_data["authorization_info"]["authorizer_appid"] dao_wxapi.save("authorizer_appid", authorizer_appid) authorizer_access_token = dict_data["authorization_info"][ "authorizer_access_token"] dao_wxapi.save("authorizer_access_token", authorizer_access_token) authorizer_refresh_token = dict_data["authorization_info"][ "authorizer_refresh_token"] dao_wxapi.save("authorizer_refresh_token", authorizer_refresh_token) auth_ex = int(dict_data["authorization_info"]['expires_in']) # 顺便获取授权方的账号基本信息 #头像、昵称、账号类型、认证类型、微信号、原始ID和二维码URL url_getinfo = config.URL_GETINFO.format(com_access_token) data_info = { "component_appid": appid, "authorizer_appid": authorizer_appid } info_dict_data = request("POST", url_getinfo, data_info) send_log("AuthorizationAccountInfoDetail:" + str(info_dict_data)) auth_info_all = '' if ("authorizer_info" in info_dict_data) or test_data: if "authorizer_info" in test_data and "authorization_info" in test_data: info_dict_data = test_data auth_info_all = json.dumps(info_dict_data, ensure_ascii=False) auth_info = info_dict_data["authorizer_info"] nick_name = auth_info["nick_name"] service_type_info = int(auth_info["service_type_info"]["id"]) verify_type_info = int(auth_info["verify_type_info"]["id"]) user_name = auth_info["user_name"] principal_name = auth_info["principal_name"] qrcode_url = auth_info["qrcode_url"] expire_ts = int(time.time()) + auth_ex - 11 * 60 else: nick_name = '' # auth_info["nick_name"] service_type_info = '' # int(auth_info["service_type_info"]["id"]) verify_type_info = '' # int(auth_info["verify_type_info"]["id"]) user_name = '' # auth_info["user_name"] principal_name = '' # auth_info["principal_name"] qrcode_url = '' # auth_info["qrcode_url"] expire_ts = 0 log_error("获取信息失败: wxappid: {}, info_dict_data: {}".format( authorizer_appid, str(info_dict_data))) logger.info("获得授权方账号信息|%s|%s", nick_name, principal_name) if service_type_info != 2: # 2 表示服务号 logger.info("接入的公众号不是服务号|%s|%s", nick_name, principal_name) else: logger.info("接入的公众号是服务号|%s|%s", nick_name, principal_name) if verify_type_info == -1: logger.warning("接入的公众号未经认证|%s|%s", nick_name, principal_name) # 接入服务号到本服务器 # 存储 save_info_data = { "appid": authorizer_appid, "authorizer_access_token": authorizer_access_token, "authorizer_refresh_token": authorizer_refresh_token, "expires_ts": expire_ts, "nick_name": nick_name, "user_name": user_name, "principal_name": principal_name, "qrcode_url": qrcode_url, } insert_id = dao_wxapi.save(authorizer_appid, save_info_data) send_log("AuthorizationAccountSaveBaseInfo|insert_id: {}".format( str(insert_id))) if insert_id and set_map: # 基本信息插入成功,并且需要建立两方appid map pre_auth_code = dao_wxapi.read_data(auth_code) or '' log_info("get_pre_code_back: {}".format(auth_code)) auth_info_data = { "pre_auth_code": pre_auth_code, "wechat_appid": authorizer_appid, "nick_name": nick_name, "auth_info": auth_info_all, } insert_id2_dict = dao_wxservice.update_auth_info(auth_info_data) send_log("AuthorizationAccountSaveInfoDetail|inser_dict: {}".format( str(insert_id2_dict))) if not insert_id2_dict.get("sign"): send_log("Authorized_Update_Map_Error") retry_appid = dao_wxapi.read_data(pre_auth_code) or pre_auth_code retry_auth_info_data = { "appid": retry_appid, "pre_auth_code": pre_auth_code, "wechat_appid": authorizer_appid, "nick_name": nick_name, "auth_info": auth_info_all, } send_log("Retry_Save: {}".format(str(retry_auth_info_data)), err=True) if retry_appid and authorizer_appid and pre_auth_code: # 删除占位,重新写入 del_data1 = dao_wxservice.get_auth_info(retry_appid, '') del_data2 = dao_wxservice.get_auth_info('', pre_auth_code) send_log("Del_Data: del_data1: {}, del_data2: {}".format( str(del_data1), str(del_data2)), err=True) dao_wxservice.real_delete_by(retry_appid, pre_auth_code) dao_wxservice.save(retry_auth_info_data) if not insert_id2_dict.get("sign"): log_error(rsp_dict["msg"]) rsp_dict[ "msg"] = "update_auth_info error. auth_info_data: {}".format( auth_info_data) if insert_id: # pre_auth_code, 一个预授权码,只能被一个公众号接入, 但blueprints中保证了每次都会新生成一个pre_auth_code rsp_dict["sign"] = 1 return rsp_dict
def msg(appid): """接受用户消息和事件""" logger.info("msg_or_event: " + appid) postdata, msg_signature, timestamp, nonce, auth_code, ex = get_paras() postdata = access.decryption(postdata, msg_signature, timestamp, nonce) log_info("User Msg:" + json.dumps(postdata)) if postdata: data_dict = postdata.get("xml") data_dict["nonce"] = nonce source_appid = data_dict.get("ToUserName") user_openid = data_dict.get("FromUserName") msg_id = data_dict.get("MsgId") msg_type = data_dict.get("MsgType") creat_time = data_dict.get("CreateTime") if appid != "wx570bc396a51b8ff8": try: auth_token_access = dao_wxapi.read_info( appid)["authorizer_access_token"] except: log_error("get auth_token_access error: appid{}".format(appid)) return Response('') response = {} if "MsgId" in data_dict and not msg_id: # 微信多次请求 return Response("success") # 全网发布测试 if msg_type == "event": rsp = wx_workers.wx_event(appid, data_dict) #if rsp["sign"] == 2: # sign == 2 时,对用户进行反馈 if not rsp["sign"] and appid == "waa111asdw43f3b5": # 这样才好返回失败原因debug return send_text_cont(fromu=user_openid, tou=source_appid, cont=rsp["msg"], nonce=nonce) elif rsp.get("reply_news"): # 优先发送图文 return send_pic_cont(fromu=user_openid, tou=source_appid, nonce=nonce, appid=appid) elif rsp.get("reply_txt"): return send_text_cont(fromu=user_openid, tou=source_appid, cont=rsp["msg"], nonce=nonce) elif msg_type == "text": msg_content = data_dict.get("Content") log_info('got the content %s' % msg_content) if msg_content == "TESTCOMPONENT_MSG_TYPE_TEXT": reply_cont = msg_content + "_callback" return send_text_cont(fromu=user_openid, tou=source_appid, cont=reply_cont, nonce=nonce) elif msg_content and msg_content.startswith('QUERY_AUTH_CODE'): # 测试 query_auth_code = msg_content.split(':')[1] com_access_token = dao_wxapi.read_data("com_access_token") auth_code = query_auth_code if appid: info = dao_wxapi.read_info(appid) send_log(f'{appid}###info: {info}') if "authorizer_access_token" in info: authorizer_access_token = dao_wxapi.read_info( appid)["authorizer_access_token"] post_cont = auth_code + '_from_api' gevent.spawn( post_custom_text_msg, **{ "touser": user_openid, "content": post_cont, "stoken": authorizer_access_token }).join() return send_bank_response() if msg_type == "text": msg_content = data_dict.get("Content") rsp_data_dict = postdata url = config.URL_MSGCUSTOM.format(auth_token_access) if "id" in msg_content or "ID" in msg_content or "同煤数据" in msg_content: # 便捷获取openid reply_cont = '' if "debug" in msg_content: try: debug_setting = msg_content.split("::")[-1] debug_setting_dict = json.loads(debug_setting) config.DEBUG_LOG["touser"] = user_openid config.DEBUG_LOG["switch"] = debug_setting_dict.get( "switch") or 0 config.DEBUG_LOG["log_key"] = debug_setting_dict.get( "log_key") or 'WOW' config.DEBUG_LOG[ "fake_appid"] = debug_setting_dict.get( "fake_appid") or config.DEBUG_LOG["fake_appid"] msg_list = [str(i) for i in config.DEBUG_LOG.values()] msg_str = ','.join(msg_list) reply_cont = msg_str except: reply_cont = """id,debug::{"log_key": "Authorization", "switch": 1}""" elif "app" in msg_content: reply_cont = appid if "source" in msg_content: reply_cont = source_appid elif "学我" in msg_content or "follow" in msg_content: reply_cont = msg_content elif "数据卡了" in msg_content and source_appid == "gh_1adc6e723b39": reply_cont = "https://web.zusadeng.com/p-record?app_id=5dw 29ea2ea76d3529ad5" else: reply_cont = user_openid return send_text_cont(fromu=user_openid, tou=source_appid, cont=reply_cont, nonce=nonce) logger.info("Send msg custom from {} to {}".format( user_openid, appid)) elif msg_type == "voice": return send_bank_response(nonce=nonce) elif msg_type == "image": return send_bank_response(nonce=nonce) elif msg_type == "link": return send_bank_response(nonce=nonce) else: none_log = { "appid": appid, "msg_signature": msg_signature, "nonce": nonce, "auth_code": auth_code, "ex": ex } send_log(f"MSG|postdata is None|{none_log}", err=True) return Response('success')