feat: set up project
This commit is contained in:
108
cmd/http/server/main.go
Normal file
108
cmd/http/server/main.go
Normal file
@@ -0,0 +1,108 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/smtp"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"gitea.urkob.com/urko/btc-pay-checker/internal/api"
|
||||
"gitea.urkob.com/urko/btc-pay-checker/internal/platform/mongodb/order"
|
||||
"gitea.urkob.com/urko/btc-pay-checker/internal/services"
|
||||
"gitea.urkob.com/urko/btc-pay-checker/internal/services/btc"
|
||||
"gitea.urkob.com/urko/btc-pay-checker/internal/services/mail"
|
||||
"gitea.urkob.com/urko/btc-pay-checker/internal/services/price"
|
||||
"gitea.urkob.com/urko/btc-pay-checker/kit/cfg"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
func main() {
|
||||
envFile := ""
|
||||
if os.Getenv("PAY_CHECKER_ENV") == "dev" {
|
||||
envFile = ".env"
|
||||
}
|
||||
config := cfg.NewConfig(envFile)
|
||||
log.SetFlags(log.Lmicroseconds)
|
||||
if config.LogFile {
|
||||
logFileName := fmt.Sprintf("%s.txt", time.Now().Format(strings.ReplaceAll(time.RFC1123Z, ":", "_")))
|
||||
f, err := os.OpenFile(logFileName, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0o644)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
log.SetOutput(f)
|
||||
}
|
||||
|
||||
dbOpts := options.Client()
|
||||
dbOpts.ApplyURI(config.DbAddress)
|
||||
|
||||
ctx, cancel := context.WithCancel(signalContext(context.Background()))
|
||||
defer cancel()
|
||||
|
||||
client, err := mongo.Connect(ctx, dbOpts)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("mongo.NewClient: %w", err))
|
||||
}
|
||||
|
||||
log.Println("mongodb client is connected")
|
||||
|
||||
ordersCollection := client.
|
||||
Database(config.DbName).
|
||||
Collection(config.OrdersCollection)
|
||||
orderRepo := order.NewRepo(ordersCollection)
|
||||
orderSrv := services.NewOrder(orderRepo)
|
||||
|
||||
priceSrv := price.NewPriceConversor(config.ConversorApi, config.ConversorApi)
|
||||
btcSrv := btc.NewBitcoinService(config.RpcHost, config.RpcAuth, config.RpcZmq, config.WalletAddress).WithTestnet()
|
||||
mailSrv := mail.NewMailService(
|
||||
mail.MailServiceConfig{
|
||||
Auth: smtp.PlainAuth("", config.MailUser, config.MailPassword, config.MailHost),
|
||||
Host: config.MailHost,
|
||||
Port: config.MailPort,
|
||||
From: config.MailFrom,
|
||||
TemplatesDir: config.MailTemplatesDir,
|
||||
},
|
||||
)
|
||||
|
||||
restServer := api.NewRestServer(config, orderSrv, btcSrv, priceSrv, mailSrv)
|
||||
go func() {
|
||||
if err = restServer.Start(ctx, config.ApiPort, config.Views); err != nil {
|
||||
panic(fmt.Errorf("restServer.Start: %w", err))
|
||||
}
|
||||
}()
|
||||
|
||||
<-ctx.Done()
|
||||
|
||||
log.Println("on shutdown")
|
||||
if restServer != nil {
|
||||
if err := restServer.Shutdown(); err != nil {
|
||||
panic(fmt.Errorf("restServer.Shutdown: %w", err))
|
||||
}
|
||||
}
|
||||
log.Println("gracefully shutdown")
|
||||
}
|
||||
|
||||
func signalContext(ctx context.Context) context.Context {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
|
||||
sigs := make(chan os.Signal, 1)
|
||||
signal.Notify(sigs, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
|
||||
|
||||
go func() {
|
||||
log.Println("listening for shutdown signal")
|
||||
<-sigs
|
||||
log.Println("shutdown signal received")
|
||||
signal.Stop(sigs)
|
||||
close(sigs)
|
||||
cancel()
|
||||
}()
|
||||
|
||||
return ctx
|
||||
}
|
||||
52
cmd/http/views/error.hbs
Normal file
52
cmd/http/views/error.hbs
Normal file
@@ -0,0 +1,52 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 80%;
|
||||
margin: auto;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.alert {
|
||||
padding: 20px;
|
||||
background-color: #f9edbe;
|
||||
color: #856404;
|
||||
border: 1px solid #ffeeba;
|
||||
border-radius: 5px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.details {
|
||||
background-color: #fff;
|
||||
padding: 20px;
|
||||
border-radius: 5px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.details h2 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.details p {
|
||||
margin: 10px 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="alert">
|
||||
<p><strong>Unexpected error: {{message}}</strong></p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
104
cmd/http/views/order.hbs
Normal file
104
cmd/http/views/order.hbs
Normal file
@@ -0,0 +1,104 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 80%;
|
||||
margin: auto;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.alert {
|
||||
padding: 20px;
|
||||
background-color: #f9edbe;
|
||||
color: #856404;
|
||||
border: 1px solid #ffeeba;
|
||||
border-radius: 5px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.details {
|
||||
background-color: #fff;
|
||||
padding: 20px;
|
||||
border-radius: 5px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.details h2 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.details p {
|
||||
margin: 10px 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="alert">
|
||||
<h1>Bitcoin Payment</h1>
|
||||
<p>Please send the exact amount of Bitcoin to the provided wallet address. Your order will be processed once the
|
||||
transaction is confirmed.</p>
|
||||
</div>
|
||||
<p id="countdown"><strong>Time Remaining:</strong></p>
|
||||
<div class="details">
|
||||
<h2>Order Details</h2>
|
||||
<p><strong>Order ID:</strong> {{order_id}}</p>
|
||||
<p><strong>Amount:</strong> {{amount}} BTC</p>
|
||||
<p><strong>Wallet Address:</strong> {{wallet_address}}</p>
|
||||
<p id="dueDate"><strong>Payment Due:</strong></p>
|
||||
<p id="countdown"><strong>Time Remaining:</strong> </p>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
// Get the expires_at time from your server and convert it to a JavaScript Date object
|
||||
const dueDate = new Date("{{expires_at}}");
|
||||
|
||||
// Format the date and time
|
||||
const formattedDate = dueDate.toLocaleDateString() + " " + dueDate.toLocaleTimeString();
|
||||
|
||||
// Display the result in the element with id="dueDate"
|
||||
document.getElementById("dueDate").innerHTML = "<strong>Payment Due:</strong> " + formattedDate;
|
||||
|
||||
// Get the expires_at time from your server and convert it to a JavaScript Date object
|
||||
const countDownDate = new Date("{{expires_at}}").getTime();
|
||||
|
||||
// Update the countdown every 1 second
|
||||
const countdownInterval = setInterval(function () {
|
||||
|
||||
// Get today's date and time
|
||||
const now = new Date().getTime();
|
||||
|
||||
// Find the distance between now and the count down date
|
||||
const distance = countDownDate - now;
|
||||
|
||||
// Time calculations for days, hours, minutes and seconds
|
||||
const days = Math.floor(distance / (1000 * 60 * 60 * 24));
|
||||
const hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
|
||||
const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
|
||||
const seconds = Math.floor((distance % (1000 * 60)) / 1000);
|
||||
|
||||
// Display the result in the element with id="countdown"
|
||||
// document.getElementById("countdown").innerHTML = "<strong>Time Remaining:</strong> " + days + "d " + hours + "h " + minutes + "m " + seconds + "s ";
|
||||
document.getElementById("countdown").innerHTML = "<strong>Time Remaining:</strong> " + minutes + "m " + seconds + "s ";
|
||||
|
||||
// If the countdown is finished, write some text
|
||||
if (distance < 0) {
|
||||
clearInterval(countdownInterval);
|
||||
document.getElementById("countdown").innerHTML = "EXPIRED";
|
||||
}
|
||||
}, 1000);
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user