Esempio n. 1
0
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")
Esempio n. 2
0
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."
Esempio n. 3
0
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)
Esempio n. 4
0
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
Esempio n. 5
0
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
Esempio n. 6
0
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
Esempio n. 7
0
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
Esempio n. 8
0
 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, "*****@*****.**")
Esempio n. 9
0
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
Esempio n. 10
0
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')