Skip to content

Commit cb1efc7

Browse files
committed
Refactorings and minor UI changes
1 parent 2537a51 commit cb1efc7

File tree

14 files changed

+376
-231
lines changed

14 files changed

+376
-231
lines changed

README.md

Lines changed: 206 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,210 @@
1-
# flutter_paystack
1+
# Paystack Plugin for Flutter
22

3-
A Flutter plugin for Paystack Payment Gateway.
3+
[![pub package](https://img.shields.io/pub/v/flutter_paystack.svg)](https://pub.dartlang.org/packages/flutter_paystack)
44

5-
## Getting Started
5+
A Flutter plugin for making payments via Paystack Payment Gateway. Completely supports Android and iOS.
66

7-
For help getting started with Flutter, view our online
8-
[documentation](https://flutter.io/).
7+
## Installation
8+
To use this plugin, add `flutter_paystack` as a [dependency in your pubspec.yaml file](https://flutter.io/platform-plugins/).
9+
10+
Then initialize the plugin preferably in the `initState` of your widget.
11+
12+
``` dart
13+
import 'package:flutter_paystack/paystack_plugin.dart'
14+
15+
class PaymentPage extends StatefulWidget {
16+
@override
17+
State<StatefulWidget> createState() => new _PaymentPageState();
18+
}
19+
20+
class _PaymentPageState extends State<PaymentPage> {
21+
var paystackPublicKey = '[YOUR_PAYSTACK_PUBLIC_KEY]';
22+
23+
@override
24+
void initState() {
25+
PaystackPlugin.initialize(publicKey: paystackPublicKey);
26+
super.initState();
27+
}
28+
29+
@override
30+
Widget build(BuildContext context) {
31+
// Return your widgets
32+
}
33+
}
34+
```
35+
36+
No other configuration required - the plugin should work out of the box.
37+
38+
## Making Payments
39+
40+
You can choose to initialize the payment locally or via Paystack's backend.
41+
42+
### 1. Initialize Via Paystack (Recommended)
43+
1.a. This starts by making a HTTP POST request to `https://api.paystack.co/transaction/initialize`
44+
with the amount(in kobo), reference, etc in the request body and your paystack secret key in request header.
45+
The request looks like this:
46+
47+
``` dart
48+
// Required imports
49+
import 'dart:async';
50+
import 'dart:convert';
51+
import 'package:http/http.dart' as http;
52+
53+
initTransaction() async {
54+
var url = 'https://api.paystack.co/transaction/initialize';
55+
56+
Map<String, String> headers = {
57+
'Authorization': 'Bearer $[YOUR_PAYSTACK_SECRET_KEY]',
58+
'Content-Type': 'application/json'
59+
};
60+
61+
Map<String, String> body = {
62+
'reference': '[YOUR_GENERATED_REFERENCE]',
63+
'amount': 500000.toString(),
64+
'email': 'user@email.com'
65+
};
66+
67+
http.Response response =
68+
await http.post(url, body: body, headers: headers);
69+
// Charge card
70+
_chargeCard(response.body);
71+
}
72+
```
73+
Please check the [official documentation](https://developers.paystack.co/reference#initialize-a-transaction) for the full details of payment initialization.
74+
75+
1.b If everything goes well, the initialization request returns a response with an `access_code`.
76+
You can then create a `Charge` object with the access code and card details. The `charge` is in turn passed to the ` PaystackPlugin.chargeCard()` function for payment:
77+
78+
```dart
79+
PaymentCard _getCardFromUI() {
80+
// Using just the must-required parameters.
81+
return PaymentCard(
82+
number: cardNumber,
83+
cvc: cvv,
84+
expiryMonth: expiryMonth,
85+
expiryYear: expiryYear,
86+
);
87+
88+
// Using Cascade notation (similar to Java's builder pattern)
89+
// return PaymentCard(
90+
// number: cardNumber,
91+
// cvc: cvv,
92+
// expiryMonth: expiryMonth,
93+
// expiryYear: expiryYear)
94+
// ..name = 'Segun Chukwuma Adamu'
95+
// ..country = 'Nigeria'
96+
// ..addressLine1 = 'Ikeja, Lagos'
97+
// ..addressPostalCode = '100001';
98+
99+
// Using optional parameters
100+
// return PaymentCard(
101+
// number: cardNumber,
102+
// cvc: cvv,
103+
// expiryMonth: expiryMonth,
104+
// expiryYear: expiryYear,
105+
// name: 'Ismail Adebola Emeka',
106+
// addressCountry: 'Nigeria',
107+
// addressLine1: '90, Nnebisi Road, Asaba, Deleta State');
108+
}
109+
110+
_chargeCard(http.Response response) {
111+
Map<String, dynamic> responseBody = json.decode(response.body);
112+
var charge = Charge()
113+
..accessCode = responseBody['access_code']
114+
..card = _getCardFromUI();
115+
116+
PaystackPlugin.chargeCard(context,
117+
charge: charge,
118+
beforeValidate: (transaction) => handleBeforeValidate(transaction),
119+
onSuccess: (transaction) => handleOnSuccess(transaction),
120+
onError: (error, transaction) => handleOnError(error, transaction));
121+
}
122+
123+
handleBeforeValidate(Transaction transaction) {
124+
// This is called only before requesting OTP
125+
// Save reference so you may send to server if error occurs with OTP
126+
}
127+
128+
handleOnError(Object e, Transaction transaction) {
129+
// If an access code has expired, simply ask your server for a new one
130+
// and restart the charge instead of displaying error
131+
}
132+
133+
134+
handleOnSuccess(Transaction transaction) {
135+
// This is called only after transaction is successful
136+
}
137+
```
138+
139+
140+
141+
### 2. Initialize Locally
142+
Just send the payment details to `PaystackPlugin.chargeCard`
143+
```dart
144+
// Set transaction params directly in app (note that these params
145+
// are only used if an access_code is not set. In debug mode,
146+
// setting them after setting an access code would throw an error
147+
Charge charge = Charge();
148+
charge.card = _getCardFromUI();
149+
charge
150+
..amount = 2000
151+
..email = 'user@email.com'
152+
..reference = _getReference()
153+
..putCustomField('Charged From', 'Flutter PLUGIN');
154+
_chargeCard();
155+
```
156+
157+
158+
## Validating Card Details
159+
You are expected to build the UI for your users to enter their payment details.
160+
For easier validation, wrap the **TextFormField**s inside a **Form** widget. Please check this article on
161+
[validating forms on Flutter](https://medium.freecodecamp.org/how-to-validate-forms-and-user-input-the-easy-way-using-flutter-e301a1531165)
162+
if this is new to you.
163+
164+
You can validate the fields with these methods:
165+
#### card.validNumber
166+
This method helps to perform a check if the card number is valid.
167+
168+
#### card.validCVC
169+
Method that checks if the card security code is valid.
170+
171+
#### card.validExpiryDate
172+
Method checks if the expiry date (combination of year and month) is valid.
173+
174+
#### card.isValid
175+
Method to check if the card is valid. Always do this check, before charging the card.
176+
177+
178+
#### card.getType
179+
This method returns an estimate of the string representation of the card type(issuer).
180+
181+
182+
## chargeCard
183+
Charging with the **PaystackPlugin** is quite straightforward. It requires the following arguments.
184+
1. `context`: your UI **BuildContext**. It's used by the plugin for showing dialogs for the user to take a required action, e.g inputting OTP.
185+
2. `charge`: You provide the payment details (`PaymentCard`, `amount` `email` etc) to an instance of the `Charge` object.
186+
3. `beforeValidate`: Pre-validation callback.
187+
4. `onSuccess`: callbacks for a successful payment.
188+
4. `onError`: callback for when an error occurs in the transaction. Provides you with a reference to the error object.
189+
190+
191+
## Verifying Transactions
192+
This is quite easy. Just send a HTTP GET request to `https://api.paystack.co/transaction/verify/$[TRANSACTION_REFERENCE]`.
193+
Please, check the [official documentaion](https://developers.paystack.co/reference#verifying-transactions) on verifying transactions.
194+
195+
## Testing your implementation
196+
Paystack provides tons of [payment cards](https://developers.paystack.co/docs/test-cards) for testing.
197+
198+
## Running Example project
199+
For help getting started with Flutter, view the online [documentation](https://flutter.io/).
200+
201+
An [example project](https://github.com/wilburt/flutter_paystack/tree/master/example) has been provided in this plugin.
202+
Clone this repo and navigate to the **example** folder. Open it with a supported IDE or execute `flutter run` from that folder in terminal.
203+
204+
## Contributing, Issues and Bug Reports
205+
The project is open to public contribution. Please feel very free to contribute.
206+
Experienced an issue or want to report a bug? Please, [report it here](https://github.com/wilburt/flutter_paystack/issues). Remember to be descriptive.
207+
208+
## Credits
209+
Thanks to the authors of Paystack [iOS](https://github.com/PaystackHQ/paystack-ios) and [Android](https://github.com/PaystackHQ/paystack-android) SDKS. I leveraged on their work to bring this plugin to fruition.
9210

10-
For help on editing plugin code, view the [documentation](https://flutter.io/platform-plugins/#edit-code).

android/src/main/kotlin/co/paystack/flutterpaystack/AuthActivity.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import android.os.Bundle
77
import android.webkit.JavascriptInterface
88
import android.webkit.WebView
99
import android.webkit.WebViewClient
10-
import co.paystack.paystackflutter.AuthSingleton
1110
import kotlinx.android.synthetic.main.co_paystack_android____activity_auth.*
1211

1312
/**

android/src/main/kotlin/co/paystack/flutterpaystack/AuthDelegate.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
package co.paystack.paystackflutter
1+
package co.paystack.flutterpaystack
22

33
import android.app.Activity
44
import android.content.Intent
55
import android.os.AsyncTask
66
import android.util.Log
7-
import co.paystack.flutterpaystack.AuthActivity
87
import io.flutter.plugin.common.MethodCall
98
import io.flutter.plugin.common.MethodChannel
109
import java.lang.ref.WeakReference

android/src/main/kotlin/co/paystack/flutterpaystack/AuthSingleton.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package co.paystack.paystackflutter
1+
package co.paystack.flutterpaystack
22

33
/**
44
* Created by Wilberforce on 29/07/18 at 06:00.

android/src/main/kotlin/co/paystack/flutterpaystack/Crypto.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package co.paystack.paystackflutter
1+
package co.paystack.flutterpaystack
22

33
import android.util.Base64
44

android/src/main/kotlin/co/paystack/flutterpaystack/FlutterPaystackPlugin.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ import android.annotation.SuppressLint
44
import android.content.Context
55
import android.os.Build
66
import android.provider.Settings
7-
import co.paystack.paystackflutter.AuthDelegate
8-
import co.paystack.paystackflutter.Crypto
97
import io.flutter.plugin.common.MethodCall
108
import io.flutter.plugin.common.MethodChannel
119
import io.flutter.plugin.common.MethodChannel.MethodCallHandler

example/lib/main.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import 'dart:io';
22

33
import 'package:flutter/cupertino.dart';
44
import 'package:flutter/material.dart';
5-
import 'package:flutter_paystack/paystack_sdk.dart';
5+
import 'package:flutter_paystack/paystack_plugin.dart';
66
import 'package:flutter/services.dart';
77
import 'package:http/http.dart' as http;
88

@@ -56,7 +56,7 @@ class _HomePageState extends State<HomePage> {
5656
@override
5757
void initState() {
5858
_validateSetupParams();
59-
PaystackSdk.initialize(publicKey: paystackPublicKey);
59+
PaystackPlugin.initialize(publicKey: paystackPublicKey);
6060
super.initState();
6161
}
6262

@@ -315,7 +315,7 @@ class _HomePageState extends State<HomePage> {
315315
_chargeCard() {
316316
_transaction = null;
317317

318-
PaystackSdk.chargeCard(context,
318+
PaystackPlugin.chargeCard(context,
319319
charge: _charge,
320320
beforeValidate: (transaction) => handleBeforeValidate(transaction),
321321
onSuccess: (transaction) => handleOnSuccess(transaction),

lib/paystack_sdk.dart renamed to lib/paystack_plugin.dart

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ export 'package:flutter_paystack/src/model/charge.dart';
1717
export 'package:flutter_paystack/src/transaction.dart';
1818
export 'package:flutter_paystack/src/exceptions.dart' hide PaystackException;
1919

20-
class PaystackSdk {
20+
class PaystackPlugin {
2121
static bool _sdkInitialized = false;
2222
static String _publicKey;
2323

24-
PaystackSdk._();
24+
PaystackPlugin._();
2525

26-
static Future<PaystackSdk> initialize({@required String publicKey}) async {
26+
static Future<PaystackPlugin> initialize({@required String publicKey}) async {
2727
assert(() {
2828
if (publicKey == null || publicKey.isEmpty) {
2929
throw new PaystackException('publicKey cannot be null or empty');
@@ -32,11 +32,11 @@ class PaystackSdk {
3232
}());
3333
//do all the init work here
3434

35-
var completer = Completer<PaystackSdk>();
35+
var completer = Completer<PaystackPlugin>();
3636

3737
//check if sdk is actually initialized
3838
if (sdkInitialized) {
39-
completer.complete(PaystackSdk._());
39+
completer.complete(PaystackPlugin._());
4040
} else {
4141
_publicKey = publicKey;
4242

@@ -52,7 +52,7 @@ class PaystackSdk {
5252
..deviceId = deviceId;
5353

5454
_sdkInitialized = true;
55-
completer.complete(PaystackSdk._());
55+
completer.complete(PaystackPlugin._());
5656
} on PlatformException catch (e) {
5757

5858
completer.completeError(e);

lib/src/api/request/charge_request_body.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import 'dart:async';
22

33
import 'package:flutter_paystack/src/api/request/base_request_body.dart';
44
import 'package:flutter_paystack/src/model/charge.dart';
5-
import 'package:flutter_paystack/paystack_sdk.dart';
5+
import 'package:flutter_paystack/paystack_plugin.dart';
66
import 'package:flutter_paystack/src/utils/card_utils.dart';
77
import 'package:flutter_paystack/src/utils/crypto.dart';
88

@@ -42,7 +42,7 @@ class ChargeRequestBody extends BaseRequestBody {
4242
this.setDeviceId();
4343
this._clientData = clientData;
4444
this._last4 = charge.card.last4Digits;
45-
this._publicKey = PaystackSdk.publicKey;
45+
this._publicKey = PaystackPlugin.publicKey;
4646
this._email = charge.email;
4747
this._amount = charge.amount.toString();
4848
this._reference = charge.reference;

0 commit comments

Comments
 (0)