diff --git a/cmd/api/handlers-api.go b/cmd/api/handlers-api.go
index 80d4e10..d6b75b6 100644
--- a/cmd/api/handlers-api.go
+++ b/cmd/api/handlers-api.go
@@ -9,6 +9,7 @@ import (
"myapp/internal/cards/encryption"
"myapp/internal/models"
"myapp/internal/urlsigner"
+ "myapp/internal/validator"
"net/http"
"strconv"
"strings"
@@ -124,6 +125,14 @@ func (app *application) CreateCustomerAndSubscribeToPlan(w http.ResponseWriter,
return
}
+ // validate data
+ v := validator.New()
+ v.Check(len(data.FirstName) > 1, "first_name", "must be at least 2 characters")
+ if !v.Valid() {
+ app.failedValidation(w, r, v.Errors)
+ return
+ }
+
app.infoLog.Println(data.Email, data.LastFour, data.PaymentMethod, data.Plan)
card := cards.Card{
diff --git a/cmd/api/helpers.go b/cmd/api/helpers.go
index 1a05763..0f74505 100644
--- a/cmd/api/helpers.go
+++ b/cmd/api/helpers.go
@@ -95,3 +95,20 @@ func (app *application) passwordMatches(hash, password string) (bool, error) {
return true, nil
}
+
+func (app *application) failedValidation(
+ w http.ResponseWriter,
+ r *http.Request,
+ errors map[string]string,
+) {
+ var payload struct {
+ OK bool `json:"ok"`
+ Message string `json:"message"`
+ Errors map[string]string `json:"errors"`
+ }
+
+ payload.OK = false
+ payload.Message = "failed validation"
+ payload.Errors = errors
+ app.writeJSON(w, http.StatusUnprocessableEntity, payload)
+}
diff --git a/cmd/web/templates/bronze-plan.page.gohtml b/cmd/web/templates/bronze-plan.page.gohtml
index b27f159..624ae0c 100644
--- a/cmd/web/templates/bronze-plan.page.gohtml
+++ b/cmd/web/templates/bronze-plan.page.gohtml
@@ -14,18 +14,22 @@ Bronze Plan
class="d-blick needs-validation charge-form"
autocomplete="off"
novalidate="">
-
+
{{$widget.Description}}
-
+
+
diff --git a/internal/validator/validator.go b/internal/validator/validator.go
new file mode 100644
index 0000000..68640a7
--- /dev/null
+++ b/internal/validator/validator.go
@@ -0,0 +1,25 @@
+package validator
+
+type Validator struct {
+ Errors map[string]string
+}
+
+func New() *Validator {
+ return &Validator{Errors: make(map[string]string)}
+}
+
+func (v *Validator) Valid() bool {
+ return len(v.Errors) == 0
+}
+
+func (v *Validator) AddError(key, message string) {
+ if _, exists := v.Errors[key]; !exists {
+ v.Errors[key] = message
+ }
+}
+
+func (v *Validator) Check(ok bool, key, message string) {
+ if !ok {
+ v.AddError(key, message)
+ }
+}
diff --git a/static/js/stripe-plan.js b/static/js/stripe-plan.js
index 797e50e..4d70516 100644
--- a/static/js/stripe-plan.js
+++ b/static/js/stripe-plan.js
@@ -47,7 +47,7 @@ function stripePaymentMethodHandler(result, plan_id, api) {
card_brand: result.paymentMethod.card.brand,
expiry_month: result.paymentMethod.card.exp_month,
expiry_year: result.paymentMethod.card.exp_year,
- first_name: document.getElementById("first-name").value,
+ first_name: document.getElementById("first_name").value,
last_name: document.getElementById("last-name").value,
amount: document.getElementById("amount").value,
};
@@ -65,9 +65,22 @@ function stripePaymentMethodHandler(result, plan_id, api) {
.then(response => response.json())
.then(function (data) {
console.log(data);
+ if (data.ok === false) {
+ document.getElementById("charge_form").classList.remove("was-validated")
+ Object.entries(data.errors).forEach((i) => {
+ const [key, value] = i
+ document.getElementById(key).classList.add("is-invalid");
+ document.getElementById(key + "-help").classList.remove("valid-feedback");
+ document.getElementById(key + "-help").classList.remove("d-none");
+ document.getElementById(key + "-help").classList.add("invalid-feedback");
+ document.getElementById(key + "-help").innerText = value;
+ });
+ showPayButton();
+ return
+ }
processing.classList.add("d-none");
showSuccess("card-messages", "Transaction successful!");
- sessionStorage.first_name = document.getElementById("first-name").value;
+ sessionStorage.first_name = document.getElementById("first_name").value;
sessionStorage.last_name = document.getElementById("last-name").value;
sessionStorage.amount = document.getElementById("amount").value;
sessionStorage.last_four = result.paymentMethod.card.last4;