Chapa Fixes
This commit is contained in:
parent
e0e4ff4b64
commit
4104d7d371
184
docs/docs.go
184
docs/docs.go
|
|
@ -2085,6 +2085,49 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/chapa/balances": {
|
||||
"get": {
|
||||
"description": "Retrieve Chapa account balance, optionally filtered by currency code (e.g., ETB, USD)",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Chapa"
|
||||
],
|
||||
"summary": "Get Chapa account balance",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Currency code (optional)",
|
||||
"name": "currency_code",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.Response"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.ErrorResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.ErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/chapa/banks": {
|
||||
"get": {
|
||||
"description": "Get list of banks supported by Chapa",
|
||||
|
|
@ -2209,6 +2252,50 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/chapa/payments/receipt/{chapa_ref}": {
|
||||
"get": {
|
||||
"description": "Retrieve the Chapa payment receipt URL using the reference ID",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Chapa"
|
||||
],
|
||||
"summary": "Get Chapa Payment Receipt URL",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Chapa Reference ID",
|
||||
"name": "chapa_ref",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.Response"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.ErrorResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.ErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/chapa/payments/webhook/verify": {
|
||||
"post": {
|
||||
"description": "Handles payment notifications from Chapa",
|
||||
|
|
@ -2319,6 +2406,87 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/chapa/swap": {
|
||||
"post": {
|
||||
"description": "Perform a USD to ETB currency swap using Chapa's API",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Chapa"
|
||||
],
|
||||
"summary": "Initiate a currency swap",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Swap Request Payload",
|
||||
"name": "payload",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.SwapRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.Response"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.ErrorResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.ErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/chapa/transfers": {
|
||||
"get": {
|
||||
"description": "Retrieve all transfer records from Chapa",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Chapa"
|
||||
],
|
||||
"summary": "Get all Chapa transfers",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.Response"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.ErrorResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.ErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/company": {
|
||||
"get": {
|
||||
"description": "Gets all companies",
|
||||
|
|
@ -9837,7 +10005,7 @@ const docTemplate = `{
|
|||
"type": "string"
|
||||
},
|
||||
"round_id": {
|
||||
"type": "integer"
|
||||
"type": "string"
|
||||
},
|
||||
"session_id": {
|
||||
"type": "string"
|
||||
|
|
@ -12934,6 +13102,20 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"domain.SwapRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"amount": {
|
||||
"type": "number"
|
||||
},
|
||||
"from": {
|
||||
"type": "string"
|
||||
},
|
||||
"to": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"domain.TelebirrPaymentCallbackPayload": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
|||
|
|
@ -2077,6 +2077,49 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/chapa/balances": {
|
||||
"get": {
|
||||
"description": "Retrieve Chapa account balance, optionally filtered by currency code (e.g., ETB, USD)",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Chapa"
|
||||
],
|
||||
"summary": "Get Chapa account balance",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Currency code (optional)",
|
||||
"name": "currency_code",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.Response"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.ErrorResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.ErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/chapa/banks": {
|
||||
"get": {
|
||||
"description": "Get list of banks supported by Chapa",
|
||||
|
|
@ -2201,6 +2244,50 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/chapa/payments/receipt/{chapa_ref}": {
|
||||
"get": {
|
||||
"description": "Retrieve the Chapa payment receipt URL using the reference ID",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Chapa"
|
||||
],
|
||||
"summary": "Get Chapa Payment Receipt URL",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Chapa Reference ID",
|
||||
"name": "chapa_ref",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.Response"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.ErrorResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.ErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/chapa/payments/webhook/verify": {
|
||||
"post": {
|
||||
"description": "Handles payment notifications from Chapa",
|
||||
|
|
@ -2311,6 +2398,87 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/chapa/swap": {
|
||||
"post": {
|
||||
"description": "Perform a USD to ETB currency swap using Chapa's API",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Chapa"
|
||||
],
|
||||
"summary": "Initiate a currency swap",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Swap Request Payload",
|
||||
"name": "payload",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.SwapRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.Response"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.ErrorResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.ErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/chapa/transfers": {
|
||||
"get": {
|
||||
"description": "Retrieve all transfer records from Chapa",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Chapa"
|
||||
],
|
||||
"summary": "Get all Chapa transfers",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.Response"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.ErrorResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/domain.ErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/company": {
|
||||
"get": {
|
||||
"description": "Gets all companies",
|
||||
|
|
@ -9829,7 +9997,7 @@
|
|||
"type": "string"
|
||||
},
|
||||
"round_id": {
|
||||
"type": "integer"
|
||||
"type": "string"
|
||||
},
|
||||
"session_id": {
|
||||
"type": "string"
|
||||
|
|
@ -12926,6 +13094,20 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"domain.SwapRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"amount": {
|
||||
"type": "number"
|
||||
},
|
||||
"from": {
|
||||
"type": "string"
|
||||
},
|
||||
"to": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"domain.TelebirrPaymentCallbackPayload": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ definitions:
|
|||
player_id:
|
||||
type: string
|
||||
round_id:
|
||||
type: integer
|
||||
type: string
|
||||
session_id:
|
||||
type: string
|
||||
timestamp:
|
||||
|
|
@ -2191,6 +2191,15 @@ definitions:
|
|||
example: SportsBook
|
||||
type: string
|
||||
type: object
|
||||
domain.SwapRequest:
|
||||
properties:
|
||||
amount:
|
||||
type: number
|
||||
from:
|
||||
type: string
|
||||
to:
|
||||
type: string
|
||||
type: object
|
||||
domain.TelebirrPaymentCallbackPayload:
|
||||
properties:
|
||||
appid:
|
||||
|
|
@ -5509,6 +5518,35 @@ paths:
|
|||
summary: Update cashier
|
||||
tags:
|
||||
- cashier
|
||||
/api/v1/chapa/balances:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Retrieve Chapa account balance, optionally filtered by currency
|
||||
code (e.g., ETB, USD)
|
||||
parameters:
|
||||
- description: Currency code (optional)
|
||||
in: query
|
||||
name: currency_code
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/domain.Response'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/domain.ErrorResponse'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/domain.ErrorResponse'
|
||||
summary: Get Chapa account balance
|
||||
tags:
|
||||
- Chapa
|
||||
/api/v1/chapa/banks:
|
||||
get:
|
||||
consumes:
|
||||
|
|
@ -5589,6 +5627,35 @@ paths:
|
|||
summary: Verify a payment manually
|
||||
tags:
|
||||
- Chapa
|
||||
/api/v1/chapa/payments/receipt/{chapa_ref}:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Retrieve the Chapa payment receipt URL using the reference ID
|
||||
parameters:
|
||||
- description: Chapa Reference ID
|
||||
in: path
|
||||
name: chapa_ref
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/domain.Response'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/domain.ErrorResponse'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/domain.ErrorResponse'
|
||||
summary: Get Chapa Payment Receipt URL
|
||||
tags:
|
||||
- Chapa
|
||||
/api/v1/chapa/payments/webhook/verify:
|
||||
post:
|
||||
consumes:
|
||||
|
|
@ -5661,6 +5728,59 @@ paths:
|
|||
summary: Initiate a withdrawal
|
||||
tags:
|
||||
- Chapa
|
||||
/api/v1/chapa/swap:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Perform a USD to ETB currency swap using Chapa's API
|
||||
parameters:
|
||||
- description: Swap Request Payload
|
||||
in: body
|
||||
name: payload
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/domain.SwapRequest'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/domain.Response'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/domain.ErrorResponse'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/domain.ErrorResponse'
|
||||
summary: Initiate a currency swap
|
||||
tags:
|
||||
- Chapa
|
||||
/api/v1/chapa/transfers:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Retrieve all transfer records from Chapa
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/domain.Response'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/domain.ErrorResponse'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/domain.ErrorResponse'
|
||||
summary: Get all Chapa transfers
|
||||
tags:
|
||||
- Chapa
|
||||
/api/v1/company:
|
||||
get:
|
||||
consumes:
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ type AtlasBetResponse struct {
|
|||
type AtlasBetWinRequest struct {
|
||||
Game string `json:"game"`
|
||||
CasinoID string `json:"casino_id"`
|
||||
RoundID int64 `json:"round_id"`
|
||||
RoundID string `json:"round_id"`
|
||||
PlayerID string `json:"player_id"`
|
||||
SessionID string `json:"session_id"`
|
||||
BetAmount float64 `json:"betAmount"`
|
||||
|
|
|
|||
|
|
@ -196,3 +196,28 @@ type ChapaWebHookPayment struct {
|
|||
} `json:"customization"`
|
||||
Meta string `json:"meta"`
|
||||
}
|
||||
|
||||
type Balance struct {
|
||||
Currency string `json:"currency"`
|
||||
AvailableBalance float64 `json:"available_balance"`
|
||||
LedgerBalance float64 `json:"ledger_balance"`
|
||||
}
|
||||
|
||||
type SwapRequest struct {
|
||||
From string `json:"from"`
|
||||
To string `json:"to"`
|
||||
Amount float64 `json:"amount"`
|
||||
}
|
||||
|
||||
type SwapResponse struct {
|
||||
Status string `json:"status"`
|
||||
RefID string `json:"ref_id"`
|
||||
FromCurrency string `json:"from_currency"`
|
||||
ToCurrency string `json:"to_currency"`
|
||||
Amount float64 `json:"amount"`
|
||||
ExchangedAmount float64 `json:"exchanged_amount"`
|
||||
Charge float64 `json:"charge"`
|
||||
Rate float64 `json:"rate"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
UpdatedAt string `json:"updated_at"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,10 +16,13 @@ import (
|
|||
|
||||
type ChapaStore interface {
|
||||
InitializePayment(request domain.ChapaDepositRequest) (domain.ChapaDepositResponse, error)
|
||||
// VerifyPayment(reference string) (domain.ChapaDepositVerification, error)
|
||||
ManualVerifTransaction(ctx context.Context, txRef string) (*domain.ChapaVerificationResponse, error)
|
||||
FetchSupportedBanks(ctx context.Context) ([]domain.Bank, error)
|
||||
CreateWithdrawal(userID string, amount float64, accountNumber, bankCode string) (*domain.ChapaWithdrawal, error)
|
||||
HandleVerifyDepositWebhook(ctx context.Context, transfer domain.ChapaWebHookTransfer) error
|
||||
HandleVerifyWithdrawWebhook(ctx context.Context, payment domain.ChapaWebHookPayment) error
|
||||
GetPaymentReceiptURL(ctx context.Context, chapaRef string) (string, error)
|
||||
GetAllTransfers(ctx context.Context) ([]domain.Transfer, error)
|
||||
GetAccountBalance(ctx context.Context, currencyCode string) ([]domain.Balance, error)
|
||||
InitiateSwap(ctx context.Context, amount float64, from, to string) (*domain.SwapResponse, error)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,13 @@
|
|||
package chapa
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
|
|
@ -63,7 +67,7 @@ func (s *Service) InitiateDeposit(ctx context.Context, userID int64, amount doma
|
|||
return "", fmt.Errorf("failed to get sender wallets: %w", err)
|
||||
}
|
||||
for _, wallet := range senderWallets {
|
||||
if wallet.IsWithdraw {
|
||||
if wallet.IsTransferable {
|
||||
senderWallet = wallet
|
||||
break
|
||||
}
|
||||
|
|
@ -364,3 +368,138 @@ func (s *Service) HandleVerifyWithdrawWebhook(ctx context.Context, payment domai
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) GetPaymentReceiptURL(ctx context.Context, chapaRef string) (string, error) {
|
||||
if chapaRef == "" {
|
||||
return "", fmt.Errorf("chapa reference ID is required")
|
||||
}
|
||||
|
||||
receiptURL := fmt.Sprintf("https://chapa.link/payment-receipt/%s", chapaRef)
|
||||
return receiptURL, nil
|
||||
}
|
||||
|
||||
func (s *Service) GetAllTransfers(ctx context.Context) ([]domain.Transfer, error) {
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, "https://api.chapa.co/v1/transfers", nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create request: %w", err)
|
||||
}
|
||||
|
||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", s.cfg.CHAPA_SECRET_KEY))
|
||||
|
||||
resp, err := s.chapaClient.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to fetch transfers: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
bodyBytes, _ := io.ReadAll(resp.Body)
|
||||
return nil, fmt.Errorf("unexpected status %d: %s", resp.StatusCode, string(bodyBytes))
|
||||
}
|
||||
|
||||
var result struct {
|
||||
Status string `json:"status"`
|
||||
Message string `json:"message"`
|
||||
Data []domain.Transfer `json:"data"`
|
||||
}
|
||||
|
||||
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode response: %w", err)
|
||||
}
|
||||
|
||||
return result.Data, nil
|
||||
}
|
||||
|
||||
func (s *Service) GetAccountBalance(ctx context.Context, currencyCode string) ([]domain.Balance, error) {
|
||||
baseURL := "https://api.chapa.co/v1/balances"
|
||||
if currencyCode != "" {
|
||||
baseURL = fmt.Sprintf("%s/%s", baseURL, strings.ToLower(currencyCode))
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, baseURL, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create balance request: %w", err)
|
||||
}
|
||||
|
||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", s.cfg.CHAPA_SECRET_KEY))
|
||||
|
||||
resp, err := s.chapaClient.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to execute balance request: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
bodyBytes, _ := io.ReadAll(resp.Body)
|
||||
return nil, fmt.Errorf("unexpected status %d: %s", resp.StatusCode, string(bodyBytes))
|
||||
}
|
||||
|
||||
var result struct {
|
||||
Status string `json:"status"`
|
||||
Message string `json:"message"`
|
||||
Data []domain.Balance `json:"data"`
|
||||
}
|
||||
|
||||
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode balance response: %w", err)
|
||||
}
|
||||
|
||||
return result.Data, nil
|
||||
}
|
||||
|
||||
func (s *Service) InitiateSwap(ctx context.Context, amount float64, from, to string) (*domain.SwapResponse, error) {
|
||||
if amount < 1 {
|
||||
return nil, fmt.Errorf("amount must be at least 1 USD")
|
||||
}
|
||||
if strings.ToUpper(from) != "USD" || strings.ToUpper(to) != "ETB" {
|
||||
return nil, fmt.Errorf("only USD to ETB swap is supported")
|
||||
}
|
||||
|
||||
payload := domain.SwapRequest{
|
||||
Amount: amount,
|
||||
From: strings.ToUpper(from),
|
||||
To: strings.ToUpper(to),
|
||||
}
|
||||
|
||||
// payload := map[string]any{
|
||||
// "amount": amount,
|
||||
// "from": strings.ToUpper(from),
|
||||
// "to": strings.ToUpper(to),
|
||||
// }
|
||||
|
||||
body, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to encode swap payload: %w", err)
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, "https://api.chapa.co/v1/swap", bytes.NewBuffer(body))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create swap request: %w", err)
|
||||
}
|
||||
|
||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", s.cfg.CHAPA_SECRET_KEY))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
resp, err := s.chapaClient.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to execute swap request: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated {
|
||||
bodyBytes, _ := io.ReadAll(resp.Body)
|
||||
return nil, fmt.Errorf("unexpected status %d: %s", resp.StatusCode, string(bodyBytes))
|
||||
}
|
||||
|
||||
var result struct {
|
||||
Message string `json:"message"`
|
||||
Status string `json:"status"`
|
||||
Data domain.SwapResponse `json:"data"`
|
||||
}
|
||||
|
||||
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode swap response: %w", err)
|
||||
}
|
||||
|
||||
return &result.Data, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -657,10 +657,6 @@ func (s *service) verifySignature(callback *domain.PopOKCallback) bool {
|
|||
return expected == callback.Signature
|
||||
}
|
||||
|
||||
// func (s *service) GetGameCounts(ctx context.Context, filter domain.ReportFilter) (total, active, inactive int64, err error) {
|
||||
// return s.repo.GetGameCounts(ctx, filter)
|
||||
// }
|
||||
|
||||
func (s *service) ListGames(ctx context.Context, currency string) ([]domain.PopOKGame, error) {
|
||||
now := time.Now().Format("02-01-2006 15:04:05") // dd-mm-yyyy hh:mm:ss
|
||||
|
||||
|
|
|
|||
|
|
@ -263,3 +263,132 @@ func (h *Handler) InitiateWithdrawal(c *fiber.Ctx) error {
|
|||
Data: withdrawal,
|
||||
})
|
||||
}
|
||||
|
||||
// GetPaymentReceipt godoc
|
||||
// @Summary Get Chapa Payment Receipt URL
|
||||
// @Description Retrieve the Chapa payment receipt URL using the reference ID
|
||||
// @Tags Chapa
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param chapa_ref path string true "Chapa Reference ID"
|
||||
// @Success 200 {object} domain.Response
|
||||
// @Failure 400 {object} domain.ErrorResponse
|
||||
// @Failure 500 {object} domain.ErrorResponse
|
||||
// @Router /api/v1/chapa/payments/receipt/{chapa_ref} [get]
|
||||
func (h *Handler) GetPaymentReceipt(c *fiber.Ctx) error {
|
||||
chapaRef := c.Params("chapa_ref")
|
||||
if chapaRef == "" {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
||||
Message: "Failed to get Chapa payment receipt",
|
||||
Error: "Chapa reference ID is required",
|
||||
})
|
||||
}
|
||||
|
||||
receiptURL, err := h.chapaSvc.GetPaymentReceiptURL(c.Context(), chapaRef)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
||||
Message: "Failed to get Chapa payment receipt",
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(domain.Response{
|
||||
Message: "Payment receipt URL generated successfully",
|
||||
Data: receiptURL,
|
||||
StatusCode: 200,
|
||||
Success: true,
|
||||
})
|
||||
}
|
||||
|
||||
// GetAllTransfers godoc
|
||||
// @Summary Get all Chapa transfers
|
||||
// @Description Retrieve all transfer records from Chapa
|
||||
// @Tags Chapa
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} domain.Response
|
||||
// @Failure 400 {object} domain.ErrorResponse
|
||||
// @Failure 500 {object} domain.ErrorResponse
|
||||
// @Router /api/v1/chapa/transfers [get]
|
||||
func (h *Handler) GetAllTransfers(c *fiber.Ctx) error {
|
||||
transfers, err := h.chapaSvc.GetAllTransfers(c.Context())
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
||||
Message: "Failed to fetch Chapa transfers",
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(domain.Response{
|
||||
Message: "Chapa transfers retrieved successfully",
|
||||
Data: transfers,
|
||||
StatusCode: fiber.StatusOK,
|
||||
Success: true,
|
||||
})
|
||||
}
|
||||
|
||||
// GetAccountBalance godoc
|
||||
// @Summary Get Chapa account balance
|
||||
// @Description Retrieve Chapa account balance, optionally filtered by currency code (e.g., ETB, USD)
|
||||
// @Tags Chapa
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param currency_code query string false "Currency code (optional)"
|
||||
// @Success 200 {object} domain.Response
|
||||
// @Failure 400 {object} domain.ErrorResponse
|
||||
// @Failure 500 {object} domain.ErrorResponse
|
||||
// @Router /api/v1/chapa/balances [get]
|
||||
func (h *Handler) GetAccountBalance(c *fiber.Ctx) error {
|
||||
currencyCode := c.Query("currency_code", "")
|
||||
|
||||
balances, err := h.chapaSvc.GetAccountBalance(c.Context(), currencyCode)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
||||
Message: "Failed to fetch Chapa account balance",
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(domain.Response{
|
||||
Message: "Chapa account balance retrieved successfully",
|
||||
Data: balances,
|
||||
StatusCode: fiber.StatusOK,
|
||||
Success: true,
|
||||
})
|
||||
}
|
||||
|
||||
// InitiateSwap godoc
|
||||
// @Summary Initiate a currency swap
|
||||
// @Description Perform a USD to ETB currency swap using Chapa's API
|
||||
// @Tags Chapa
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param payload body domain.SwapRequest true "Swap Request Payload"
|
||||
// @Success 200 {object} domain.Response
|
||||
// @Failure 400 {object} domain.ErrorResponse
|
||||
// @Failure 500 {object} domain.ErrorResponse
|
||||
// @Router /api/v1/chapa/swap [post]
|
||||
func (h *Handler) InitiateSwap(c *fiber.Ctx) error {
|
||||
var req domain.SwapRequest
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
||||
Message: "Invalid request payload",
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
swapResult, err := h.chapaSvc.InitiateSwap(c.Context(), req.Amount, req.From, req.To)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
||||
Message: "Failed to initiate currency swap",
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(domain.Response{
|
||||
Message: "Currency swap initiated successfully",
|
||||
Data: swapResult,
|
||||
StatusCode: fiber.StatusOK,
|
||||
Success: true,
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -383,6 +383,10 @@ func (a *App) initAppRoutes() {
|
|||
groupV1.Post("/chapa/payments/deposit", a.authMiddleware, h.InitiateDeposit)
|
||||
groupV1.Post("/chapa/payments/withdraw", a.authMiddleware, h.InitiateWithdrawal)
|
||||
groupV1.Get("/chapa/banks", h.GetSupportedBanks)
|
||||
groupV1.Get("/chapa/payments/receipt/:chapa_ref", h.GetPaymentReceipt)
|
||||
groupV1.Get("/chapa/transfers", h.GetAllTransfers)
|
||||
groupV1.Get("/chapa/balance", h.GetAccountBalance)
|
||||
groupV1.Post("/chapa/init-swap", h.InitiateSwap)
|
||||
|
||||
// Currencies
|
||||
groupV1.Get("/currencies", h.GetSupportedCurrencies)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user