插件计费接入
ExtensionBillingModuleExtensionBillingServiceuser.power。1. 计费模块位置
packages/@chatbuddy-ai/extension-sdk/src/modules/billing/
├── extension-billing.module.ts
└── extension-billing.service.tsBaseBillingServiceUserAccountLog2. 为什么插件也必须走计费服务
1.
2.
account_log3.
4.
5.
user.power,会丢失:3. 如何注册ExtensionBillingModule
import { ExtensionBillingModule } from "@chatbuddy-ai/extension-sdk"; @Module({ imports: [ExtensionBillingModule], providers: [ArticleService],
})
export class ArticleModule {}@Global,但仍建议由插件某个根模块显式导入一次,避免运行时 provider 不可见。@Injectable
export class ArticleService { constructor( private readonly extensionBillingService: ExtensionBillingService, ) {}
}4.ExtensionBillingService提供的方法
hasSufficientPower(userId, requiredAmount)
const ok = await this.extensionBillingService.hasSufficientPower(userId, 5);
if (!ok) { throw HttpErrorFactory.badRequest("积分不足");
}deductUserPower(options, entityManager?)
addUserPower(options, entityManager?)
@Injectable
export class ArticleService { constructor( private readonly extensionBillingService: ExtensionBillingService, ) {} async polish(userId: string, taskNo: string) { await this.extensionBillingService.deductUserPower({ userId, amount: 5, remark: "文章润色消耗", associationNo: taskNo, }); }
}5. 插件扣费参数怎么填
sourceaccountTypeExtensionBillingService自动补。await this.extensionBillingService.deductUserPower({ userId, amount: 5, remark: "文章生成消耗", associationNo: taskNo,
});accountType: ACCOUNT_LOG_TYPE.PLUGIN_DECsource.type: ACCOUNT_LOG_SOURCE.PLUGINsource.source: 当前插件名称6. 插件加积分参数怎么填
await this.extensionBillingService.addUserPower({ userId, amount: 10, remark: "任务失败返还积分", associationNo: taskNo,
});7. 插件计费的一个关键注意点
deductUserPower和addUserPowerACCOUNT_LOG_TYPE.PLUGIN_DECAccountLog.action:ACTION.DECACTION.INCaccountType判断增减,要结合:accountTypeaction8. 插件名称是怎么识别出来的
ExtensionBillingService会通过调用栈识别当前插件标识符,再去扩展配置里取插件名称。Extension not found9. 插件计费的常见模式
模式一:执行前先校验最低积分
const ok = await this.extensionBillingService.hasSufficientPower(userId, 5);
if (!ok) { throw HttpErrorFactory.badRequest("积分不足,充值后再试");
}模式二:执行成功后按固定价格扣费
await this.extensionBillingService.deductUserPower({ userId, amount: 5, remark: "文章润色消耗", associationNo: taskNo,
});模式三:执行失败返还积分
await this.extensionBillingService.addUserPower({ userId, amount: 5, remark: "文章润色失败返还", associationNo: taskNo,
});模式四:按流程分段扣费
await this.extensionBillingService.deductUserPower({ userId, amount: 2, remark: "文档解析消耗", associationNo: taskNo,
}); await this.extensionBillingService.deductUserPower({ userId, amount: 3, remark: "摘要生成消耗", associationNo: taskNo,
});10. 事务里的正确写法
entityManager传进去。await this.articleRepository.manager.transaction(async (entityManager) => { await this.extensionBillingService.deductUserPower( { userId, amount: 5, remark: "文章生成消耗", associationNo: taskNo, }, entityManager, ); await entityManager.insert(ArticleTask, { userId, taskNo, status: "done", });
});11. 插件计费最佳实践
associationNo建议用任务号、订单号、工作流号remark要能让运营一眼看懂ExtensionBillingService自己改余额共 319 篇文档 · 内容同步自官方帮助中心