Yimaru-BackEnd/internal/services/chapa/service.go
2025-05-30 23:59:55 +03:00

138 lines
3.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package chapa
import (
"context"
"fmt"
"strconv"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
"github.com/SamuelTariku/FortuneBet-Backend/internal/repository"
referralservice "github.com/SamuelTariku/FortuneBet-Backend/internal/services/referal"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/transaction"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/user"
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet"
"github.com/shopspring/decimal"
)
type Service struct {
transactionStore transaction.TransactionStore
walletStore wallet.WalletStore
userStore user.UserStore
referralStore referralservice.ReferralStore
store *repository.Store
}
func NewService(
txStore transaction.TransactionStore,
walletStore wallet.WalletStore,
userStore user.UserStore,
referralStore referralservice.ReferralStore,
store *repository.Store,
) *Service {
return &Service{
transactionStore: txStore,
walletStore: walletStore,
userStore: userStore,
referralStore: referralStore,
store: store,
}
}
func (s *Service) HandleChapaTransferWebhook(ctx context.Context, req domain.ChapaWebHookTransfer) error {
_, tx, err := s.store.BeginTx(ctx)
if err != nil {
return err
}
defer tx.Rollback(ctx)
// Use your services normally (they dont use the transaction, unless you wire `q`)
referenceID, err := strconv.ParseInt(req.Reference, 10, 64)
if err != nil {
return fmt.Errorf("invalid reference ID: %w", err)
}
txn, err := s.transactionStore.GetTransactionByID(ctx, referenceID)
if err != nil {
return err
}
if txn.Verified {
return nil
}
webhookAmount, _ := decimal.NewFromString(req.Amount)
storedAmount, _ := decimal.NewFromString(txn.Amount.String())
if !webhookAmount.Equal(storedAmount) {
return fmt.Errorf("amount mismatch")
}
txn.Verified = true
if err := s.transactionStore.UpdateTransactionVerified(ctx, txn.ID, txn.Verified, txn.ApprovedBy.Value, txn.ApproverName.Value); err != nil {
return err
}
return tx.Commit(ctx)
}
func (s *Service) HandleChapaPaymentWebhook(ctx context.Context, req domain.ChapaWebHookPayment) error {
_, tx, err := s.store.BeginTx(ctx)
if err != nil {
return err
}
defer tx.Rollback(ctx)
if req.Status != "success" {
return fmt.Errorf("payment status not successful")
}
// 1. Parse reference ID
referenceID, err := strconv.ParseInt(req.TxRef, 10, 64)
if err != nil {
return fmt.Errorf("invalid tx_ref: %w", err)
}
// 2. Fetch transaction
txn, err := s.transactionStore.GetTransactionByID(ctx, referenceID)
if err != nil {
return err
}
if txn.Verified {
return nil // already processed
}
webhookAmount, _ := strconv.ParseFloat(req.Amount, 32)
if webhookAmount < float64(txn.Amount) {
return fmt.Errorf("webhook amount is less than expected")
}
// 4. Fetch wallet
wallet, err := s.walletStore.GetWalletByID(ctx, txn.ID)
if err != nil {
return err
}
// 5. Update wallet balance
newBalance := wallet.Balance + txn.Amount
if err := s.walletStore.UpdateBalance(ctx, wallet.ID, newBalance); err != nil {
return err
}
// 6. Mark transaction as verified
if err := s.transactionStore.UpdateTransactionVerified(ctx, txn.ID, true, txn.ApprovedBy.Value, txn.ApproverName.Value); err != nil {
return err
}
// 7. Check & Create Referral
stats, err := s.referralStore.GetReferralStats(ctx, string(wallet.UserID))
if err != nil {
return err
}
if stats == nil {
if err := s.referralStore.CreateReferral(ctx, wallet.UserID); err != nil {
return err
}
}
return tx.Commit(ctx)
}