This PR fixes three issues: 1. Token bound_channel_id not updating: Add bound field to Update() method 2. Channel pricing quota_type detection: Use QuotaTypeByCall constant instead of magic number 1 3. Log display for ratio-based pricing: Set ModelPrice=-1 for ratio-based pricing Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>feat/alipay-payment
| @@ -32,3 +32,6 @@ data/ | |||||
| .gomodcache/ | .gomodcache/ | ||||
| .gocache-temp | .gocache-temp | ||||
| .gopath | .gopath | ||||
| # 测试脚本目录 | |||||
| test-scripts/ | |||||
| @@ -191,6 +191,9 @@ func Relay(c *gin.Context, relayFormat types.RelayFormat) { | |||||
| break | break | ||||
| } | } | ||||
| // 在渠道选择后更新价格数据以使用渠道定价 | |||||
| helper.UpdatePriceDataForChannelPricing(c, relayInfo, channel.Id) | |||||
| addUsedChannel(c, channel.Id) | addUsedChannel(c, channel.Id) | ||||
| bodyStorage, bodyErr := common.GetBodyStorage(c) | bodyStorage, bodyErr := common.GetBodyStorage(c) | ||||
| if bodyErr != nil { | if bodyErr != nil { | ||||
| @@ -150,7 +150,7 @@ func GetEffectivePricing(modelName string, channelId int) (modelRatio, completio | |||||
| if time.Since(channelPricingCacheTime) < channelPricingCacheTTL { | if time.Since(channelPricingCacheTime) < channelPricingCacheTTL { | ||||
| if cp, ok := channelPricingCache[cacheKey]; ok { | if cp, ok := channelPricingCache[cacheKey]; ok { | ||||
| channelPricingCacheLock.RUnlock() | channelPricingCacheLock.RUnlock() | ||||
| return cp.ModelRatio, cp.CompletionRatio, cp.ModelPrice, true, true | |||||
| return cp.ModelRatio, cp.CompletionRatio, cp.ModelPrice, cp.QuotaType == QuotaTypeByCall, true | |||||
| } | } | ||||
| } | } | ||||
| channelPricingCacheLock.RUnlock() | channelPricingCacheLock.RUnlock() | ||||
| @@ -173,7 +173,7 @@ func GetEffectivePricing(modelName string, channelId int) (modelRatio, completio | |||||
| channelPricingCache[cacheKey] = &cp | channelPricingCache[cacheKey] = &cp | ||||
| channelPricingCacheLock.Unlock() | channelPricingCacheLock.Unlock() | ||||
| return cp.ModelRatio, cp.CompletionRatio, cp.ModelPrice, true, true | |||||
| return cp.ModelRatio, cp.CompletionRatio, cp.ModelPrice, cp.QuotaType == QuotaTypeByCall, true | |||||
| } | } | ||||
| // RefreshChannelPricingCache 刷新渠道定价缓存 | // RefreshChannelPricingCache 刷新渠道定价缓存 | ||||
| @@ -284,7 +284,7 @@ func (token *Token) Update() (err error) { | |||||
| } | } | ||||
| }() | }() | ||||
| err = DB.Model(token).Select("name", "status", "expired_time", "remain_quota", "unlimited_quota", | err = DB.Model(token).Select("name", "status", "expired_time", "remain_quota", "unlimited_quota", | ||||
| "model_limits_enabled", "model_limits", "allow_ips", "group", "cross_group_retry").Updates(token).Error | |||||
| "model_limits_enabled", "model_limits", "allow_ips", "group", "cross_group_retry", "bound_channel_id").Updates(token).Error | |||||
| return err | return err | ||||
| } | } | ||||
| @@ -54,7 +54,7 @@ func ModelPriceHelper(c *gin.Context, info *relaycommon.RelayInfo, promptTokens | |||||
| var channelPricingFound bool | var channelPricingFound bool | ||||
| // 尝试获取渠道定价(优先于全局定价) | // 尝试获取渠道定价(优先于全局定价) | ||||
| if info.ChannelMeta != nil && info.ChannelId > 0 { | |||||
| if info != nil && info.ChannelMeta != nil && info.ChannelId > 0 { | |||||
| cpRatio, cpCompletionRatio, cpPrice, cpUsePrice, found := model.GetEffectivePricing(info.OriginModelName, info.ChannelId) | cpRatio, cpCompletionRatio, cpPrice, cpUsePrice, found := model.GetEffectivePricing(info.OriginModelName, info.ChannelId) | ||||
| if found { | if found { | ||||
| modelRatio = cpRatio | modelRatio = cpRatio | ||||
| @@ -207,3 +207,39 @@ func ContainPriceOrRatio(modelName string) bool { | |||||
| } | } | ||||
| return false | return false | ||||
| } | } | ||||
| // UpdatePriceDataForChannelPricing 在渠道选择后更新 PriceData 以使用渠道定价 | |||||
| // ModelPriceHelper 在渠道选择之前被调用,此时 ChannelMeta 为 nil,导致渠道定价无法使用。 | |||||
| // 需要在渠道选择后调用此函数更新价格数据,用于后续的日志记录和计费计算。 | |||||
| func UpdatePriceDataForChannelPricing(c *gin.Context, info *relaycommon.RelayInfo, channelId int) { | |||||
| if info == nil || channelId <= 0 { | |||||
| return | |||||
| } | |||||
| cpRatio, cpCompletionRatio, cpPrice, cpUsePrice, found := model.GetEffectivePricing(info.OriginModelName, channelId) | |||||
| if !found { | |||||
| return | |||||
| } | |||||
| // 更新 PriceData 中的定价相关字段 | |||||
| info.PriceData.ModelRatio = cpRatio | |||||
| info.PriceData.CompletionRatio = cpCompletionRatio | |||||
| info.PriceData.UsePrice = cpUsePrice | |||||
| // 按次计费模式下使用渠道价格,按量计费模式下设置 ModelPrice = -1 让前端识别计费模式 | |||||
| if cpUsePrice { | |||||
| info.PriceData.ModelPrice = cpPrice | |||||
| } else { | |||||
| info.PriceData.ModelPrice = -1 | |||||
| } | |||||
| // 重新计算预扣费额度(用于后续可能的引用) | |||||
| if cpUsePrice { | |||||
| info.PriceData.QuotaToPreConsume = int(cpPrice * common.QuotaPerUnit * info.PriceData.GroupRatioInfo.GroupRatio) | |||||
| } else { | |||||
| estimateTokens := info.GetEstimatePromptTokens() | |||||
| if estimateTokens > 0 { | |||||
| ratio := cpRatio * info.PriceData.GroupRatioInfo.GroupRatio | |||||
| info.PriceData.QuotaToPreConsume = int(float64(estimateTokens) * ratio) | |||||
| } | |||||
| } | |||||
| } | |||||