Skip to content

Billing 模块(统一计费)

Billing 是对免费次数 + 积分扣除的高层统一封装。内部整合了 3 个后端接口,开发者无需分别调用。

计费优先级:免费时段(30 秒内重复操作免费) → 免费次数 → 积分扣除

API 列表

方法返回值说明
sdk.billing.getUsage()Promise<UsageInfo>获取使用额度(网络请求)
sdk.billing.getCachedUsage()UsageInfo | null获取缓存额度(首次调用前返回 null)
sdk.billing.check()BillingCheckResult同步校验是否可操作(不扣费)
sdk.billing.consume(options?)Promise<BillingConsumeResult>消耗一次
sdk.billing.refreshCredits()Promise<void>手动刷新积分余额
sdk.billing.onChange(callback)() => void监听额度变化

详细用法

获取使用额度

typescript
const usage = await sdk.billing.getUsage()
// {
//   isEnabled: true,          当前模块是否启用计费
//   freeRemaining: 5,         剩余免费次数
//   freeTotal: 10,            免费总次数
//   creditsPerUse: 6,         每次操作所需积分(免费用完后)
//   creditsBalance: 78633,    当前积分余额
//   inFreePeriod: false,      是否在免费时段内
//   freePeriodRemaining: 0,   免费时段剩余秒数
// }

内部并行请求:

  1. GET /ai/v5/artimind/free_trial/count?module=generator_{appKey} → 免费次数
  2. credits.getBalance() → 积分余额

返回值中的 isEnabled 直接来自后端 free_trial/count 响应里的 is_enabled 字段,可用于判断当前生成器模块是否已启用计费。

校验是否可操作

typescript
const check = sdk.billing.check()
// { canProceed: true,  reason: 'free_period' }   免费时段内
// { canProceed: true,  reason: 'free_count' }     有免费次数
// { canProceed: true,  reason: 'credits' }        将扣积分
// { canProceed: false, reason: 'insufficient' }   积分不足

消耗一次

typescript
const result = await sdk.billing.consume({
  externalId: 'download_123',  // 可选,业务幂等 ID,未传则 SDK 自动生成 UUID
})
// { freeRemaining: 4, isCredit: false, isBlacklisted: false }   扣了免费次数
// { freeRemaining: 0, isCredit: true, isBlacklisted: false }    扣了积分
// { freeRemaining: 4, isCredit: false, isBlacklisted: true }    命中黑名单用户

// isCredit=true 时 SDK 自动调用 credits.getBalance() 刷新余额

返回字段说明:

  • freeRemaining: 当前剩余免费次数
  • isCredit: 本次是否实际扣了积分
  • isBlacklisted: 是否为黑名单用户;当后端返回状态码 20102 时为 true,此时 SDK 不再抛错,业务层可据此决定提示或拦截后续流程

监听额度变化

typescript
const unsubscribe = sdk.billing.onChange((usage) => {
  renderBillingUI(usage)
})

免费时段机制

consume() 成功后 30 秒内视为免费时段:

  • 期间再次调用 consume() 不会发起后端请求,直接返回成功
  • 适用于"导出后短时间内免费重复导出"的体验
  • SDK 内部通过时间戳 _freePeriodEnd 管理,无需开发者维护定时器
typescript
function renderBilling(usage) {
  if (usage.inFreePeriod) {
    btn.textContent = `Free Re-export ${usage.freePeriodRemaining}s`
  } else if (usage.freeRemaining > 0) {
    btn.textContent = `Download (Free ${usage.freeRemaining}/${usage.freeTotal})`
  } else {
    btn.textContent = `Download (${usage.creditsPerUse} credits)`
  }
}

免费时段倒计时实现示例

javascript
let timer = null
sdk.billing.onChange((usage) => {
  clearInterval(timer)
  if (usage.inFreePeriod) {
    timer = setInterval(() => {
      const cached = sdk.billing.getCachedUsage()
      if (cached) updateUI(cached)
      if (!cached?.inFreePeriod) clearInterval(timer)
    }, 1000)
  }
})

后端接口对照

SDK 方法后端接口说明
getUsage()GET /ai/v5/artimind/free_trial/count?module=generator_{appKey}查询免费次数
getUsage()GET /ai/v1/credit/getBalance并行查积分(复用 credits)
consume()POST /ai/v5/artimind/free_trial后端自动判断扣免费/扣积分

module 参数格式为 generator_{appKey},后端以此区分不同生成器应用。

MIT Licensed