Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented Transfers service #1

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ import "github.com/NdoleStudio/flutterwave-go"
- **Payments**
- `GET /v3/transactions/:id/verify`: Verify a transaction
- `POST /v3/transactions/:id/refund`: Create a Refund
- **Transfers**
- `GET /v3/transfers/rates`: Get the transfer rate of a transaction

## Usage

Expand Down
2 changes: 2 additions & 0 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type Client struct {
Bills *billsService
Payments *paymentsService
Transactions *transactionsService
Transfers *transfersService
}

// New creates and returns a new flutterwave.Client from a slice of flutterwave.ClientOption.
Expand All @@ -44,6 +45,7 @@ func New(options ...ClientOption) *Client {
client.Bills = (*billsService)(&client.common)
client.Payments = (*paymentsService)(&client.common)
client.Transactions = (*transactionsService)(&client.common)
client.Transfers = (*transfersService)(&client.common)
I-Frostbyte marked this conversation as resolved.
Show resolved Hide resolved
return client
}

Expand Down
21 changes: 21 additions & 0 deletions internal/stubs/api_responses.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,24 @@ func TransactionRefundResponse() []byte {
}
`)
}

// TransferRatesResponse is a dummy response for fetching the tranfer rate of a given transaction.
func TransferRateResponse() []byte {
return []byte(`
{
"status": "success",
"message": "Transfer amount fetched",
"data": {
"rate": 624.24,
"source": {
"currency": "NGN",
"amount": 624240
},
"destination": {
"currency": "USD",
"amount": 1000
}
}
}
`)
}
18 changes: 18 additions & 0 deletions transfers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package flutterwave

// ExchangeRateResponse is data returned when querying a transaction.
type TransferRateResponse struct {
Status string `json:"status"`
Message string `json:"message"`
Data struct {
Rate float64 `json:"rate"`
Source Payment `json:"source"`
Destination Payment `json:"destination"`
}
}

// Payment is data returned for either the source or the destination.
type Payment struct {
I-Frostbyte marked this conversation as resolved.
Show resolved Hide resolved
Currency string `json:"currency"`
Amount int `json:"amount"`
}
43 changes: 43 additions & 0 deletions transfers_service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package flutterwave

import (
"context"
"encoding/json"
"net/http"
"strconv"
)

// transfersService is the API client for the `/v3/transfers` endpoint
type transfersService service

// Estimate the Transfer Rate of a transaction
//
// API Docs: https://developer.flutterwave.com/reference/check-transfer-rates
func (service *transfersService) Rate(ctx context.Context, amount int, destination_currency, source_currency string) (*TransferRateResponse, *Response, error) {
uri := "/v3/transfers/rates"

request, err := service.client.newRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, nil, err
}

// Adding the parameters
requestWithParams := service.client.addURLParams(request, map[string]string{
"amount": strconv.Itoa(amount),
"destination_currency": destination_currency,
"source_currency": source_currency,
})

response, err := service.client.do(requestWithParams)
if err != nil {
return nil, response, err
}

var data TransferRateResponse
if err = json.Unmarshal(*response.Body, &data); err != nil {
return nil, response, err
}

return &data, response, nil

}
53 changes: 53 additions & 0 deletions transfers_service_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package flutterwave

import (
"context"
"github.com/NdoleStudio/flutterwave-go/internal/helpers"
"github.com/NdoleStudio/flutterwave-go/internal/stubs"
"github.com/stretchr/testify/assert"
"net/http"
"testing"
)

func TestTransfersService_Rate(t *testing.T) {
// Setup
t.Parallel()

// Arrange
server := helpers.MakeTestServer(http.StatusOK, string(stubs.TransferRateResponse()))
client := New(WithBaseURL(server.URL))

// Act
rate, response, err := client.Transfers.Rate(context.Background(), 1000, "USD", "NGN")

// Assert
assert.Nil(t, err)

assert.Equal(t, http.StatusOK, response.HTTPResponse.StatusCode)
assert.Equal(t, stubs.TransferRateResponse(), *response.Body)
assert.Equal(t, 624240, rate.Data.Source.Amount)

I-Frostbyte marked this conversation as resolved.
Show resolved Hide resolved
// Teardown
server.Close()
}

func TestTransfersService_Rate_Failure(t *testing.T) {
// Setup
t.Parallel()

// Arrange
server := helpers.MakeTestServer(http.StatusInternalServerError, `{"error": "internal server error"}`)
client := New(WithBaseURL(server.URL))

// Act
rate, response, err := client.Transfers.Rate(context.Background(), 1000, "USD", "NGN")

// Assert
assert.NotNil(t, err) // Expect an error
assert.Nil(t, rate) // The rate should be nil due to failure
assert.Equal(t, http.StatusInternalServerError, response.HTTPResponse.StatusCode)
assert.Contains(t, err.Error(), "500") // Ensure error message contains 500

// Teardown
server.Close()
}