如何用Firebase、Flet和Python监控用户导入动作并执行订阅限制?
基于Firebase的订阅制导入额度限制实现方案
一、优先用Firebase生态实现(推荐)
你已经在用Firebase做认证,直接复用现有服务成本最低,无需额外引入第三方平台。
核心思路
通过Firebase Firestore/Realtime Database记录用户导入动作,用Cloud Functions做后端额度校验(避免客户端篡改),达到限制时自动拦截导入流程。
具体步骤
- 记录导入动作
每次用户触发导入前,先通过Firebase Auth获取当前用户UID,然后向Firestore的user_imports集合写入一条记录,字段包括:
user_id: 用户UIDimport_time: 导入时间(UTC)import_count: 单次导入的产品条数success: 导入是否成功(用于后续统计有效额度)month: 导入月份(格式YYYY-MM,方便按自然月查询)
Python代码示例(Flet桌面端):
from firebase_admin import firestore, auth from datetime import datetime import firebase_admin # 初始化Firebase(注意:桌面端不要打包服务账号密钥,建议用环境变量加载) if not firebase_admin._apps: cred = firebase_admin.credentials.Certificate("path/to/your/service-account.json") firebase_admin.initialize_app(cred) db = firestore.client() def log_import(user_uid, import_count, success=True): db.collection("user_imports").add({ "user_id": user_uid, "import_time": datetime.utcnow(), "import_count": import_count, "success": success, "month": datetime.utcnow().strftime("%Y-%m") })
- 后端额度校验(关键,防止客户端篡改)
编写Firebase Cloud Functions的Callable函数,负责计算用户当月已用额度并判断是否允许导入:
- 校验用户是否已认证
- 查询当月该用户成功导入的总条数
- 从
users集合读取用户的订阅额度(比如每月100条) - 对比已用额度+本次请求条数是否超过限制,返回结果
Node.js代码示例(Cloud Functions):
const functions = require("firebase-functions"); const admin = require("firebase-admin"); admin.initializeApp(); exports.checkImportQuota = functions.https.onCall(async (data, context) => { if (!context.auth) throw new functions.https.HttpsError("unauthenticated", "未登录"); const userUid = context.auth.uid; const requestedCount = data.requestedCount; const currentMonth = new Date().toISOString().slice(0, 7); // 统计当月成功导入总条数 const snapshot = await admin.firestore() .collection("user_imports") .where("user_id", "==", userUid) .where("month", "==", currentMonth) .where("success", "==", true) .get(); let totalUsed = 0; snapshot.forEach(doc => totalUsed += doc.data().import_count); // 获取用户订阅额度(默认100条/月) const userDoc = await admin.firestore().collection("users").doc(userUid).get(); if (!userDoc.exists) throw new functions.https.HttpsError("not-found", "用户不存在"); const quota = userDoc.data().subscription_quota || 100; if (totalUsed + requestedCount > quota) { throw new functions.https.HttpsError("resource-exhausted", "当月导入额度已用完"); } return { allowed: true, remaining: quota - totalUsed - requestedCount }; });
- 客户端拦截逻辑
在Flet的导入按钮点击事件中,先调用Cloud Functions校验额度,通过后再执行Shopify API导入,否则弹出提示拦截:
import pyrebase4 import flet as ft # 初始化pyrebase(用户已登录状态) firebase_config = { /* 你的Firebase配置 */ } firebase = pyrebase4.initialize_app(firebase_config) auth = firebase.auth() current_user = auth.current_user functions = firebase.functions() def on_import_button_click(e): requested_count = int(e.page.controls[0].value) # 假设输入框是第一个控件 try: # 调用校验函数 result = functions.call("checkImportQuota", {"requestedCount": requested_count}) # 执行Shopify导入操作 # ... 你的Shopify API调用代码 ... # 导入成功后记录动作 log_import(current_user["localId"], requested_count) e.page.snack_bar = ft.SnackBar(ft.Text(f"导入成功,剩余额度:{result['remaining']}")) e.page.snack_bar.open = True e.page.update() except Exception as err: e.page.snack_bar = ft.SnackBar(ft.Text(f"导入失败:{str(err)}")) e.page.snack_bar.open = True e.page.update()
二、备选方案:本地数据库+Firebase同步
适合需要离线功能的场景,用SQLite本地记录导入动作,定期同步到Firebase,但最终额度校验仍需依赖Firebase后端数据(防止本地数据被篡改):
- 本地SQLite存储用户导入记录,包含UID、导入时间、条数等
- 软件启动/联网时,将本地未同步的记录上传到Firebase
- 导入前先查询Firebase的当月已用额度,再执行本地校验(快速反馈),最后调用后端校验确认
三、其他思路
- 自建Python后端:用FastAPI搭建简单的额度校验接口,部署在Cloud Run/Vercel,桌面端调用该接口做校验,适合需要高度定制化逻辑的场景,但需要额外维护后端服务
- Firebase Extensions:可使用现成的额度管理扩展(如
firebase/extensions/quota-management),快速配置用户额度规则,减少自定义代码量
关键注意事项
- 绝对不要依赖客户端校验:所有额度判断必须在后端完成,客户端仅做前置提示,防止用户篡改本地数据绕过限制
- 额度重置逻辑:可通过Cloud Functions定时任务,每月初自动重置用户当月已用额度(或直接按自然月查询统计,无需重置)
- 异常处理:导入失败时,需标记记录为
success: false,统计额度时排除该记录,避免误扣额度 - 密钥安全:桌面端不要将Firebase服务账号密钥打包到exe中,建议用Firebase Auth的ID Token调用Cloud Functions,或通过环境变量加载密钥
内容的提问来源于stack exchange,提问作者Vanderlei Custodio Vander
相关产品推荐
相关产品推荐

