diff --git a/handlers.go b/handlers.go index 0253af7..51a11e6 100644 --- a/handlers.go +++ b/handlers.go @@ -239,7 +239,7 @@ func register(w http.ResponseWriter, r *http.Request) { } } - err := users.Insert(account.Username, string(account.Password), account.Firstname, account.Lastname, account.Email) + _, err := users.Insert(account.Username, string(account.Password), account.Firstname, account.Lastname, account.Email) if err == ErrDuplicateEmail || err == ErrDuplicateUsername { @@ -395,6 +395,8 @@ func managebilling(w http.ResponseWriter, r *http.Request) { } func webhooks(w http.ResponseWriter, r *http.Request) { + id := authenticated_user(w, r) + const MaxBodyBytes = int64(65536) r.Body = http.MaxBytesReader(w, r.Body, MaxBodyBytes) payload, err := ioutil.ReadAll(r.Body) @@ -433,7 +435,7 @@ func webhooks(w http.ResponseWriter, r *http.Request) { } // Then define and call a func to handle the successful payment intent. // handlePaymentIntentSucceeded(paymentIntent) - handle_checkout_session_completed(checkoutSession) + handle_checkout_session_completed(id, checkoutSession) case "payment_intent.succeeded": var paymentIntent stripe.PaymentIntent @@ -473,7 +475,7 @@ func webhooks(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) } -func handle_checkout_session_completed(checkoutsession stripe.CheckoutSession) error { +func handle_checkout_session_completed(userid int32, checkoutsession stripe.CheckoutSession) error { //toprint, _ := json.MarshalIndent(checkoutSession, "", " ") //fmt.Println(string(toprint)) @@ -483,7 +485,30 @@ func handle_checkout_session_completed(checkoutsession stripe.CheckoutSession) e return err } - fmt.Println(subscription) + fmt.Println(userid) + fmt.Println(subscription.Customer.ID) + + //var status SubscriptionStatus + //switch subscription.Status { + // case "incomplete": + // status = incomplete + // case "incomplete_expired": + // status = incomplete_expired + // case "trialing": + // status = trialing + // case "active": + // status = active + // case "past_due": + // status = past_due + // case "canceled": + // status = canceled + // case "unpaid": + // status = unpaid + // case "paused": + // status = paused + //} + + subscriptions.Insert(userid, subscription.ID, checkoutsession.ID, subscription.Status) return nil } diff --git a/main.go b/main.go index aaff8f0..4329d2a 100644 --- a/main.go +++ b/main.go @@ -18,6 +18,7 @@ import "github.com/stripe/stripe-go/v78" //import "github.com/stripe/stripe-go/v78/customer" var users *Usermodel +var subscriptions *SubscriptionModel var key = []byte("super-secret-key") var store = sessions.NewCookieStore(key) @@ -40,6 +41,7 @@ func main() { defer db.Close() users = &Usermodel{db} + subscriptions = &SubscriptionModel{db} mux := http.NewServeMux() diff --git a/models.go b/models.go index e857de7..68e42ff 100644 --- a/models.go +++ b/models.go @@ -2,144 +2,199 @@ // Created by vfs on 02.05.2024. // -package main; +package main -import "errors"; -import "time"; -import "golang.org/x/crypto/bcrypt"; -import "database/sql"; -import _ "github.com/lib/pq"; -import "fmt"; +import "errors" +import "time" +import "golang.org/x/crypto/bcrypt" +import "database/sql" +import _ "github.com/lib/pq" +import "fmt" -import "github.com/stripe/stripe-go/v78"; -import "github.com/stripe/stripe-go/v78/customer"; +import "github.com/stripe/stripe-go/v78" +import "github.com/stripe/stripe-go/v78/customer" -var ErrRoRecord = errors.New("no matching record found"); -var ErrInvalidCredentials = errors.New("invalid credentials"); -var ErrDuplicateEmail = errors.New("duplicate email"); -var ErrDuplicateUsername = errors.New("duplicate username"); +var ErrRoRecord = errors.New("no matching record found") +var ErrInvalidCredentials = errors.New("invalid credentials") +var ErrDuplicateEmail = errors.New("duplicate email") +var ErrDuplicateUsername = errors.New("duplicate username") type Account struct { - Id int32; - Username string; - Password []byte; - Color int32; - Firstname string; - Lastname string; - Email string; - Created time.Time; - StripeID string; + Id int32 + Username string + Password []byte + Color int32 + Firstname string + Lastname string + Email string + Created time.Time + StripeID string } +type SubscriptionStatus int32 + +const ( + incomplete SubscriptionStatus = iota + incomplete_expired + trialing + active + past_due + canceled + unpaid + paused +) + type Usermodel struct { - DB *sql.DB; + DB *sql.DB } -func (m *Usermodel) Insert(username string, password string, firstname string, lastname string, email string) error { +type SubscriptionModel struct { + DB *sql.DB +} + +func (m *Usermodel) Insert(username string, password string, firstname string, lastname string, email string) (int32, error) { - hashedpassword, err := bcrypt.GenerateFromPassword([]byte(password), 12); - stmt := `INSERT INTO accounts (username, password, firstname, lastname, email, created) VALUES ($1, $2, $3, $4, $5, NOW()) RETURNING id;`; + hashedpassword, err := bcrypt.GenerateFromPassword([]byte(password), 12) + stmt := `INSERT INTO accounts (username, password, firstname, lastname, email, created) VALUES ($1, $2, $3, $4, $5, NOW()) RETURNING id` - var insertid int32; + var insertid int32 - row := m.DB.QueryRow(stmt, username, string(hashedpassword), firstname, lastname, email); + row := m.DB.QueryRow(stmt, username, string(hashedpassword), firstname, lastname, email) if row.Err() != nil { - fmt.Println(row.Err()); - return row.Err(); + fmt.Println(row.Err()) + return 0, row.Err() } - err = row.Scan(&insertid); + err = row.Scan(&insertid) + if err != nil { + fmt.Println(err) + return 0, err + } params := &stripe.CustomerParams{ Name: stripe.String(fmt.Sprintf("%s %s", firstname, lastname)), Email: stripe.String(email), - }; - customer, err := customer.New(params); + } + customer, err := customer.New(params) - stmt = `UPDATE accounts SET stripe_id = $1 WHERE id = $2;`; + stmt = `UPDATE accounts SET stripe_id = $1 WHERE id = $2` - fmt.Println(customer.ID, insertid); + fmt.Println(customer.ID, insertid) - _, err = m.DB.Exec(stmt, customer.ID, insertid); + _, err = m.DB.Exec(stmt, customer.ID, insertid) if err != nil { - fmt.Println(err); - return err; + fmt.Println(err) + return 0, err } - return nil; + return insertid, nil } func (m *Usermodel) Delete(id int32) error { - account, err := users.Get_account(id); + account, err := users.Get_account(id) if account.StripeID != "" { - result, err := customer.Del(account.StripeID, nil); + result, err := customer.Del(account.StripeID, nil) if err != nil { - fmt.Println(err); + fmt.Println(err) } - fmt.Println(result); + fmt.Println(result) } - stmt := `DELETE FROM accounts WHERE id = $1;`; + stmt := `DELETE FROM accounts WHERE id = $1` - _, err = m.DB.Exec(stmt, id); + _, err = m.DB.Exec(stmt, id) if err != nil { - fmt.Println(err); + fmt.Println(err) } - return nil; + return nil } func (m *Usermodel) Get_account(id int32) (Account, error) { if id == 0 { - return Account{}, nil; + return Account{}, nil } - stmt := `SELECT id, username, password, color, firstname, lastname, email, created, stripe_id FROM accounts WHERE id = $1;`; - row := m.DB.QueryRow(stmt, id); + stmt := `SELECT id, username, password, color, firstname, lastname, email, created, stripe_id FROM accounts WHERE id = $1` + row := m.DB.QueryRow(stmt, id) - var account Account; - err := row.Scan(&account.Id, &account.Username, &account.Password, &account.Color, &account.Firstname, &account.Lastname, &account.Email, &account.Created, &account.StripeID); + var account Account + err := row.Scan(&account.Id, &account.Username, &account.Password, &account.Color, &account.Firstname, &account.Lastname, &account.Email, &account.Created, &account.StripeID) if err == sql.ErrNoRows { - return Account{}, sql.ErrNoRows; + return Account{}, sql.ErrNoRows } else if err != nil { - return Account{}, err; + return Account{}, err } - return account, nil; + return account, nil } func (m *Usermodel) Authenticate(username string, password string) (int32, error) { - var id int32; - var hashedpassword []byte; - row := m.DB.QueryRow("SELECT id, password FROM accounts WHERE username = $1", username); - err := row.Scan(&id, &hashedpassword); + var id int32 + var hashedpassword []byte + row := m.DB.QueryRow("SELECT id, password FROM accounts WHERE username = $1", username) + err := row.Scan(&id, &hashedpassword) if err == sql.ErrNoRows { - return 0, ErrInvalidCredentials; + return 0, ErrInvalidCredentials } - err = bcrypt.CompareHashAndPassword(hashedpassword, []byte(password)); + err = bcrypt.CompareHashAndPassword(hashedpassword, []byte(password)) if err == bcrypt.ErrMismatchedHashAndPassword { - return 0, ErrInvalidCredentials; + return 0, ErrInvalidCredentials } else if err != nil { - return 0, err; + return 0, err } - return id, nil; + return id, nil } func (m *Usermodel) Exists_account(id int32) bool { - var exists bool; - stmt := `SELECT EXISTS(SELECT 1 FROM accounts WHERE id = $1);`; - row := m.DB.QueryRow(stmt, id); + var exists bool + stmt := `SELECT EXISTS(SELECT 1 FROM accounts WHERE id = $1)` + row := m.DB.QueryRow(stmt, id) if row.Err() != nil { - fmt.Println(row.Err()); + fmt.Println(row.Err()) } - row.Scan(&exists); + row.Scan(&exists) - fmt.Println(exists); + fmt.Println(exists) - return exists; + return exists +} + +func (m *SubscriptionModel) Insert(accountid int32, stripesubscriptionid string, stripecheckoutid string, status stripe.SubscriptionStatus) (int32, error) { + + + stmt := `INSERT INTO subscriptions (account_id, stripe_subscription_id, stripe_checkout_id, status) VALUES ($1, $2, $3, $4::subscription_status) RETURNING id` + + var insertid int32 + + row := m.DB.QueryRow(stmt, accountid, string(stripesubscriptionid), string(stripecheckoutid), string(status)) + if row.Err() != nil { + fmt.Println(row.Err()) + return 0, row.Err() + } + + err := row.Scan(&insertid) + if err != nil { + fmt.Println(err) + return 0, err + } + + return insertid, nil +} + +func (m *SubscriptionModel) Delete(id int32) error { + stmt := `DELETE FROM accounts WHERE id = $1` + + _, err := m.DB.Exec(stmt, id) + if err != nil { + fmt.Println(err) + return err + } + + return nil }