diff --git a/controller/subscription_payment_creem.go b/controller/subscription_payment_creem.go index a449bc190d4f..0fd838535674 100644 --- a/controller/subscription_payment_creem.go +++ b/controller/subscription_payment_creem.go @@ -8,6 +8,7 @@ import ( "time" "github.com/QuantumNous/new-api/common" + "github.com/QuantumNous/new-api/i18n" "github.com/QuantumNous/new-api/logger" "github.com/QuantumNous/new-api/model" "github.com/QuantumNous/new-api/setting" @@ -31,13 +32,13 @@ func SubscriptionRequestCreemPay(c *gin.Context) { bodyBytes, err := io.ReadAll(c.Request.Body) if err != nil { logger.LogError(c.Request.Context(), fmt.Sprintf("Creem 订阅支付请求读取失败 error=%q", err.Error())) - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "read query error"}) + paymentDataErrorI18n(c, i18n.MsgPaymentRequestReadFailed) return } c.Request.Body = io.NopCloser(bytes.NewReader(bodyBytes)) if err := c.ShouldBindJSON(&req); err != nil || req.PlanId <= 0 { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "参数错误"}) + paymentDataErrorI18n(c, i18n.MsgInvalidParams) return } @@ -47,15 +48,15 @@ func SubscriptionRequestCreemPay(c *gin.Context) { return } if !plan.Enabled { - common.ApiErrorMsg(c, "套餐未启用") + common.ApiErrorI18n(c, i18n.MsgSubscriptionNotEnabled) return } if plan.CreemProductId == "" { - common.ApiErrorMsg(c, "该套餐未配置 CreemProductId") + common.ApiErrorI18n(c, i18n.MsgPaymentCreemNotConfig) return } if setting.CreemWebhookSecret == "" && !setting.CreemTestMode { - common.ApiErrorMsg(c, "Creem Webhook 未配置") + common.ApiErrorI18n(c, i18n.MsgPaymentWebhookNotConfig) return } @@ -66,7 +67,7 @@ func SubscriptionRequestCreemPay(c *gin.Context) { return } if user == nil { - common.ApiErrorMsg(c, "用户不存在") + common.ApiErrorI18n(c, i18n.MsgUserNotExists) return } @@ -77,7 +78,7 @@ func SubscriptionRequestCreemPay(c *gin.Context) { return } if count >= int64(plan.MaxPurchasePerUser) { - common.ApiErrorMsg(c, "已达到该套餐购买上限") + common.ApiErrorI18n(c, i18n.MsgSubscriptionPurchaseMax) return } } @@ -97,7 +98,7 @@ func SubscriptionRequestCreemPay(c *gin.Context) { Status: common.TopUpStatusPending, } if err := order.Insert(); err != nil { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "创建订单失败"}) + paymentDataErrorI18n(c, i18n.MsgPaymentCreateFailed) return } @@ -122,7 +123,7 @@ func SubscriptionRequestCreemPay(c *gin.Context) { checkoutUrl, err := genCreemLink(c.Request.Context(), referenceId, product, user.Email, user.Username) if err != nil { logger.LogError(c.Request.Context(), fmt.Sprintf("Creem 订阅支付链接创建失败 trade_no=%s product_id=%s error=%q", referenceId, product.ProductId, err.Error())) - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "拉起支付失败"}) + paymentDataErrorI18n(c, i18n.MsgPaymentStartFailed) return } diff --git a/controller/subscription_payment_epay.go b/controller/subscription_payment_epay.go index 7dece6badce2..fb7e6e8527f6 100644 --- a/controller/subscription_payment_epay.go +++ b/controller/subscription_payment_epay.go @@ -9,6 +9,7 @@ import ( "github.com/Calcium-Ion/go-epay/epay" "github.com/QuantumNous/new-api/common" + "github.com/QuantumNous/new-api/i18n" "github.com/QuantumNous/new-api/model" "github.com/QuantumNous/new-api/service" "github.com/QuantumNous/new-api/setting/operation_setting" @@ -28,7 +29,7 @@ func SubscriptionRequestEpay(c *gin.Context) { var req SubscriptionEpayPayRequest if err := c.ShouldBindJSON(&req); err != nil || req.PlanId <= 0 { - common.ApiErrorMsg(c, "参数错误") + common.ApiErrorI18n(c, i18n.MsgInvalidParams) return } @@ -38,15 +39,15 @@ func SubscriptionRequestEpay(c *gin.Context) { return } if !plan.Enabled { - common.ApiErrorMsg(c, "套餐未启用") + common.ApiErrorI18n(c, i18n.MsgSubscriptionNotEnabled) return } if plan.PriceAmount < 0.01 { - common.ApiErrorMsg(c, "套餐金额过低") + common.ApiErrorI18n(c, i18n.MsgPaymentAmountTooLow) return } if !operation_setting.ContainsPayMethod(req.PaymentMethod) { - common.ApiErrorMsg(c, "支付方式不存在") + common.ApiErrorI18n(c, i18n.MsgPaymentMethodNotExists) return } @@ -58,7 +59,7 @@ func SubscriptionRequestEpay(c *gin.Context) { return } if count >= int64(plan.MaxPurchasePerUser) { - common.ApiErrorMsg(c, "已达到该套餐购买上限") + common.ApiErrorI18n(c, i18n.MsgSubscriptionPurchaseMax) return } } @@ -66,12 +67,12 @@ func SubscriptionRequestEpay(c *gin.Context) { callBackAddress := service.GetCallbackAddress() returnUrl, err := url.Parse(callBackAddress + "/api/subscription/epay/return") if err != nil { - common.ApiErrorMsg(c, "回调地址配置错误") + common.ApiErrorI18n(c, i18n.MsgPaymentCallbackError) return } notifyUrl, err := url.Parse(callBackAddress + "/api/subscription/epay/notify") if err != nil { - common.ApiErrorMsg(c, "回调地址配置错误") + common.ApiErrorI18n(c, i18n.MsgPaymentCallbackError) return } @@ -80,7 +81,7 @@ func SubscriptionRequestEpay(c *gin.Context) { client := GetEpayClient() if client == nil { - common.ApiErrorMsg(c, "当前管理员未配置支付信息") + common.ApiErrorI18n(c, i18n.MsgPaymentNotConfigured) return } @@ -95,7 +96,7 @@ func SubscriptionRequestEpay(c *gin.Context) { Status: common.TopUpStatusPending, } if err := order.Insert(); err != nil { - common.ApiErrorMsg(c, "创建订单失败") + common.ApiErrorI18n(c, i18n.MsgPaymentCreateFailed) return } uri, params, err := client.Purchase(&epay.PurchaseArgs{ @@ -109,7 +110,7 @@ func SubscriptionRequestEpay(c *gin.Context) { }) if err != nil { _ = model.ExpireSubscriptionOrder(tradeNo, model.PaymentProviderEpay) - common.ApiErrorMsg(c, "拉起支付失败") + common.ApiErrorI18n(c, i18n.MsgPaymentStartFailed) return } c.JSON(http.StatusOK, gin.H{"message": "success", "data": params, "url": uri}) diff --git a/controller/subscription_payment_stripe.go b/controller/subscription_payment_stripe.go index f6e95867ca4f..bf63fef54a48 100644 --- a/controller/subscription_payment_stripe.go +++ b/controller/subscription_payment_stripe.go @@ -7,6 +7,7 @@ import ( "time" "github.com/QuantumNous/new-api/common" + "github.com/QuantumNous/new-api/i18n" "github.com/QuantumNous/new-api/logger" "github.com/QuantumNous/new-api/model" "github.com/QuantumNous/new-api/setting" @@ -27,7 +28,7 @@ func SubscriptionRequestStripePay(c *gin.Context) { var req SubscriptionStripePayRequest if err := c.ShouldBindJSON(&req); err != nil || req.PlanId <= 0 { - common.ApiErrorMsg(c, "参数错误") + common.ApiErrorI18n(c, i18n.MsgInvalidParams) return } @@ -37,19 +38,19 @@ func SubscriptionRequestStripePay(c *gin.Context) { return } if !plan.Enabled { - common.ApiErrorMsg(c, "套餐未启用") + common.ApiErrorI18n(c, i18n.MsgSubscriptionNotEnabled) return } if plan.StripePriceId == "" { - common.ApiErrorMsg(c, "该套餐未配置 StripePriceId") + common.ApiErrorI18n(c, i18n.MsgPaymentPriceIdNotConfig) return } if !strings.HasPrefix(setting.StripeApiSecret, "sk_") && !strings.HasPrefix(setting.StripeApiSecret, "rk_") { - common.ApiErrorMsg(c, "Stripe 未配置或密钥无效") + common.ApiErrorI18n(c, i18n.MsgPaymentStripeNotConfig) return } if setting.StripeWebhookSecret == "" { - common.ApiErrorMsg(c, "Stripe Webhook 未配置") + common.ApiErrorI18n(c, i18n.MsgPaymentWebhookNotConfig) return } @@ -60,7 +61,7 @@ func SubscriptionRequestStripePay(c *gin.Context) { return } if user == nil { - common.ApiErrorMsg(c, "用户不存在") + common.ApiErrorI18n(c, i18n.MsgUserNotExists) return } @@ -71,7 +72,7 @@ func SubscriptionRequestStripePay(c *gin.Context) { return } if count >= int64(plan.MaxPurchasePerUser) { - common.ApiErrorMsg(c, "已达到该套餐购买上限") + common.ApiErrorI18n(c, i18n.MsgSubscriptionPurchaseMax) return } } @@ -82,7 +83,7 @@ func SubscriptionRequestStripePay(c *gin.Context) { payLink, err := genStripeSubscriptionLink(referenceId, user.StripeCustomer, user.Email, plan.StripePriceId) if err != nil { logger.LogError(c.Request.Context(), fmt.Sprintf("Stripe 订阅支付链接创建失败 trade_no=%s plan_id=%d error=%q", referenceId, plan.Id, err.Error())) - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "拉起支付失败"}) + paymentDataErrorI18n(c, i18n.MsgPaymentStartFailed) return } @@ -97,7 +98,7 @@ func SubscriptionRequestStripePay(c *gin.Context) { Status: common.TopUpStatusPending, } if err := order.Insert(); err != nil { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "创建订单失败"}) + paymentDataErrorI18n(c, i18n.MsgPaymentCreateFailed) return } diff --git a/controller/topup.go b/controller/topup.go index 69e1b5e304c4..9d8bafa2cee3 100644 --- a/controller/topup.go +++ b/controller/topup.go @@ -9,6 +9,7 @@ import ( "time" "github.com/QuantumNous/new-api/common" + "github.com/QuantumNous/new-api/i18n" "github.com/QuantumNous/new-api/logger" "github.com/QuantumNous/new-api/model" "github.com/QuantumNous/new-api/service" @@ -132,6 +133,14 @@ type AmountRequest struct { Amount int64 `json:"amount"` } +func paymentDataErrorI18n(c *gin.Context, key string, args ...map[string]any) { + c.JSON(http.StatusOK, gin.H{"message": "error", "data": common.TranslateMessage(c, key, args...)}) +} + +func paymentMessageErrorI18n(c *gin.Context, status int, key string, data any, args ...map[string]any) { + c.JSON(status, gin.H{"message": common.TranslateMessage(c, key, args...), "data": data}) +} + func GetEpayClient() *epay.Client { if operation_setting.PayAddress == "" || operation_setting.EpayId == "" || operation_setting.EpayKey == "" { return nil @@ -190,28 +199,28 @@ func RequestEpay(c *gin.Context) { var req EpayRequest err := c.ShouldBindJSON(&req) if err != nil { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "参数错误"}) + paymentDataErrorI18n(c, i18n.MsgInvalidParams) return } if req.Amount < getMinTopup() { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": fmt.Sprintf("充值数量不能小于 %d", getMinTopup())}) + paymentDataErrorI18n(c, i18n.MsgTopupAmountMin, map[string]any{"Amount": getMinTopup()}) return } id := c.GetInt("id") group, err := model.GetUserGroup(id, true) if err != nil { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "获取用户分组失败"}) + paymentDataErrorI18n(c, i18n.MsgTopupGroupFailed) return } payMoney := getPayMoney(req.Amount, group) if payMoney < 0.01 { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "充值金额过低"}) + paymentDataErrorI18n(c, i18n.MsgPaymentAmountTooLow) return } if !operation_setting.ContainsPayMethod(req.PaymentMethod) { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "支付方式不存在"}) + paymentDataErrorI18n(c, i18n.MsgPaymentMethodNotExists) return } @@ -222,7 +231,7 @@ func RequestEpay(c *gin.Context) { tradeNo = fmt.Sprintf("USR%dNO%s", id, tradeNo) client := GetEpayClient() if client == nil { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "当前管理员未配置支付信息"}) + paymentDataErrorI18n(c, i18n.MsgPaymentNotConfigured) return } uri, params, err := client.Purchase(&epay.PurchaseArgs{ @@ -236,7 +245,7 @@ func RequestEpay(c *gin.Context) { }) if err != nil { logger.LogError(c.Request.Context(), fmt.Sprintf("易支付 拉起支付失败 user_id=%d trade_no=%s payment_method=%s amount=%d error=%q", id, tradeNo, req.PaymentMethod, req.Amount, err.Error())) - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "拉起支付失败"}) + paymentDataErrorI18n(c, i18n.MsgPaymentStartFailed) return } amount := req.Amount @@ -258,7 +267,7 @@ func RequestEpay(c *gin.Context) { err = topUp.Insert() if err != nil { logger.LogError(c.Request.Context(), fmt.Sprintf("易支付 创建充值订单失败 user_id=%d trade_no=%s payment_method=%s amount=%d error=%q", id, tradeNo, req.PaymentMethod, req.Amount, err.Error())) - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "创建订单失败"}) + paymentDataErrorI18n(c, i18n.MsgPaymentCreateFailed) return } logger.LogInfo(c.Request.Context(), fmt.Sprintf("易支付 充值订单创建成功 user_id=%d trade_no=%s payment_method=%s amount=%d money=%.2f uri=%q params=%q", id, tradeNo, req.PaymentMethod, req.Amount, payMoney, uri, common.GetJsonString(params))) @@ -415,23 +424,23 @@ func RequestAmount(c *gin.Context) { var req AmountRequest err := c.ShouldBindJSON(&req) if err != nil { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "参数错误"}) + paymentDataErrorI18n(c, i18n.MsgInvalidParams) return } if req.Amount < getMinTopup() { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": fmt.Sprintf("充值数量不能小于 %d", getMinTopup())}) + paymentDataErrorI18n(c, i18n.MsgTopupAmountMin, map[string]any{"Amount": getMinTopup()}) return } id := c.GetInt("id") group, err := model.GetUserGroup(id, true) if err != nil { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "获取用户分组失败"}) + paymentDataErrorI18n(c, i18n.MsgTopupGroupFailed) return } payMoney := getPayMoney(req.Amount, group) if payMoney <= 0.01 { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "充值金额过低"}) + paymentDataErrorI18n(c, i18n.MsgPaymentAmountTooLow) return } c.JSON(http.StatusOK, gin.H{"message": "success", "data": strconv.FormatFloat(payMoney, 'f', 2, 64)}) @@ -495,7 +504,7 @@ type AdminCompleteTopupRequest struct { func AdminCompleteTopUp(c *gin.Context) { var req AdminCompleteTopupRequest if err := c.ShouldBindJSON(&req); err != nil || req.TradeNo == "" { - common.ApiErrorMsg(c, "参数错误") + common.ApiErrorI18n(c, i18n.MsgInvalidParams) return } diff --git a/controller/topup_creem.go b/controller/topup_creem.go index 7472690e22fb..fde69fc30bdc 100644 --- a/controller/topup_creem.go +++ b/controller/topup_creem.go @@ -6,10 +6,10 @@ import ( "crypto/hmac" "crypto/sha256" "encoding/hex" - "encoding/json" "errors" "fmt" "github.com/QuantumNous/new-api/common" + "github.com/QuantumNous/new-api/i18n" "github.com/QuantumNous/new-api/logger" "github.com/QuantumNous/new-api/model" "github.com/QuantumNous/new-api/setting" @@ -65,21 +65,21 @@ type CreemAdaptor struct { func (*CreemAdaptor) RequestPay(c *gin.Context, req *CreemPayRequest) { if req.PaymentMethod != model.PaymentMethodCreem { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "不支持的支付渠道"}) + paymentDataErrorI18n(c, i18n.MsgPaymentMethodNotExists) return } if req.ProductId == "" { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "请选择产品"}) + paymentDataErrorI18n(c, i18n.MsgPaymentProductRequired) return } // 解析产品列表 var products []CreemProduct - err := json.Unmarshal([]byte(setting.CreemProducts), &products) + err := common.Unmarshal([]byte(setting.CreemProducts), &products) if err != nil { logger.LogError(c.Request.Context(), fmt.Sprintf("Creem 产品配置解析失败 user_id=%d error=%q", c.GetInt("id"), err.Error())) - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "产品配置错误"}) + paymentDataErrorI18n(c, i18n.MsgPaymentProductConfigErr) return } @@ -93,7 +93,7 @@ func (*CreemAdaptor) RequestPay(c *gin.Context, req *CreemPayRequest) { } if selectedProduct == nil { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "产品不存在"}) + paymentDataErrorI18n(c, i18n.MsgPaymentProductNotFound) return } @@ -118,7 +118,7 @@ func (*CreemAdaptor) RequestPay(c *gin.Context, req *CreemPayRequest) { err = topUp.Insert() if err != nil { logger.LogError(c.Request.Context(), fmt.Sprintf("Creem 创建充值订单失败 user_id=%d trade_no=%s product_id=%s error=%q", id, referenceId, selectedProduct.ProductId, err.Error())) - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "创建订单失败"}) + paymentDataErrorI18n(c, i18n.MsgPaymentCreateFailed) return } @@ -126,7 +126,7 @@ func (*CreemAdaptor) RequestPay(c *gin.Context, req *CreemPayRequest) { checkoutUrl, err := genCreemLink(c.Request.Context(), referenceId, selectedProduct, user.Email, user.Username) if err != nil { logger.LogError(c.Request.Context(), fmt.Sprintf("Creem 创建支付链接失败 user_id=%d trade_no=%s product_id=%s error=%q", id, referenceId, selectedProduct.ProductId, err.Error())) - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "拉起支付失败"}) + paymentDataErrorI18n(c, i18n.MsgPaymentStartFailed) return } @@ -148,7 +148,7 @@ func RequestCreemPay(c *gin.Context) { bodyBytes, err := io.ReadAll(c.Request.Body) if err != nil { logger.LogError(c.Request.Context(), fmt.Sprintf("Creem 支付请求读取失败 error=%q", err.Error())) - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "read query error"}) + paymentDataErrorI18n(c, i18n.MsgPaymentRequestReadFailed) return } @@ -159,7 +159,7 @@ func RequestCreemPay(c *gin.Context) { err = c.ShouldBindJSON(&req) if err != nil { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "参数错误"}) + paymentDataErrorI18n(c, i18n.MsgInvalidParams) return } creemAdaptor.RequestPay(c, &req) @@ -402,7 +402,7 @@ func genCreemLink(ctx context.Context, referenceId string, product *CreemProduct } // 序列化请求数据 - jsonData, err := json.Marshal(requestData) + jsonData, err := common.Marshal(requestData) if err != nil { return "", fmt.Errorf("序列化请求数据失败: %v", err) } @@ -443,7 +443,7 @@ func genCreemLink(ctx context.Context, referenceId string, product *CreemProduct } // 解析响应 var checkoutResp CreemCheckoutResponse - err = json.Unmarshal(body, &checkoutResp) + err = common.Unmarshal(body, &checkoutResp) if err != nil { return "", fmt.Errorf("解析响应失败: %v", err) } diff --git a/controller/topup_stripe.go b/controller/topup_stripe.go index bcae201ec4f3..3ef5f725ee74 100644 --- a/controller/topup_stripe.go +++ b/controller/topup_stripe.go @@ -11,6 +11,7 @@ import ( "time" "github.com/QuantumNous/new-api/common" + "github.com/QuantumNous/new-api/i18n" "github.com/QuantumNous/new-api/logger" "github.com/QuantumNous/new-api/model" "github.com/QuantumNous/new-api/setting" @@ -44,18 +45,18 @@ type StripeAdaptor struct { func (*StripeAdaptor) RequestAmount(c *gin.Context, req *StripePayRequest) { if req.Amount < getStripeMinTopup() { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": fmt.Sprintf("充值数量不能小于 %d", getStripeMinTopup())}) + paymentDataErrorI18n(c, i18n.MsgTopupAmountMin, map[string]any{"Amount": getStripeMinTopup()}) return } id := c.GetInt("id") group, err := model.GetUserGroup(id, true) if err != nil { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "获取用户分组失败"}) + paymentDataErrorI18n(c, i18n.MsgTopupGroupFailed) return } payMoney := getStripePayMoney(float64(req.Amount), group) if payMoney <= 0.01 { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "充值金额过低"}) + paymentDataErrorI18n(c, i18n.MsgPaymentAmountTooLow) return } c.JSON(http.StatusOK, gin.H{"message": "success", "data": strconv.FormatFloat(payMoney, 'f', 2, 64)}) @@ -63,25 +64,25 @@ func (*StripeAdaptor) RequestAmount(c *gin.Context, req *StripePayRequest) { func (*StripeAdaptor) RequestPay(c *gin.Context, req *StripePayRequest) { if req.PaymentMethod != model.PaymentMethodStripe { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "不支持的支付渠道"}) + paymentDataErrorI18n(c, i18n.MsgPaymentMethodNotExists) return } if req.Amount < getStripeMinTopup() { - c.JSON(http.StatusOK, gin.H{"message": fmt.Sprintf("充值数量不能小于 %d", getStripeMinTopup()), "data": 10}) + paymentMessageErrorI18n(c, http.StatusOK, i18n.MsgTopupAmountMin, 10, map[string]any{"Amount": getStripeMinTopup()}) return } if req.Amount > 10000 { - c.JSON(http.StatusOK, gin.H{"message": "充值数量不能大于 10000", "data": 10}) + paymentMessageErrorI18n(c, http.StatusOK, i18n.MsgTopupAmountMax, 10, map[string]any{"Amount": 10000}) return } if req.SuccessURL != "" && common.ValidateRedirectURL(req.SuccessURL) != nil { - c.JSON(http.StatusBadRequest, gin.H{"message": "支付成功重定向URL不在可信任域名列表中", "data": ""}) + paymentMessageErrorI18n(c, http.StatusBadRequest, i18n.MsgPaymentRedirectUntrusted, "") return } if req.CancelURL != "" && common.ValidateRedirectURL(req.CancelURL) != nil { - c.JSON(http.StatusBadRequest, gin.H{"message": "支付取消重定向URL不在可信任域名列表中", "data": ""}) + paymentMessageErrorI18n(c, http.StatusBadRequest, i18n.MsgPaymentRedirectUntrusted, "") return } @@ -95,7 +96,7 @@ func (*StripeAdaptor) RequestPay(c *gin.Context, req *StripePayRequest) { payLink, err := genStripeLink(referenceId, user.StripeCustomer, user.Email, req.Amount, req.SuccessURL, req.CancelURL) if err != nil { logger.LogError(c.Request.Context(), fmt.Sprintf("Stripe 创建 Checkout Session 失败 user_id=%d trade_no=%s amount=%d error=%q", id, referenceId, req.Amount, err.Error())) - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "拉起支付失败"}) + paymentDataErrorI18n(c, i18n.MsgPaymentStartFailed) return } @@ -112,7 +113,7 @@ func (*StripeAdaptor) RequestPay(c *gin.Context, req *StripePayRequest) { err = topUp.Insert() if err != nil { logger.LogError(c.Request.Context(), fmt.Sprintf("Stripe 创建充值订单失败 user_id=%d trade_no=%s amount=%d error=%q", id, referenceId, req.Amount, err.Error())) - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "创建订单失败"}) + paymentDataErrorI18n(c, i18n.MsgPaymentCreateFailed) return } logger.LogInfo(c.Request.Context(), fmt.Sprintf("Stripe 充值订单创建成功 user_id=%d trade_no=%s amount=%d money=%.2f", id, referenceId, req.Amount, chargedMoney)) @@ -128,7 +129,7 @@ func RequestStripeAmount(c *gin.Context) { var req StripePayRequest err := c.ShouldBindJSON(&req) if err != nil { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "参数错误"}) + paymentDataErrorI18n(c, i18n.MsgInvalidParams) return } stripeAdaptor.RequestAmount(c, &req) @@ -138,7 +139,7 @@ func RequestStripePay(c *gin.Context) { var req StripePayRequest err := c.ShouldBindJSON(&req) if err != nil { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "参数错误"}) + paymentDataErrorI18n(c, i18n.MsgInvalidParams) return } stripeAdaptor.RequestPay(c, &req) diff --git a/controller/topup_waffo.go b/controller/topup_waffo.go index 344630f7421b..2831a694ad81 100644 --- a/controller/topup_waffo.go +++ b/controller/topup_waffo.go @@ -9,6 +9,7 @@ import ( "time" "github.com/QuantumNous/new-api/common" + "github.com/QuantumNous/new-api/i18n" "github.com/QuantumNous/new-api/logger" "github.com/QuantumNous/new-api/model" "github.com/QuantumNous/new-api/service" @@ -102,26 +103,26 @@ type WaffoPayRequest struct { func RequestWaffoAmount(c *gin.Context) { var req WaffoPayRequest if err := c.ShouldBindJSON(&req); err != nil { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "参数错误"}) + paymentDataErrorI18n(c, i18n.MsgInvalidParams) return } waffoMinTopup := int64(setting.WaffoMinTopUp) if req.Amount < waffoMinTopup { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": fmt.Sprintf("充值数量不能小于 %d", waffoMinTopup)}) + paymentDataErrorI18n(c, i18n.MsgTopupAmountMin, map[string]any{"Amount": waffoMinTopup}) return } id := c.GetInt("id") group, err := model.GetUserGroup(id, true) if err != nil { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "获取用户分组失败"}) + paymentDataErrorI18n(c, i18n.MsgTopupGroupFailed) return } payMoney := getWaffoPayMoney(float64(req.Amount), group) if payMoney <= 0.01 { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "充值金额过低"}) + paymentDataErrorI18n(c, i18n.MsgPaymentAmountTooLow) return } @@ -131,25 +132,25 @@ func RequestWaffoAmount(c *gin.Context) { // RequestWaffoPay 创建 Waffo 支付订单 func RequestWaffoPay(c *gin.Context) { if !setting.WaffoEnabled { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "Waffo 支付未启用"}) + paymentDataErrorI18n(c, i18n.MsgPaymentDisabled) return } var req WaffoPayRequest if err := c.ShouldBindJSON(&req); err != nil { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "参数错误"}) + paymentDataErrorI18n(c, i18n.MsgInvalidParams) return } waffoMinTopup := int64(setting.WaffoMinTopUp) if req.Amount < waffoMinTopup { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": fmt.Sprintf("充值数量不能小于 %d", waffoMinTopup)}) + paymentDataErrorI18n(c, i18n.MsgTopupAmountMin, map[string]any{"Amount": waffoMinTopup}) return } id := c.GetInt("id") user, err := model.GetUserById(id, false) if err != nil || user == nil { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "用户不存在"}) + paymentDataErrorI18n(c, i18n.MsgUserNotExists) return } @@ -161,7 +162,7 @@ func RequestWaffoPay(c *gin.Context) { idx := *req.PayMethodIndex if idx < 0 || idx >= len(methods) { logger.LogWarn(c.Request.Context(), fmt.Sprintf("Waffo 支付方式索引无效 user_id=%d pay_method_index=%d method_count=%d", id, idx, len(methods))) - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "不支持的支付方式"}) + paymentDataErrorI18n(c, i18n.MsgPaymentMethodNotExists) return } resolvedPayMethodType = methods[idx].PayMethodType @@ -179,7 +180,7 @@ func RequestWaffoPay(c *gin.Context) { } if !valid { logger.LogWarn(c.Request.Context(), fmt.Sprintf("Waffo 支付方式无效 user_id=%d pay_method_type=%s pay_method_name=%q", id, req.PayMethodType, req.PayMethodName)) - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "不支持的支付方式"}) + paymentDataErrorI18n(c, i18n.MsgPaymentMethodNotExists) return } } @@ -188,7 +189,7 @@ func RequestWaffoPay(c *gin.Context) { group, _ := model.GetUserGroup(id, true) payMoney := getWaffoPayMoney(float64(req.Amount), group) if payMoney < 0.01 { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "充值金额过低"}) + paymentDataErrorI18n(c, i18n.MsgPaymentAmountTooLow) return } @@ -218,7 +219,7 @@ func RequestWaffoPay(c *gin.Context) { } if err := topUp.Insert(); err != nil { logger.LogError(c.Request.Context(), fmt.Sprintf("Waffo 创建充值订单失败 user_id=%d trade_no=%s amount=%d error=%q", id, merchantOrderId, req.Amount, err.Error())) - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "创建订单失败"}) + paymentDataErrorI18n(c, i18n.MsgPaymentCreateFailed) return } @@ -227,7 +228,7 @@ func RequestWaffoPay(c *gin.Context) { logger.LogError(c.Request.Context(), fmt.Sprintf("Waffo SDK 初始化失败 user_id=%d trade_no=%s error=%q", id, merchantOrderId, err.Error())) topUp.Status = common.TopUpStatusFailed _ = topUp.Update() - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "支付配置错误"}) + paymentDataErrorI18n(c, i18n.MsgPaymentConfigIncomplete) return } @@ -271,14 +272,14 @@ func RequestWaffoPay(c *gin.Context) { logger.LogError(c.Request.Context(), fmt.Sprintf("Waffo 创建订单失败 user_id=%d trade_no=%s error=%q", id, merchantOrderId, err.Error())) topUp.Status = common.TopUpStatusFailed _ = topUp.Update() - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "拉起支付失败"}) + paymentDataErrorI18n(c, i18n.MsgPaymentStartFailed) return } if !resp.IsSuccess() { logger.LogWarn(c.Request.Context(), fmt.Sprintf("Waffo 创建订单业务失败 user_id=%d trade_no=%s code=%s message=%q response=%q", id, merchantOrderId, resp.Code, resp.Message, common.GetJsonString(resp))) topUp.Status = common.TopUpStatusFailed _ = topUp.Update() - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "拉起支付失败"}) + paymentDataErrorI18n(c, i18n.MsgPaymentStartFailed) return } diff --git a/controller/topup_waffo_pancake.go b/controller/topup_waffo_pancake.go index cd8b0d668b2c..3c2fd601b691 100644 --- a/controller/topup_waffo_pancake.go +++ b/controller/topup_waffo_pancake.go @@ -8,6 +8,7 @@ import ( "time" "github.com/QuantumNous/new-api/common" + "github.com/QuantumNous/new-api/i18n" "github.com/QuantumNous/new-api/logger" "github.com/QuantumNous/new-api/model" "github.com/QuantumNous/new-api/service" @@ -25,25 +26,25 @@ type WaffoPancakePayRequest struct { func RequestWaffoPancakeAmount(c *gin.Context) { var req WaffoPancakePayRequest if err := c.ShouldBindJSON(&req); err != nil { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "参数错误"}) + paymentDataErrorI18n(c, i18n.MsgInvalidParams) return } if req.Amount < int64(setting.WaffoPancakeMinTopUp) { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": fmt.Sprintf("充值数量不能小于 %d", setting.WaffoPancakeMinTopUp)}) + paymentDataErrorI18n(c, i18n.MsgTopupAmountMin, map[string]any{"Amount": setting.WaffoPancakeMinTopUp}) return } id := c.GetInt("id") group, err := model.GetUserGroup(id, true) if err != nil { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "获取用户分组失败"}) + paymentDataErrorI18n(c, i18n.MsgTopupGroupFailed) return } payMoney := getWaffoPancakePayMoney(req.Amount, group) if payMoney <= 0.01 { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "充值金额过低"}) + paymentDataErrorI18n(c, i18n.MsgPaymentAmountTooLow) return } @@ -347,36 +348,36 @@ func getWaffoPancakeBuyerIdentity(user *model.User) string { func RequestWaffoPancakePay(c *gin.Context) { if !isWaffoPancakeTopUpEnabled() { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "Waffo Pancake 配置不完整"}) + paymentDataErrorI18n(c, i18n.MsgPaymentConfigIncomplete) return } var req WaffoPancakePayRequest if err := c.ShouldBindJSON(&req); err != nil { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "参数错误"}) + paymentDataErrorI18n(c, i18n.MsgInvalidParams) return } if req.Amount < int64(setting.WaffoPancakeMinTopUp) { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": fmt.Sprintf("充值数量不能小于 %d", setting.WaffoPancakeMinTopUp)}) + paymentDataErrorI18n(c, i18n.MsgTopupAmountMin, map[string]any{"Amount": setting.WaffoPancakeMinTopUp}) return } id := c.GetInt("id") user, err := model.GetUserById(id, false) if err != nil || user == nil { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "用户不存在"}) + paymentDataErrorI18n(c, i18n.MsgUserNotExists) return } group, err := model.GetUserGroup(id, true) if err != nil { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "获取用户分组失败"}) + paymentDataErrorI18n(c, i18n.MsgTopupGroupFailed) return } payMoney := getWaffoPancakePayMoney(req.Amount, group) if payMoney < 0.01 { - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "充值金额过低"}) + paymentDataErrorI18n(c, i18n.MsgPaymentAmountTooLow) return } @@ -393,7 +394,7 @@ func RequestWaffoPancakePay(c *gin.Context) { } if err := topUp.Insert(); err != nil { logger.LogError(c.Request.Context(), fmt.Sprintf("Waffo Pancake 创建充值订单失败 user_id=%d trade_no=%s amount=%d error=%q", id, tradeNo, req.Amount, err.Error())) - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "创建订单失败"}) + paymentDataErrorI18n(c, i18n.MsgPaymentCreateFailed) return } @@ -413,7 +414,7 @@ func RequestWaffoPancakePay(c *gin.Context) { logger.LogError(c.Request.Context(), fmt.Sprintf("Waffo Pancake 创建结账会话失败 user_id=%d trade_no=%s error=%q", id, tradeNo, err.Error())) topUp.Status = common.TopUpStatusFailed _ = topUp.Update() - c.JSON(http.StatusOK, gin.H{"message": "error", "data": "拉起支付失败"}) + paymentDataErrorI18n(c, i18n.MsgPaymentStartFailed) return } logger.LogInfo(c.Request.Context(), fmt.Sprintf("Waffo Pancake 充值订单创建成功 user_id=%d trade_no=%s session_id=%s amount=%d money=%.2f", id, tradeNo, session.SessionID, req.Amount, payMoney)) diff --git a/i18n/keys.go b/i18n/keys.go index 6cf5c1bdc333..2078018a98c4 100644 --- a/i18n/keys.go +++ b/i18n/keys.go @@ -148,6 +148,13 @@ const ( MsgPaymentCreateFailed = "payment.create_failed" MsgPaymentStartFailed = "payment.start_failed" MsgPaymentAmountTooLow = "payment.amount_too_low" + MsgPaymentDisabled = "payment.disabled" + MsgPaymentConfigIncomplete = "payment.config_incomplete" + MsgPaymentRequestReadFailed = "payment.request_read_failed" + MsgPaymentRedirectUntrusted = "payment.redirect_untrusted" + MsgPaymentProductRequired = "payment.product_required" + MsgPaymentProductConfigErr = "payment.product_config_error" + MsgPaymentProductNotFound = "payment.product_not_found" MsgPaymentStripeNotConfig = "payment.stripe_not_configured" MsgPaymentWebhookNotConfig = "payment.webhook_not_configured" MsgPaymentPriceIdNotConfig = "payment.price_id_not_configured" @@ -162,6 +169,9 @@ const ( MsgTopupOrderStatus = "topup.order_status" MsgTopupFailed = "topup.failed" MsgTopupInvalidQuota = "topup.invalid_quota" + MsgTopupAmountMin = "topup.amount_min" + MsgTopupAmountMax = "topup.amount_max" + MsgTopupGroupFailed = "topup.group_failed" ) // Channel related messages diff --git a/i18n/locales/en.yaml b/i18n/locales/en.yaml index 198aa27412b8..c01b9dfd5790 100644 --- a/i18n/locales/en.yaml +++ b/i18n/locales/en.yaml @@ -129,7 +129,14 @@ payment.method_not_exists: "Payment method does not exist" payment.callback_error: "Callback URL configuration error" payment.create_failed: "Failed to create order" payment.start_failed: "Failed to start payment" -payment.amount_too_low: "Plan amount is too low" +payment.amount_too_low: "Payment amount is too low" +payment.disabled: "Payment is not enabled" +payment.config_incomplete: "Payment configuration is incomplete" +payment.request_read_failed: "Failed to read payment request" +payment.redirect_untrusted: "Payment redirect URL is not in the trusted domain list" +payment.product_required: "Please select a product" +payment.product_config_error: "Product configuration error" +payment.product_not_found: "Product does not exist" payment.stripe_not_configured: "Stripe is not configured or key is invalid" payment.webhook_not_configured: "Webhook is not configured" payment.price_id_not_configured: "StripePriceId is not configured for this plan" @@ -142,6 +149,9 @@ topup.order_not_exists: "Top-up order does not exist" topup.order_status: "Top-up order status error" topup.failed: "Top-up failed, please try again later" topup.invalid_quota: "Invalid top-up quota" +topup.amount_min: "Top-up amount cannot be less than {{.Amount}}" +topup.amount_max: "Top-up amount cannot be greater than {{.Amount}}" +topup.group_failed: "Failed to get user group" # Channel messages channel.not_exists: "Channel does not exist" diff --git a/i18n/locales/zh-CN.yaml b/i18n/locales/zh-CN.yaml index 45a10a584e53..02852e2c2df7 100644 --- a/i18n/locales/zh-CN.yaml +++ b/i18n/locales/zh-CN.yaml @@ -130,7 +130,14 @@ payment.method_not_exists: "支付方式不存在" payment.callback_error: "回调地址配置错误" payment.create_failed: "创建订单失败" payment.start_failed: "拉起支付失败" -payment.amount_too_low: "套餐金额过低" +payment.amount_too_low: "支付金额过低" +payment.disabled: "支付未启用" +payment.config_incomplete: "支付配置不完整" +payment.request_read_failed: "读取支付请求失败" +payment.redirect_untrusted: "支付重定向 URL 不在可信任域名列表中" +payment.product_required: "请选择产品" +payment.product_config_error: "产品配置错误" +payment.product_not_found: "产品不存在" payment.stripe_not_configured: "Stripe 未配置或密钥无效" payment.webhook_not_configured: "Webhook 未配置" payment.price_id_not_configured: "该套餐未配置 StripePriceId" @@ -143,6 +150,9 @@ topup.order_not_exists: "充值订单不存在" topup.order_status: "充值订单状态错误" topup.failed: "充值失败,请稍后重试" topup.invalid_quota: "无效的充值额度" +topup.amount_min: "充值数量不能小于 {{.Amount}}" +topup.amount_max: "充值数量不能大于 {{.Amount}}" +topup.group_failed: "获取用户分组失败" # Channel messages channel.not_exists: "渠道不存在" diff --git a/i18n/locales/zh-TW.yaml b/i18n/locales/zh-TW.yaml index ad5a6eae3220..98af4a554472 100644 --- a/i18n/locales/zh-TW.yaml +++ b/i18n/locales/zh-TW.yaml @@ -130,7 +130,14 @@ payment.method_not_exists: "不存在此支付方式" payment.callback_error: "回調位址設定錯誤" payment.create_failed: "建立訂單失敗" payment.start_failed: "啟用支付失敗" -payment.amount_too_low: "訂閱方案金額過低" +payment.amount_too_low: "支付金額過低" +payment.disabled: "支付未啟用" +payment.config_incomplete: "支付設定不完整" +payment.request_read_failed: "讀取支付請求失敗" +payment.redirect_untrusted: "支付重定向 URL 不在可信任網域列表中" +payment.product_required: "請選擇產品" +payment.product_config_error: "產品設定錯誤" +payment.product_not_found: "產品不存在" payment.stripe_not_configured: "Stripe 未設定或密鑰無效" payment.webhook_not_configured: "Webhook 未設定" payment.price_id_not_configured: "該訂閱方案未設定 StripePriceId" @@ -143,6 +150,9 @@ topup.order_not_exists: "充值訂單不存在" topup.order_status: "充值訂單狀態錯誤" topup.failed: "充值失敗,請稍後重試" topup.invalid_quota: "無效的充值額度" +topup.amount_min: "充值數量不能小於 {{.Amount}}" +topup.amount_max: "充值數量不能大於 {{.Amount}}" +topup.group_failed: "獲取使用者分組失敗" # Channel messages channel.not_exists: "管道不存在"