Skip to content

Commit

Permalink
Add payment api
Browse files Browse the repository at this point in the history
  • Loading branch information
AchoArnold committed May 1, 2022
1 parent 5ff1e95 commit d425498
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 7 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import "github.com/NdoleStudio/flutterwave-go"

## Implemented

- [BILLS](#bills)
- [Status Codes](#bills)
- `POST /bills/`: Create a bill payment
- `GET /bill-items/{item_code}/validate`: Validate services like DSTV smartcard number, Meter number etc.
- `GET /bills/{reference}`: Get the verbose status of a bill payment
Expand Down
2 changes: 1 addition & 1 deletion bills_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func (service *billsService) CreatePayment(ctx context.Context, payload *BillsCr
return &data, response, nil
}

// Validate validates services like DSTV smartcard number, Meter number etc.
// Validate validates services like DStv smartcard number, Meter number etc.
//
// API Docs: https://developer.flutterwave.com/reference/validate-bill-service
func (service *billsService) Validate(ctx context.Context, itemCode string, billerCode string, customer string) (*BillsValidateResponse, *Response, error) {
Expand Down
4 changes: 2 additions & 2 deletions bills_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ func TestBillsService_CreatePayment(t *testing.T) {
Customer: "7034504232",
Amount: 100,
Recurrence: "ONCE",
Type: "DSTV",
Type: "DStv",
Reference: uuid.New().String(),
BillerName: "DSTV",
BillerName: "DStv",
})

// Assert
Expand Down
8 changes: 5 additions & 3 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,19 @@ type service struct {
client *Client
}

// Client is the campay API client.
// Client is the flutterwave API client.
// Do not instantiate this client with Client{}. Use the New method instead.
type Client struct {
httpClient *http.Client
common service
secretKey string
baseURL string

Bills *billsService
Bills *billsService
Payment *paymentsService
}

// New creates and returns a new campay.Client from a slice of campay.ClientOption.
// New creates and returns a new flutterwave.Client from a slice of flutterwave.ClientOption.
func New(options ...ClientOption) *Client {
config := defaultClientConfig()

Expand All @@ -41,6 +42,7 @@ func New(options ...ClientOption) *Client {

client.common.client = client
client.Bills = (*billsService)(&client.common)
client.Payment = (*paymentsService)(&client.common)
return client
}

Expand Down
34 changes: 34 additions & 0 deletions payments.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package flutterwave

// GetPaymentLinkRequest is data needed to create a payment link
type GetPaymentLinkRequest struct {
TransactionReference string `json:"tx_ref"`
Amount string `json:"amount"`
Currency string `json:"currency"`
Meta map[string]interface{} `json:"meta"`
RedirectURL string `json:"redirect_url"`
Customer GetPaymentLinkCustomer `json:"customer"`
Customizations GetPaymentLinkCustomizations `json:"customizations"`
}

// GetPaymentLinkCustomer contains the customer details.
type GetPaymentLinkCustomer struct {
Email string `json:"email"`
Name string `json:"name"`
PhoneNumber string `json:"phonenumber"`
}

// GetPaymentLinkCustomizations contains options to customize the look of the payment modal.
type GetPaymentLinkCustomizations struct {
Title string `json:"title"`
Logo string `json:"logo"`
}

// GetPaymentLinkResponse is the data returned after creating a payment link
type GetPaymentLinkResponse struct {
Status string `json:"status"`
Message string `json:"message"`
Data struct {
Link string `json:"link"`
} `json:"data"`
}
32 changes: 32 additions & 0 deletions payments_service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package flutterwave

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

// paymentsService is the API client for the `/gateway` endpoint
type paymentsService service

// GetPaymentLink Call flutterwave to get a payment link, redirect your customer to the link, and flutterwave will redirect back when payment is done.
//
// API Docs: https://developer.flutterwave.com/docs/collecting-payments/standard
func (service *paymentsService) GetPaymentLink(ctx context.Context, payload *GetPaymentLinkRequest) (*GetPaymentLinkResponse, *Response, error) {
request, err := service.client.newRequest(ctx, http.MethodPost, "/v3/payments", payload)
if err != nil {
return nil, nil, err
}

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

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

return &data, response, nil
}
67 changes: 67 additions & 0 deletions webhook.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package flutterwave

import "time"

const (
// HeaderNameVerifHash is the name of the header used to verify your webhook requests.
HeaderNameVerifHash = "verif-hash"
)

const (
eventChargeCompleted = "charge.completed"
)

const (
statusSuccessful = "successful"
statusFailed = "failed"
)

// PaymentEventV3 is the payload for webhook requests after a payment
type PaymentEventV3 struct {
Event string `json:"event"`
Data struct {
ID int64 `json:"id"`
TxRef string `json:"tx_ref"`
FlwRef string `json:"flw_ref"`
DeviceFingerprint string `json:"device_fingerprint"`
Amount int `json:"amount"`
Currency string `json:"currency"`
ChargedAmount int `json:"charged_amount"`
AppFee float64 `json:"app_fee"`
MerchantFee int `json:"merchant_fee"`
ProcessorResponse string `json:"processor_response"`
AuthModel string `json:"auth_model"`
IP string `json:"ip"`
Narration string `json:"narration"`
Status string `json:"status"`
PaymentType string `json:"payment_type"`
CreatedAt time.Time `json:"created_at"`
AccountID int `json:"account_id"`
Customer struct {
ID int `json:"id"`
Name string `json:"name"`
PhoneNumber interface{} `json:"phone_number"`
Email string `json:"email"`
CreatedAt time.Time `json:"created_at"`
} `json:"customer"`
Card struct {
First6Digits string `json:"first_6digits"`
Last4Digits string `json:"last_4digits"`
Issuer string `json:"issuer"`
Country string `json:"country"`
Type string `json:"type"`
Expiry string `json:"expiry"`
} `json:"card"`
} `json:"data"`
EventType string `json:"event.type"`
}

// IsSuccessful checks if the payment event is successfull
func (event PaymentEventV3) IsSuccessful() bool {
return event.Event == eventChargeCompleted && event.Data.Status == statusSuccessful
}

// IsFailed checks if the payment failed
func (event PaymentEventV3) IsFailed() bool {
return event.Event == eventChargeCompleted && event.Data.Status == statusFailed
}

0 comments on commit d425498

Please sign in to comment.