Code cleanup

This commit is contained in:
Borna Rajković 2023-07-30 12:14:05 +02:00
parent dcc9754d43
commit 1307c7bc6e
18 changed files with 129 additions and 459 deletions

View File

@ -31,7 +31,7 @@ type PaymentEntry struct {
PaymentIntentId *string `db:"payment_intent_id"` PaymentIntentId *string `db:"payment_intent_id"`
// wspay field // wspay field
ShoppingCardID *string `db:"shopping_card_it"` ShoppingCardID *string `db:"shopping_card_id"`
STAN *string `db:"stan"` STAN *string `db:"stan"`
Success *int `db:"success"` Success *int `db:"success"`
ApprovalCode *string `db:"approval_code"` ApprovalCode *string `db:"approval_code"`

View File

@ -16,7 +16,7 @@ func (p *PaymentEntryProvider) CreateEntry(entry PaymentEntry) (PaymentEntry, er
} }
entry.Created = time.Now() entry.Created = time.Now()
_, err := p.DB.Exec(`INSERT INTO "payment_entry" ("id", "created", "gateway", "state", "lang", "error", "amount", "total_amount", "eci", "payment_intent_id", "shopping_card_id", "stan", "success", "approval_code", "order_id", "transaction_id", "event_id")`, _, err := p.DB.Exec(`INSERT INTO "payment_entry" ("id", "created", "gateway", "state", "lang", "error", "amount", "total_amount", "eci", "payment_intent_id", "shopping_card_id", "stan", "success", "approval_code", "order_id", "transaction_id", "event_id") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)`,
&entry.Id, &entry.Created, &entry.Gateway, &entry.State, &entry.Lang, &entry.Error, &entry.Amount, &entry.TotalAmount, &entry.ECI, &entry.PaymentIntentId, &entry.ShoppingCardID, &entry.STAN, &entry.Success, &entry.ApprovalCode, &entry.OrderId, &entry.TransactionId, &entry.EventId, &entry.Id, &entry.Created, &entry.Gateway, &entry.State, &entry.Lang, &entry.Error, &entry.Amount, &entry.TotalAmount, &entry.ECI, &entry.PaymentIntentId, &entry.ShoppingCardID, &entry.STAN, &entry.Success, &entry.ApprovalCode, &entry.OrderId, &entry.TransactionId, &entry.EventId,
) )
if err != nil { if err != nil {

View File

@ -1,65 +1,30 @@
CREATE TABLE IF NOT EXISTS "payment_entry"
CREATE TABLE IF NOT EXISTS "wspay"
( (
"id" uuid NOT NULL, "id" uuid NOT NULL,
"shop_id" varchar(128) NOT NULL, "created" timestamp NOT NULL,
"shopping_card_id" varchar(128) NOT NULL, "modified" timestamp DEFAULT NULL,
"gateway" varchar(255) NOT NULL,
"state" varchar(255) NOT NULL,
"lang" varchar(16) DEFAULT NULL,
"error" varchar(255) DEFAULT NULL,
"amount" int DEFAULT NULL,
"total_amount" int NOT NULL, "total_amount" int NOT NULL,
"lang" varchar(128) DEFAULT '', "eci" varchar(255) DEFAULT NULL,
"customer_first_name" varchar(128) DEFAULT '', "payment_intent_id" varchar(255) DEFAULT NULL,
"customer_last_name" varchar(128) DEFAULT '',
"customer_address" varchar(128) DEFAULT '',
"customer_city" varchar(128) DEFAULT '',
"customer_zip" varchar(128) DEFAULT '',
"customer_country" varchar(128) DEFAULT '',
"customer_phone" varchar(128) DEFAULT '',
"payment_plan" varchar(128) DEFAULT '', "shopping_card_id" varchar(255) DEFAULT NULL,
"credit_card_name" varchar(128) DEFAULT '', "stan" varchar(255) DEFAULT NULL,
"credit_card_number" varchar(128) DEFAULT '', "success" int DEFAULT NULL,
"payment_method" varchar(128) DEFAULT '', "approval_code" varchar(255) DEFAULT NULL,
"currency_code" int DEFAULT 0,
"date_time" timestamp DEFAULT current_timestamp, "order_id" varchar(255) DEFAULT NULL,
"eci" varchar(256) DEFAULT '',
"stan" varchar(256) DEFAULT '',
"success" int DEFAULT 0,
"approval_code" varchar(256) DEFAULT '',
"error_message" varchar(256) DEFAULT '',
"error_codes" varchar(256) DEFAULT '',
"payment_state" varchar(256) DEFAULT '',
PRIMARY KEY (id),
CONSTRAINT unique_id UNIQUE ("shopping_card_id")
);
CREATE TABLE IF NOT EXISTS "stripe"
(
"id" uuid NOT NULL,
"total_amount" int NOT NULL,
"lang" varchar(128) DEFAULT '',
"payment_intent_id" varchar(256) DEFAULT '',
"payment_state" varchar(256) DEFAULT '',
PRIMARY KEY (id)
);
CREATE TABLE IF NOT EXISTS "viva"
(
"id" uuid NOT NULL,
"order_id" varchar(24) DEFAULT '',
"transaction_id" uuid DEFAULT NULL, "transaction_id" uuid DEFAULT NULL,
"total_amount" int NOT NULL, "event_id" varchar(255) DEFAULT NULL,
"event_id" varchar(128) DEFAULT '',
"eci" varchar(128) DEFAULT '',
"payment_state" varchar(256) DEFAULT '',
PRIMARY KEY (id) PRIMARY KEY (id)
); );

View File

@ -1,65 +0,0 @@
CREATE TABLE IF NOT EXISTS "wspay"
(
"id" uuid NOT NULL,
"shop_id" varchar(128) NOT NULL,
"shopping_card_id" varchar(128) NOT NULL,
"total_amount" int NOT NULL,
"lang" varchar(128) DEFAULT '',
"customer_first_name" varchar(128) DEFAULT '',
"customer_last_name" varchar(128) DEFAULT '',
"customer_address" varchar(128) DEFAULT '',
"customer_city" varchar(128) DEFAULT '',
"customer_zip" varchar(128) DEFAULT '',
"customer_country" varchar(128) DEFAULT '',
"customer_phone" varchar(128) DEFAULT '',
"payment_plan" varchar(128) DEFAULT '',
"credit_card_name" varchar(128) DEFAULT '',
"credit_card_number" varchar(128) DEFAULT '',
"payment_method" varchar(128) DEFAULT '',
"currency_code" int DEFAULT 0,
"date_time" timestamp DEFAULT current_timestamp,
"eci" varchar(256) DEFAULT '',
"stan" varchar(256) DEFAULT '',
"success" int DEFAULT 0,
"approval_code" varchar(256) DEFAULT '',
"error_message" varchar(256) DEFAULT '',
"error_codes" varchar(256) DEFAULT '',
"payment_state" varchar(256) DEFAULT '',
PRIMARY KEY (id),
CONSTRAINT unique_id UNIQUE ("shopping_card_id")
);
CREATE TABLE IF NOT EXISTS "stripe"
(
"id" uuid NOT NULL,
"total_amount" int NOT NULL,
"lang" varchar(128) DEFAULT '',
"payment_intent_id" varchar(256) DEFAULT '',
"payment_state" varchar(256) DEFAULT '',
PRIMARY KEY (id)
);
CREATE TABLE IF NOT EXISTS "viva"
(
"id" uuid NOT NULL,
"order_id" varchar(24) DEFAULT '',
"transaction_id" uuid DEFAULT NULL,
"total_amount" int NOT NULL,
"event_id" varchar(128) DEFAULT '',
"eci" varchar(128) DEFAULT '',
"payment_state" varchar(256) DEFAULT '',
PRIMARY KEY (id)
);

39
main.go
View File

@ -18,6 +18,7 @@ import (
stripe2 "payment-poc/stripe" stripe2 "payment-poc/stripe"
"payment-poc/viva" "payment-poc/viva"
"payment-poc/wspay" "payment-poc/wspay"
"sort"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@ -121,6 +122,9 @@ func main() {
for key := range paymentGateways { for key := range paymentGateways {
gateways = append(gateways, key) gateways = append(gateways, key)
} }
sort.Slice(gateways, func(i, j int) bool {
return string(gateways[i]) < string(gateways[j])
})
c.HTML(200, "methods.gohtml", gin.H{"Amount": amount, "Gateways": gateways}) c.HTML(200, "methods.gohtml", gin.H{"Amount": amount, "Gateways": gateways})
}) })
g.GET("/:gateway", func(c *gin.Context) { g.GET("/:gateway", func(c *gin.Context) {
@ -146,6 +150,15 @@ func main() {
return return
} }
}) })
g.GET("/entries/:id", func(c *gin.Context) {
id := uuid.MustParse(c.Param("id"))
entry, err := entryProvider.FetchById(id)
if err != nil {
c.AbortWithError(http.StatusBadRequest, err)
return
}
c.HTML(200, "info.gohtml", gin.H{"Entry": entry})
})
g.POST("/entries/:id/complete", func(c *gin.Context) { g.POST("/entries/:id/complete", func(c *gin.Context) {
id := uuid.MustParse(c.Param("id")) id := uuid.MustParse(c.Param("id"))
entry, err := entryProvider.FetchById(id) entry, err := entryProvider.FetchById(id)
@ -160,7 +173,7 @@ func main() {
return return
} }
entry, err = paymentGateway.CompleteTransaction(entry, amount) entry, err = paymentGateway.CompleteTransaction(entry, amount)
if err != nil { if err == nil {
entryProvider.UpdateEntry(entry) entryProvider.UpdateEntry(entry)
c.Redirect(http.StatusSeeOther, "/entries/"+id.String()) c.Redirect(http.StatusSeeOther, "/entries/"+id.String())
} else { } else {
@ -183,7 +196,7 @@ func main() {
} }
if paymentGateway, ok := paymentGateways[entry.Gateway]; ok { if paymentGateway, ok := paymentGateways[entry.Gateway]; ok {
entry, err = paymentGateway.CancelTransaction(entry) entry, err = paymentGateway.CancelTransaction(entry)
if err != nil { if err == nil {
entryProvider.UpdateEntry(entry) entryProvider.UpdateEntry(entry)
c.Redirect(http.StatusSeeOther, "/entries/"+id.String()) c.Redirect(http.StatusSeeOther, "/entries/"+id.String())
} else { } else {
@ -218,14 +231,6 @@ func getAccounts() gin.Accounts {
return gin.Accounts{auth[0]: auth[1]} return gin.Accounts{auth[0]: auth[1]}
} }
func parseDateTime(dateTime string) time.Time {
t, err := time.Parse("20060102150405", dateTime)
if err != nil {
log.Printf("couldn't parse response time %s: %v", dateTime, err)
}
return t
}
func fetchAmount(amount string) (int64, error) { func fetchAmount(amount string) (int64, error) {
if amount, err := strconv.ParseFloat(amount, 64); err == nil { if amount, err := strconv.ParseFloat(amount, 64); err == nil {
return int64(amount * 100), nil return int64(amount * 100), nil
@ -329,19 +334,21 @@ func hasProfile(profile string) bool {
func formatState(stt state.PaymentState) string { func formatState(stt state.PaymentState) string {
switch stt { switch stt {
case state.StateCanceled: case state.StateCanceled:
return "Otkazano" return "Otkazana"
case state.StateVoided: case state.StateVoided:
return "Otkazano sa strane administratora" return "Otkazana sa strane administratora"
case state.StateAccepted: case state.StateAccepted:
return "Prihvačeno" return "Predautorizirana"
case state.StateError: case state.StateError:
return "Greška" return "Greška"
case state.StatePreinitialized:
return "Predinicijalizirana"
case state.StateInitialized: case state.StateInitialized:
return "Inicijalna izrada" return "Inicijalizirana"
case state.StateCanceledInitialization: case state.StateCanceledInitialization:
return "Otkazano tijekom izrade" return "Otkazana tijekom izrade"
case state.StateCompleted: case state.StateCompleted:
return "Završeno" return "Autorizirana"
} }
return "nepoznato stanje '" + string(stt) + "'" return "nepoznato stanje '" + string(stt) + "'"
} }

View File

@ -3,6 +3,8 @@ package state
type PaymentState string type PaymentState string
const ( const (
// initial state
StatePreinitialized PaymentState = "preinitialized"
// initial state // initial state
StateInitialized PaymentState = "initialized" StateInitialized PaymentState = "initialized"

View File

@ -1,16 +0,0 @@
package stripe
import (
"github.com/google/uuid"
"payment-poc/state"
)
type StripeDb struct {
Id uuid.UUID `db:"id"`
TotalAmount int64 `db:"total_amount"`
Lang string `db:"lang"`
PaymentIntentId string `db:"payment_intent_id"`
State state.PaymentState `db:"payment_state"`
}

View File

@ -19,7 +19,7 @@ type Service struct {
func (s *Service) CreatePaymentUrl(amount int64) (url string, err error) { func (s *Service) CreatePaymentUrl(amount int64) (url string, err error) {
entry, err := s.Provider.CreateEntry(database.PaymentEntry{ entry, err := s.Provider.CreateEntry(database.PaymentEntry{
Gateway: state.GatewayVivaWallet, Gateway: state.GatewayStripe,
State: state.StateInitialized, State: state.StateInitialized,
TotalAmount: amount, TotalAmount: amount,
}) })
@ -83,7 +83,7 @@ func (s *Service) CompleteTransaction(entry database.PaymentEntry, amount int64)
} }
log.Printf("received state on completion: %v", pi.Status) log.Printf("received state on completion: %v", pi.Status)
if pi.Status == stripe.PaymentIntentStatusSucceeded || pi.Status == stripe.PaymentIntentStatusProcessing { if pi.Status == stripe.PaymentIntentStatusSucceeded || pi.Status == stripe.PaymentIntentStatusProcessing {
entry.TotalAmount = pi.Amount entry.Amount = &pi.AmountReceived
entry.State = state.StateCompleted entry.State = state.StateCompleted
} }
return entry, nil return entry, nil

View File

@ -1,35 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Obrada odgovora</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz" crossorigin="anonymous"></script>
<style>
th {text-align: left}
h2 {
margin-top: 16px;
}
</style>
</head>
<body class="container">
<p>Obrada odgovora...</p>
<div id="error"></div>
<script>
window.onload = () => {
setTimeout(() => {
window?.top?.postMessage(JSON.stringify({"success": true}), {targetOrigin: "*"});
if(window?.top) {
document.querySelector("#error").innerHTML = `<p>Izgleda da je došlo do greške, jer stranica nije otvorena u iframe-u</p><a href="/">Stisnite ovdje da se vratite na naslovnicu</a>`;
}
}, 2000);
}
</script>
</body>
</html>

View File

@ -10,10 +10,10 @@
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz" crossorigin="anonymous"></script>
<style> <style>
th {text-align: left} th {text-align: left}
tr > td:nth-child(2) { tr > td:nth-child(3) {
text-align: right; text-align: right;
} }
tr > th:nth-child(2) { tr > th:nth-child(3) {
text-align: right; text-align: right;
} }
td, th { td, th {
@ -25,70 +25,32 @@
</style> </style>
</head> </head>
<body class="container"> <body class="container">
<h2>Novo plačanje</h2> <h2>Novo plaćanje</h2>
<form method="get" action="/methods"> <form method="get" action="/methods">
<div class="mb-3"> <div class="mb-3">
<label class="form-label" for="amount">Vrijednost</label> <label class="form-label" for="amount">Vrijednost</label>
<input class="form-control" id="amount" required name="amount" type="number" step="0.01" min="0"> <input class="form-control" id="amount" required name="amount" type="number" step="0.01" min="0">
</div> </div>
<button class="btn btn-primary" type="submit">Izradi novo plačanje</button> <button class="btn btn-primary" type="submit">Izradi novo plaćanje</button>
</form> </form>
<div> <div>
<h2>WsPay</h2> <h2>Entries</h2>
<table class="table"> <table class="table">
<thead> <thead>
<tr> <tr>
<th>Id</th> <th>Id</th>
<th>Gateway</th>
<th>Vrijednost</th> <th>Vrijednost</th>
<th>Stanje</th> <th>Stanje</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{{range .WsPay}} {{range .Entries}}
<tr> <tr>
<td><a class="link-primary" href="/wspay/info/{{.Id}}">{{.Id}}</a></td> <td><a class="link-primary" href="/entries/{{.Id}}">{{.Id}}</a></td>
<td>{{formatCurrency .TotalAmount}}</td> <td>{{.Gateway}}</td>
<td>{{formatState .State}}</td>
</tr>
{{end}}
</tbody>
</table>
<h2>Stripe</h2>
<table class="table">
<thead>
<tr>
<th>Id</th>
<th>Vrijednost</th>
<th>Stanje</th>
</tr>
</thead>
<tbody>
{{range .Stripe}}
<tr>
<td><a class="link-primary" href="/stripe/info/{{.Id}}">{{.Id}}</a></td>
<td>{{formatCurrency .TotalAmount}}</td>
<td>{{formatState .State}}</td>
</tr>
{{end}}
</tbody>
</table>
<h2>Viva</h2>
<table class="table">
<thead>
<tr>
<th>Id</th>
<th>Vrijednost</th>
<th>Stanje</th>
</tr>
</thead>
<tbody>
{{range .Viva}}
<tr>
<td><a class="link-primary" href="/viva/info/{{.Id}}">{{.Id}}</a></td>
<td>{{formatCurrency .TotalAmount}}</td> <td>{{formatCurrency .TotalAmount}}</td>
<td>{{formatState .State}}</td> <td>{{formatState .State}}</td>
</tr> </tr>

65
templates/info.gohtml Normal file
View File

@ -0,0 +1,65 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Index</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz" crossorigin="anonymous"></script>
<style>
th {text-align: left}
h2 {
margin-top: 16px;
}
</style>
</head>
<body class="container">
<h2>Plaćanje {{.Entry.Id}}</h2>
<table class="table">
<tr><th>Id: </th><td>{{.Entry.Id}}</td></tr>
<tr><th>Datum izrade: </th><td>{{.Entry.Created.Format "Jan 02, 2006 15:04:05 UTC"}}</td></tr>
<tr><th>Zadnja izmjena: </th><td>{{or (.Entry.Modified.Format "Jan 02, 2006 15:04:05 UTC") .Entry.Created.Format "Jan 02, 2006 15:04:05 UTC"}}</td></tr>
<tr><th>Gateway: </th><td>{{.Entry.Gateway}}</td></tr>
<tr><th>Naplaćena vrijednost: </th><td>{{or .Entry.Amount "-"}}</td></tr>
<tr><th>Ukupna vrijednost: </th><td>{{formatCurrency .Entry.TotalAmount}}</td></tr>
<tr><th>Jezik: </th><td>{{or .Entry.Lang "-"}}</td></tr>
<tr><th>Greške: </th><td>{{or .Entry.Error "-"}}</td></tr>
<tr><th>Stanje: </th><td>{{formatState .Entry.State}}</td></tr>
{{if eq .Entry.Gateway "wspay"}}
<tr><th>WsPay</th><td></td></tr>
<tr><th>Shopping cart ID: </th><td>{{or .Entry.ShoppingCartID "-"}}</td></tr>
<tr><th>Success: </th><td>{{or .Entry.Success "-"}}</td></tr>
{{end}}
{{if eq .Entry.Gateway "stripe"}}
<tr><th>Stripe</th><td></td></tr>
<tr><th>Payment intent ID: </th><td>{{or .Entry.PaymentIntentId "-"}}</td></tr>
{{end}}
{{if eq .Entry.Gateway "viva-wallet"}}
<tr><th>Viva wallet</th><td></td></tr>
<tr><th>Order ID: </th><td>{{or .Entry.OrderId "-"}}</td></tr>
<tr><th>Transaction ID: </th><td>{{or .Entry.TransactionId "-"}}</td></tr>
<tr><th>Event ID: </th><td>{{or .Entry.EventId "-"}}</td></tr>
{{end}}
</table>
{{if eq .Entry.State "accepted"}}
<form class="mb-3" method="post" action="/entries/{{.Entry.Id}}/complete">
<div class="mb-3">
<label class="form-label" for="amount">Završi plaćanje</label>
<input class="form-control" id="amount" required name="amount" type="number" value="{{decimalCurrency .Entry.TotalAmount}}" step="0.01" min="0.01" max="{{decimalCurrency .Entry.TotalAmount}}">
</div>
<button class="btn btn-primary" type="submit">Završi plaćanje</button>
</form>
<form method="post" action="/entries/{{.Entry.Id}}/cancel">
<button class="btn btn-primary" type="submit">Otkaži plaćanje</button>
</form>
{{end}}
</body>
</html>

View File

@ -22,9 +22,9 @@
</style> </style>
</head> </head>
<body class="container"> <body class="container">
<h2>Izaberi metodu plačanja</h2> <h2>Izaberi metodu plaćanja</h2>
<a class="btn btn-success" href="/wspay?amount={{.Amount}}">WsPay</a> {{range .Gateways}}
<a class="btn btn-success" href="/stripe?amount={{.Amount}}">Stripe</a> <a class="btn btn-success" href="/{{.}}?amount={{$.Amount}}">{{.}}</a>
<a class="btn btn-success" href="/viva?amount={{.Amount}}">Viva</a> {{end}}
</body> </body>
</html> </html>

View File

@ -1,42 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Info</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz" crossorigin="anonymous"></script>
<style>
th {text-align: left}
h2 {
margin-top: 16px;
}
</style>
</head>
<body class="container">
<h2>Plačanje {{.Entry.Id}}</h2>
<table class="table">
<tr><th>Id: </th><td>{{.Entry.Id}}</td></tr>
<tr><th>Ukupna vrijednost: </th><td>{{formatCurrency .Entry.TotalAmount}}</td></tr>
<tr><th>Jezik: </th><td>{{omitempty .Entry.Lang}}</td></tr>
<tr><th>Stanje: </th><td>{{formatState .Entry.State}}</td></tr>
</table>
{{if eq .Entry.State "accepted"}}
<form class="mb-3" method="post" action="/stripe/complete/{{.Entry.Id}}">
<div class="mb-3">
<label class="form-label" for="amount">Završi transakciju</label>
<input class="form-control" id="amount" required name="amount" type="number" value="{{decimalCurrency .Entry.TotalAmount}}" step="0.01" min="0.01" max="{{decimalCurrency .Entry.TotalAmount}}">
</div>
<button class="btn btn-primary" type="submit">Završi transakciju</button>
</form>
<form method="post" action="/stripe/cancel/{{.Entry.Id}}">
<button class="btn btn-primary" type="submit">Otkaži transakciju</button>
</form>
{{end}}
</body>
</html>

View File

@ -1,44 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Info</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz" crossorigin="anonymous"></script>
<style>
th {text-align: left}
h2 {
margin-top: 16px;
}
</style>
</head>
<body class="container">
<h2>Plačanje {{.Entry.Id}}</h2>
<table class="table">
<tr><th>Id: </th><td>{{.Entry.Id}}</td></tr>
<tr><th>Order id: </th><td>{{.Entry.OrderId}}</td></tr>
<tr><th>Transaction id: </th><td>{{.Entry.TransactionId.String}}</td></tr>
<tr><th>Ukupna vrijednost: </th><td>{{formatCurrency .Entry.TotalAmount}}</td></tr>
<tr><th>Jezik: </th><td>{{omitempty .Entry.Lang}}</td></tr>
<tr><th>Događaj: </th><td>{{.Entry.EventId}}</td></tr>
<tr><th>Stanje: </th><td>{{formatState .Entry.State}}</td></tr>
</table>
{{if eq .Entry.State "accepted"}}
<form class="mb-3" method="post" action="/viva/complete/{{.Entry.Id}}">
<div class="mb-3">
<label class="form-label" for="amount">Završi transakciju</label>
<input class="form-control" id="amount" required name="amount" type="number" value="{{decimalCurrency .Entry.TotalAmount}}" step="0.01" min="0.01" max="{{decimalCurrency .Entry.TotalAmount}}">
</div>
<button class="btn btn-primary" type="submit">Završi transakciju</button>
</form>
<form method="post" action="/viva/cancel/{{.Entry.Id}}">
<button class="btn btn-primary" type="submit">Otkaži transakciju</button>
</form>
{{end}}
</body>
</html>

View File

@ -17,7 +17,7 @@
<body class="container" style="margin-top: 32px"> <body class="container" style="margin-top: 32px">
<h2>Započni proces plačanja</h2> <h2>Započni proces plačanja</h2>
<form action="{{.Action}}" method="POST"> <form id="wspay-form" action="{{.Action}}" method="POST">
<input type="hidden" name="ShopID" value="{{.Form.ShopID}}"> <input type="hidden" name="ShopID" value="{{.Form.ShopID}}">
<input type="hidden" name="ShoppingCartID" value="{{.Form.ShoppingCartID}}"> <input type="hidden" name="ShoppingCartID" value="{{.Form.ShoppingCartID}}">
<input type="hidden" name="Version" value="{{.Form.Version}}"> <input type="hidden" name="Version" value="{{.Form.Version}}">
@ -26,36 +26,10 @@
<input type="hidden" name="ReturnURL" value="{{.Form.ReturnURL}}"> <input type="hidden" name="ReturnURL" value="{{.Form.ReturnURL}}">
<input type="hidden" name="CancelURL" value="{{.Form.CancelURL}}"> <input type="hidden" name="CancelURL" value="{{.Form.CancelURL}}">
<input type="hidden" name="ReturnErrorURL" value="{{.Form.ReturnErrorURL}}"> <input type="hidden" name="ReturnErrorURL" value="{{.Form.ReturnErrorURL}}">
<input type="submit" class="btn btn-primary" value="Koristi normalni redirect">
</form> </form>
<h2>Započni normalni proces u iframe-u</h2>
<form target="payment-frame" name="pay" action="{{.Action}}" method="POST">
<input type="hidden" name="Iframe" value="True">
<input type="hidden" name="IframeResponseTarget" value="SELF">
<input type="hidden" name="ShopID" value="{{.Form.ShopID}}">
<input type="hidden" name="ShoppingCartID" value="{{.Form.ShoppingCartID}}">
<input type="hidden" name="Version" value="{{.Form.Version}}">
<input type="hidden" name="TotalAmount" value="{{formatCurrency .Form.TotalAmount}}">
<input type="hidden" name="Signature" value="{{.Form.Signature}}">
<input type="hidden" name="ReturnURL" value="{{.Form.ReturnURL}}?iframe=true">
<input type="hidden" name="CancelURL" value="{{.Form.CancelURL}}?iframe=true">
<input type="hidden" name="ReturnErrorURL" value="{{.Form.ReturnErrorURL}}?iframe=true">
<input type="submit" class="btn btn-primary" value="Koristi navigaciju u iframe-u">
</form>
<iframe id="payment-frame" name="payment-frame" style="width: 100%; min-height: 600px"></iframe>
<script> <script>
window.addEventListener( document.querySelector("#wspay-form").submit();
"message",
(event) => {
console.log("received response")
window.location.href = "/";
},
false
);
</script> </script>
</body> </body>
</html> </html>

View File

@ -1,62 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Info</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz" crossorigin="anonymous"></script>
<style>
th {text-align: left}
h2 {
margin-top: 16px;
}
</style>
</head>
<body class="container">
<h2>Plačanje {{.Entry.Id}}</h2>
<table class="table">
<tr><th>CartId: </th><td>{{.Entry.ShoppingCartID}}</td></tr>
<tr><th>Ukupna vrijednost: </th><td>{{formatCurrency .Entry.TotalAmount}}</td></tr>
<tr><th>Jezik: </th><td>{{omitempty .Entry.Lang}}</td></tr>
<tr><th>Ime: </th><td>{{omitempty .Entry.CustomerFirstName}}</td></tr>
<tr><th>Prezime: </th><td>{{omitempty .Entry.CustomerLastName}}</td></tr>
<tr><th>Adresa: </th><td>{{omitempty .Entry.CustomerAddress}}</td></tr>
<tr><th>Grad: </th><td>{{omitempty .Entry.CustomerCity}}</td></tr>
<tr><th>ZIP: </th><td>{{omitempty .Entry.CustomerZIP}}</td></tr>
<tr><th>Zemlja: </th><td>{{omitempty .Entry.CustomerCountry}}</td></tr>
<tr><th>Broj telefona: </th><td>{{omitempty .Entry.CustomerPhone}}</td></tr>
<tr><th>Plan plačanja: </th><td>{{omitempty .Entry.PaymentPlan}}</td></tr>
<tr><th>Ime kartice: </th><td>{{omitempty .Entry.CreditCardName}}</td></tr>
<tr><th>Broj kartice: </th><td>{{omitempty .Entry.CreditCardNumber}}</td></tr>
<tr><th>Metoda plačanja: </th><td>{{omitempty .Entry.PaymentMethod}}</td></tr>
<tr><th>Oznaka valute: </th><td>{{.Entry.CurrencyCode}}</td></tr>
<tr><th>Datum i vrijeme: </th><td>{{.Entry.DateTime.Format "Jan 02, 2006 15:04:05 UTC"}}</td></tr>
<tr><th>Uspjeh: </th> <td>{{.Entry.Success}}</td></tr>
<tr><th>Kod: </th> <td>{{omitempty .Entry.ApprovalCode}}</td></tr>
<tr><th>Poruka greške: </th> <td>{{omitempty .Entry.ErrorMessage}}</td></tr>
<tr><th>Kodovi greške: </th> <td>{{omitempty .Entry.ErrorCodes}}</td></tr>
<tr><th>Stanje: </th><td>{{formatState .Entry.State}}</td></tr>
</table>
{{if eq .Entry.State "accepted"}}
<form class="mb-3" method="post" action="/wspay/complete/{{.Entry.Id}}">
<div class="mb-3">
<label class="form-label" for="amount">Završi transakciju</label>
<input class="form-control" id="amount" required name="amount" type="number" value="{{decimalCurrency .Entry.TotalAmount}}" step="0.01" min="0.01" max="{{decimalCurrency .Entry.TotalAmount}}">
</div>
<button class="btn btn-primary" type="submit">Završi transakciju</button>
</form>
<form method="post" action="/wspay/cancel/{{.Entry.Id}}">
<button class="btn btn-primary" type="submit">Otkaži transakciju</button>
</form>
{{end}}
</body>
</html>

View File

@ -1,41 +0,0 @@
package wspay
import (
"github.com/google/uuid"
"payment-poc/state"
"time"
)
type WsPayDb struct {
Id uuid.UUID `db:"id"`
ShopID string `db:"shop_id"`
ShoppingCartID string `db:"shopping_card_id"`
TotalAmount int64 `db:"total_amount"`
Lang string `db:"lang"`
CustomerFirstName string `db:"customer_first_name"`
CustomerLastName string `db:"customer_last_name"`
CustomerAddress string `db:"customer_address"`
CustomerCity string `db:"customer_city"`
CustomerZIP string `db:"customer_zip"`
CustomerCountry string `db:"customer_country"`
CustomerPhone string `db:"customer_phone"`
PaymentPlan string `db:"payment_plan"`
CreditCardName string `db:"credit_card_name"`
CreditCardNumber string `db:"credit_card_number"`
PaymentMethod string `db:"payment_method"`
CurrencyCode int `db:"currency_code"`
DateTime time.Time `db:"date_time"`
ECI string `db:"eci"`
STAN string `db:"stan"`
Success int `db:"success"`
ApprovalCode string `db:"approval_code"`
ErrorMessage string `db:"error_message"`
ErrorCodes string `db:"error_codes"`
State state.PaymentState `db:"payment_state"`
}

View File

@ -24,7 +24,7 @@ type Service struct {
func (s *Service) CreatePaymentUrl(amount int64) (string, error) { func (s *Service) CreatePaymentUrl(amount int64) (string, error) {
entry, err := s.Provider.CreateEntry(database.PaymentEntry{ entry, err := s.Provider.CreateEntry(database.PaymentEntry{
Gateway: state.GatewayVivaWallet, Gateway: state.GatewayWsPay,
State: state.StateInitialized, State: state.StateInitialized,
TotalAmount: amount, TotalAmount: amount,
}) })