Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions controller/subscription_payment_creem.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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
}

Expand All @@ -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
}

Expand All @@ -66,7 +67,7 @@ func SubscriptionRequestCreemPay(c *gin.Context) {
return
}
if user == nil {
common.ApiErrorMsg(c, "用户不存在")
common.ApiErrorI18n(c, i18n.MsgUserNotExists)
return
}

Expand All @@ -77,7 +78,7 @@ func SubscriptionRequestCreemPay(c *gin.Context) {
return
}
if count >= int64(plan.MaxPurchasePerUser) {
common.ApiErrorMsg(c, "已达到该套餐购买上限")
common.ApiErrorI18n(c, i18n.MsgSubscriptionPurchaseMax)
return
}
}
Expand All @@ -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
}

Expand All @@ -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
}

Expand Down
21 changes: 11 additions & 10 deletions controller/subscription_payment_epay.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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
}

Expand All @@ -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
}

Expand All @@ -58,20 +59,20 @@ func SubscriptionRequestEpay(c *gin.Context) {
return
}
if count >= int64(plan.MaxPurchasePerUser) {
common.ApiErrorMsg(c, "已达到该套餐购买上限")
common.ApiErrorI18n(c, i18n.MsgSubscriptionPurchaseMax)
return
}
}

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
}

Expand All @@ -80,7 +81,7 @@ func SubscriptionRequestEpay(c *gin.Context) {

client := GetEpayClient()
if client == nil {
common.ApiErrorMsg(c, "当前管理员未配置支付信息")
common.ApiErrorI18n(c, i18n.MsgPaymentNotConfigured)
return
}

Expand All @@ -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{
Expand All @@ -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})
Expand Down
19 changes: 10 additions & 9 deletions controller/subscription_payment_stripe.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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
}

Expand All @@ -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
}

Expand All @@ -60,7 +61,7 @@ func SubscriptionRequestStripePay(c *gin.Context) {
return
}
if user == nil {
common.ApiErrorMsg(c, "用户不存在")
common.ApiErrorI18n(c, i18n.MsgUserNotExists)
return
}

Expand All @@ -71,7 +72,7 @@ func SubscriptionRequestStripePay(c *gin.Context) {
return
}
if count >= int64(plan.MaxPurchasePerUser) {
common.ApiErrorMsg(c, "已达到该套餐购买上限")
common.ApiErrorI18n(c, i18n.MsgSubscriptionPurchaseMax)
return
}
}
Expand All @@ -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
}

Expand All @@ -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
}

Expand Down
35 changes: 22 additions & 13 deletions controller/topup.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
}

Expand All @@ -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{
Expand All @@ -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
Expand All @@ -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)))
Expand Down Expand Up @@ -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)})
Expand Down Expand Up @@ -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
}

Expand Down
Loading