From 53ebad02ae5cd1ed4d11be9e0974d630f9931eb8 Mon Sep 17 00:00:00 2001 From: Immanuel Onyeka Date: Sat, 3 Feb 2024 18:54:15 -0500 Subject: [PATCH] Store price ID in subscriptions --- migrations/0_29092022_setup_tables.sql | 2 + skouter.go | 58 +++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/migrations/0_29092022_setup_tables.sql b/migrations/0_29092022_setup_tables.sql index 0bb57b9..1f799ad 100644 --- a/migrations/0_29092022_setup_tables.sql +++ b/migrations/0_29092022_setup_tables.sql @@ -63,6 +63,8 @@ CREATE TABLE subscription ( stripe_id VARCHAR(255) DEFAULT '', user_id INT, customer_id VARCHAR(255) NOT NULL, + price_id VARCHAR(255) NOT NULL, + // Key used by stripejs client_secret VARCHAR(255) NOT NULL, payment_status VARCHAR(50) NOT NULL, current_period_end INT DEFAULT 0, diff --git a/skouter.go b/skouter.go index 24f84d2..f9c3267 100644 --- a/skouter.go +++ b/skouter.go @@ -33,6 +33,7 @@ import ( "github.com/stripe/stripe-go/v76/subscription" "github.com/stripe/stripe-go/v76/invoice" "github.com/stripe/stripe-go/v76/paymentintent" + "github.com/stripe/stripe-go/v76/webhook" "image" _ "image/jpeg" "image/png" @@ -69,6 +70,7 @@ type Subscription struct { UserId int `json:"userId"` StripeId string `json:"stripeId"` CustomerId string `json:"customerId"` + PriceId string `json:"priceId"` Start int `json:"start"` End int `json:"end"` ClientSecret string `json:"clientSecret,omitempty"` @@ -273,6 +275,8 @@ var feeTypes = []string{ "Other", } +var standardPriceId = "price_1OZLK9BPMoXn2pf9kuTAf8rs" + // Used to validate claim in JWT token body. Checks if user id is greater than // zero and time format is valid func (c UserClaims) Valid() error { @@ -1291,6 +1295,7 @@ func (user *User) querySub(db *sql.DB) error { stripe_id, user_id, customer_id, + price_id, current_period_end, current_period_start, client_secret, @@ -1304,6 +1309,7 @@ func (user *User) querySub(db *sql.DB) error { &user.Sub.StripeId, &user.Sub.UserId, &user.Sub.CustomerId, + &user.Sub.PriceId, &user.Sub.End, &user.Sub.Start, &user.Sub.ClientSecret, @@ -1424,12 +1430,13 @@ func (sub *Subscription) insertSub(db *sql.DB) (error) { stripe_id, user_id, customer_id, + price_id, current_period_end, current_period_start, client_secret, payment_status ) - VALUES (?, ?, ?, ?, ?, ?, ?) + VALUES (?, ?, ?, ?, ?, ?, ?, ?) RETURNING id ` @@ -1437,6 +1444,7 @@ func (sub *Subscription) insertSub(db *sql.DB) (error) { sub.StripeId, sub.UserId, sub.CustomerId, + sub.PriceId, sub.End, sub.Start, sub.ClientSecret, @@ -2946,7 +2954,7 @@ func createSubscription(cid string) (*stripe.Subscription, error) { Customer: stripe.String(cid), Items: []*stripe.SubscriptionItemsParams{ { - Price: stripe.String("price_1OZLK9BPMoXn2pf9kuTAf8rs"), + Price: stripe.String(standardPriceId), }, }, PaymentSettings: paymentSettings, @@ -2994,6 +3002,7 @@ func subscribe(w http.ResponseWriter, db *sql.DB, r *http.Request) { user.Sub.UserId = user.Id user.Sub.StripeId = s.ID user.Sub.CustomerId = user.CustomerId + user.Sub.PriceId = standardPriceId user.Sub.End = int(s.CurrentPeriodEnd) user.Sub.Start = int(s.CurrentPeriodStart) user.Sub.ClientSecret = s.LatestInvoice.PaymentIntent.ClientSecret @@ -3019,6 +3028,44 @@ func subscribe(w http.ResponseWriter, db *sql.DB, r *http.Request) { } +func invoicePaid(w http.ResponseWriter, db *sql.DB, r *http.Request) { + b, err := io.ReadAll(r.Body) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + log.Printf("io.ReadAll: %v", err) + return + } + + event, err := webhook.ConstructEvent(b, r.Header.Get("Stripe-Signature"), + os.Getenv("STRIPE_SECRET_KEY")) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + log.Printf("webhook.ConstructEvent: %v", err) + return + } + + log.Println(event.Data) +} + +func invoiceFailed(w http.ResponseWriter, db *sql.DB, r *http.Request) { + b, err := io.ReadAll(r.Body) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + log.Printf("io.ReadAll: %v", err) + return + } + + event, err := webhook.ConstructEvent(b, r.Header.Get("Stripe-Signature"), + os.Getenv("STRIPE_SECRET_KEY")) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + log.Printf("webhook.ConstructEvent: %v", err) + return + } + + log.Println(event.Data) +} + func api(w http.ResponseWriter, r *http.Request) { var args []string @@ -3141,6 +3188,12 @@ func api(w http.ResponseWriter, r *http.Request) { r.Method == http.MethodPost && guard(r, 1): getPdf(w, db, r) + case match(p, "/api/stripe/invoice-paid", &args) && + r.Method == http.MethodPost: + invoicePaid(w, db, r) + case match(p, "/api/stripe/invoice-payment-failed", &args) && + r.Method == http.MethodPost: + invoiceFailed(w, db, r) default: http.Error(w, "Invalid route or token", 404) } @@ -3469,6 +3522,7 @@ func dev(args []string) { os.Setenv("DBUser", "tester") os.Setenv("DBPass", "test123") stripe.Key = os.Getenv("STRIPE_SECRET_KEY") + standardPriceId = "price_1OZLK9BPMoXn2pf9kuTAf8rs" db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(127.0.0.1:3306)/%s?multiStatements=true",