Skip to content

Commit d425498

Browse files
committed
Add payment api
1 parent 5ff1e95 commit d425498

7 files changed

+142
-7
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import "github.com/NdoleStudio/flutterwave-go"
2727

2828
## Implemented
2929

30-
- [BILLS](#bills)
30+
- [Status Codes](#bills)
3131
- `POST /bills/`: Create a bill payment
3232
- `GET /bill-items/{item_code}/validate`: Validate services like DSTV smartcard number, Meter number etc.
3333
- `GET /bills/{reference}`: Get the verbose status of a bill payment

bills_service.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ func (service *billsService) CreatePayment(ctx context.Context, payload *BillsCr
3131
return &data, response, nil
3232
}
3333

34-
// Validate validates services like DSTV smartcard number, Meter number etc.
34+
// Validate validates services like DStv smartcard number, Meter number etc.
3535
//
3636
// API Docs: https://developer.flutterwave.com/reference/validate-bill-service
3737
func (service *billsService) Validate(ctx context.Context, itemCode string, billerCode string, customer string) (*BillsValidateResponse, *Response, error) {

bills_service_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ func TestBillsService_CreatePayment(t *testing.T) {
2727
Customer: "7034504232",
2828
Amount: 100,
2929
Recurrence: "ONCE",
30-
Type: "DSTV",
30+
Type: "DStv",
3131
Reference: uuid.New().String(),
32-
BillerName: "DSTV",
32+
BillerName: "DStv",
3333
})
3434

3535
// Assert

client.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,19 @@ type service struct {
1414
client *Client
1515
}
1616

17-
// Client is the campay API client.
17+
// Client is the flutterwave API client.
1818
// Do not instantiate this client with Client{}. Use the New method instead.
1919
type Client struct {
2020
httpClient *http.Client
2121
common service
2222
secretKey string
2323
baseURL string
2424

25-
Bills *billsService
25+
Bills *billsService
26+
Payment *paymentsService
2627
}
2728

28-
// New creates and returns a new campay.Client from a slice of campay.ClientOption.
29+
// New creates and returns a new flutterwave.Client from a slice of flutterwave.ClientOption.
2930
func New(options ...ClientOption) *Client {
3031
config := defaultClientConfig()
3132

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

4243
client.common.client = client
4344
client.Bills = (*billsService)(&client.common)
45+
client.Payment = (*paymentsService)(&client.common)
4446
return client
4547
}
4648

payments.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package flutterwave
2+
3+
// GetPaymentLinkRequest is data needed to create a payment link
4+
type GetPaymentLinkRequest struct {
5+
TransactionReference string `json:"tx_ref"`
6+
Amount string `json:"amount"`
7+
Currency string `json:"currency"`
8+
Meta map[string]interface{} `json:"meta"`
9+
RedirectURL string `json:"redirect_url"`
10+
Customer GetPaymentLinkCustomer `json:"customer"`
11+
Customizations GetPaymentLinkCustomizations `json:"customizations"`
12+
}
13+
14+
// GetPaymentLinkCustomer contains the customer details.
15+
type GetPaymentLinkCustomer struct {
16+
Email string `json:"email"`
17+
Name string `json:"name"`
18+
PhoneNumber string `json:"phonenumber"`
19+
}
20+
21+
// GetPaymentLinkCustomizations contains options to customize the look of the payment modal.
22+
type GetPaymentLinkCustomizations struct {
23+
Title string `json:"title"`
24+
Logo string `json:"logo"`
25+
}
26+
27+
// GetPaymentLinkResponse is the data returned after creating a payment link
28+
type GetPaymentLinkResponse struct {
29+
Status string `json:"status"`
30+
Message string `json:"message"`
31+
Data struct {
32+
Link string `json:"link"`
33+
} `json:"data"`
34+
}

payments_service.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package flutterwave
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"net/http"
7+
)
8+
9+
// paymentsService is the API client for the `/gateway` endpoint
10+
type paymentsService service
11+
12+
// GetPaymentLink Call flutterwave to get a payment link, redirect your customer to the link, and flutterwave will redirect back when payment is done.
13+
//
14+
// API Docs: https://developer.flutterwave.com/docs/collecting-payments/standard
15+
func (service *paymentsService) GetPaymentLink(ctx context.Context, payload *GetPaymentLinkRequest) (*GetPaymentLinkResponse, *Response, error) {
16+
request, err := service.client.newRequest(ctx, http.MethodPost, "/v3/payments", payload)
17+
if err != nil {
18+
return nil, nil, err
19+
}
20+
21+
response, err := service.client.do(request)
22+
if err != nil {
23+
return nil, response, err
24+
}
25+
26+
var data GetPaymentLinkResponse
27+
if err = json.Unmarshal(*response.Body, &data); err != nil {
28+
return nil, response, err
29+
}
30+
31+
return &data, response, nil
32+
}

webhook.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package flutterwave
2+
3+
import "time"
4+
5+
const (
6+
// HeaderNameVerifHash is the name of the header used to verify your webhook requests.
7+
HeaderNameVerifHash = "verif-hash"
8+
)
9+
10+
const (
11+
eventChargeCompleted = "charge.completed"
12+
)
13+
14+
const (
15+
statusSuccessful = "successful"
16+
statusFailed = "failed"
17+
)
18+
19+
// PaymentEventV3 is the payload for webhook requests after a payment
20+
type PaymentEventV3 struct {
21+
Event string `json:"event"`
22+
Data struct {
23+
ID int64 `json:"id"`
24+
TxRef string `json:"tx_ref"`
25+
FlwRef string `json:"flw_ref"`
26+
DeviceFingerprint string `json:"device_fingerprint"`
27+
Amount int `json:"amount"`
28+
Currency string `json:"currency"`
29+
ChargedAmount int `json:"charged_amount"`
30+
AppFee float64 `json:"app_fee"`
31+
MerchantFee int `json:"merchant_fee"`
32+
ProcessorResponse string `json:"processor_response"`
33+
AuthModel string `json:"auth_model"`
34+
IP string `json:"ip"`
35+
Narration string `json:"narration"`
36+
Status string `json:"status"`
37+
PaymentType string `json:"payment_type"`
38+
CreatedAt time.Time `json:"created_at"`
39+
AccountID int `json:"account_id"`
40+
Customer struct {
41+
ID int `json:"id"`
42+
Name string `json:"name"`
43+
PhoneNumber interface{} `json:"phone_number"`
44+
Email string `json:"email"`
45+
CreatedAt time.Time `json:"created_at"`
46+
} `json:"customer"`
47+
Card struct {
48+
First6Digits string `json:"first_6digits"`
49+
Last4Digits string `json:"last_4digits"`
50+
Issuer string `json:"issuer"`
51+
Country string `json:"country"`
52+
Type string `json:"type"`
53+
Expiry string `json:"expiry"`
54+
} `json:"card"`
55+
} `json:"data"`
56+
EventType string `json:"event.type"`
57+
}
58+
59+
// IsSuccessful checks if the payment event is successfull
60+
func (event PaymentEventV3) IsSuccessful() bool {
61+
return event.Event == eventChargeCompleted && event.Data.Status == statusSuccessful
62+
}
63+
64+
// IsFailed checks if the payment failed
65+
func (event PaymentEventV3) IsFailed() bool {
66+
return event.Event == eventChargeCompleted && event.Data.Status == statusFailed
67+
}

0 commit comments

Comments
 (0)