From 3310e01cccacf50ff3664a185e08a40d66c1709e Mon Sep 17 00:00:00 2001 From: Yared Yemane Date: Wed, 13 Aug 2025 14:45:05 +0300 Subject: [PATCH] veli games .env + signature fixes --- Dockerfile | 2 +- cmd/main.go | 5 +- db/migrations/000001_fortune.up.sql | 52 ++++++++----- db/migrations/000007_setting_data.up.sql | 11 +-- go.mod | 12 +-- go.sum | 28 +++---- internal/config/config.go | 30 ++++---- internal/services/virtualGame/veli/client.go | 16 +++- internal/services/virtualGame/veli/service.go | 76 ++++++++++++------- internal/web_server/app.go | 4 +- .../web_server/handlers/direct_deposit.go | 2 +- internal/web_server/routes.go | 2 +- 12 files changed, 144 insertions(+), 96 deletions(-) diff --git a/Dockerfile b/Dockerfile index 2f5adc5..2ac8143 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,7 +3,7 @@ FROM golang:1.24-alpine AS builder WORKDIR /app COPY go.mod go.sum ./ -RUN go mod download +# RUN go mod download COPY . . RUN go build -ldflags="-s -w" -o ./bin/web ./cmd/main.go diff --git a/cmd/main.go b/cmd/main.go index b154765..c737e71 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -57,6 +57,7 @@ import ( "github.com/SamuelTariku/FortuneBet-Backend/internal/services/user" virtualgameservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/virtualGame" alea "github.com/SamuelTariku/FortuneBet-Backend/internal/services/virtualGame/Alea" + "github.com/SamuelTariku/FortuneBet-Backend/internal/services/virtualGame/veli" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet/monitor" @@ -151,7 +152,8 @@ func main() { referalSvc := referralservice.New(referalRepo, *walletSvc, store, cfg, logger) virtualGameSvc := virtualgameservice.New(vitualGameRepo, *walletSvc, store, cfg, logger) aleaService := alea.NewAleaPlayService(vitualGameRepo, *walletSvc, cfg, logger) - // veliService := veli.NewVeliPlayService(vitualGameRepo, *walletSvc, cfg, logger) + veliCLient := veli.NewClient(cfg, walletSvc) + veliVirtualGameService := veli.New(veliCLient) recommendationSvc := recommendation.NewService(recommendationRepo) chapaClient := chapa.NewClient(cfg.CHAPA_BASE_URL, cfg.CHAPA_SECRET_KEY) @@ -242,6 +244,7 @@ func main() { // Initialize and start HTTP server app := httpserver.NewApp( + veliVirtualGameService, telebirrSvc, arifpaySvc, santimpaySvc, diff --git a/db/migrations/000001_fortune.up.sql b/db/migrations/000001_fortune.up.sql index 968ba99..9a952a1 100644 --- a/db/migrations/000001_fortune.up.sql +++ b/db/migrations/000001_fortune.up.sql @@ -1,21 +1,3 @@ -CREATE TABLE direct_deposits ( - id BIGSERIAL PRIMARY KEY, - customer_id BIGINT NOT NULL REFERENCES users(id), - wallet_id BIGINT NOT NULL REFERENCES wallets(id), - amount NUMERIC(15, 2) NOT NULL, - bank_reference TEXT NOT NULL, - sender_account TEXT NOT NULL, - status TEXT NOT NULL CHECK (status IN ('pending', 'completed', 'rejected')), - created_at TIMESTAMP NOT NULL DEFAULT NOW(), - verified_by BIGINT REFERENCES users(id), - verification_notes TEXT, - verified_at TIMESTAMP -); - -CREATE INDEX idx_direct_deposits_status ON direct_deposits(status); -CREATE INDEX idx_direct_deposits_customer ON direct_deposits(customer_id); -CREATE INDEX idx_direct_deposits_reference ON direct_deposits(bank_reference); - CREATE TABLE IF NOT EXISTS users ( id BIGSERIAL PRIMARY KEY, first_name VARCHAR(255) NOT NULL, @@ -37,6 +19,20 @@ CREATE TABLE IF NOT EXISTS users ( OR phone_number IS NOT NULL ) ); + +CREATE TABLE IF NOT EXISTS wallets ( + id BIGSERIAL PRIMARY KEY, + balance BIGINT NOT NULL DEFAULT 0, + is_withdraw BOOLEAN NOT NULL, + is_bettable BOOLEAN NOT NULL, + is_transferable BOOLEAN NOT NULL, + user_id BIGINT NOT NULL, + type VARCHAR(255) NOT NULL, + is_active BOOLEAN NOT NULL DEFAULT true, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + CREATE TABLE refresh_tokens ( id BIGSERIAL PRIMARY KEY, user_id BIGINT NOT NULL, @@ -46,6 +42,26 @@ CREATE TABLE refresh_tokens ( revoked BOOLEAN DEFAULT FALSE NOT NULL, CONSTRAINT unique_token UNIQUE (token) ); + + +CREATE TABLE direct_deposits ( + id BIGSERIAL PRIMARY KEY, + customer_id BIGINT NOT NULL REFERENCES users(id), + wallet_id BIGINT NOT NULL REFERENCES wallets(id), + amount NUMERIC(15, 2) NOT NULL, + bank_reference TEXT NOT NULL, + sender_account TEXT NOT NULL, + status TEXT NOT NULL CHECK (status IN ('pending', 'completed', 'rejected')), + created_at TIMESTAMP NOT NULL DEFAULT NOW(), + verified_by BIGINT REFERENCES users(id), + verification_notes TEXT, + verified_at TIMESTAMP +); + +CREATE INDEX idx_direct_deposits_status ON direct_deposits(status); +CREATE INDEX idx_direct_deposits_customer ON direct_deposits(customer_id); +CREATE INDEX idx_direct_deposits_reference ON direct_deposits(bank_reference); + ----- CREATE TABLE otps ( id BIGSERIAL PRIMARY KEY, diff --git a/db/migrations/000007_setting_data.up.sql b/db/migrations/000007_setting_data.up.sql index 458da81..e98967b 100644 --- a/db/migrations/000007_setting_data.up.sql +++ b/db/migrations/000007_setting_data.up.sql @@ -1,20 +1,11 @@ -- Settings Initial Data INSERT INTO settings (key, value) VALUES ('sms_provider', '30'), -<<<<<<< HEAD -('max_number_of_outcomes', '30'), - ('bet_amount_limit', '100000'), -======= ('max_number_of_outcomes', '30'), ('bet_amount_limit', '10000000'), ->>>>>>> 7d8d824a94381bd82c40398654c3bd78218c5950 ('daily_ticket_limit', '50'), ('total_winnings_limit', '1000000'), ('amount_for_bet_referral', '1000000'), ('cashback_amount_cap', '1000') ON CONFLICT (key) DO UPDATE -<<<<<<< HEAD -SET value = EXCLUDED.value; -======= -SET value = EXCLUDED.value; ->>>>>>> 7d8d824a94381bd82c40398654c3bd78218c5950 +SET value = EXCLUDED.value; \ No newline at end of file diff --git a/go.mod b/go.mod index 47017a5..71351a2 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/swaggo/fiber-swagger v1.3.0 github.com/swaggo/swag v1.16.4 github.com/valyala/fasthttp v1.63.0 - golang.org/x/crypto v0.39.0 + golang.org/x/crypto v0.41.0 ) require ( @@ -53,11 +53,11 @@ require ( github.com/valyala/bytebufferpool v1.0.0 // indirect go.mongodb.org/mongo-driver v1.17.3 golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect - golang.org/x/net v0.41.0 // indirect - golang.org/x/sync v0.15.0 // indirect - golang.org/x/sys v0.33.0 // indirect - golang.org/x/text v0.26.0 // indirect - golang.org/x/tools v0.33.0 // indirect + golang.org/x/net v0.43.0 // indirect + golang.org/x/sync v0.16.0 // indirect + golang.org/x/sys v0.35.0 // indirect + golang.org/x/text v0.28.0 // indirect + golang.org/x/tools v0.36.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 07c697f..868b34b 100644 --- a/go.sum +++ b/go.sum @@ -216,13 +216,13 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= -golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= +golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= +golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w= -golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= +golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= +golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -236,14 +236,14 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= -golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= +golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= +golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= -golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -261,8 +261,8 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= -golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -276,8 +276,8 @@ golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= -golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= +golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= +golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -285,8 +285,8 @@ golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= -golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= +golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= +golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/internal/config/config.go b/internal/config/config.go index 3730309..a0acbb1 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -59,11 +59,11 @@ type VeliConfig struct { } type ARIFPAYConfig struct { - APIKey string `mapstructure:"VELI_API_KEY"` - CancelUrl string `mapstructure:"VELI_BASE_URL"` - ErrorUrl string `mapstructure:"VELI_SECRET_KEY"` - NotifyUrl string `mapstructure:"VELI_OPERATOR_ID"` - SuccessUrl string `mapstructure:"VELI_BRAND_ID"` + APIKey string `mapstructure:"ARIFPAYAPI_KEY"` + CancelUrl string `mapstructure:"ARIFPAY_BASE_URL"` + ErrorUrl string `mapstructure:"ARIFPAY_SECRET_KEY"` + NotifyUrl string `mapstructure:"ARIFPAY_OPERATOR_ID"` + SuccessUrl string `mapstructure:"ARIFPAY_BRAND_ID"` } type SANTIMPAYConfig struct { @@ -275,12 +275,12 @@ func (c *Config) loadEnv() error { //Veli Games veliEnabled := os.Getenv("VELI_ENABLED") if veliEnabled == "" { - veliEnabled = "false" // Default to disabled if not specified + veliEnabled = "true" // Default to disabled if not specified } - veliOperatorID := os.Getenv("VELI_OPERATOR_ID") - veliBrandID := os.Getenv("VELI_BRAND_ID") - c.VeliGames.OperatorID = veliOperatorID - c.VeliGames.BrandID = veliBrandID + // veliOperatorID := os.Getenv("VELI_OPERATOR_ID") + // veliBrandID := os.Getenv("VELI_BRAND_ID") + c.VeliGames.OperatorID = os.Getenv("VELI_OPERATOR_ID") + c.VeliGames.BrandID = os.Getenv("VELI_BRAND_ID") if enabled, err := strconv.ParseBool(veliEnabled); err != nil { return fmt.Errorf("invalid VELI_ENABLED value: %w", err) @@ -288,11 +288,11 @@ func (c *Config) loadEnv() error { c.VeliGames.Enabled = enabled } - apiURL := os.Getenv("VELI_API_URL") - if apiURL == "" { - apiURL = "https://api.velitech.games" // Default production URL - } - c.VeliGames.BaseURL = apiURL + // apiURL := os.Getenv("VELI_BASE_URL") + // if apiURL == "" { + // apiURL = "https://api.velitech.games" // Default production URL + // } + c.VeliGames.BaseURL = os.Getenv("VELI_BASE_URL") operatorKey := os.Getenv("VELI_OPERATOR_KEY") if operatorKey == "" && c.VeliGames.Enabled { diff --git a/internal/services/virtualGame/veli/client.go b/internal/services/virtualGame/veli/client.go index 67079f6..c2ac022 100644 --- a/internal/services/virtualGame/veli/client.go +++ b/internal/services/virtualGame/veli/client.go @@ -54,9 +54,17 @@ func (c *Client) generateSignature(params map[string]string) (string, error) { b.WriteString(fmt.Sprintf("%s:%s", k, params[k])) } + fmt.Println("String being signed:", b.String()) + fmt.Println("Using secret key:", c.SecretKey) + h := hmac.New(sha512.New, []byte(c.SecretKey)) h.Write([]byte(b.String())) - return fmt.Sprintf("%s:%s", c.OperatorID, base64.StdEncoding.EncodeToString(h.Sum(nil))), nil + hash := h.Sum(nil) + signature := base64.StdEncoding.EncodeToString(hash) + fmt.Println("Generated signature:", signature) + return fmt.Sprintf("%s:%s", c.OperatorID, signature), nil + + // return fmt.Sprintf("%s:%s", c.OperatorID, base64.StdEncoding.EncodeToString(h.Sum(nil))), nil } // POST helper @@ -77,6 +85,12 @@ func (c *Client) post(ctx context.Context, path string, body any, sigParams map[ } defer res.Body.Close() + fmt.Println("Request URL:", c.BaseURL+path) + fmt.Println("Request Headers:") + fmt.Println(" Content-Type: application/json") + fmt.Println(" signature:", sig) + fmt.Println("Request Body:", string(data)) + b, _ := io.ReadAll(res.Body) if res.StatusCode >= 400 { return fmt.Errorf("error: %s", b) diff --git a/internal/services/virtualGame/veli/service.go b/internal/services/virtualGame/veli/service.go index de98686..3d4638c 100644 --- a/internal/services/virtualGame/veli/service.go +++ b/internal/services/virtualGame/veli/service.go @@ -17,31 +17,53 @@ var ( ErrDuplicateTransaction = errors.New("DUPLICATE_TRANSACTION") ) -func (c *Client) GetProviders(ctx context.Context, req domain.ProviderRequest) (*domain.ProviderResponse, error) { - sigParams := map[string]string{"brandId": req.BrandID} - if req.Page > 0 { - sigParams["page"] = fmt.Sprintf("%d", req.Page) +type service struct { + client *Client +} + +func New(client *Client) VeliVirtualGameService { + return &service{ + client: client, } +} + +func (s *service) GetProviders(ctx context.Context, req domain.ProviderRequest) (*domain.ProviderResponse, error) { + // Always mirror request body fields into sigParams + sigParams := map[string]string{ + "brandId": req.BrandID, + } + + // Optional fields + sigParams["extraData"] = fmt.Sprintf("%t", req.ExtraData) // false is still included if req.Size > 0 { sigParams["size"] = fmt.Sprintf("%d", req.Size) + } else { + sigParams["size"] = "" // keep empty if not set } + if req.Page > 0 { + sigParams["page"] = fmt.Sprintf("%d", req.Page) + } else { + sigParams["page"] = "" + } + var res domain.ProviderResponse - err := c.post(ctx, "/game-lists/public/providers", req, sigParams, &res) + err := s.client.post(ctx, "/game-lists/public/providers", req, sigParams, &res) return &res, err } -func (c *Client) GetGames(ctx context.Context, req domain.GameListRequest) ([]domain.GameEntity, error) { + +func (s *service) GetGames(ctx context.Context, req domain.GameListRequest) ([]domain.GameEntity, error) { sigParams := map[string]string{ "brandId": req.BrandID, "providerId": req.ProviderID, } var res struct { Items []domain.GameEntity `json:"items"` } - err := c.post(ctx, "/game-lists/public/games", req, sigParams, &res) + err := s.client.post(ctx, "/game-lists/public/games", req, sigParams, &res) return res.Items, err } -func (c *Client) StartGame(ctx context.Context, req domain.GameStartRequest) (*domain.GameStartResponse, error) { +func (s *service) StartGame(ctx context.Context, req domain.GameStartRequest) (*domain.GameStartResponse, error) { sigParams := map[string]string{ "sessionId": req.SessionID, "providerId": req.ProviderID, "gameId": req.GameID, "language": req.Language, "playerId": req.PlayerID, @@ -49,22 +71,22 @@ func (c *Client) StartGame(ctx context.Context, req domain.GameStartRequest) (*d "ip": req.IP, "brandId": req.BrandID, } var res domain.GameStartResponse - err := c.post(ctx, "/unified-api/public/start-game", req, sigParams, &res) + err := s.client.post(ctx, "/unified-api/public/start-game", req, sigParams, &res) return &res, err } -func (c *Client) StartDemoGame(ctx context.Context, req domain.DemoGameRequest) (*domain.GameStartResponse, error) { +func (s *service) StartDemoGame(ctx context.Context, req domain.DemoGameRequest) (*domain.GameStartResponse, error) { sigParams := map[string]string{ "providerId": req.ProviderID, "gameId": req.GameID, "language": req.Language, "deviceType": req.DeviceType, "ip": req.IP, "brandId": req.BrandID, } var res domain.GameStartResponse - err := c.post(ctx, "/unified-api/public/start-demo-game", req, sigParams, &res) + err := s.client.post(ctx, "/unified-api/public/start-demo-game", req, sigParams, &res) return &res, err } -func (c *Client) GetBalance(ctx context.Context, req domain.BalanceRequest) (*domain.BalanceResponse, error) { +func (s *service) GetBalance(ctx context.Context, req domain.BalanceRequest) (*domain.BalanceResponse, error) { sigParams := map[string]string{ "sessionId": req.SessionID, "providerId": req.ProviderID, @@ -77,11 +99,11 @@ func (c *Client) GetBalance(ctx context.Context, req domain.BalanceRequest) (*do } var res domain.BalanceResponse - err := c.post(ctx, "/balance", req, sigParams, &res) + err := s.client.post(ctx, "/balance", req, sigParams, &res) return &res, err } -func (c *Client) ProcessBet(ctx context.Context, req domain.BetRequest) (*domain.BetResponse, error) { +func (s *service) ProcessBet(ctx context.Context, req domain.BetRequest) (*domain.BetResponse, error) { sigParams := map[string]string{ "sessionId": req.SessionID, "providerId": req.ProviderID, @@ -105,24 +127,24 @@ func (c *Client) ProcessBet(ctx context.Context, req domain.BetRequest) (*domain } var res domain.BetResponse - err := c.post(ctx, "/bet", req, sigParams, &res) + err := s.client.post(ctx, "/bet", req, sigParams, &res) playerIDInt64, err := strconv.ParseInt(req.PlayerID, 10, 64) if err != nil { return &domain.BetResponse{}, fmt.Errorf("invalid PlayerID: %w", err) } - wallets, err := c.walletSvc.GetWalletsByUser(ctx, playerIDInt64) + wallets, err := s.client.walletSvc.GetWalletsByUser(ctx, playerIDInt64) if err != nil { return &domain.BetResponse{}, err } - c.walletSvc.DeductFromWallet(ctx, wallets[0].ID, domain.Currency(req.Amount.Amount), domain.ValidInt64{}, domain.TRANSFER_DIRECT, + s.client.walletSvc.DeductFromWallet(ctx, wallets[0].ID, domain.Currency(req.Amount.Amount), domain.ValidInt64{}, domain.TRANSFER_DIRECT, fmt.Sprintf("Deducting %v from wallet for creating Veli Game Bet", req.Amount.Amount), ) return &res, err } -func (c *Client) ProcessWin(ctx context.Context, req domain.WinRequest) (*domain.WinResponse, error) { +func (s *service) ProcessWin(ctx context.Context, req domain.WinRequest) (*domain.WinResponse, error) { sigParams := map[string]string{ "sessionId": req.SessionID, "providerId": req.ProviderID, @@ -146,26 +168,26 @@ func (c *Client) ProcessWin(ctx context.Context, req domain.WinRequest) (*domain } var res domain.WinResponse - err := c.post(ctx, "/win", req, sigParams, &res) + err := s.client.post(ctx, "/win", req, sigParams, &res) playerIDInt64, err := strconv.ParseInt(req.PlayerID, 10, 64) if err != nil { return &domain.WinResponse{}, fmt.Errorf("invalid PlayerID: %w", err) } - wallets, err := c.walletSvc.GetWalletsByUser(ctx, playerIDInt64) + wallets, err := s.client.walletSvc.GetWalletsByUser(ctx, playerIDInt64) if err != nil { return &domain.WinResponse{}, err } - c.walletSvc.AddToWallet(ctx, wallets[0].ID, domain.Currency(req.Amount.Amount), domain.ValidInt64{}, domain.TRANSFER_DIRECT, domain.PaymentDetails{}, + s.client.walletSvc.AddToWallet(ctx, wallets[0].ID, domain.Currency(req.Amount.Amount), domain.ValidInt64{}, domain.TRANSFER_DIRECT, domain.PaymentDetails{}, fmt.Sprintf("Adding %v to wallet due to winning Veli Games bet", req.Amount), ) return &res, err } -func (c *Client) ProcessCancel(ctx context.Context, req domain.CancelRequest) (*domain.CancelResponse, error) { +func (s *service) ProcessCancel(ctx context.Context, req domain.CancelRequest) (*domain.CancelResponse, error) { sigParams := map[string]string{ "sessionId": req.SessionID, "providerId": req.ProviderID, @@ -191,25 +213,25 @@ func (c *Client) ProcessCancel(ctx context.Context, req domain.CancelRequest) (* } var res domain.CancelResponse - err := c.post(ctx, "/cancel", req, sigParams, &res) + err := s.client.post(ctx, "/cancel", req, sigParams, &res) playerIDInt64, err := strconv.ParseInt(req.PlayerID, 10, 64) if err != nil { return &domain.CancelResponse{}, fmt.Errorf("invalid PlayerID: %w", err) } - wallets, err := c.walletSvc.GetWalletsByUser(ctx, playerIDInt64) + wallets, err := s.client.walletSvc.GetWalletsByUser(ctx, playerIDInt64) if err != nil { return &domain.CancelResponse{}, err } - c.walletSvc.AddToWallet(ctx, wallets[0].ID, domain.Currency(req.AdjustmentRefund.Amount), domain.ValidInt64{}, domain.TRANSFER_DIRECT, domain.PaymentDetails{}, + s.client.walletSvc.AddToWallet(ctx, wallets[0].ID, domain.Currency(req.AdjustmentRefund.Amount), domain.ValidInt64{}, domain.TRANSFER_DIRECT, domain.PaymentDetails{}, fmt.Sprintf("Adding %v to wallet due to cancelling virtual game bet", req.AdjustmentRefund.Amount), ) return &res, err } -func (c *Client) GetGamingActivity(ctx context.Context, req domain.GamingActivityRequest) (*domain.GamingActivityResponse, error) { +func (s *service) GetGamingActivity(ctx context.Context, req domain.GamingActivityRequest) (*domain.GamingActivityResponse, error) { // Prepare signature parameters (sorted string map of non-nested fields) sigParams := map[string]string{ "fromDate": req.FromDate, @@ -241,7 +263,7 @@ func (c *Client) GetGamingActivity(ctx context.Context, req domain.GamingActivit } var res domain.GamingActivityResponse - err := c.post(ctx, "/report-api/public/gaming-activity", req, sigParams, &res) + err := s.client.post(ctx, "/report-api/public/gaming-activity", req, sigParams, &res) if err != nil { return nil, err } diff --git a/internal/web_server/app.go b/internal/web_server/app.go index 7313199..fa016c0 100644 --- a/internal/web_server/app.go +++ b/internal/web_server/app.go @@ -43,6 +43,7 @@ import ( ) type App struct { + veliVirtualGameService veli.VeliVirtualGameService telebirrSvc *telebirr.TelebirrService arifpaySvc *arifpay.ArifpayService santimpaySvc *santimpay.SantimPayService @@ -51,7 +52,6 @@ type App struct { currSvc *currency.Service fiber *fiber.App aleaVirtualGameService alea.AleaVirtualGameService - veliVirtualGameService veli.VeliVirtualGameService recommendationSvc recommendation.RecommendationService cfg *config.Config logger *slog.Logger @@ -82,6 +82,7 @@ type App struct { } func NewApp( + veliVirtualGameService veli.VeliVirtualGameService, telebirrSvc *telebirr.TelebirrService, arifpaySvc *arifpay.ArifpayService, santimpaySvc *santimpay.SantimPayService, @@ -131,6 +132,7 @@ func NewApp( })) s := &App{ + veliVirtualGameService: veliVirtualGameService, telebirrSvc: telebirrSvc, arifpaySvc: arifpaySvc, santimpaySvc: santimpaySvc, diff --git a/internal/web_server/handlers/direct_deposit.go b/internal/web_server/handlers/direct_deposit.go index 64f1fde..fa3a28f 100644 --- a/internal/web_server/handlers/direct_deposit.go +++ b/internal/web_server/handlers/direct_deposit.go @@ -53,7 +53,7 @@ func (h *Handler) InitiateDirectDeposit(c *fiber.Ctx) error { // @Tags Direct Deposits // @Accept json // @Produce json -// @Param request body domain.VerifyDepositRequest true "Verification details" +// @Param request body domain.VerifyDirectDepositRequest true "Verification details" // @Success 200 {object} domain.Response // @Failure 400 {object} domain.ErrorResponse // @Failure 401 {object} domain.ErrorResponse diff --git a/internal/web_server/routes.go b/internal/web_server/routes.go index 8311bb5..0e5f230 100644 --- a/internal/web_server/routes.go +++ b/internal/web_server/routes.go @@ -282,7 +282,7 @@ func (a *App) initAppRoutes() { groupV1.Post("/veli/providers", h.GetProviders) groupV1.Post("/veli/games-list", h.GetGamesByProvider) groupV1.Post("/veli/start-game", a.authMiddleware, h.StartGame) - groupV1.Post("/veli/start-demo-game", a.authMiddleware, h.StartDemoGame) + groupV1.Post("/veli/start-demo-game", h.StartDemoGame) a.fiber.Post("/balance", h.GetBalance) groupV1.Post("/veli/gaming-activity", h.GetGamingActivity)