fix(billing): 异步任务退款时同步减少 used_quota (#6795)
* fix(billing): 异步任务退款时同步减少 used_quota 退款时仅恢复了 quota(剩余额度),但未同步减少 used_quota(已用额度), 导致"总额度"(quota + used_quota)随退款次数持续虚增,超出用户实际充值金额。 修复三处退款路径: - RefundTaskQuota:任务失败完整退款 - RecalculateTaskQuota:差额结算退款分支 - controller/midjourney.go:Midjourney 任务失败退款 新增 model.UpdateUserUsedQuota 公开函数,仅调整 used_quota 不影响 request_count。 * fix(billing): 任务退款时同步扣减渠道 used_quota * fix(billing): complete async task refund accounting * style(model): group internal Midjourney fields --------- Co-authored-by: CaIon <i@caion.me>
This commit is contained in:
+62
-50
@@ -232,30 +232,6 @@ func RelaySwapFace(c *gin.Context, info *relaycommon.RelayInfo) *dto.MidjourneyR
|
||||
if err != nil {
|
||||
return &mjResp.Response
|
||||
}
|
||||
defer func() {
|
||||
if mjResp.StatusCode == 200 && mjResp.Response.Code == 1 {
|
||||
err := service.PostConsumeQuota(info, priceData.Quota, 0, true)
|
||||
if err != nil {
|
||||
common.SysLog("error consuming token remain quota: " + err.Error())
|
||||
}
|
||||
|
||||
tokenName := c.GetString("token_name")
|
||||
logContent := fmt.Sprintf("模型固定价格 %.2f,分组倍率 %.2f,操作 %s", priceData.ModelPrice, priceData.GroupRatioInfo.GroupRatio, constant.MjActionSwapFace)
|
||||
other := service.GenerateMjOtherInfo(info, priceData)
|
||||
model.RecordConsumeLog(c, info.UserId, model.RecordConsumeLogParams{
|
||||
ChannelId: info.ChannelId,
|
||||
ModelName: modelName,
|
||||
TokenName: tokenName,
|
||||
Quota: priceData.Quota,
|
||||
Content: logContent,
|
||||
TokenId: info.TokenId,
|
||||
Group: info.UsingGroup,
|
||||
Other: other,
|
||||
})
|
||||
model.UpdateUserUsedQuotaAndRequestCount(info.UserId, priceData.Quota)
|
||||
model.UpdateChannelUsedQuota(info.ChannelId, priceData.Quota)
|
||||
}
|
||||
}()
|
||||
midjResponse := &mjResp.Response
|
||||
midjourneyTask := &model.Midjourney{
|
||||
UserId: info.UserId,
|
||||
@@ -274,12 +250,42 @@ func RelaySwapFace(c *gin.Context, info *relaycommon.RelayInfo) *dto.MidjourneyR
|
||||
Progress: "0%",
|
||||
FailReason: "",
|
||||
ChannelId: c.GetInt("channel_id"),
|
||||
Quota: priceData.Quota,
|
||||
}
|
||||
billingPrepared, billingErr := service.PrepareMidjourneyTaskBilling(
|
||||
info,
|
||||
midjourneyTask,
|
||||
priceData.Quota,
|
||||
mjResp.StatusCode == http.StatusOK && midjResponse.Code == 1,
|
||||
)
|
||||
if billingErr != nil {
|
||||
common.SysLog("error consuming Midjourney quota: " + billingErr.Error())
|
||||
}
|
||||
err = midjourneyTask.Insert()
|
||||
if err != nil {
|
||||
return service.MidjourneyErrorWrapper(constant.MjRequestError, "insert_midjourney_task_failed")
|
||||
}
|
||||
billingApplied, billingErr := service.SettleMidjourneyTaskBilling(info, midjourneyTask, billingPrepared)
|
||||
if billingErr != nil {
|
||||
common.SysLog("error settling Midjourney quota: " + billingErr.Error())
|
||||
}
|
||||
if billingApplied {
|
||||
billingChannelId := midjourneyTask.GetBillingChannelId()
|
||||
tokenName := c.GetString("token_name")
|
||||
logContent := fmt.Sprintf("模型固定价格 %.2f,分组倍率 %.2f,操作 %s", priceData.ModelPrice, priceData.GroupRatioInfo.GroupRatio, constant.MjActionSwapFace)
|
||||
other := service.GenerateMjOtherInfo(info, priceData)
|
||||
model.RecordConsumeLog(c, info.UserId, model.RecordConsumeLogParams{
|
||||
ChannelId: billingChannelId,
|
||||
ModelName: modelName,
|
||||
TokenName: tokenName,
|
||||
Quota: midjourneyTask.Quota,
|
||||
Content: logContent,
|
||||
TokenId: midjourneyTask.TokenId,
|
||||
Group: info.UsingGroup,
|
||||
Other: other,
|
||||
})
|
||||
model.UpdateUserUsedQuotaAndRequestCount(info.UserId, midjourneyTask.Quota)
|
||||
model.UpdateChannelUsedQuota(billingChannelId, midjourneyTask.Quota)
|
||||
}
|
||||
c.Writer.WriteHeader(mjResp.StatusCode)
|
||||
respBody, err := json.Marshal(midjResponse)
|
||||
if err != nil {
|
||||
@@ -539,30 +545,6 @@ func RelayMidjourneySubmit(c *gin.Context, relayInfo *relaycommon.RelayInfo) *dt
|
||||
}
|
||||
midjResponse := &midjResponseWithStatus.Response
|
||||
|
||||
defer func() {
|
||||
if consumeQuota && midjResponseWithStatus.StatusCode == 200 {
|
||||
err := service.PostConsumeQuota(relayInfo, priceData.Quota, 0, true)
|
||||
if err != nil {
|
||||
common.SysLog("error consuming token remain quota: " + err.Error())
|
||||
}
|
||||
tokenName := c.GetString("token_name")
|
||||
logContent := fmt.Sprintf("模型固定价格 %.2f,分组倍率 %.2f,操作 %s,ID %s", priceData.ModelPrice, priceData.GroupRatioInfo.GroupRatio, midjRequest.Action, midjResponse.Result)
|
||||
other := service.GenerateMjOtherInfo(relayInfo, priceData)
|
||||
model.RecordConsumeLog(c, relayInfo.UserId, model.RecordConsumeLogParams{
|
||||
ChannelId: relayInfo.ChannelId,
|
||||
ModelName: modelName,
|
||||
TokenName: tokenName,
|
||||
Quota: priceData.Quota,
|
||||
Content: logContent,
|
||||
TokenId: relayInfo.TokenId,
|
||||
Group: relayInfo.UsingGroup,
|
||||
Other: other,
|
||||
})
|
||||
model.UpdateUserUsedQuotaAndRequestCount(relayInfo.UserId, priceData.Quota)
|
||||
model.UpdateChannelUsedQuota(relayInfo.ChannelId, priceData.Quota)
|
||||
}
|
||||
}()
|
||||
|
||||
// 文档:https://github.com/novicezk/midjourney-proxy/blob/main/docs/api.md
|
||||
//1-提交成功
|
||||
// 21-任务已存在(处理中或者有结果了) {"code":21,"description":"任务已存在","result":"0741798445574458","properties":{"status":"SUCCESS","imageUrl":"https://xxxx"}}
|
||||
@@ -587,7 +569,6 @@ func RelayMidjourneySubmit(c *gin.Context, relayInfo *relaycommon.RelayInfo) *dt
|
||||
Progress: "0%",
|
||||
FailReason: "",
|
||||
ChannelId: c.GetInt("channel_id"),
|
||||
Quota: priceData.Quota,
|
||||
}
|
||||
if midjResponse.Code == 3 {
|
||||
//无实例账号自动禁用渠道(No available account instance)
|
||||
@@ -632,6 +613,15 @@ func RelayMidjourneySubmit(c *gin.Context, relayInfo *relaycommon.RelayInfo) *dt
|
||||
midjourneyTask.Progress = "100%"
|
||||
midjourneyTask.Status = "SUCCESS"
|
||||
}
|
||||
billingPrepared, billingErr := service.PrepareMidjourneyTaskBilling(
|
||||
relayInfo,
|
||||
midjourneyTask,
|
||||
priceData.Quota,
|
||||
consumeQuota && midjResponseWithStatus.StatusCode == http.StatusOK,
|
||||
)
|
||||
if billingErr != nil {
|
||||
common.SysLog("error consuming Midjourney quota: " + billingErr.Error())
|
||||
}
|
||||
err = midjourneyTask.Insert()
|
||||
if err != nil {
|
||||
return &dto.MidjourneyResponse{
|
||||
@@ -639,6 +629,28 @@ func RelayMidjourneySubmit(c *gin.Context, relayInfo *relaycommon.RelayInfo) *dt
|
||||
Description: "insert_midjourney_task_failed",
|
||||
}
|
||||
}
|
||||
billingApplied, billingErr := service.SettleMidjourneyTaskBilling(relayInfo, midjourneyTask, billingPrepared)
|
||||
if billingErr != nil {
|
||||
common.SysLog("error settling Midjourney quota: " + billingErr.Error())
|
||||
}
|
||||
if billingApplied {
|
||||
billingChannelId := midjourneyTask.GetBillingChannelId()
|
||||
tokenName := c.GetString("token_name")
|
||||
logContent := fmt.Sprintf("模型固定价格 %.2f,分组倍率 %.2f,操作 %s,ID %s", priceData.ModelPrice, priceData.GroupRatioInfo.GroupRatio, midjRequest.Action, midjResponse.Result)
|
||||
other := service.GenerateMjOtherInfo(relayInfo, priceData)
|
||||
model.RecordConsumeLog(c, relayInfo.UserId, model.RecordConsumeLogParams{
|
||||
ChannelId: billingChannelId,
|
||||
ModelName: modelName,
|
||||
TokenName: tokenName,
|
||||
Quota: midjourneyTask.Quota,
|
||||
Content: logContent,
|
||||
TokenId: midjourneyTask.TokenId,
|
||||
Group: relayInfo.UsingGroup,
|
||||
Other: other,
|
||||
})
|
||||
model.UpdateUserUsedQuotaAndRequestCount(relayInfo.UserId, midjourneyTask.Quota)
|
||||
model.UpdateChannelUsedQuota(billingChannelId, midjourneyTask.Quota)
|
||||
}
|
||||
|
||||
if midjResponse.Code == 22 { //22-排队中,说明任务已存在
|
||||
//修改返回值
|
||||
|
||||
Reference in New Issue
Block a user