Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,53 @@ Add Custom Fields by calling the `withCustomField` function (These will shown on

Finally call `build()` to get your JSON metadata string.

### Using Custom Routes

You can add your custom routes by calling the `useRoutes` method on the paystack object.

```php
$paystack = new Yabacon\Paystack(SECRET_KEY);
$paystack->useRoutes(["charge" => Charge::class]);

$paystack->charge->chargeMobileMoney([
'email' => 'hey@example.com',
'reference' => 'trnx_ref',
'amount' => 50 * 100,
'currency' => 'GHS',
'mobile_money' => [
'phone' => '5533467',
'provider' => 'MTN'
]
]);
```
Your custom routes should implement the ```Yabacon\Paystack\Contracts\RouteInterface``` contract

```php
class Charge implements RouteInterface
{

public static function root()
{
return '/charge';
}

public static function chargeMobileMoney()
{
return [
RouteInterface::METHOD_KEY => RouteInterface::POST_METHOD,
RouteInterface::ENDPOINT_KEY => Charge::root(),
RouteInterface::PARAMS_KEY => [
'email',
'reference',
'amount',
'currency',
'mobile_money',
],
];
}
}
```

## Change log

Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently.
Expand Down
27 changes: 27 additions & 0 deletions src/Paystack.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
namespace Yabacon;

use \Yabacon\Paystack\Helpers\Router;
use \Yabacon\Paystack\Contracts\RouteInterface;
use \Yabacon\Paystack\Exception\ValidationException;

class Paystack
{
public $secret_key;
public $use_guzzle = false;
public $custom_routes = [];
public static $fallback_to_file_get_contents = true;
const VERSION="2.1.19";

Expand All @@ -25,6 +27,31 @@ public function useGuzzle()
$this->use_guzzle = true;
}

public function useRoutes(array $routes)
{
foreach ($routes as $route => $class) {
if (! is_string($route)) {
throw new \InvalidArgumentException(
'Custom routes should map to a route class'
);
}

if (in_array($route, Router::$ROUTES)) {
throw new \InvalidArgumentException(
$route . ' is already an existing defined route'
);
}

if (! in_array(RouteInterface::class, class_implements($class))) {
throw new \InvalidArgumentException(
'Custom route class ' . $class . 'should implement ' . RouteInterface::class
);
}
}

$this->custom_routes = $routes;
}

public static function disableFileGetContentsFallback()
{
Paystack::$fallback_to_file_get_contents = false;
Expand Down
20 changes: 18 additions & 2 deletions src/Paystack/Helpers/Router.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,16 @@ public static function singularFor($method)

public function __construct($route, $paystackObj)
{
if (!in_array($route, Router::$ROUTES)) {
$routes = $this->getAllRoutes($paystackObj);

if (!in_array($route, $routes)) {
throw new ValidationException(
"Route '{$route}' does not exist."
);
}

$this->route = strtolower($route);
$this->route_class = 'Yabacon\\Paystack\\Routes\\' . ucwords($route);
$this->route_class = $this->getRouteClass($paystackObj);

$mets = get_class_methods($this->route_class);
if (empty($mets)) {
Expand All @@ -86,4 +88,18 @@ public function __construct($route, $paystackObj)
$this->methods[$mtd] = \Closure::bind($mtdFunc, $this, get_class());
}
}

private function getAllRoutes($paystackObj)
{
return array_merge(static::$ROUTES, array_keys($paystackObj->custom_routes));
}

private function getRouteClass($paystackObj)
{
try {
return $paystackObj->custom_routes[$this->route];
} catch (\Exception $execption) {
return 'Yabacon\\Paystack\\Routes\\' . ucwords($this->route);
}
}
}
35 changes: 34 additions & 1 deletion tests/Helpers/RouterTest.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<?php
namespace Yabacon\Paystack\Tests\Helpers;

use Yabacon\Paystack\Helpers\Router;
use Yabacon\Paystack;
use Yabacon\Paystack\Helpers\Router;
use Yabacon\Paystack\Test\Mock\CustomRoute;
use Yabacon\Paystack\Contracts\RouteInterface;
use Yabacon\Paystack\Exception\ValidationException;

Expand Down Expand Up @@ -53,4 +54,36 @@ public function testAllSingularsAreValidRoutes()

$this->assertEmpty(array_diff($singulars, $available));
}

public function testThatCustomRouteCanBeCalled()
{
$custom_route = ['charge' => CustomRoute::class];
$p = new Paystack('sk_');

$p->useRoutes($custom_route);

$r = $p->charge;
$reflection_property = new \ReflectionProperty($r, "methods");
$reflection_property->setAccessible(true);
$methods = $reflection_property->getValue($r);

$this->assertTrue(in_array("test_route", array_keys($methods)));
$this->assertTrue(is_callable($methods["test_route"]));
}

public function testThatOriginalRoutesCanBeCalledWhenCustomRouteIsSet()
{
$custom_route = ['charge' => CustomRoute::class];
$p = new Paystack('sk_');

$p->useRoutes($custom_route);

$r = $p->balance;
$reflection_property = new \ReflectionProperty($r, "methods");
$reflection_property->setAccessible(true);
$methods = $reflection_property->getValue($r);

$this->assertTrue(in_array("getList", array_keys($methods)));
$this->assertTrue(is_callable($methods["getList"]));
}
}
21 changes: 21 additions & 0 deletions tests/Mock/CustomRoute.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php
namespace Yabacon\Paystack\Test\Mock;

use Yabacon\Paystack\Contracts\RouteInterface;

class CustomRoute implements RouteInterface
{

public static function root()
{
return '/custom_route';
}

public static function test_route()
{
return [
RouteInterface::METHOD_KEY => RouteInterface::GET_METHOD,
RouteInterface::ENDPOINT_KEY => CustomRoute::root(),
];
}
}
37 changes: 37 additions & 0 deletions tests/PaystackTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

use Yabacon\Paystack;
use Yabacon\Paystack\Helpers\Router;
use Yabacon\Paystack\Test\Mock\CustomRoute;
use \Yabacon\Paystack\Exception\ValidationException;

class PaystackTest extends \PHPUnit_Framework_TestCase
Expand Down Expand Up @@ -73,4 +74,40 @@ public function testFetchWithInvalidParams3()
$this->expectException(\InvalidArgumentException::class);
$this->assertNull($r->customers(1));
}

public function testUseRoutes()
{
$custom_routes = ['custom_route' => CustomRoute::class];

$r = new Paystack('sk_');
$r->useRoutes($custom_routes);
$this->assertTrue($r->custom_routes == $custom_routes);
}

public function testUseRoutesWithInvalidParams1()
{
$custom_routes = ['custom_route'];
$r = new Paystack('sk_');
$this->expectException(\InvalidArgumentException::class);
$r->useRoutes($custom_routes);
$this->assertNull($r->custom_routes);
}

public function testUseRoutesWithInvalidParams2()
{
$custom_routes = ['custom_route' => Paystack::class];
$r = new Paystack('sk_');
$this->expectException(\InvalidArgumentException::class);
$r->useRoutes($custom_routes);
$this->assertNull($r->custom_routes);
}

public function testUseRoutesWithInvalidParams3()
{
$custom_routes = ['balance' => CustomRoute::class];
$r = new Paystack('sk_');
$this->expectException(\InvalidArgumentException::class);
$r->useRoutes($custom_routes);
$this->assertNull($r->custom_routes);
}
}