package controller import ( "fmt" "log" "net/http" "strings" "time" "github.com/QuantumNous/new-api/common" "github.com/QuantumNous/new-api/model" "github.com/QuantumNous/new-api/setting" "github.com/QuantumNous/new-api/setting/system_setting" "github.com/gin-gonic/gin" "github.com/stripe/stripe-go/v81" "github.com/stripe/stripe-go/v81/checkout/session" "github.com/thanhpk/randstr" ) type SubscriptionStripePayRequest struct { PlanId int `json:"plan_id"` } func SubscriptionRequestStripePay(c *gin.Context) { var req SubscriptionStripePayRequest if err := c.ShouldBindJSON(&req); err != nil || req.PlanId <= 0 { common.ApiErrorMsg(c, "参数错误") return } plan, err := model.GetSubscriptionPlanById(req.PlanId) if err != nil { common.ApiError(c, err) return } if !plan.Enabled { common.ApiErrorMsg(c, "套餐未启用") return } if plan.StripePriceId == "" { common.ApiErrorMsg(c, "该套餐未配置 StripePriceId") return } if !strings.HasPrefix(setting.StripeApiSecret, "sk_") && !strings.HasPrefix(setting.StripeApiSecret, "rk_") { common.ApiErrorMsg(c, "Stripe 未配置或密钥无效") return } if setting.StripeWebhookSecret == "" { common.ApiErrorMsg(c, "Stripe Webhook 未配置") return } userId := c.GetInt("id") user, err := model.GetUserById(userId, false) if err != nil { common.ApiError(c, err) return } if user == nil { common.ApiErrorMsg(c, "用户不存在") return } if plan.MaxPurchasePerUser > 0 { count, err := model.CountUserSubscriptionsByPlan(userId, plan.Id) if err != nil { common.ApiError(c, err) return } if count >= int64(plan.MaxPurchasePerUser) { common.ApiErrorMsg(c, "已达到该套餐购买上限") return } } reference := fmt.Sprintf("sub-stripe-ref-%d-%d-%s", user.Id, time.Now().UnixMilli(), randstr.String(4)) referenceId := "sub_ref_" + common.Sha1([]byte(reference)) payLink, err := genStripeSubscriptionLink(referenceId, user.StripeCustomer, user.Email, plan.StripePriceId) if err != nil { log.Println("获取Stripe Checkout支付链接失败", err) c.JSON(http.StatusOK, gin.H{"message": "error", "data": "拉起支付失败"}) return } order := &model.SubscriptionOrder{ UserId: userId, PlanId: plan.Id, Money: plan.PriceAmount, TradeNo: referenceId, PaymentMethod: PaymentMethodStripe, CreateTime: time.Now().Unix(), Status: common.TopUpStatusPending, } if err := order.Insert(); err != nil { c.JSON(http.StatusOK, gin.H{"message": "error", "data": "创建订单失败"}) return } c.JSON(http.StatusOK, gin.H{ "message": "success", "data": gin.H{ "pay_link": payLink, }, }) } func genStripeSubscriptionLink(referenceId string, customerId string, email string, priceId string) (string, error) { stripe.Key = setting.StripeApiSecret params := &stripe.CheckoutSessionParams{ ClientReferenceID: stripe.String(referenceId), SuccessURL: stripe.String(system_setting.ServerAddress + "/console/topup"), CancelURL: stripe.String(system_setting.ServerAddress + "/console/topup"), LineItems: []*stripe.CheckoutSessionLineItemParams{ { Price: stripe.String(priceId), Quantity: stripe.Int64(1), }, }, Mode: stripe.String(string(stripe.CheckoutSessionModeSubscription)), } if "" == customerId { if "" != email { params.CustomerEmail = stripe.String(email) } params.CustomerCreation = stripe.String(string(stripe.CheckoutSessionCustomerCreationAlways)) } else { params.Customer = stripe.String(customerId) } result, err := session.New(params) if err != nil { return "", err } return result.URL, nil }