11package subscriptions
22
33import (
4+ "errors"
45 "fmt"
56 "time"
67 "website-pb/config"
78
9+ "github.com/pocketbase/dbx"
810 "github.com/pocketbase/pocketbase"
911 "github.com/pocketbase/pocketbase/core"
1012 "github.com/stripe/stripe-go/v84"
1113 "github.com/stripe/stripe-go/v84/checkout/session"
12- "github.com/stripe/stripe-go/v84/subscription"
1314)
1415
1516type SubscriptionService struct {
@@ -21,6 +22,31 @@ func NewService(app *pocketbase.PocketBase, cfg *config.Config) *SubscriptionSer
2122 return & SubscriptionService {app : app , cfg : cfg }
2223}
2324
25+ func (s * SubscriptionService ) CheckValidSubscription (user * core.Record ) (* core.Record , error ) {
26+
27+ now := time .Now ().UTC ().Format ("2006-01-02 15:04:05.000Z" )
28+
29+ record := & core.Record {}
30+
31+ err := s .app .RecordQuery ("subscriptions" ).
32+ // 1. 基础过滤:用户 ID
33+ AndWhere (dbx.HashExp {"user_id" : user .Id }).
34+ // 2. 时间过滤:未过期
35+ AndWhere (dbx .NewExp ("expires_at > {:now}" , dbx.Params {"now" : now })).
36+ // 3. 排序:将到期时间最远的排在最前面
37+ OrderBy ("expires_at DESC" ).
38+ // 4. 只取一条
39+ Limit (1 ).
40+ // 5. 将结果映射到 record 对象
41+ One (record )
42+
43+ if err != nil {
44+ return nil , err // 没找到会返回 sql.ErrNoRows
45+ }
46+
47+ return record , nil
48+ }
49+
2450// CreateCheckoutSession 处理 Stripe 会话创建
2551func (s * SubscriptionService ) CreateCheckoutSession (user * core.Record , plan string , frontendURL string ) (string , error ) {
2652 priceID , exists := s .cfg .PlanToPrice [plan ]
@@ -33,8 +59,11 @@ func (s *SubscriptionService) CreateCheckoutSession(user *core.Record, plan stri
3359 CancelURL : stripe .String (frontendURL ),
3460 Mode : stripe .String (string (stripe .CheckoutSessionModeSubscription )),
3561 ClientReferenceID : stripe .String (user .Id ),
36- Metadata : map [string ]string {"plan" : plan },
37- LineItems : []* stripe.CheckoutSessionLineItemParams {{Price : stripe .String (priceID ), Quantity : stripe .Int64 (1 )}},
62+ SubscriptionData : & stripe.CheckoutSessionSubscriptionDataParams {
63+ Metadata : map [string ]string {"plan" : "pro" }, // 存到订阅对象里
64+ },
65+ Metadata : map [string ]string {"plan" : plan },
66+ LineItems : []* stripe.CheckoutSessionLineItemParams {{Price : stripe .String (priceID ), Quantity : stripe .Int64 (1 )}},
3867 }
3968
4069 // 关联已有 Stripe Customer ID
@@ -48,28 +77,63 @@ func (s *SubscriptionService) CreateCheckoutSession(user *core.Record, plan stri
4877 return sess .URL , err
4978}
5079
51- // HandleCheckoutCompleted 处理支付成功后的数据更新
52- func (s * SubscriptionService ) HandleCheckoutCompleted (sess stripe.CheckoutSession ) error {
53- // 1. 获取用户
54- user , err := s .app .FindRecordById ("users" , sess .ClientReferenceID )
80+ func (s * SubscriptionService ) HandleInvoicePaid (inv stripe.Invoice ) error {
81+
82+ if inv .Customer == nil {
83+ fmt .Println ("invoice customer is nil" )
84+ return errors .New ("invoice customer is nil" )
85+ }
86+
87+ if len (inv .Lines .Data ) == 0 {
88+ fmt .Println ("invoice has no lines" )
89+
90+ return errors .New ("invoice has no lines" )
91+ }
92+
93+ stripeCustomerID := inv .Customer .ID
94+ user , err := s .app .FindFirstRecordByFilter ("users" , "stripe_customer_id = {:id}" , map [string ]any {"id" : stripeCustomerID })
5595 if err != nil {
5696 return err
5797 }
5898
59- // 2. 更新用户信息
60- user .Set ("stripe_customer_id" , sess .Customer .ID )
61- user .Set ("plan" , sess .Metadata ["plan" ])
62- if err := s .app .Save (user ); err != nil {
63- return err
99+ collection , err := s .app .FindCollectionByNameOrId ("subscriptions" )
100+ if err != nil {
101+ return errors .New ("subscriptions collection not found" )
64102 }
65103
66- // 3. 创建订阅记录
67- sub , _ := subscription .Get (sess .Subscription .ID , nil )
68- collection , _ := s .app .FindCollectionByNameOrId ("subscriptions" )
69104 record := core .NewRecord (collection )
105+
106+ fmt .Println (inv .Lines .Data [0 ].Pricing .PriceDetails .Price )
107+
108+ priceID := inv .Lines .Data [0 ].Pricing .PriceDetails .Price
109+
110+ priceIDMap := s .cfg .PriceToPlan [priceID ]
111+ fmt .Println (priceID )
112+
113+ if priceIDMap == "" {
114+ return errors .New ("invalid price" )
115+ }
116+
117+ expiresAt := time .Unix (inv .Lines .Data [0 ].Period .End , 0 ).UTC ()
118+ fmt .Println ("Expires at:" , expiresAt )
119+ fmt .Println (inv .Lines .Data [0 ].Period .End )
120+
70121 record .Set ("user_id" , user .Id )
71- record .Set ("plan" , sess .Metadata ["plan" ])
72- record .Set ("expires_at" , time .Unix (sub .Items .Data [0 ].CurrentPeriodEnd , 0 ).UTC ())
122+ record .Set ("plan" , priceIDMap )
123+ record .Set ("stripe_invoice_id" , inv .ID )
124+ record .Set ("expires_at" , expiresAt )
73125
74126 return s .app .Save (record )
75127}
128+
129+ func (s * SubscriptionService ) HandleCheckoutCompleted (sess stripe.CheckoutSession ) error {
130+ user , err := s .app .FindRecordById ("users" , sess .ClientReferenceID )
131+ if err != nil {
132+ return err
133+ }
134+
135+ // 2. 更新用户信息
136+ user .Set ("stripe_customer_id" , sess .Customer .ID )
137+
138+ return s .app .Save (user )
139+ }
0 commit comments