mirror of
https://github.com/tavo-wasd-gh/conex-builder.git
synced 2025-06-07 12:13:30 -06:00
pretty
This commit is contained in:
parent
7c50792f26
commit
eec6e358db
4 changed files with 151 additions and 116 deletions
6
Makefile
6
Makefile
|
@ -1,6 +1,10 @@
|
||||||
BIN = builder
|
BIN = builder
|
||||||
SRCDIR = server
|
SRCDIR = server
|
||||||
SRC = ${SRCDIR}/main.go
|
SRC = ${SRCDIR}/init.go \
|
||||||
|
${SRCDIR}/main.go \
|
||||||
|
${SRCDIR}/paypal.go \
|
||||||
|
${SRCDIR}/db.go \
|
||||||
|
|
||||||
GOFILES = ${SRCDIR}/go.sum ${SRCDIR}/go.mod
|
GOFILES = ${SRCDIR}/go.sum ${SRCDIR}/go.mod
|
||||||
GOMODS = github.com/joho/godotenv github.com/lib/pq
|
GOMODS = github.com/joho/godotenv github.com/lib/pq
|
||||||
|
|
||||||
|
|
55
server/db.go
55
server/db.go
|
@ -3,13 +3,13 @@ package main
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"log"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
_ "github.com/lib/pq"
|
_ "github.com/lib/pq"
|
||||||
)
|
)
|
||||||
|
|
||||||
func RegisterSite(capture Capture, directory string, editorData json.RawMessage) {
|
func RegisterSitePayment(capture Capture, directory string, editorData json.RawMessage) error {
|
||||||
var (
|
var (
|
||||||
// Payment
|
// Payment
|
||||||
id string
|
id string
|
||||||
|
@ -41,7 +41,6 @@ func RegisterSite(capture Capture, directory string, editorData json.RawMessage)
|
||||||
country = capture.Payer.Address.CountryCode
|
country = capture.Payer.Address.CountryCode
|
||||||
|
|
||||||
var pkey int
|
var pkey int
|
||||||
|
|
||||||
newSite := db.QueryRow(`SELECT id FROM sites WHERE folder = $1`, directory).Scan(&pkey)
|
newSite := db.QueryRow(`SELECT id FROM sites WHERE folder = $1`, directory).Scan(&pkey)
|
||||||
|
|
||||||
if newSite == sql.ErrNoRows {
|
if newSite == sql.ErrNoRows {
|
||||||
|
@ -52,8 +51,7 @@ func RegisterSite(capture Capture, directory string, editorData json.RawMessage)
|
||||||
directory, wstatus, due,
|
directory, wstatus, due,
|
||||||
name, surname, email, phone, country,
|
name, surname, email, phone, country,
|
||||||
editorData).Scan(&pkey); err != nil {
|
editorData).Scan(&pkey); err != nil {
|
||||||
log.Printf("Error: Could not register site to database: %v", err)
|
return fmt.Errorf("Error: Could not register site to database: %v", err)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err := db.QueryRow(
|
if err := db.QueryRow(
|
||||||
|
@ -61,8 +59,7 @@ func RegisterSite(capture Capture, directory string, editorData json.RawMessage)
|
||||||
WHERE id = $1
|
WHERE id = $1
|
||||||
RETURNING id`,
|
RETURNING id`,
|
||||||
pkey).Scan(&pkey); err != nil {
|
pkey).Scan(&pkey); err != nil {
|
||||||
log.Fatalf("Error: Could not update due date: %v", err)
|
return fmt.Errorf("Error: Could not update due date: %v", err)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,9 +67,47 @@ func RegisterSite(capture Capture, directory string, editorData json.RawMessage)
|
||||||
`INSERT INTO payments (capture, site, amount, currency, date, status)
|
`INSERT INTO payments (capture, site, amount, currency, date, status)
|
||||||
VALUES ($1, $2, $3, $4, $5, $6)`,
|
VALUES ($1, $2, $3, $4, $5, $6)`,
|
||||||
id, pkey, amount, currency, date, pstatus); err != nil {
|
id, pkey, amount, currency, date, pstatus); err != nil {
|
||||||
log.Printf("Error: Could not register payment to database: %v", err)
|
return fmt.Errorf("Error: Could not register payment to database: %v", err)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func UpdateSite(by string, pkey int, editorData json.RawMessage) error {
|
||||||
|
tx, err := db.Begin()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error: Could not start transaction: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
var prev json.RawMessage
|
||||||
|
if err := tx.QueryRow(
|
||||||
|
`SELECT raw FROM sites WHERE id = $1`,
|
||||||
|
pkey).Scan(&prev); err != nil {
|
||||||
|
return fmt.Errorf("Error: Could not retrieve old value: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err = tx.Exec(
|
||||||
|
`UPDATE sites SET raw = $1 WHERE id = $2`,
|
||||||
|
editorData, pkey); err != nil {
|
||||||
|
return fmt.Errorf("Error: Could not update raw column: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err = tx.Exec(
|
||||||
|
`INSERT INTO changes (by, site, payment, col, prev, next, date)
|
||||||
|
VALUES ($1, $2, NULL, 'raw', $3, $4, CURRENT_DATE);`,
|
||||||
|
by, pkey, prev, editorData); err != nil {
|
||||||
|
return fmt.Errorf("Error: Could not register change to database: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tx.Commit(); err != nil {
|
||||||
|
return fmt.Errorf("Error: Could not commit transaction: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,21 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
initialize()
|
initialize()
|
||||||
|
|
||||||
http.HandleFunc("/api/orders", CreateOrder)
|
http.HandleFunc("/api/orders", CreateOrderHandler)
|
||||||
http.HandleFunc("/api/orders/", CaptureOrder)
|
http.HandleFunc("/api/orders/", CaptureOrderHandler)
|
||||||
http.Handle("/", http.FileServer(http.Dir("./public")))
|
http.Handle("/", http.FileServer(http.Dir("./public")))
|
||||||
|
|
||||||
stop := make(chan os.Signal, 1)
|
stop := make(chan os.Signal, 1)
|
||||||
|
@ -31,3 +34,71 @@ func main() {
|
||||||
shutdown()
|
shutdown()
|
||||||
log.Println("Server shutdown gracefully.")
|
log.Println("Server shutdown gracefully.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fail(w http.ResponseWriter, err error, notice string) {
|
||||||
|
log.Printf("%s: %v", notice, err)
|
||||||
|
http.Error(w, notice, http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateOrderHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
orderID, err := CreateOrder()
|
||||||
|
if err != nil {
|
||||||
|
fail(w, err, "Failed to obtain orderID")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var response struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
}
|
||||||
|
response.ID = orderID
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
json.NewEncoder(w).Encode(response)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func CaptureOrderHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
info, err := io.ReadAll(r.Body)
|
||||||
|
if err != nil {
|
||||||
|
fail(w, err, "Failed to read request body")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var cart struct {
|
||||||
|
Directory string `json:"directory"`
|
||||||
|
EditorData json.RawMessage `json:"editor_data"`
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(info, &cart)
|
||||||
|
if err != nil {
|
||||||
|
fail(w, err, "Failed to parse request body")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
directory := cart.Directory
|
||||||
|
editorData := cart.EditorData
|
||||||
|
|
||||||
|
path := strings.TrimPrefix(r.URL.Path, "/api/orders/")
|
||||||
|
parts := strings.Split(path, "/")
|
||||||
|
orderID := parts[0]
|
||||||
|
if orderID == "" {
|
||||||
|
fail(w, err, "Failed to get orderID from client URL")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
capture, receipt, err := CaptureOrder(orderID)
|
||||||
|
if err != nil {
|
||||||
|
fail(w, err, "Failed to capture order")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := RegisterSitePayment(capture, directory, editorData); err != nil {
|
||||||
|
fail(w, err, "Failed to register '"+directory+"'in database")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
if err := json.NewEncoder(w).Encode(receipt); err != nil {
|
||||||
|
fail(w, err, "Failed to encode response")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
131
server/paypal.go
131
server/paypal.go
|
@ -45,6 +45,17 @@ type Capture struct {
|
||||||
} `json:"payer"`
|
} `json:"payer"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Receipt struct {
|
||||||
|
PurchaseUnits []struct {
|
||||||
|
Payments struct {
|
||||||
|
Captures []struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
} `json:"captures"`
|
||||||
|
} `json:"payments"`
|
||||||
|
} `json:"purchase_units"`
|
||||||
|
}
|
||||||
|
|
||||||
func Token() (string, error) {
|
func Token() (string, error) {
|
||||||
req, err := http.NewRequest("POST",
|
req, err := http.NewRequest("POST",
|
||||||
os.Getenv("BASE_URL")+"/v1/oauth2/token",
|
os.Getenv("BASE_URL")+"/v1/oauth2/token",
|
||||||
|
@ -69,13 +80,10 @@ func Token() (string, error) {
|
||||||
return response.AccessToken, nil
|
return response.AccessToken, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateOrder(w http.ResponseWriter, r *http.Request) {
|
func CreateOrder() (string, error) {
|
||||||
token, err := Token()
|
token, err := Token()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w,
|
return "", fmt.Errorf("Failed to get acess token: %v", err)
|
||||||
"Failed to get access token",
|
|
||||||
http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Amount struct {
|
type Amount struct {
|
||||||
|
@ -129,10 +137,7 @@ func CreateOrder(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
raw, err := http.DefaultClient.Do(req)
|
raw, err := http.DefaultClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w,
|
return "", fmt.Errorf("Failed to send request: %v", err)
|
||||||
"Failed to send request",
|
|
||||||
http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
defer raw.Body.Close()
|
defer raw.Body.Close()
|
||||||
|
|
||||||
|
@ -141,64 +146,16 @@ func CreateOrder(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := json.NewDecoder(raw.Body).Decode(&response); err != nil {
|
if err := json.NewDecoder(raw.Body).Decode(&response); err != nil {
|
||||||
http.Error(w,
|
return "", fmt.Errorf("Failed to decode response: %v", err)
|
||||||
"Failed to decode response",
|
|
||||||
http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
return response.ID, nil
|
||||||
json.NewEncoder(w).Encode(response)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func CaptureOrder(w http.ResponseWriter, r *http.Request) {
|
func CaptureOrder(orderID string) (Capture, Receipt, error) {
|
||||||
info, err := io.ReadAll(r.Body)
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w,
|
|
||||||
"Failed to read request body",
|
|
||||||
http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var cart struct {
|
|
||||||
Directory string `json:"directory"`
|
|
||||||
EditorData json.RawMessage `json:"editor_data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err = json.Unmarshal(info, &cart)
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w,
|
|
||||||
"Failed to parse request body",
|
|
||||||
http.StatusBadRequest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
directory := cart.Directory
|
|
||||||
editorData := cart.EditorData
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w,
|
|
||||||
"Failed to parse request body",
|
|
||||||
http.StatusBadRequest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
path := strings.TrimPrefix(r.URL.Path, "/api/orders/")
|
|
||||||
parts := strings.Split(path, "/")
|
|
||||||
orderID := parts[0]
|
|
||||||
if orderID == "" {
|
|
||||||
http.Error(w,
|
|
||||||
"Failed to get orderID from client URL",
|
|
||||||
http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
token, err := Token()
|
token, err := Token()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w,
|
return Capture{}, Receipt{}, fmt.Errorf("Failed to get acess token: %v", err)
|
||||||
"Failed to get access token",
|
|
||||||
http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
req, err := http.NewRequest("POST",
|
req, err := http.NewRequest("POST",
|
||||||
|
@ -209,57 +166,25 @@ func CaptureOrder(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
raw, err := http.DefaultClient.Do(req)
|
raw, err := http.DefaultClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w,
|
return Capture{}, Receipt{}, fmt.Errorf("Failed to send request: %v", err)
|
||||||
"Failed to send request",
|
|
||||||
http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
defer raw.Body.Close()
|
defer raw.Body.Close()
|
||||||
|
|
||||||
|
var capture Capture
|
||||||
|
var receipt Receipt
|
||||||
|
|
||||||
body, err := io.ReadAll(raw.Body)
|
body, err := io.ReadAll(raw.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w,
|
return Capture{}, Receipt{}, fmt.Errorf("Failed to read response body: %v", err)
|
||||||
"Failed to read response body",
|
|
||||||
http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var capture Capture
|
if err := json.NewDecoder(bytes.NewReader(body)).Decode(&capture); err != nil {
|
||||||
if err := json.Unmarshal(body, &capture); err != nil {
|
return Capture{}, Receipt{}, fmt.Errorf("Failed to decode into capture: %v", err)
|
||||||
http.Error(w,
|
|
||||||
"Failed to decode response into capture",
|
|
||||||
http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var receipt = struct {
|
if err := json.NewDecoder(bytes.NewReader(body)).Decode(&receipt); err != nil {
|
||||||
PurchaseUnits []struct {
|
return Capture{}, Receipt{}, fmt.Errorf("Failed to decode into capture: %v", err)
|
||||||
Payments struct {
|
|
||||||
Captures []struct {
|
|
||||||
ID string `json:"id"`
|
|
||||||
Status string `json:"status"`
|
|
||||||
} `json:"captures"`
|
|
||||||
} `json:"payments"`
|
|
||||||
} `json:"purchase_units"`
|
|
||||||
}{}
|
|
||||||
|
|
||||||
if err := json.Unmarshal(body, &receipt); err != nil {
|
|
||||||
http.Error(w,
|
|
||||||
"Failed to decode response into receipt",
|
|
||||||
http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RegisterSite(capture, directory, editorData)
|
return capture, receipt, nil
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
if err := json.NewEncoder(w).Encode(receipt); err != nil {
|
|
||||||
http.Error(w,
|
|
||||||
"Failed to encode response",
|
|
||||||
http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue