Files
ttstd-infinite-canvas/backend/internal/app/credit_cost.go

71 lines
2.5 KiB
Go

package app
import (
"yingce/backend/internal/kernel"
"yingce/backend/internal/model"
)
func validateCreditCostPricing(capability, billingMode string, cost model.CreditCostPricing) error {
for _, price := range []int64{cost.UnitPriceMicrocredits, cost.InputTokenPriceMicrocredits, cost.OutputTokenPriceMicrocredits, cost.CachedTokenPriceMicrocredits} {
if price < 0 || price > 1_000_000_000_000 {
return BadAuthRequest("积分成本价必须在 0 到 1000000 积分之间")
}
}
if !cost.Configured {
return nil
}
if billingMode != "token" {
capability = ""
}
return validateTokenPrices(capability, cost.InputTokenPriceMicrocredits, cost.OutputTokenPriceMicrocredits, cost.CachedTokenPriceMicrocredits)
}
func snapshotCreditCost(order *model.BillingOrder, tier *model.ChannelModelPriceTier, quantity int64, estimate tokenBillingEstimate) {
if tier == nil {
return
}
order.CostPricing = tier.CostPricing
order.CostBillingMode = tier.BillingMode
order.CostQuantity = 1
if tier.BillingMode == "per_second" {
order.CostQuantity = quantity
}
if tier.BillingMode == "token" && estimate.Video != nil {
order.CostVideoFormulaTokens = estimate.Video.FormulaTokens
}
}
// 成本使用下单快照和真实用量,不套用销售倍率或用户扣费上限。
// 未结算、未配置或无法确定用量时不编造金额,历史订单也不反查当前价格。
func billingCreditCost(order model.BillingOrder) (*int64, error) {
if !order.CostPricing.Configured || order.Status != model.BillingStatusSettled {
return nil, nil
}
cost := order.CostPricing
var amount int64
var err error
switch order.CostBillingMode {
case "fixed_request", "per_second":
amount, err = creditAmount(cost.UnitPriceMicrocredits, order.CostQuantity, 10_000)
case "token":
input, output, cached := order.InputTokens, order.OutputTokens, order.CachedTokens
if !order.UsageAvailable {
if order.Capability != "video" || order.CostVideoFormulaTokens <= 0 {
return nil, nil
}
input, cached, output = 0, 0, order.CostVideoFormulaTokens
}
amount, err = kernel.TokenBillingAmount(10_000,
kernel.TokenBillingTerm{Tokens: max(0, input-cached), PriceMicrocredits: cost.InputTokenPriceMicrocredits},
kernel.TokenBillingTerm{Tokens: output, PriceMicrocredits: cost.OutputTokenPriceMicrocredits},
kernel.TokenBillingTerm{Tokens: cached, PriceMicrocredits: cost.CachedTokenPriceMicrocredits},
)
default:
return nil, nil
}
if err != nil {
return nil, err
}
return &amount, nil
}