save orders
This commit is contained in:
parent
88be25d77f
commit
8e482aa712
@ -2,12 +2,19 @@ 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)
|
||||
@ -22,12 +29,14 @@ func (app *application) PaymentSucceeded(w http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
|
||||
// read posted data
|
||||
cardHolder := r.Form.Get("cardholder_name")
|
||||
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")
|
||||
widgetID, _ := strconv.Atoi(r.Form.Get("product_id"))
|
||||
|
||||
card := cards.Card{
|
||||
Secret: app.config.stripe.secret,
|
||||
@ -50,8 +59,47 @@ func (app *application) PaymentSucceeded(w http.ResponseWriter, r *http.Request)
|
||||
expiryMonth := pm.Card.ExpMonth
|
||||
expiryYear := pm.Card.ExpYear
|
||||
|
||||
customerID, err := app.SaveCustomer(firstName, lastName, email)
|
||||
if err != nil {
|
||||
app.errorLog.Println(err)
|
||||
return
|
||||
}
|
||||
app.infoLog.Printf("custumer id: %d", customerID)
|
||||
|
||||
amount, _ := strconv.Atoi(paymentAmount)
|
||||
transaction := models.Transaction{
|
||||
Amount: amount,
|
||||
Currency: paymentCurrency,
|
||||
LastFour: lastFour,
|
||||
ExpiryMonth: int(expiryMonth),
|
||||
ExpiryYear: int(expiryYear),
|
||||
BankReturnCode: pi.LatestCharge.ID,
|
||||
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: amount,
|
||||
}
|
||||
orderID, err := app.SaveOrder(order)
|
||||
if err != nil {
|
||||
app.errorLog.Println(err)
|
||||
return
|
||||
}
|
||||
app.infoLog.Printf("order id: %d", orderID)
|
||||
|
||||
data := make(map[string]interface{})
|
||||
data["cardholder"] = cardHolder
|
||||
data["email"] = email
|
||||
data["pi"] = paymentIntent
|
||||
data["pm"] = paymentMethod
|
||||
@ -61,6 +109,10 @@ func (app *application) PaymentSucceeded(w http.ResponseWriter, r *http.Request)
|
||||
data["expiry_month"] = expiryMonth
|
||||
data["expiry_year"] = expiryYear
|
||||
data["bank_return_code"] = pi.LatestCharge.ID
|
||||
data["first_name"] = firstName
|
||||
data["last_name"] = lastName
|
||||
|
||||
// should write this data to session, and then redirect user to the new page
|
||||
|
||||
if err := app.renderTemplate(w, r, "succeeded", &templateData{
|
||||
Data: data,
|
||||
@ -69,6 +121,41 @@ func (app *application) PaymentSucceeded(w http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
}
|
||||
|
||||
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")
|
||||
|
@ -10,6 +10,8 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/alexedwards/scs/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -17,6 +19,8 @@ const (
|
||||
cssVersion = "1"
|
||||
)
|
||||
|
||||
var session *scs.SessionManager
|
||||
|
||||
type config struct {
|
||||
port int
|
||||
env string
|
||||
@ -37,6 +41,7 @@ type application struct {
|
||||
templateCache map[string]*template.Template
|
||||
version string
|
||||
DB models.DBModel
|
||||
Session *scs.SessionManager
|
||||
}
|
||||
|
||||
func (app *application) serve() error {
|
||||
@ -83,6 +88,10 @@ func main() {
|
||||
infoLog := log.New(os.Stdout, "INFO\t", log.Ldate|log.Ltime)
|
||||
errorLog := log.New(os.Stdout, "ERROR\t", log.Ldate|log.Ltime|log.Lshortfile)
|
||||
|
||||
// set up session
|
||||
session = scs.New()
|
||||
session.Lifetime = 24 * time.Hour
|
||||
|
||||
conn, err := driver.OpenDB(cfg.db.dsn)
|
||||
if err != nil {
|
||||
errorLog.Fatal(err)
|
||||
@ -98,6 +107,7 @@ func main() {
|
||||
templateCache: tc,
|
||||
version: version,
|
||||
DB: models.DBModel{DB: conn},
|
||||
Session: session,
|
||||
}
|
||||
|
||||
app.infoLog.Println("Connected to MariaDB")
|
||||
|
@ -8,7 +8,9 @@ import (
|
||||
|
||||
func (app *application) routes() http.Handler {
|
||||
mux := chi.NewRouter()
|
||||
mux.Use(SessionLoad)
|
||||
|
||||
mux.Get("/", app.Home)
|
||||
mux.Get("/virtual-terminal", app.VirtualTerminal)
|
||||
mux.Post("/payment-succeeded", app.PaymentSucceeded)
|
||||
mux.Get("/widget/{id}", app.ChargeOnce)
|
||||
|
@ -23,7 +23,33 @@ Buy one widget
|
||||
<p class="mt-2 mb-3 text-center">{{$widget.Description}}</p>
|
||||
<hr>
|
||||
<div class="mb-3">
|
||||
<label for="cardholder-name" class="form-label">Cardholder Name</label>
|
||||
<label for="first-name" class="form-label">First Name</label>
|
||||
<input type="text"
|
||||
id="first-name"
|
||||
name="first_name"
|
||||
autocomplete="first-name-new"
|
||||
required=""
|
||||
class="form-control">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="last-name" class="form-label">Last Name</label>
|
||||
<input type="text"
|
||||
id="last-name"
|
||||
name="last_name"
|
||||
autocomplete="last-name-new"
|
||||
required=""
|
||||
class="form-control">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="cardholder-email" class="form-label">Email</label>
|
||||
<input type="text"
|
||||
id="cardholder-email"
|
||||
name="cardholder_email"
|
||||
autocomplete="cardholder-email-new"
|
||||
required=""
|
||||
class="form-control">
|
||||
<div class="mb-3">
|
||||
<label for="cardholder-name" class="form-label">Name on card</label>
|
||||
<input type="text"
|
||||
id="cardholder-name"
|
||||
name="cardholder_name"
|
||||
@ -31,14 +57,6 @@ Buy one widget
|
||||
required=""
|
||||
class="form-control">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="cardholder-email" class="form-label">Cardholder Email</label>
|
||||
<input type="text"
|
||||
id="cardholder-email"
|
||||
name="cardholder_email"
|
||||
autocomplete="cardholder-email-new"
|
||||
required=""
|
||||
class="form-control">
|
||||
</div>
|
||||
<!-- card number will be built by stripe -->
|
||||
<div class="mb-3">
|
||||
|
@ -6,7 +6,7 @@ Payment Succedded!
|
||||
<h2 class="mt-5">Payment Succeeded</h2>
|
||||
<hr>
|
||||
<p>Payment Intent: {{ index .Data "pi" }}</p>
|
||||
<p>Cardholder: {{ index .Data "cardholder" }}</p>
|
||||
<p>Customer Name: {{ index .Data "first_name" }} {{ index .Data "last_name" }}</p>
|
||||
<p>Email: {{ index .Data "email" }}</p>
|
||||
<p>Payment Method: {{ index .Data "pm" }}</p>
|
||||
<p>Payment Amount: {{ index .Data "pa" }}</p>
|
||||
|
5
go.mod
5
go.mod
@ -9,4 +9,7 @@ require (
|
||||
github.com/stripe/stripe-go/v79 v79.6.0
|
||||
)
|
||||
|
||||
require filippo.io/edwards25519 v1.1.0 // indirect
|
||||
require (
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/alexedwards/scs/v2 v2.8.0 // indirect
|
||||
)
|
||||
|
2
go.sum
2
go.sum
@ -1,5 +1,7 @@
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
github.com/alexedwards/scs/v2 v2.8.0 h1:h31yUYoycPuL0zt14c0gd+oqxfRwIj6SOjHdKRZxhEw=
|
||||
github.com/alexedwards/scs/v2 v2.8.0/go.mod h1:ToaROZxyKukJKT/xLcVQAChi5k6+Pn1Gvmdl7h3RRj8=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw=
|
||||
|
@ -70,6 +70,8 @@ type Transaction struct {
|
||||
Amount int `json:"amount"`
|
||||
Currency string `json:"currency"`
|
||||
LastFour string `json:"last_four"`
|
||||
ExpiryMonth int `json:"expiry_month"`
|
||||
ExpiryYear int `json:"expiry_year"`
|
||||
BankReturnCode string `json:"bank_return_code"`
|
||||
TransactionStatusID int `json:"transaction_status_id"`
|
||||
CreatedAt time.Time `json:"-"`
|
||||
@ -131,14 +133,17 @@ func (m *DBModel) InsertTransaction(txn Transaction) (int, error) {
|
||||
defer cancel()
|
||||
|
||||
stmt := `INSERT INTO transactions
|
||||
(amount, currency, last_four, bank_return_code,
|
||||
(amount, currency, last_four, expiry_month, expiry_year,
|
||||
bank_return_code,
|
||||
transaction_status_id, created_at, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)`
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
||||
|
||||
result, err := m.DB.ExecContext(ctx, stmt,
|
||||
txn.Amount,
|
||||
txn.Currency,
|
||||
txn.LastFour,
|
||||
txn.ExpiryMonth,
|
||||
txn.ExpiryYear,
|
||||
txn.BankReturnCode,
|
||||
txn.TransactionStatusID,
|
||||
time.Now(),
|
||||
@ -160,17 +165,45 @@ func (m *DBModel) InsertOrder(order Order) (int, error) {
|
||||
defer cancel()
|
||||
|
||||
stmt := `INSERT INTO orders
|
||||
(widget_id, transaction_id, status_id, quantity,
|
||||
(widget_id, transaction_id, customer_id, status_id, quantity,
|
||||
amount, created_at, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)`
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`
|
||||
|
||||
result, err := m.DB.ExecContext(ctx, stmt,
|
||||
order.WidgetID,
|
||||
order.TransactionID,
|
||||
order.CustomerID,
|
||||
order.StatusID,
|
||||
order.Quantity,
|
||||
order.Amount,
|
||||
time.Now(),
|
||||
time.Now(),
|
||||
)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
id, err := result.LastInsertId()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int(id), nil
|
||||
}
|
||||
|
||||
// InsertCustomer inserts a new customer, and returns its id
|
||||
func (m *DBModel) InsertCustomer(customer Customer) (int, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||
defer cancel()
|
||||
|
||||
stmt := `INSERT INTO customers
|
||||
(first_name, last_name, email, created_at, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?)`
|
||||
|
||||
result, err := m.DB.ExecContext(ctx, stmt,
|
||||
customer.FirstName,
|
||||
customer.LastName,
|
||||
customer.Email,
|
||||
time.Now(),
|
||||
time.Now(),
|
||||
)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
|
Loading…
Reference in New Issue
Block a user