package main import ( "myapp/internal/cards" "myapp/internal/models" "net/http" "strconv" "github.com/go-chi/chi/v5" ) func (app *application) Home(w http.ResponseWriter, r *http.Request) { if err := app.renderTemplate(w, r, "home", &templateData{}); err != nil { app.errorLog.Println(err) } } func (app *application) VirtualTerminal(w http.ResponseWriter, r *http.Request) { if err := app.renderTemplate(w, r, "terminal", &templateData{}); err != nil { app.errorLog.Println(err) } } type TransactionData struct { FirstName string LastName string Email string PaymentIntentID string PaymentMethodID string PaymentAmount int PaymentCurrency string LastFour string ExpiryMonth int ExpiryYear int BankReturnCode string } func (app *application) GetTransactionData(r *http.Request) (TransactionData, error) { var txnData TransactionData err := r.ParseForm() if err != nil { app.errorLog.Println(err) return txnData, err } firstName := r.Form.Get("first_name") lastName := r.Form.Get("last_name") email := r.Form.Get("cardholder_email") paymentIntent := r.Form.Get("payment_intent") paymentMethod := r.Form.Get("payment_method") paymentAmount := r.Form.Get("payment_amount") paymentCurrency := r.Form.Get("payment_currency") amount, _ := strconv.Atoi(paymentAmount) // TODO: validation of the data card := cards.Card{ Secret: app.config.stripe.secret, Key: app.config.stripe.key, } pi, err := card.RetrievePaymentIntent(paymentIntent) if err != nil { app.errorLog.Println(err) return txnData, err } pm, err := card.GetPaymentMethod(paymentMethod) if err != nil { app.errorLog.Println(err) return txnData, err } lastFour := pm.Card.Last4 expiryMonth := pm.Card.ExpMonth expiryYear := pm.Card.ExpYear txnData = TransactionData{ FirstName: firstName, LastName: lastName, Email: email, PaymentIntentID: paymentIntent, PaymentMethodID: paymentMethod, PaymentAmount: amount, PaymentCurrency: paymentCurrency, LastFour: lastFour, ExpiryMonth: int(expiryMonth), ExpiryYear: int(expiryYear), BankReturnCode: pi.LatestCharge.ID, } return txnData, nil } func (app *application) PaymentSucceeded(w http.ResponseWriter, r *http.Request) { // read posted data err := r.ParseForm() if err != nil { app.errorLog.Println(err) return } widgetID, _ := strconv.Atoi(r.Form.Get("product_id")) txnData, err := app.GetTransactionData(r) if err != nil { app.errorLog.Println(err) return } customerID, err := app.SaveCustomer(txnData.FirstName, txnData.LastName, txnData.Email) if err != nil { app.errorLog.Println(err) return } app.infoLog.Printf("custumer id: %d", customerID) transaction := models.Transaction{ Amount: txnData.PaymentAmount, Currency: txnData.PaymentCurrency, LastFour: txnData.LastFour, ExpiryMonth: txnData.ExpiryMonth, ExpiryYear: txnData.ExpiryYear, PaymentIntent: txnData.PaymentIntentID, PaymentMethod: txnData.PaymentMethodID, BankReturnCode: txnData.BankReturnCode, TransactionStatusID: 2, // TODO: use an enum } txnID, err := app.SaveTransaction(transaction) if err != nil { app.errorLog.Println(err) return } app.infoLog.Printf("transaction id: %d", txnID) order := models.Order{ WidgetID: widgetID, TransactionID: txnID, CustomerID: customerID, StatusID: 1, Quantity: 1, Amount: txnData.PaymentAmount, } orderID, err := app.SaveOrder(order) if err != nil { app.errorLog.Println(err) return } app.infoLog.Printf("order id: %d", orderID) app.Session.Put(r.Context(), "txn", txnData) http.Redirect(w, r, "/receipt", http.StatusSeeOther) } func (app *application) Receipt(w http.ResponseWriter, r *http.Request) { txn := app.Session.Pop(r.Context(), "txn").(TransactionData) data := make(map[string]interface{}) data["txn"] = txn if err := app.renderTemplate(w, r, "receipt", &templateData{ Data: data, }); err != nil { app.errorLog.Println(err) } } func (app *application) SaveCustomer(firstName, lastName, email string) (int, error) { customer := models.Customer{ FirstName: firstName, LastName: lastName, Email: email, } id, err := app.DB.InsertCustomer(customer) if err != nil { return 0, err } return id, nil } func (app *application) SaveTransaction(txn models.Transaction) (int, error) { txnID, err := app.DB.InsertTransaction(txn) if err != nil { app.errorLog.Println(err) return 0, err } return txnID, nil } func (app *application) SaveOrder(order models.Order) (int, error) { id, err := app.DB.InsertOrder(order) if err != nil { app.errorLog.Println(err) return 0, err } return id, nil } // ChargeOnce displays the page to buy one widget func (app *application) ChargeOnce(w http.ResponseWriter, r *http.Request) { id := chi.URLParam(r, "id") widgetID, _ := strconv.Atoi(id) widget, err := app.DB.GetWidget(widgetID) if err != nil { app.errorLog.Println(err) } data := make(map[string]interface{}) data["widget"] = widget if err := app.renderTemplate(w, r, "buy-once", &templateData{ Data: data, }); err != nil { app.errorLog.Println(err) } }