Skip to content

Commit ff0035b

Browse files
initial Lib source code created
1 parent 85eb831 commit ff0035b

File tree

8 files changed

+366
-2
lines changed

8 files changed

+366
-2
lines changed

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2021 webirr
3+
Copyright (c) 2021 WeBirr Technologies PLC
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

Lines changed: 149 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,150 @@
11
# webirr-api-dart-client
2-
Official Dart Client Library for WeBirr APIs
2+
Official Dart Client Library for WeBirr Payment Gateway APIs
3+
4+
*Requires Dart SDK >=2.12.0 <3.0.0*
5+
6+
>This Client Library provides convenient access to WeBirr Payment Gateway APIs from Dart/Flutter Apps.
7+
8+
## Install
9+
1. Add the dependecny in pubspec.yaml
10+
11+
>dependencies:
12+
> webirr: ^0.1.0
13+
14+
2. run the dart pub get command
15+
16+
```bash
17+
$ dart pub get
18+
```
19+
20+
## Usage
21+
22+
The library needs to be configured with a *merchant Id* & *API key*. You can get it by contacting [webirr.com](https://webirr.com)
23+
24+
> You can use this library for production or test environments. you will need to set isTestEnv=true for test, and false for production apps when creating objects of class WeBirrClient
25+
26+
## Example
27+
28+
# Creating a new Bill / Updating an existing Bill on WeBirr Servers
29+
30+
```dart
31+
32+
import 'package:webirr/webirr.dart';
33+
34+
const apikey = 'YOUR_API_KEY';
35+
const merchantId = 'YOUR_MERCHANT_ID';
36+
37+
var api = new WeBirrClient(apikey: apikey, isTestEnv: true);
38+
39+
var bill = new Bill(
40+
amount: '270.90',
41+
customerCode: 'cc01', // it can be email address or phone number if you dont have customer code
42+
customerName: 'Elias Haileselassie',
43+
time: '2021-07-22 22:14', // your bill time, always in this format
44+
description: 'hotel booking',
45+
billReference: 'drt/2021/125', // your unique reference number
46+
merchantID: merchantId,
47+
);
48+
49+
print('Creating Bill...');
50+
var res = await api.createBill(bill);
51+
52+
var paymentCode = '';
53+
54+
if (res.error == null) {
55+
// success
56+
paymentCode = res.res ?? ''; // returns paymentcode such as 429 723 975
57+
print(
58+
'Payment Code = $paymentCode'); // we may want to save payment code in local db.
59+
60+
} else {
61+
// fail
62+
print('error: ${res.error}');
63+
print(
64+
'errorCode: ${res.errorCode}'); // can be used to handle specific busines error such as ERROR_INVLAID_INPUT_DUP_REF
65+
}
66+
67+
// update existing bill if it is not paid
68+
bill.amount = "278.00";
69+
bill.customerName = 'Elias dart3';
70+
//bill.billReference = "WE CAN NOT CHANGE THIS";
71+
72+
print('Updating Bill...');
73+
res = await api.updateBill(bill);
74+
75+
if (res.error == null) {
76+
// success
77+
print(
78+
'bill is updated succesfully'); //res.res will be 'OK' no need to check here!
79+
} else {
80+
// fail
81+
print('error: ${res.error}');
82+
print(
83+
'errorCode: ${res.errorCode}'); // can be used to handle specific busines error such as ERROR_INVLAID_INPUT
84+
}
85+
86+
```
87+
88+
# Getting Payment status of an existing Bill from WeBirr Servers
89+
90+
```dart
91+
92+
import 'package:webirr/webirr.dart';
93+
94+
const apikey = 'YOUR_API_KEY';
95+
const merchantId = 'YOUR_MERCHANT_ID';
96+
97+
var api = new WeBirrClient(apikey: apikey, isTestEnv: true);
98+
99+
var paymentCode = 'PAYMENT_CODE_YOU_SAVED_AFTER_CREATING_A_NEW_BILL' // suchas as '141 263 782';
100+
101+
print('Getting Payment Status...');
102+
var r = await api.getPaymentStatus(paymentCode);
103+
104+
if (r.error == null) {
105+
// success
106+
if (r.res?.isPaid ?? false) {
107+
print('bill is paid');
108+
print('bill payment detail');
109+
print('Bank: ${r.res?.data?.bankID}');
110+
print('Bank Reference Number: ${r.res?.data?.paymentReference}');
111+
print('Amount Paid: ${r.res?.data?.amount}');
112+
} else
113+
print('bill is pending payment');
114+
} else {
115+
// fail
116+
print('error: ${r.error}');
117+
print(
118+
'errorCode: ${r.errorCode}'); // can be used to handle specific busines error such as ERROR_INVLAID_INPUT
119+
}
120+
121+
```
122+
123+
# Deleting an existing Bill from WeBirr Servers (if it is not paid)
124+
125+
```dart
126+
127+
import 'package:webirr/webirr.dart';
128+
129+
const apikey = 'YOUR_API_KEY';
130+
const merchantId = 'YOUR_MERCHANT_ID';
131+
132+
var api = new WeBirrClient(apikey: apikey, isTestEnv: true);
133+
134+
var paymentCode = 'PAYMENT_CODE_YOU_SAVED_AFTER_CREATING_A_NEW_BILL' // suchas as '141 263 782';
135+
136+
print('Deleting Bill...');
137+
res = await api.deleteBill(paymentCode);
138+
139+
if (res.error == null) {
140+
// success
141+
print(
142+
'bill is deleted succesfully'); //res.res will be 'OK' no need to check here!
143+
} else {
144+
// fail
145+
print('error: ${res.error}');
146+
print(
147+
'errorCode: ${res.errorCode}'); // can be used to handle specific bussines error such as ERROR_INVLAID_INPUT
148+
}
149+
150+
```

lib/src/api_response.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
class ApiResponse<T> {
2+
String? error = null;
3+
String? errorCode = null;
4+
T? res = null;
5+
6+
ApiResponse({this.error, this.errorCode, this.res});
7+
}

lib/src/bill.dart

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
class Bill {
2+
String customerCode;
3+
String customerName;
4+
5+
/// 24 hour format 2020-01-01 16:00
6+
String time;
7+
String description;
8+
9+
/// amount as two decimal digits 1246.50
10+
String amount;
11+
String billReference;
12+
String merchantID;
13+
14+
Bill(
15+
{required this.customerCode,
16+
required this.customerName,
17+
required this.time,
18+
required this.description,
19+
required this.amount,
20+
required this.billReference,
21+
required this.merchantID});
22+
23+
Map<String, dynamic> toJson() {
24+
final Map<String, dynamic> data = new Map<String, dynamic>();
25+
data['customerCode'] = this.customerCode;
26+
data['customerName'] = this.customerName;
27+
data['time'] = this.time;
28+
data['description'] = this.description;
29+
data['amount'] = this.amount;
30+
data['billReference'] = this.billReference;
31+
data['merchantID'] = this.merchantID;
32+
return data;
33+
}
34+
}

lib/src/payment.dart

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
class Payment {
2+
/// 0 = not paid, 1 = payment in progress, 2. paid !
3+
late int status;
4+
PaymentDetail? data;
5+
6+
Payment.fromJson(Map<String, dynamic> json) {
7+
status = json['status'];
8+
data =
9+
json['data'] != null ? new PaymentDetail.fromJson(json['data']) : null;
10+
}
11+
12+
/// true if the bill is paid (payment process completed)
13+
bool get isPaid => status == 2;
14+
}
15+
16+
class PaymentDetail {
17+
late int id;
18+
late String paymentReference;
19+
late bool confirmed;
20+
late String confirmedTime;
21+
late String bankID;
22+
late String time;
23+
late String amount;
24+
late String wbcCode;
25+
26+
PaymentDetail.fromJson(Map<String, dynamic> json) {
27+
id = json['id'];
28+
paymentReference = json['paymentReference'];
29+
confirmed = json['confirmed'];
30+
confirmedTime = json['confirmedTime'];
31+
bankID = json['bankID'];
32+
time = json['time'];
33+
amount = json['amount'];
34+
wbcCode = json['wbcCode'];
35+
}
36+
}

lib/src/webirr_client.dart

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import "dart:async";
2+
import 'dart:convert';
3+
4+
import 'package:http/http.dart' as http;
5+
import 'package:http/retry.dart';
6+
7+
import 'bill.dart';
8+
import 'payment.dart';
9+
import 'api_response.dart';
10+
11+
/// A WeBirrClient instance object can be used to
12+
/// Create, Update or Delete a Bill at WeBirr Servers and also to
13+
/// Get the Payment Status of a bill.
14+
/// It is a wrapper for the REST Web Service API.
15+
class WeBirrClient {
16+
late String _baseAddress;
17+
late String _apiKey;
18+
19+
WeBirrClient({required String apikey, required bool isTestEnv}) {
20+
_apiKey = apikey;
21+
_baseAddress =
22+
isTestEnv ? 'https://api.webirr.com' : 'https://api.webirr.com:8080';
23+
}
24+
25+
/// Create a new bill at WeBirr Servers.
26+
/// Check if(ApiResponse.error == null) to see if there are errors.
27+
/// ApiResponse.res will have the value of the returned PaymentCode on success.
28+
Future<ApiResponse<String>> createBill(Bill bill) async {
29+
var client = RetryClient(http.Client());
30+
try {
31+
var resp = await client.post(
32+
Uri.parse('${_baseAddress}/einvoice/api/postbill?api_key=${_apiKey}'),
33+
headers: {"Content-Type": "application/json"},
34+
body: jsonEncode(bill.toJson()));
35+
36+
if (resp.statusCode == 200) {
37+
var map = jsonDecode(resp.body) as Map<String, dynamic>;
38+
return ApiResponse<String>(
39+
error: map['error'], errorCode: map['errorCode'], res: map['res']);
40+
} else {
41+
return new ApiResponse<String>(
42+
error: 'http error ${resp.statusCode} ${resp.reasonPhrase}');
43+
}
44+
} finally {
45+
client.close();
46+
}
47+
}
48+
49+
/// Update an existing bill at WeBirr Servers, if the bill is not paid yet.
50+
/// The billReference has to be the same as the original bill created.
51+
/// Check if(ApiResponse.error == null) to see if there are errors.
52+
/// ApiResponse.res will have the value of "OK" on success.
53+
Future<ApiResponse<String>> updateBill(Bill bill) async {
54+
var client = RetryClient(http.Client());
55+
try {
56+
var resp = await client.put(
57+
Uri.parse('${_baseAddress}/einvoice/api/postbill?api_key=${_apiKey}'),
58+
headers: {"Content-Type": "application/json"},
59+
body: jsonEncode(bill.toJson()));
60+
61+
if (resp.statusCode == 200) {
62+
var map = jsonDecode(resp.body) as Map<String, dynamic>;
63+
return ApiResponse<String>(
64+
error: map['error'], errorCode: map['errorCode'], res: map['res']);
65+
} else {
66+
return new ApiResponse<String>(
67+
error: 'http error ${resp.statusCode} ${resp.reasonPhrase}');
68+
}
69+
} finally {
70+
client.close();
71+
}
72+
}
73+
74+
/// Delete an existing bill at WeBirr Servers, if the bill is not paid yet.
75+
/// [paymentCode] is the number that WeBirr Payment Gateway returns on createBill.
76+
/// Check if(ApiResponse.error == null) to see if there are errors.
77+
/// ApiResponse.res will have the value of "OK" on success.
78+
Future<ApiResponse<String>> deleteBill(String paymentCode) async {
79+
var client = RetryClient(http.Client());
80+
try {
81+
var resp = await client.put(Uri.parse(
82+
'${_baseAddress}/einvoice/api/deletebill?api_key=${_apiKey}&wbc_code=$paymentCode'));
83+
84+
if (resp.statusCode == 200) {
85+
var map = jsonDecode(resp.body) as Map<String, dynamic>;
86+
return ApiResponse<String>(
87+
error: map['error'], errorCode: map['errorCode'], res: map['res']);
88+
} else {
89+
return new ApiResponse<String>(
90+
error: 'http error ${resp.statusCode} ${resp.reasonPhrase}');
91+
}
92+
} finally {
93+
client.close();
94+
}
95+
}
96+
97+
/// Get Payment Status of a bill from WeBirr Servers
98+
/// [paymentCode] is the number that WeBirr Payment Gateway returns on createBill.
99+
/// Check if(ApiResponse.error == null) to see if there are errors.
100+
/// ApiResponse.res will have `Payment` object on success (will be null otherwise!)
101+
/// ApiResponse.res?.isPaid ?? false -> will return true if the bill is paid (payment completed)
102+
/// ApiResponse.res?.data ?? null -> will have `PaymentDetail` object
103+
Future<ApiResponse<Payment>> getPaymentStatus(String paymentCode) async {
104+
var client = RetryClient(http.Client());
105+
try {
106+
var resp = await client.get(Uri.parse(
107+
'${_baseAddress}/einvoice/api/getPaymentStatus?api_key=${_apiKey}&wbc_code=$paymentCode'));
108+
if (resp.statusCode == 200) {
109+
var map = jsonDecode(resp.body) as Map<String, dynamic>;
110+
return ApiResponse<Payment>(
111+
error: map['error'],
112+
errorCode: map['errorCode'],
113+
res: map['res'] != null ? Payment.fromJson(map['res']) : null);
114+
} else {
115+
return new ApiResponse<Payment>(
116+
error: 'http error ${resp.statusCode} ${resp.reasonPhrase}');
117+
}
118+
} finally {
119+
client.close();
120+
}
121+
}
122+
}

lib/webirr.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export 'src/webirr_client.dart';
2+
export 'src/bill.dart';
3+
export 'src/payment.dart';
4+
export 'src/api_response.dart';

pubspec.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
name: webirr
2+
version: 0.1.0
3+
author: WeBirr Team <[email protected]>
4+
description: >-
5+
Official Dart Client Library for WeBirr APIs
6+
This package can be used to integrate your apps with WeBirr payment gateway.
7+
It is a wrapper for the REST Web Service API. It can be used to create, update
8+
& delete bills and also check the payment status of bills
9+
homepage: https://github.com/webirr/webirr-api-dart-client
10+
environment:
11+
sdk: '>=2.12.0 <3.0.0'
12+
dependencies:
13+
http: ^0.13.3

0 commit comments

Comments
 (0)