套餐、积分与支付
本文档基于 Aivory v2.4.7 编写。相关界面:“计费与权益 → 用户组 / 积分与配额 / 兑换码 / 支付渠道 / 支付方式 / 支付订单”,以及“数据与运营 → 用量与计费 / 用量”。
套餐、积分和支付把模型成本、用户可用能力与订单流程连接起来。建议先用管理员和测试账号验证配额与积分,再开放真实支付;支付渠道凭据、webhook 密钥和配置导出都按高敏感资产管理。
先建立成本边界
在添加任何商品之前,明确每一类用户可以消耗什么:
- 可以使用哪些聊天、图片、语音或 embedding 模型。
- 每日消息数、图片数、上传、工具调用和并发生成的合理上限。
- 积分如何换算到不同模型与服务商成本(模型页的每 1M token 单价是扣积分的依据),免费额度是否足够支撑试用。
- 超出额度后是拒绝、提示充值、切换低成本模型,还是管理员手工处理。
先用低成本模型和小额度测试。在没有成本监控、滥用限制和退款/人工处理流程之前,不要公开高价模型、深度研究、图片生成或 Python 执行。
计费模型速览
| 概念 | 机制 |
|---|---|
| 积分换算 | 全局设置“模型成本内部换算(每 USD)”:每 1 USD 模型成本扣除的积分数,与用户结算货币无关;设 0 = 停用积分体系 |
| 预检扣费 | 生成前按模型价格预留积分(预占→结算→释放),余额不足直接拒绝,避免超额黑洞 |
| 周期额度 | 用户组可配置周期性赠送积分(credit_period_seconds 滚动窗口),到期未用清零 |
| 永久积分 | 兑换码与积分套餐发放的不过期余额,与周期额度分账本记账 |
| 模型配额 | 每个模型可按用户组配置免费额度(按费用或次数、按天/小时滚动);未启用的组每次使用直接扣积分;一条配额记录都不存在 = 对所有组开放 |
| 平台限制 | 每日消息上限(默认 200)、每日图片上限(默认 30)、并发生成数等按用户限制,0 = 不限制;启动默认来自 DAILY_MESSAGE_LIMIT / IMAGE_DAILY_LIMIT |
| 结算货币 | 用户组价格与永久积分套餐使用的三位 ISO 4217 代码;修改不会自动换算已有价格 |
积分扣除写入不可裁剪的积分账本;每次成功调用的费用事实追加进独立统计表。删除“用量”记录不会改变“用量与计费”分析的全局趋势,也不会退积分——两套数据职责不同,对账时以账本与订单为准。
一次计费的生命周期
以“换算率 100 积分 / USD”、模型输入 $2.5/1M、输出 $10/1M 为例,看一次对话请求的积分流向:
- 预检:请求到达时按模型价格估算预留积分(如预留 2,000 积分)。余额不足 → 立即拒绝,返回“积分不足”而不是先烧钱。
- 保留(reserved):预占记录挂在本次生成上;用户看不到中间态。
- 结算(settled):生成完成后按真实 token 用量扣减,差额释放。多轮工具调用与服务商重试都归并进同一结算事实。
- 释放(released):生成失败、被停止或被审核拦截时预占全额退回。
“超额提示”文案与超限行为(拒绝 / 扣积分 / 切换模型)在用户组额度里配置;管理员还可以在“积分与配额”为单个用户做一次性调整,用户下次登录会看到入账通知。
模型配额配置示例
| 经营场景 | 推荐配置 |
|---|---|
| 试用组只能用经济模型 50 次/天 | 该模型为用户组设 count=50 的周期配额;高价模型不给试用组建配额记录 → 改用权限隐藏 |
| 付费组全模型可用但费用兜底 | 每个高价模型配 cost 类配额(按周期费用上限) |
| 内部组不受限 | 不建配额记录 + 权限放开;注意“未启用配额 = 每次扣积分”,内部组应配足周期额度 |
| 演示站 | 关闭积分或全局低额 + 默认模型选 mock/低价渠道,双保险 |
用户组(套餐)
“计费与权益 → 用户组”编辑会员等级:名称、价格与功能会展示在用户的订阅页面。系统始终存在一个免费默认组(不可删除),删除其他组时成员自动移入免费组。编辑页分四个标签:
套餐信息
名称、月/年价格(以结算货币的分为单位)、简介与功能列表、默认组标记、排序。价格仅决定“卖什么”,不直接决定额度——额度在另外三个标签里。
额度
| 区块 | 字段 | 说明 |
|---|---|---|
| 资源额度 | 最大项目数 / 知识库数 / 存储空间(MB) | 0 = 不限制 |
| 积分 | 周期赠送积分、周期长度 | 到期滚动清零 |
| 模型配额 | 按模型设置免费额度与超限行为 | 提示语可自定义(“您已达到当前套餐对此模型的使用上限…”) |
权限
按目录勾选该组可访问的资源与能力,三种模式(全部 / 指定 / 无):
- 提示词访问、技能访问、工具和 MCP 访问(受限工具会显示在选择器中但不可选;管理员全局关闭的工具不显示)。
- 功能权限:分享对话、使用知识库、分享知识库、上传文件、导出对话、删除对话、语音识别、使用记忆、绘图。
用户
搜索并分页查看组内成员,便于核对迁移结果。
推荐层次:管理员、内部成员、试用、付费。每层明确默认模型、可见模型、每日配额、积分余额上限和敏感工具权限。避免为单个用户建大量不可追踪的例外;特殊情况用一次性积分调整或有限期兑换码,并记录原因。
积分与配额页
“计费与权益 → 积分与配额”放全局开关与平台限制:计费策略(积分换算率、预检开关、结算货币)适用于所有会员和所有扣积分模型;平台限制按用户维度(每日消息/图片、并发生成)。页面里的“计费策略”区块——模型成本内部换算、积分预检、结算货币——对每个会员和每个扣积分模型生效,与页面引导文案一致;下方“平台限制”区块按用户维度:每日消息与图片上限、每日输入+输出 token 上限(按 UTC 日)、同时进行的生成流上限,各项 0 = 不限制。
模型成本内部换算(per USD)
结算货币(settlement_currency,三位 ISO 4217 代码)
积分预检:
[✓] 预估并拦截余额不足的请求
每天消息上限: [ 200 ]
每天图片上限: [ 30 ]
每天令牌上限: [ 0 ]
每用户并发生成数: [ 3 ]
超出配额提示:
[ 您已达到当前套餐对此模型的使用上限… ]
对照持久化默认存储可知全新部署启动时:credit_preflight_enabled=true、daily_message_limit=200、daily_image_limit=30、daily_token_limit=0、max_concurrent_generations=3;全局 credits_per_usd(每 USD 积分数)初始为 0(关闭积分)、settlement_currency 为 "USD"。环境变量只作为两个每日上限的启动默认值(DAILY_MESSAGE_LIMIT、IMAGE_DAILY_LIMIT);本页其余设置由管理员持久化在 settings 表中并按请求热加载。
同页下半部分是永久积分套餐(可拖拽排序,每行:名称、积分数、结算货币价格、描述、启用开关、编辑/删除)。套餐是公开定价数据——用户订阅页与匿名只读接口 GET /api/credit-packages 都只展示已启用且价格大于 0 的套餐。管理员可以从“用户与访问 → 用户”直接调整某个用户的永久余额,系统会写入一条积分调整通知,用户下次登录时可见。
核心字段与默认值:
| 字段 | 机制 | 默认 |
|---|---|---|
| 模型成本内部换算(每 USD) | 每 1 USD 模型成本折多少积分;0 = 停用整个积分体系(credits_per_usd) | 0(停用) |
| 积分预检 | 生成前预占、完成后按真实用量结算(credit_preflight_enabled) | 开 |
| 结算货币 | 用户组价格与积分套餐使用的 ISO 4217 三位代码(settlement_currency) | USD |
| 每日消息上限 | 每用户每天消息条数;0 = 不限(DAILY_MESSAGE_LIMIT) | 200 |
| 每日图片上限 | 每用户每天图片生成数;0 = 不限(IMAGE_DAILY_LIMIT) | 30 |
| 每日令牌上限 | 每用户每天输入+输出 token 数(按 UTC 日);0 = 不限(daily_token_limit) | 0 |
| 并发生成数 | 每用户同时进行的生成请求数(max_concurrent_generations) | 3 |
调整模型配额前先检查模型实际价格、上下文长度、输出上限和工具成本;配额变化只影响后续请求,不会抹去已发生的使用或订单。
兑换码
“计费与权益 → 兑换码”按批次生成,两类权益:
| 类型 | 行为 |
|---|---|
| 用户组兑换码 | 兑换后把用户加入指定组并续期(组 + 有效期) |
| 永久积分兑换码 | 发放不过期积分 |
批次字段:面额/目标组、有效期、单码最大使用次数、批次名、启用状态。同一用户对同一码只能兑换一次(redeem_redemptions 上的数据库唯一约束 UNIQUE(code_id, user_id));已用次数不会超过上限(used_count <= max_uses,max_uses 默认为 1,即默认单次使用——只有刻意做共享促销码时才提高)。kind='credits' 的积分码发放永不过期的积分,其目标组字段只是满足外键的占位值,永远不会应用给兑换者。
管理员可以单独启用、作废或删除单码与整批,复制单个兑换码、复制全部未使用兑换码,或把整批导出为 CSV。作废(enabled=0)只停用未兑换的码而不删除记录,保留审计痕迹;即使物理删除码记录,已入账的积分也不受影响。
运营纪律:批量生成后先导出到受控的加密存储,再通过可撤销、可追踪的渠道发放;不要把码列表放进公开页面、客户端常量或客服截图。码泄露时立即停用批次——已入账的积分不受删除影响。活动结束处理兑换记录与批次负责人归档。
支付渠道与支付方式
两层结构让同一渠道提供多个方式、故障时独立停用其一:
- 支付渠道(“计费与权益 → 支付渠道”)保存某个网关的协议凭据,支持 Stripe、EPay 兼容接口、Waffo;同一协议可建多条渠道(如不同商户号)。凭据只保留在服务端。每条渠道有名称、协议、环境(
live/test)和该协议的凭据表单。测试渠道只对管理员可见可用,因此安全上线流程完全可以在生产密钥之前跑完。webhook 回调到达GET/POST /api/payments/webhooks/:channelId;后台展示的回调地址在渠道生命周期内保持不变,需在服务商后台注册。配置值保存后以••••••掩码显示——保持已被掩码的字段不变即可保留原密钥。绑定支付方式或存在进行中订单的渠道不能删除;先清理这些记录,或到订单页处理挂单。 - 支付方式(“计费与权益 → 支付方式”)决定用户在结算页看到什么:显示名称与图标公开,协议参数指向具体渠道(EPay 额外有网关
type,如alipay、wxpay、qqpay)。只有绑定已启用渠道的已启用方式才会出现在购买页。该页还保存可选的卡密购买链接(card_purchase_url):设置后,用户的支付弹窗会增加一项“购买卡密”并打开该地址(HTTP(S) 或根相对/路径)。
安全上线流程
- 在支付服务商创建受限 API/Webhook 凭据,测试与生产严格分开(不同密钥、不同商品配置)。
- 在“支付渠道”新建渠道,用后台展示的 webhook 地址在服务商侧注册回调。
- 确认回调通过 HTTPS 到达公开实例,签名/密钥校验开启;webhook 依赖服务器出网与入站两条路径都健康。
- 创建一个仅管理员可见的测试支付方式 + 低价积分套餐。
- 用服务商测试环境跑完:下单、成功、失败、取消、重复回调与延迟回调。
- 核对订单状态、积分入账、用量记录,验证退款或人工对账流程后,再切换生产并公开。
支付事件按(服务商, 渠道, 事件 ID)唯一去重:重复 webhook 不会二次入账,测试时不要人工“补”积分。长期挂起的订单用订单页的“安全关闭”处理,而不是直接改库。
支付订单与对账
“计费与权益 → 支付订单”查看结账、验签和履约状态,可对账或安全关闭停滞订单。台账按步骤完整可追:订单本身(创建 → 处理中 → 已履约 / 失败 / 已过期 / 已取消)、一次或多次服务商尝试(payment_order_attempts,EPay 续作会复用未结的 merchant_order_id),以及 webhook 送达的原始事件(payment_events,按 UNIQUE(provider, channel_id, event_id) 幂等)。人工对账只用于修复已核实的外部支付事实,不能当作绕过支付验证的发积分通道。发生争议或金额不一致时:
- 保留服务商的订单号、事件 ID、时间、金额、币种与签名验证结果。
- 检查 Aivory 订单状态、是否已入账、是否收到重复 webhook。
- 先在服务商后台确认最终状态,再执行人工对账。
- 记录操作者、原因与关联证据,避免多个管理员重复发放。
对账与安全关闭是两个动作,安全边界不同:
- 对账(reconcile) 重新拉取服务商订单,并按已核实事实推进 Aivory 订单状态;服务商已支付而本地仍挂起时变为已履约。
- 安全关闭(safe close) 只作用于停滞订单(pending / processing),对已支付状态拒绝操作——界面在执行前要求逐项确认。EPay 兼容协议没有可靠的通用关单接口,因此关闭只翻转本地订单状态、渠道保持启用;之后如收到经过验签的成功事件,订单仍会履约并发放权益。永久删除单独受
can_delete(终态)控制,EPay 还需要管理员确认“服务商端已核实未支付或已关闭”。
支付订单是不可变的商业快照:服务商、渠道/方式、商品名、金额/币种与权益字段在创建时拷贝,之后修改渠道或价格都永远不会改写历史订单。
定价与货币约定
- 用户组价格与积分套餐一律用结算货币(ISO 4217 三位代码)的分为单位存储;换货币不会自动换算历史价格。
- 模型单价用 USD/1M token 记录(成本以美元计的服务商直接填);积分换算率也锚定 USD,两者相乘得到扣费。跨币种经营时接受“显示价 ≠ 成本价”,用换算率吸收汇率差。
- 定价改动只影响之后的结算;测试环境验证后再生效,并在公告页同步用户。
常见经营场景配方
| 场景 | 推荐做法 |
|---|---|
| 客服补偿 | 对单用户的一次性积分调整(带原因、留通知记录),不要建“补偿套餐”公开可买 |
| 企业批量采购 | 生成一组用户组兑换码:限定批次名、有效期与使用次数,线下签收后发放 |
| 邀请返利 | 兑换码按活动批次发放;结束后立即停用批次,已入账积分不受影响 |
| 限时促销 | 新建低价积分套餐 + 排序/启用控制上下架;保留旧套餐订单可查 |
| 内部员工 | 独立用户组 + 充足周期积分 + 宽松权限;离职时移组而非删号 |
支付故障速查
| 症状 | 优先检查 |
|---|---|
| 服务商显示已支付,Aivory 订单仍挂起 | webhook 是否到达(HTTPS 公开入口、回调地址、服务商 IP 白名单/出站日志) |
| 回调验签失败 | 渠道密钥是否填了测试环境的另一把;服务商轮换过签名密钥 |
| 用户已付款但没到账 | 事件去重表是否已有该 event_id(已到但未履约 → 走对账);订单是否被安全关闭 |
| 担心重复入账 | 不必人工补——(provider, channel, event ID) 唯一去重,重发 webhook 是安全的 |
| 购买页没有某个支付方式 | 方式未启用、绑定的渠道被停用、或用户组/货币不匹配 |
| 积分到账数与预期不符 | 换算率(每 USD 积分数)与模型单价是否刚改过;改价不回溯 |
用量与计费分析
“数据与运营 → 用量与计费”提供持久化用量看板:默认 30 天窗口(AIVORY_API_ANALYTICS_WINDOW,默认 30)、可对比等长周期、趋势指标(计量操作、已交付轮次、输入+输出 token、模型成本、消耗积分、活跃用户)、经济模块(扣积分轮次占比、成本覆盖率、每轮次成本、每活跃用户成本、每扣积分轮次消耗积分、每轮次计量操作数、扣积分用户数),并按用户 / 模型 / 工作空间 / 用途 / 渠道核对消耗,还可切换到“模型反馈”视图。用量与计费趋势反映不可变的用量事实;“用量”页查看逐条计费调用(输入/输出 token、费用、关联对话、调用时间)并按记录删除诊断日志。
上线后定期(至少每周)检查:
- 每个用户组的平均成本、失败率、退款与可疑高频使用。
- 订单与服务商账单是否一致,是否存在长期挂起或重复订单。
- 模型价格、积分换算、免费额度是否仍覆盖成本(服务商调价后同步更新模型单价)。
- 管理员是否仍能访问并轮换支付凭据,webhook 是否能继续验签。
用户侧接口(买家使用的界面)
买家与普通用户不会进入管理员侧。他们使用的界面对应同一批底层表:
- 订阅页(
/subscription):当前套餐与余额、可购买的用户组目录(月付/年付)与永久积分套餐、“兑换码”输入框(用户组 + 有效期,或永久积分)、周期费用展示,以及带明细的支付记录(商品、金额、税费、币种、方式、服务商、时间戳、失败原因)。 - 结账与回跳:选择套餐或套餐后打开支付方式选择器,再进入服务商托管页面(Stripe Checkout 重定向/form_post,或 Waffo/EPay 网关);回跳路由核实订单状态并确认或解释结果(重复结账保护、过期会话处理、“必须确认旧结账后才可重试”等护栏)。
- 积分调整通知:管理员对单用户的一次性积分调整会在该用户下次登录时以横幅通知(
credit_adjustment_notifications,通过POST /api/me/credit-adjustments/claim一次性领取)。
审计可依赖的不可变事实
payment_orders是创建时的商业快照;之后修改渠道或价格都不会改写历史订单。payment_order_attempts记录每次结账尝试;payment_events保留每一条验签通过的 webhook。credit_ledger(timed_debit/permanent_debit)与quota_ledger(按编号窗口的count/cost限额)是权威计费账本;用量日志清理永远不会顺手删掉它们。billing_usage每次成功计费轮次追加一条成本事实(按 USD 微单位计),并喂给持久的“用量与计费”趋势。
“计费与权益”导航组各页暂无随发行版提供的截图;布局以“名称 + 说明 + 数值”的列表编辑页为主,与用户组/渠道页同构。
支付、渠道、OAuth、SMTP 和存储配置都含机密:管理员配置导出与完整备份都应加密保存、限制访问,按生产密钥同等标准保护。