Skip to content

Commit 082c5cc

Browse files
committed
chore: bills
1 parent 005bf34 commit 082c5cc

7 files changed

Lines changed: 345 additions & 1 deletion

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ array(21) { ... }
7272
- [x] Subscriptions
7373
- [x] Collection subaccounts
7474
- [x] Payout subaccounts
75-
- [ ] Bills
75+
- [x] Bills
7676
- [ ] Remita payments
7777
- [x] Banks
7878
- [ ] Misc

src/API/Bill.php

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace StarfolkSoftware\Flutterwave\API;
4+
5+
use StarfolkSoftware\Flutterwave\Abstracts\ApiAbstract;
6+
use StarfolkSoftware\Flutterwave\HttpClient\Message\ResponseMediator;
7+
use StarfolkSoftware\Flutterwave\Options\BillCategoriesQueryParams;
8+
use StarfolkSoftware\Flutterwave\Options\CreateBillOptions;
9+
10+
final class Bill extends ApiAbstract
11+
{
12+
/**
13+
* Fetches bill categories
14+
*
15+
* @param array $params
16+
* @return array
17+
*/
18+
public function categories(array $params = []): array
19+
{
20+
$options = new BillCategoriesQueryParams($params);
21+
22+
$response = $this->httpClient->get('bill-categories', [
23+
'query' => json_encode($options->all()),
24+
]);
25+
26+
return ResponseMediator::getContent($response);
27+
}
28+
29+
/**
30+
* Validates service
31+
*
32+
* @param string $itemCode
33+
* @param string $code
34+
* @param string $customer
35+
* @return array
36+
*/
37+
public function validate(string $itemCode, string $code, string $customer): array
38+
{
39+
$response = $this->httpClient->get("bill-items/{$itemCode}/validate", [
40+
'query' => json_encode([
41+
'code' => $code,
42+
'customer' => $customer,
43+
]),
44+
]);
45+
46+
return ResponseMediator::getContent($response);
47+
}
48+
49+
/**
50+
* Creates a bill payment
51+
*
52+
* @param array $params
53+
* @return array
54+
*/
55+
public function create(array $params): array
56+
{
57+
$options = new CreateBillOptions($params);
58+
59+
$response = $this->httpClient->post("bills", [
60+
'json' => json_encode($options->all()),
61+
]);
62+
63+
return ResponseMediator::getContent($response);
64+
}
65+
66+
/**
67+
* Create a bulk bill payment
68+
*
69+
* @param string $bulkReference
70+
* @param string $callbackUrl
71+
* @param array $bulkData
72+
*/
73+
public function bulkCreate(string $bulkReference, string $callbackUrl, array $bulkData): array
74+
{
75+
foreach ($bulkData as $params) {
76+
new CreateBillOptions($params);
77+
}
78+
79+
$response = $this->httpClient->post("bulk-bills", [
80+
'json' => json_encode([
81+
'bulk_reference' => $bulkReference,
82+
'callback_url' => $callbackUrl,
83+
'bulk_data' => $bulkData,
84+
]),
85+
]);
86+
87+
return ResponseMediator::getContent($response);
88+
}
89+
90+
/**
91+
* Gets status of a bill payment
92+
*
93+
* @param string $reference
94+
* @param int $verbose
95+
* @return array
96+
*/
97+
public function status(string $reference, int $verbose = 1): array
98+
{
99+
$response = $this->httpClient->get("bills/{$reference}", [
100+
'query' => json_encode([
101+
'verbose' => $verbose,
102+
]),
103+
]);
104+
105+
return ResponseMediator::getContent($response);
106+
}
107+
108+
/**
109+
* Gets all payments
110+
*
111+
* @param string $from
112+
* @param string $to
113+
* @param int $page
114+
* @param string $reference
115+
* @return array
116+
*/
117+
public function payments(string $from, string $to, int $page = 20, string $reference = ''): array
118+
{
119+
$response = $this->httpClient->get("bills", [
120+
'query' => json_encode([
121+
'from' => $from,
122+
'to' => $to,
123+
'page' => $page,
124+
'reference' => $reference
125+
]),
126+
]);
127+
128+
return ResponseMediator::getContent($response);
129+
}
130+
}

src/Client.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Http\Client\Common\Plugin\HeaderDefaultsPlugin;
99
use StarfolkSoftware\Flutterwave\API\Bank;
1010
use StarfolkSoftware\Flutterwave\API\Beneficiary;
11+
use StarfolkSoftware\Flutterwave\API\Bill;
1112
use StarfolkSoftware\Flutterwave\API\Charge;
1213
use StarfolkSoftware\Flutterwave\API\Chargeback;
1314
use StarfolkSoftware\Flutterwave\API\Otp;
@@ -227,6 +228,16 @@ protected function chargebacks(): Chargeback
227228
return new Chargeback($this);
228229
}
229230

231+
/**
232+
* Bill API
233+
*
234+
* @return Bill
235+
*/
236+
protected function bills(): Bill
237+
{
238+
return new Bill($this);
239+
}
240+
230241
/**
231242
* Payout Subaccount API
232243
*
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
namespace StarfolkSoftware\Flutterwave\Options;
4+
5+
use StarfolkSoftware\Flutterwave\Abstracts\OptionsAbstract;
6+
use Symfony\Component\OptionsResolver\OptionsResolver;
7+
8+
final class BillCategoriesQueryParams extends OptionsAbstract
9+
{
10+
/**
11+
* Set defaults, allowed types and values of the options.
12+
*
13+
* @param OptionsResolver $resolver
14+
*
15+
* @return void
16+
*/
17+
public function configureOptions(OptionsResolver $resolver): void
18+
{
19+
$resolver->define('airtime')
20+
->allowedTypes('int')
21+
->info('Airtime categories');
22+
23+
$resolver->define('data_bundle')
24+
->allowedTypes('int')
25+
->info('Data bundle categories');
26+
27+
$resolver->define('power')
28+
->allowedTypes('int')
29+
->info('Power categories');
30+
31+
$resolver->define('internet')
32+
->allowedTypes('int')
33+
->info('Internet categories');
34+
35+
$resolver->define('toll')
36+
->allowedTypes('int')
37+
->info('Toll categories');
38+
39+
$resolver->define('biller_code')
40+
->allowedTypes('string')
41+
->info('Bill code categories');
42+
43+
$resolver->define('cables')
44+
->allowedTypes('int')
45+
->info('Cable categories');
46+
}
47+
}

src/Options/CreateBillOptions.php

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace StarfolkSoftware\Flutterwave\Options;
4+
5+
use StarfolkSoftware\Flutterwave\Abstracts\OptionsAbstract;
6+
use Symfony\Component\OptionsResolver\OptionsResolver;
7+
8+
final class CreateBillOptions extends OptionsAbstract
9+
{
10+
/**
11+
* Set defaults, allowed types and values of the options.
12+
*
13+
* @param OptionsResolver $resolver
14+
* @return void
15+
*/
16+
public function configureOptions(OptionsResolver $resolver): void
17+
{
18+
$resolver->define('country')
19+
->required()
20+
->allowedTypes('string')
21+
->info('Country');
22+
23+
$resolver->define('customer')
24+
->required()
25+
->allowedTypes('string')
26+
->info('Customer');
27+
28+
$resolver->define('amount')
29+
->required()
30+
->allowedTypes('int')
31+
->info('Amount');
32+
33+
$resolver->define('recurrence')
34+
->allowedTypes('string')
35+
->allowedValues('ONCE', 'HOURLY', 'DAILY', 'WEEKLY', 'MONTHLY')
36+
->info('Recurrence');
37+
38+
$resolver->define('type')
39+
->required()
40+
->allowedTypes('string')
41+
->info("Type");
42+
43+
$resolver->define('reference')
44+
->allowedTypes('string')
45+
->info('Reference');
46+
47+
$resolver->define('biller_name')
48+
->allowedTypes('string')
49+
->info('Biller Name');
50+
}
51+
}

tests/BillTest.php

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
<?php
2+
3+
namespace StarfolkSoftware\Flutterwave\Tests;
4+
5+
use Laminas\Diactoros\Response\JsonResponse;
6+
7+
final class BillTest extends TestCase
8+
{
9+
public function testBillCategoriesCanBeRetrieved(): void
10+
{
11+
$this->mockClient->addResponse((new JsonResponse([
12+
"status" => "success",
13+
]))->withStatus(200));
14+
15+
$response = $this->client()->bills->categories();
16+
17+
$this->assertEquals('success', $response['status']);
18+
}
19+
20+
public function testBillServiceCanBeValidated(): void
21+
{
22+
$this->mockClient->addResponse((new JsonResponse([
23+
"status" => "success",
24+
]))->withStatus(200));
25+
26+
$response = $this->client()->bills->validate('1234567890', '0987654321', '0987654321');
27+
28+
$this->assertEquals('success', $response['status']);
29+
}
30+
31+
public function testBillPaymentCanBeCreated(): void
32+
{
33+
$this->mockClient->addResponse((new JsonResponse([
34+
"status" => "success",
35+
]))->withStatus(200));
36+
37+
$response = $this->client()->bills->create([
38+
"country" => "NG",
39+
"customer" => "+23490803840303",
40+
"amount" => 500,
41+
"recurrence" => "ONCE",
42+
"type" => "AIRTIME",
43+
"reference" => "9300049404444"
44+
]);
45+
46+
$this->assertEquals('success', $response['status']);
47+
}
48+
49+
public function testBillPaymentCanBeCreatedInBulk(): void
50+
{
51+
$this->mockClient->addResponse((new JsonResponse([
52+
"status" => "success",
53+
]))->withStatus(200));
54+
55+
$response = $this->client()->bills->bulkCreate(
56+
"edf-12de5223d2f32",
57+
"https://webhook.site/5f9a659a-11a2-4925-89cf-8a59ea6a019a",
58+
[
59+
[
60+
"country" => "NG",
61+
"customer" => "+23490803840303",
62+
"amount" => 500,
63+
"recurrence" => "WEEKLY",
64+
"type" => "AIRTIME",
65+
"reference" => "930049200929"
66+
],
67+
[
68+
"country" => "NG",
69+
"customer" => "+23490803840304",
70+
"amount" => 500,
71+
"recurrence" => "WEEKLY",
72+
"type" => "AIRTIME",
73+
"reference" => "930004912332"
74+
]
75+
]
76+
);
77+
78+
$this->assertEquals('success', $response['status']);
79+
}
80+
81+
public function testBillPaymentStatusCanBeRetrieved(): void
82+
{
83+
$this->mockClient->addResponse((new JsonResponse([
84+
"status" => "success",
85+
]))->withStatus(200));
86+
87+
$response = $this->client()->bills->status('dsdfsdf');
88+
89+
$this->assertEquals('success', $response['status']);
90+
}
91+
92+
public function testBillPaymentsCanBeRetrieved(): void
93+
{
94+
$this->mockClient->addResponse((new JsonResponse([
95+
"status" => "success",
96+
]))->withStatus(200));
97+
98+
$response = $this->client()->bills->payments(
99+
'from',
100+
'to',
101+
);
102+
103+
$this->assertEquals('success', $response['status']);
104+
}
105+
}

0 commit comments

Comments
 (0)