| 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 |
| } |
|
|