BuildingAI 帮助文档
BuildingAI 官网
  1. 插件与框架开发
  • 欢迎使用 BuildingAI
  • 演示环境
  • 用户社群
  • 企业版咨询
  • 产品线路图
  • 更新日志
  • API 赞助商
  • 积分获取方式
  • 应用安装教程「必看」
  • 使用教程
    • 快速使用
      • 对话
      • 智能体
      • 知识库
      • 工作流
      • MCP 服务
      • 登录配置
      • 密钥配置
      • 模型计费
      • 积分充值
      • 会员订阅
      • 卡密兑换
      • DIY装修
    • 常见配置教程
      • 微信支付配置
      • 支付宝支付配置
      • 微信公众号配置
      • OSS存储配置
      • 短信配置
      • 谷歌登录配置
      • Ollama配置
    • 应用配置教程
      • 香蕉绘画-使用教程
      • Sora2短剧视频-使用教程
      • 即梦AI绘画-使用教程
      • wan2.6漫剧-使用教程
    • 大模型申请教程
      • 即梦AI密钥-申请教程
      • 豆包大模型-申请教程
      • 通义千问-申请教程
    • 老版本教程
      • 功能使用教程
      • 智能体
      • MCP工具
      • DIY中心
  • 部署教程
    • 宝塔面板部署
    • Windows 环境下 Docker 部署
    • Docker方式安装
  • 开发文档
    • 网络接口
      • 登录注册
        • 账号密码登录
        • 账号密码注册
      • 前台
        • 文件上传/下载
          • 单个上传
          • 多个上传
          • 列表
          • 详情
          • 下载
          • 删除
        • 用户
          • 算力明细
          • 登录配置
        • AI聊天
          • 对话(非流式)
          • 流式对话
          • 对话记录
          • 对话详情
          • 修改记录
          • 删除记录
          • 获取记录对话
        • MCP
          • 列表
          • 所有记录
          • 详情:id
          • 创建
          • 修改
          • 可见状态
          • 添加
          • 关联详情
          • 系统MCP
          • json导入
          • 移除
          • 删除
          • 获取快捷菜单
          • 系统MCP详情:id
          • 连通性
          • 批量连通性
        • 充值中心
          • 充值中心
          • 充值提交订单
          • 充值记录
          • 预支付
          • 获取支付结果
        • 模型厂商
          • 列表
          • 详情:id
          • 详情:code
        • AI模型
          • 列表
          • 详情:id
          • 默认模型
        • 数据分析
          • 数据记录
        • 会员中心
          • 会员中心信息
          • 获取套餐列表
          • 预支付
          • 订阅提交订单
      • 后台
        • 工作空间
          • MCP
            • 列表
            • 详情
            • 创建
            • 修改
            • 删除
            • 批量删除
            • 启用状态
            • json导入
            • 连通性
            • 批量连通性
            • 获取快捷菜单
            • 设置快捷菜单
          • AI模型
            • 厂商管理
              • 列表
              • 新增
              • 详情:id
              • 详情:provider
              • 修改
              • 删除
              • 状态
            • 模型管理
              • 列表
              • 新增
              • 详情:id
              • 修改
              • 删除:id
              • 批量删除
              • 设为默认
              • 模型类型
              • 模型支持能力
              • 父级模型类型
          • AI知识库
            • 知识库列表
            • 知识库详情
            • 转移知识库
            • 知识库删除
            • 知识库文档列表
            • 知识库文档详情
            • 知识库文档删除
            • 知识库分段列表
            • 知识库分段详情
            • 知识库分段删除
            • 数据列表接口
          • AI智能体
            • 智能体创建
            • 智能体列表
            • 智能体详情
            • 智能体对话记录列表
            • 智能体对话记录详情
            • 智能体对话
            • 智能体发布API接口对话
            • 智能体发布API获取对话列表
            • 智能体发布API获取对话消息
            • 智能体发布API更新对话
            • 智能体发布API删除对话
          • 密钥管理
            • 密钥模板
              • 列表
              • 全部列表
              • 详情
              • 创建
              • 修改
              • 删除
              • 批量删除
              • 修改状态
              • json导入
            • 密钥配置
              • 列表
              • 列表:templateId
              • 创建
              • 统计
              • 详情
              • 完整详情
              • 修改
              • 修改状态
              • 删除
              • 批量删除
        • 用户管理
          • 列表
          • 创建
          • 详情:id
          • 删除
          • 批量删除
          • 重置密码
          • 更新状态
          • 重置随机密码
          • 登录设置
          • 登录设置
        • 角色管理
          • 创建
          • 详情:id
          • 修改
          • 删除
          • 列表
        • 菜单管理
          • 创建
          • 详情:id
          • 修改
          • 删除
          • 列表
        • 插件管理
          • 我的插件
            • 列表
            • 修改
            • 详情:id
            • 创建
            • 启用列表
            • 批量删除
            • 删除:id
            • 批量状态
            • 禁用:id
            • 启用:id
            • 是否存在:identifier
            • 详情:identifier
            • 入库插件详情:identifier
            • 本地列表
            • 类型列表
            • 版本列表:identifier
            • 安装
            • 卸载
          • 插件操作
            • 下载
            • 安装
          • 平台密钥
            • 获取开发者密钥
            • 设置开发者密钥
        • 权限管理
          • 列表
          • 扫描权限
          • 同步到库
          • 扫描接口
          • 清理废弃权限
          • 详情:code
        • 字典配置
          • 列表
        • 系统操作
          • 支付配置
            • 列表
            • 详情:id
            • 状态
            • 更新
          • 系统信息
            • 安装状态
            • 安装状态
          • pm2
            • 进程列表
            • 日志
            • 重启
            • 重载
            • 停止进程
            • 进程详情
            • 进程状态
            • 清空日志
            • 保存进程
            • 健康检查
            • 删除进程
        • 套餐充值
          • 获取套餐充值配置
          • 获取套餐充值配置 Copy
        • 财务
          • 财务中心
          • 用户余额明细
        • 订单管理
          • 充值订单列表
          • 充值订单详情
          • 充值订单退款
          • 会员订单列表
        • 渠道管理
          • 公众号配置
            • 详情
            • 修改
        • 数据分析
          • 数据看板
        • VIP 会员
          • 会员等级
            • 新增会员等级
            • 会员等级列表
            • 修改会员等级
            • 会员等级详情
            • 删除会员等级
          • 订阅计划
            • 新增订阅计划
            • 订阅计划设置
            • 设置会员功能状态
            • 更改订阅计划状态
            • 订阅计划详情
            • 修改订阅计划
            • 删除订阅计划
            • 更新订阅计划排序
      • 插件
        • 文章插件
          • 前台
            • 列表
          • 后台
            • 文章
              • 列表
              • 创建
            • 分类
              • 列表
              • 创建
        • 智能体-企业微信插件
          • 对话接口
        • 配图大师
          • 后台
            • 配图记录
            • 获取配图插件
            • 插件设置
    • 插件与框架开发
      • 技术规范
      • 前置准备
      • 本地部署与开发
      • 目录结构
      • 项目配置
      • 主程序启动链路
      • 请求处理链路
      • 后端开发约定
      • BaseController 与 BaseService
      • DTO、工具与通用服务
      • 前端开发
      • 主程序计费接入
      • 数据库与实体建议
      • AI SDK 开发文档
      • BuildingAI 升级开发文档
      • 应用开发
        • 介绍
        • 创建应用
        • 模板结构
        • 应用开发
        • 打包发布
        • 插件更新
        • 插件清单文件
        • 插件后端开发
        • 插件前端开发
        • Extension SDK 怎么用
        • 插件计费接入
        • 插件 AI 能力接入建议
        • Seeds、Upgrade 与存储
        • 插件升级开发文档
        • 构建与发布
      • PC 客户端
        • 开发文档
        • 构建文档
  • 设计资源
    • 官方素材库
  • 政策
    • 开源许可
    • 服务条款
    • 隐私政策
  1. 插件与框架开发

主程序计费接入

主程序里的计费,不建议自己直接改 user.power,而应该统一走 AppBillingService 或 BaseBillingService。

1. 计费模块结构#

主程序计费能力在:
packages/core/src/modules/billing/
├── billing.module.ts
├── base-billing.service.ts
├── app-billing.service.ts
└── types.ts
关系:
BillingModule
全局模块,提供计费服务
BaseBillingService
底层能力,负责真正加减积分与记账
AppBillingService
主程序使用的服务,当前主要继承 BaseBillingService
主程序里 packages/api/src/modules/app.module.ts 已经导入了 BillingModule,所以大多数主程序 service 里可以直接注入:
@Injectable()
export class ReportService {
    constructor(private readonly appBillingService: AppBillingService) {}
}

2. 为什么必须走计费服务#

因为 BaseBillingService 不只是改一个数字,它还会:
1.
查询用户当前积分
2.
校验余额是否足够
3.
事务里更新 user.power
4.
插入 account_log
5.
对会员赠送积分做优先扣减
如果你直接改 user.power,会丢掉:
余额流水
关联单号
来源信息
会员赠送积分扣减顺序

3. BaseBillingService 提供的方法#

getUserPower(userId)#

读取当前积分余额。
const power = await this.appBillingService.getUserPower(userId);

hasSufficientPower(userId, requiredAmount)#

校验余额是否足够。
const ok = await this.appBillingService.hasSufficientPower(userId, 10);
if (!ok) {
    throw HttpErrorFactory.badRequest("积分不足");
}

deductUserPower(options, entityManager?)#

扣减积分。

addUserPower(options, entityManager?)#

增加积分。
一个最小可运行示例:
@Injectable()
export class FeatureService {
    constructor(private readonly appBillingService: AppBillingService) {}

    async run(userId: string, taskNo: string) {
        await this.appBillingService.deductUserPower({
            userId,
            amount: 3,
            accountType: ACCOUNT_LOG_TYPE.CHAT_DEC,
            source: {
                type: ACCOUNT_LOG_SOURCE.CHAT,
                source: "报告生成",
            },
            remark: "报告生成消耗",
            associationNo: taskNo,
        });
    }
}

4. 扣费参数怎么填#

扣费参数结构:
await this.appBillingService.deductUserPower({
    userId,
    amount,
    accountType,
    source: {
        type,
        source: "来源描述",
    },
    remark: "备注",
    associationNo: "关联单号",
    associationUserId: "关联用户ID",
});
字段说明:
userId
被扣费用户
amount
扣减积分
accountType
账户流水类型
source.type
来源大类
source.source
可读的来源名称
remark
备注
associationNo
关联单号、会话号、订单号、任务号
associationUserId
操作人或关联人

5. 加积分参数怎么填#

await this.appBillingService.addUserPower({
    userId,
    amount,
    accountType,
    source: {
        type,
        source: "来源描述",
    },
    remark: "备注",
    associationNo: "订单号",
    expireAt,
    subscriptionId,
});
仅加积分时才有的附加字段:
expireAt
过期时间,会员赠送积分常用
subscriptionId
关联会员订阅

6. ACCOUNT_LOG_SOURCE 与 ACCOUNT_LOG_TYPE#

常见来源:
ACCOUNT_LOG_SOURCE.RECHARGE
ACCOUNT_LOG_SOURCE.SYSTEM
ACCOUNT_LOG_SOURCE.CHAT
ACCOUNT_LOG_SOURCE.AGENT_CHAT
ACCOUNT_LOG_SOURCE.PLUGIN
ACCOUNT_LOG_SOURCE.MEMBERSHIP_GIFT
ACCOUNT_LOG_SOURCE.CARD_KEY_REDEEM
常见类型:
ACCOUNT_LOG_TYPE.RECHARGE_INC
ACCOUNT_LOG_TYPE.RECHARGE_GIVE_INC
ACCOUNT_LOG_TYPE.RECHARGE_DEC
ACCOUNT_LOG_TYPE.SYSTEM_MANUAL_INC
ACCOUNT_LOG_TYPE.SYSTEM_MANUAL_DEC
ACCOUNT_LOG_TYPE.CHAT_DEC
ACCOUNT_LOG_TYPE.AGENT_CHAT_DEC
ACCOUNT_LOG_TYPE.AGENT_GUEST_CHAT_DEC
ACCOUNT_LOG_TYPE.PLUGIN_DEC
ACCOUNT_LOG_TYPE.MEMBERSHIP_GIFT_INC
ACCOUNT_LOG_TYPE.MEMBERSHIP_GIFT_DEC
ACCOUNT_LOG_TYPE.MEMBERSHIP_GIFT_EXPIRED
ACCOUNT_LOG_TYPE.CARD_KEY_REDEEM_INC
选择原则:
主程序自己扣用户积分:
用与业务场景最接近的 ACCOUNT_LOG_TYPE
source.type 选大类
source.source 写清楚业务名,方便财务和运营排查

7. 主程序常见计费场景#

场景一:对话前先校验最低余额#

这个模式在 chat-billing.handler.ts 和 agent-billing.ts 里都有。
const currentPower = await this.appBillingService.getUserPower(userId);
const minRequired = Math.ceil((estimatedTokens / billingRule.tokens) * billingRule.power);

if (currentPower < minRequired) {
    throw HttpErrorFactory.badRequest("积分不足,请充值后重试");
}
适合:
AI 对话
智能体执行
提交任务前先校验余额

场景二:按实际消耗扣费#

await this.appBillingService.deductUserPower({
    userId,
    amount,
    accountType: ACCOUNT_LOG_TYPE.CHAT_DEC,
    source: {
        type: ACCOUNT_LOG_SOURCE.CHAT,
        source: "基本对话",
    },
    remark: "基本对话消耗",
    associationNo: conversationId,
});
适合:
大模型 token 消耗
图片生成
文档解析
报告生成

场景三:系统后台手动调积分#

项目内 user.service.ts 就是这么做的:
await this.appBillingService.addUserPower({
    userId,
    amount: dto.amount,
    accountType: ACCOUNT_LOG_TYPE.SYSTEM_MANUAL_INC,
    source: {
        type: ACCOUNT_LOG_SOURCE.SYSTEM,
        source: "系统操作",
    },
    remark: "系统调整用户积分",
    associationUserId: currentUser.id,
});
扣减则改成:
deductUserPower
ACCOUNT_LOG_TYPE.SYSTEM_MANUAL_DEC

场景四:充值到账#

充值回调里建议和订单状态更新放一个事务:
await this.userRepository.manager.transaction(async (entityManager) => {
    await this.appBillingService.addUserPower(
        {
            userId: order.userId,
            amount: power,
            accountType: ACCOUNT_LOG_TYPE.RECHARGE_INC,
            source: {
                type: ACCOUNT_LOG_SOURCE.RECHARGE,
                source: "用户充值",
            },
            remark: "充值成功",
            associationNo: order.orderNo,
        },
        entityManager,
    );

    await entityManager.update(RechargeOrder, order.id, {
        payStatus: 1,
        payTime: new Date(),
    });
});

场景五:会员赠送积分#

await this.appBillingService.addUserPower({
    userId,
    amount: giftPower,
    accountType: ACCOUNT_LOG_TYPE.MEMBERSHIP_GIFT_INC,
    source: {
        type: ACCOUNT_LOG_SOURCE.MEMBERSHIP_GIFT,
        source: "会员赠送",
    },
    remark: "会员周期赠送积分",
    expireAt,
    subscriptionId,
});
这个场景非常重要,因为 BaseBillingService 在扣费时会优先扣:
1.
未过期的会员赠送积分
2.
且优先扣最早过期的赠送积分
3.
最后再体现为用户总积分减少

8. 事务里的正确用法#

如果一个业务流程里既要扣积分,又要落业务数据,建议放一个事务,并把 entityManager 传进去:
await this.userRepository.manager.transaction(async (entityManager) => {
    await this.appBillingService.deductUserPower(
        {
            userId,
            amount: 5,
            accountType: ACCOUNT_LOG_TYPE.CHAT_DEC,
            source: {
                type: ACCOUNT_LOG_SOURCE.CHAT,
                source: "报告生成",
            },
            remark: "报告生成消耗",
            associationNo: taskNo,
        },
        entityManager,
    );

    await entityManager.insert(TaskEntity, {
        userId,
        taskNo,
        status: "done",
    });
});
这样能保证:
扣费成功但业务落库失败时回滚
业务落库成功但扣费失败时也回滚

9. 主程序计费最佳实践#

不要直接 user.power = user.power - x
不要只记订单,不记 account_log
预校验余额与实际扣费建议分两步
associationNo 尽量传业务单号,方便排查
source.source 写清楚具体功能,不要只写“系统”
涉及订单、任务、订阅联动时尽量放事务里
修改于 2026-04-17 02:49:31
上一页
前端开发
下一页
数据库与实体建议
Built with