chapa integration 1st phase
This commit is contained in:
parent
252bf04b1e
commit
66a7affeba
17
cmd/main.go
17
cmd/main.go
|
|
@ -7,12 +7,15 @@ import (
|
|||
"os"
|
||||
|
||||
"github.com/go-playground/validator/v10"
|
||||
// "github.com/gofiber/fiber/v2"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/config"
|
||||
customlogger "github.com/SamuelTariku/FortuneBet-Backend/internal/logger"
|
||||
mockemail "github.com/SamuelTariku/FortuneBet-Backend/internal/mocks/mock_email"
|
||||
mocksms "github.com/SamuelTariku/FortuneBet-Backend/internal/mocks/mock_sms"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/repository"
|
||||
|
||||
// "github.com/SamuelTariku/FortuneBet-Backend/internal/router"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/bet"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/branch"
|
||||
|
|
@ -27,6 +30,8 @@ import (
|
|||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/user"
|
||||
virtualgameservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/virtualGame"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet"
|
||||
|
||||
// "github.com/SamuelTariku/FortuneBet-Backend/internal/utils"
|
||||
httpserver "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server"
|
||||
jwtutil "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/jwt"
|
||||
customvalidator "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/validator"
|
||||
|
|
@ -46,6 +51,16 @@ import (
|
|||
// @name Authorization
|
||||
// @BasePath /
|
||||
func main() {
|
||||
|
||||
// utils.Init()
|
||||
|
||||
// fiberApp := fiber.New()
|
||||
|
||||
// fiberApp.Get("/health", func(c *fiber.Ctx) error {
|
||||
// return c.SendString("Betting service is up and running!")
|
||||
// })
|
||||
// router.ChapaRoutes(fiberApp)
|
||||
|
||||
cfg, err := config.NewConfig()
|
||||
if err != nil {
|
||||
slog.Error(" Config error:", "err", err)
|
||||
|
|
@ -92,7 +107,7 @@ func main() {
|
|||
JwtAccessKey: cfg.JwtKey,
|
||||
JwtAccessExpiry: cfg.AccessExpiry,
|
||||
}, userSvc,
|
||||
ticketSvc, betSvc, walletSvc, transactionSvc, branchSvc, companySvc, notificationSvc, oddsSvc, eventSvc, referalSvc, virtualGameSvc, resultSvc)
|
||||
ticketSvc, betSvc, walletSvc, transactionSvc, branchSvc, companySvc, notificationSvc, oddsSvc, eventSvc, referalSvc, virtualGameSvc, resultSvc, cfg)
|
||||
logger.Info("Starting server", "port", cfg.Port)
|
||||
|
||||
if err := app.Run(); err != nil {
|
||||
|
|
|
|||
9
cmd/router.go
Normal file
9
cmd/router.go
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
package main
|
||||
|
||||
import "github.com/gofiber/fiber/v2"
|
||||
|
||||
func SetupRoutes(app *fiber.App) {
|
||||
app.Get("/health", func(c *fiber.Ctx) error {
|
||||
return c.SendString("Betting service is up and running!")
|
||||
})
|
||||
}
|
||||
3
go.mod
3
go.mod
|
|
@ -21,6 +21,7 @@ require (
|
|||
require (
|
||||
github.com/KyleBanks/depth v1.2.1 // indirect
|
||||
github.com/andybalholm/brotli v1.1.1 // indirect
|
||||
// github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2
|
||||
github.com/bytedance/sonic/loader v0.2.4 // indirect
|
||||
github.com/cloudwego/base64x v0.1.5 // indirect
|
||||
github.com/fasthttp/websocket v1.5.8 // indirect
|
||||
|
|
@ -31,7 +32,7 @@ require (
|
|||
github.com/go-openapi/swag v0.23.1 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/gofiber/contrib/websocket v1.3.4
|
||||
// github.com/gofiber/contrib/websocket v1.3.4
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
||||
|
|
|
|||
6
go.sum
6
go.sum
|
|
@ -22,8 +22,6 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
|
|||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fasthttp/websocket v1.5.3 h1:TPpQuLwJYfd4LJPXvHDYPMFWbLjsT91n3GpWtCQtdek=
|
||||
github.com/fasthttp/websocket v1.5.3/go.mod h1:46gg/UBmTU1kUaTcwQXpUxtRwG2PvIZYeA8oL6vF3Fs=
|
||||
github.com/fasthttp/websocket v1.5.8 h1:k5DpirKkftIF/w1R8ZzjSgARJrs54Je9YJK37DL/Ah8=
|
||||
github.com/fasthttp/websocket v1.5.8/go.mod h1:d08g8WaT6nnyvg9uMm8K9zMYyDjfKyj3170AtPRuVU0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
|
||||
|
|
@ -51,8 +49,6 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
|
|||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k=
|
||||
github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
|
||||
github.com/gofiber/contrib/websocket v1.3.4 h1:tWeBdbJ8q0WFQXariLN4dBIbGH9KBU75s0s7YXplOSg=
|
||||
github.com/gofiber/contrib/websocket v1.3.4/go.mod h1:kTFBPC6YENCnKfKx0BoOFjgXxdz7E85/STdkmZPEmPs=
|
||||
github.com/gofiber/fiber/v2 v2.32.0/go.mod h1:CMy5ZLiXkn6qwthrl03YMyW1NLfj0rhxz2LKl4t7ZTY=
|
||||
github.com/gofiber/fiber/v2 v2.52.6 h1:Rfp+ILPiYSvvVuIPvxrBns+HJp8qGLDnLJawAu27XVI=
|
||||
github.com/gofiber/fiber/v2 v2.52.6/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw=
|
||||
|
|
@ -118,8 +114,6 @@ github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzG
|
|||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee h1:8Iv5m6xEo1NR1AvpV+7XmhI4r39LGNzwUL4YpMuL5vk=
|
||||
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee/go.mod h1:qwtSXrKuJh/zsFQ12yEE89xfCrGKK63Rr7ctU/uCo4g=
|
||||
github.com/savsgio/gotils v0.0.0-20240303185622-093b76447511 h1:KanIMPX0QdEdB4R3CiimCAbxFrhB3j7h0/OvpYGVQa8=
|
||||
github.com/savsgio/gotils v0.0.0-20240303185622-093b76447511/go.mod h1:sM7Mt7uEoCeFSCBM+qBrqvEo+/9vdmj19wzp3yzUhmg=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ var (
|
|||
ErrInvalidLevel = errors.New("invalid log level")
|
||||
ErrInvalidEnv = errors.New("env not set or invalid")
|
||||
ErrInvalidSMSAPIKey = errors.New("SMS API key is invalid")
|
||||
ErrMissingBetToken = errors.New("missing BET365_TOKEN in .env")
|
||||
ErrMissingBetToken = errors.New("missing BET365_TOKEN in .env")
|
||||
ErrInvalidPopOKClientID = errors.New("PopOK client ID is invalid")
|
||||
ErrInvalidPopOKSecretKey = errors.New("PopOK secret key is invalid")
|
||||
ErrInvalidPopOKBaseURL = errors.New("PopOK base URL is invalid")
|
||||
|
|
@ -40,7 +40,13 @@ type Config struct {
|
|||
AFRO_SMS_SENDER_NAME string
|
||||
AFRO_SMS_RECEIVER_PHONE_NUMBER string
|
||||
ADRO_SMS_HOST_URL string
|
||||
Bet365Token string
|
||||
CHAPA_SECRET_KEY string
|
||||
CHAPA_PUBLIC_KEY string
|
||||
CHAPA_BASE_URL string
|
||||
CHAPA_ENCRYPTION_KEY string
|
||||
CHAPA_CALLBACK_URL string
|
||||
CHAPA_RETURN_URL string
|
||||
Bet365Token string
|
||||
PopOK domain.PopOKConfig
|
||||
}
|
||||
|
||||
|
|
@ -115,6 +121,17 @@ func (c *Config) loadEnv() error {
|
|||
if !ok {
|
||||
return ErrInvalidLevel
|
||||
}
|
||||
|
||||
c.CHAPA_SECRET_KEY = os.Getenv("CHAPA_SECRET_KEY")
|
||||
c.CHAPA_PUBLIC_KEY = os.Getenv("CHAPA_PUBLIC_KEY")
|
||||
c.CHAPA_ENCRYPTION_KEY = os.Getenv("CHAPA_ENCRYPTION_KEY")
|
||||
c.CHAPA_BASE_URL = os.Getenv("CHAPA_BASE_URL")
|
||||
if c.CHAPA_BASE_URL == "" {
|
||||
c.CHAPA_BASE_URL = "https://api.chapa.co/v1"
|
||||
}
|
||||
c.CHAPA_CALLBACK_URL = os.Getenv("CHAPA_CALLBACK_URL")
|
||||
c.CHAPA_RETURN_URL = os.Getenv("CHAPA_RETURN_URL")
|
||||
|
||||
c.LogLevel = lvl
|
||||
|
||||
c.AFRO_SMS_API_KEY = os.Getenv("AFRO_SMS_API_KEY")
|
||||
|
|
|
|||
2
internal/models/models.chapa.go
Normal file
2
internal/models/models.chapa.go
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
package models
|
||||
|
||||
37
internal/router/router.chapa.go
Normal file
37
internal/router/router.chapa.go
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
package router
|
||||
|
||||
// @title FortuneBet Chapa API
|
||||
|
||||
// import (
|
||||
// "github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet"
|
||||
// "github.com/gofiber/fiber/v2"
|
||||
// )
|
||||
|
||||
// func ChapaRoutes(app *fiber.App) {
|
||||
|
||||
// chapaRouter := app.Group("/api/v1/chapa")
|
||||
|
||||
// chapaRouter.Post("/payments/initialize",
|
||||
// wallet.InitializePayment,
|
||||
// )
|
||||
|
||||
// chapaRouter.Get("/payments/verify/:tx_ref",
|
||||
// wallet.VerifyTransaction,
|
||||
// )
|
||||
|
||||
// chapaRouter.Post("/payments/callback",
|
||||
// wallet.ReceiveWebhook,
|
||||
// )
|
||||
|
||||
// chapaRouter.Get("/banks",
|
||||
// wallet.GetBanks,
|
||||
// )
|
||||
|
||||
// chapaRouter.Post("/transfers",
|
||||
// wallet.CreateTransfer,
|
||||
// )
|
||||
|
||||
// chapaRouter.Get("/transfers/:transfer_ref",
|
||||
// wallet.VerifyTransfer,
|
||||
// )
|
||||
// }
|
||||
|
|
@ -1 +0,0 @@
|
|||
package wallet
|
||||
19
internal/utils/utils.chapa.go
Normal file
19
internal/utils/utils.chapa.go
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
package utils
|
||||
|
||||
// import (
|
||||
// "log"
|
||||
// "os"
|
||||
|
||||
// "github.com/SamuelTariku/FortuneBet-Backend/internal/models"
|
||||
// )
|
||||
|
||||
// func Init() {
|
||||
// if err != nil {
|
||||
// log.Println("No .env file found")
|
||||
// }
|
||||
// models.ChapaSecret = os.Getenv("CHAPA_SECRET_KEY")
|
||||
// models.ChapaBaseURL = os.Getenv("CHAPA_BASE_URL")
|
||||
// if models.ChapaBaseURL == "" {
|
||||
// models.ChapaBaseURL = "https://api.chapa.co/v1"
|
||||
// }
|
||||
// }
|
||||
|
|
@ -4,6 +4,7 @@ import (
|
|||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/config"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/bet"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/branch"
|
||||
|
|
@ -47,6 +48,7 @@ type App struct {
|
|||
prematchSvc *odds.ServiceImpl
|
||||
eventSvc event.Service
|
||||
resultSvc *result.Service
|
||||
cfg *config.Config
|
||||
}
|
||||
|
||||
func NewApp(
|
||||
|
|
@ -67,6 +69,7 @@ func NewApp(
|
|||
referralSvc referralservice.ReferralStore,
|
||||
virtualGameSvc virtualgameservice.VirtualGameService,
|
||||
resultSvc *result.Service,
|
||||
cfg *config.Config,
|
||||
) *App {
|
||||
app := fiber.New(fiber.Config{
|
||||
CaseSensitive: true,
|
||||
|
|
@ -103,6 +106,7 @@ func NewApp(
|
|||
eventSvc: eventSvc,
|
||||
virtualGameSvc: virtualGameSvc,
|
||||
resultSvc: resultSvc,
|
||||
cfg: cfg,
|
||||
}
|
||||
|
||||
s.initAppRoutes()
|
||||
|
|
|
|||
250
internal/web_server/handlers/chapa.go
Normal file
250
internal/web_server/handlers/chapa.go
Normal file
|
|
@ -0,0 +1,250 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
// "github.com/SamuelTariku/FortuneBet-Backend/internal/config"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
var (
|
||||
ChapaSecret string
|
||||
ChapaBaseURL string
|
||||
)
|
||||
|
||||
type InitPaymentRequest struct {
|
||||
Amount string `json:"amount"`
|
||||
Currency string `json:"currency"`
|
||||
Email string `json:"email"`
|
||||
FirstName string `json:"first_name"`
|
||||
LastName string `json:"last_name"`
|
||||
TxRef string `json:"tx_ref"`
|
||||
CallbackURL string `json:"callback_url"`
|
||||
ReturnURL string `json:"return_url"`
|
||||
}
|
||||
|
||||
type TransferRequest struct {
|
||||
AccountNumber string `json:"account_number"`
|
||||
BankCode string `json:"bank_code"`
|
||||
Amount string `json:"amount"`
|
||||
Currency string `json:"currency"`
|
||||
Reference string `json:"reference"`
|
||||
Reason string `json:"reason"`
|
||||
RecipientName string `json:"recipient_name"`
|
||||
}
|
||||
|
||||
func (h *Handler) GetBanks(c *fiber.Ctx) error {
|
||||
httpReq, err := http.NewRequest("GET", h.Cfg.CHAPA_BASE_URL+"/banks", nil)
|
||||
// log.Printf("\n\nbase url is: %v\n\n", h.Cfg.CHAPA_BASE_URL)
|
||||
if err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": "Failed to create request", "details": err.Error()})
|
||||
}
|
||||
httpReq.Header.Set("Authorization", "Bearer "+h.Cfg.CHAPA_SECRET_KEY)
|
||||
|
||||
resp, err := http.DefaultClient.Do(httpReq)
|
||||
if err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": "Failed to fetch banks", "details": err.Error()})
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": "Failed to read response", "details": err.Error()})
|
||||
}
|
||||
|
||||
return c.Status(resp.StatusCode).Send(body)
|
||||
}
|
||||
|
||||
func (h *Handler) InitializePayment(c *fiber.Ctx) error {
|
||||
var req InitPaymentRequest
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
||||
"error": "Invalid request body",
|
||||
"details": err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
payload, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{
|
||||
"error": "Failed to serialize request",
|
||||
"details": err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
httpReq, err := http.NewRequest("POST", h.Cfg.CHAPA_BASE_URL+"/transaction/initialize", bytes.NewBuffer(payload))
|
||||
if err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{
|
||||
"error": "Failed to create request",
|
||||
"details": err.Error(),
|
||||
})
|
||||
}
|
||||
httpReq.Header.Set("Authorization", "Bearer "+h.Cfg.CHAPA_SECRET_KEY)
|
||||
httpReq.Header.Set("Content-Type", "application/json")
|
||||
|
||||
resp, err := http.DefaultClient.Do(httpReq)
|
||||
if err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{
|
||||
"error": "Failed to initialize payment",
|
||||
"details": err.Error(),
|
||||
})
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{
|
||||
"error": "Failed to read response",
|
||||
"details": err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return c.Status(resp.StatusCode).Send(body)
|
||||
}
|
||||
|
||||
func (h *Handler) VerifyTransaction(c *fiber.Ctx) error {
|
||||
txRef := c.Params("tx_ref")
|
||||
if txRef == "" {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
||||
"error": "Missing transaction reference",
|
||||
})
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("%s/transaction/verify/%s", h.Cfg.CHAPA_BASE_URL, txRef)
|
||||
|
||||
httpReq, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{
|
||||
"error": "Failed to create request",
|
||||
"details": err.Error(),
|
||||
})
|
||||
}
|
||||
httpReq.Header.Set("Authorization", "Bearer "+h.Cfg.CHAPA_SECRET_KEY)
|
||||
|
||||
resp, err := http.DefaultClient.Do(httpReq)
|
||||
if err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{
|
||||
"error": "Failed to verify transaction",
|
||||
"details": err.Error(),
|
||||
})
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{
|
||||
"error": "Failed to read response",
|
||||
"details": err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return c.Status(resp.StatusCode).Send(body)
|
||||
}
|
||||
|
||||
func (h *Handler) ReceiveWebhook(c *fiber.Ctx) error {
|
||||
var payload map[string]interface{}
|
||||
if err := c.BodyParser(&payload); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
||||
"error": "Invalid webhook data",
|
||||
"details": err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
h.logger.Info("Chapa webhook received", "payload", payload)
|
||||
|
||||
// Optional: you can verify tx_ref here again if needed
|
||||
|
||||
return c.SendStatus(fiber.StatusOK)
|
||||
}
|
||||
|
||||
func (h *Handler) CreateTransfer(c *fiber.Ctx) error {
|
||||
var req TransferRequest
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
||||
"error": "Invalid request",
|
||||
"details": err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
payload, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"error": "Failed to serialize request",
|
||||
"details": err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
httpReq, err := http.NewRequest("POST", h.Cfg.CHAPA_BASE_URL+"/transfers", bytes.NewBuffer(payload))
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"error": "Failed to create HTTP request",
|
||||
"details": err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
httpReq.Header.Set("Authorization", "Bearer "+h.Cfg.CHAPA_SECRET_KEY)
|
||||
httpReq.Header.Set("Content-Type", "application/json")
|
||||
|
||||
resp, err := http.DefaultClient.Do(httpReq)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"error": "Transfer request failed",
|
||||
"details": err.Error(),
|
||||
})
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"error": "Failed to read response",
|
||||
"details": err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return c.Status(resp.StatusCode).Send(body)
|
||||
}
|
||||
|
||||
func (h *Handler) VerifyTransfer(c *fiber.Ctx) error {
|
||||
transferRef := c.Params("transfer_ref")
|
||||
if transferRef == "" {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
||||
"error": "Missing transfer reference in URL",
|
||||
})
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("%s/transfers/%s", h.Cfg.CHAPA_BASE_URL, transferRef)
|
||||
|
||||
httpReq, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"error": "Failed to create HTTP request",
|
||||
"details": err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
httpReq.Header.Set("Authorization", "Bearer "+h.Cfg.CHAPA_SECRET_KEY)
|
||||
|
||||
resp, err := http.DefaultClient.Do(httpReq)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"error": "Verification request failed",
|
||||
"details": err.Error(),
|
||||
})
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"error": "Failed to read response body",
|
||||
"details": err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return c.Status(resp.StatusCode).Send(body)
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ package handlers
|
|||
import (
|
||||
"log/slog"
|
||||
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/config"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/bet"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/branch"
|
||||
|
|
@ -37,6 +38,7 @@ type Handler struct {
|
|||
authSvc *authentication.Service
|
||||
jwtConfig jwtutil.JwtConfig
|
||||
validator *customvalidator.CustomValidator
|
||||
Cfg *config.Config
|
||||
}
|
||||
|
||||
func New(
|
||||
|
|
@ -56,6 +58,7 @@ func New(
|
|||
companySvc *company.Service,
|
||||
prematchSvc *odds.ServiceImpl,
|
||||
eventSvc event.Service,
|
||||
cfg *config.Config,
|
||||
) *Handler {
|
||||
return &Handler{
|
||||
logger: logger,
|
||||
|
|
@ -74,5 +77,6 @@ func New(
|
|||
virtualGameSvc: virtualGameSvc,
|
||||
authSvc: authSvc,
|
||||
jwtConfig: jwtConfig,
|
||||
Cfg: cfg,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,10 @@ import (
|
|||
"strconv"
|
||||
|
||||
_ "github.com/SamuelTariku/FortuneBet-Backend/docs"
|
||||
// "github.com/SamuelTariku/FortuneBet-Backend/internal/config"
|
||||
// "github.com/SamuelTariku/FortuneBet-Backend/internal/config"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
||||
// "github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet"
|
||||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/handlers"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
|
|
@ -30,6 +33,7 @@ func (a *App) initAppRoutes() {
|
|||
a.companySvc,
|
||||
a.prematchSvc,
|
||||
a.eventSvc,
|
||||
a.cfg,
|
||||
)
|
||||
|
||||
a.fiber.Get("/", func(c *fiber.Ctx) error {
|
||||
|
|
@ -162,6 +166,14 @@ func (a *App) initAppRoutes() {
|
|||
a.fiber.Get("/transfer/wallet/:id", a.authMiddleware, h.GetTransfersByWallet)
|
||||
a.fiber.Post("/transfer/refill/:id", a.authMiddleware, h.RefillWallet)
|
||||
|
||||
//Chapa Routes
|
||||
a.fiber.Post("/api/v1/chapa/payments/initialize", a.authMiddleware, h.InitializePayment)
|
||||
a.fiber.Get("/api/v1/chapa/payments/verify/:tx_ref", a.authMiddleware, h.VerifyTransaction)
|
||||
a.fiber.Post("/api/v1/chapa/payments/callback", a.authMiddleware, h.ReceiveWebhook)
|
||||
a.fiber.Get("/api/v1/chapa/banks", a.authMiddleware, h.GetBanks)
|
||||
a.fiber.Post("/api/v1/chapa/transfers", a.authMiddleware, h.CreateTransfer)
|
||||
a.fiber.Get("/api/v1/chapa/transfers/:transfer_ref", a.authMiddleware, h.VerifyTransfer)
|
||||
|
||||
// Transactions /transactions
|
||||
a.fiber.Post("/transaction", a.authMiddleware, h.CreateTransaction)
|
||||
a.fiber.Get("/transaction", a.authMiddleware, h.GetAllTransactions)
|
||||
|
|
|
|||
4
makefile
4
makefile
|
|
@ -9,7 +9,7 @@ coverage:
|
|||
@go tool cover -func=coverage.out -o coverage/coverage.txt
|
||||
.PHONY: build
|
||||
build:
|
||||
@go build -ldflags="-s" -o ./bin/web ./
|
||||
@go build -ldflags="-s" -o ./bin/web ./cmd/main.go
|
||||
.PHONY: run
|
||||
run:
|
||||
@echo "Running Go application"
|
||||
|
|
@ -18,7 +18,7 @@ run:
|
|||
air:
|
||||
@echo "Running air"
|
||||
@air -c .air.toml
|
||||
.PHONY: migrations/up
|
||||
.PHONY: migrations/new
|
||||
migrations/new:
|
||||
@echo 'Creating migration files for DB_URL'
|
||||
@migrate create -seq -ext=.sql -dir=./db/migrations $(name)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user