Gbowo
A unified API for hippy nigerian payment processors (Currently supports Paystack and Amplifypay)
Install / Use
/learn @adelowo/GbowoREADME
Gbowo - Unified API for Hippy Nigerian Payment Gateways
<h2 id="installation">Installation </h2>Install Gbowo via one of the following methods :
- Composer (Recommended) :
composer require "adelowo/gbowo" : "~1.0"
<h2 id="usage"> Usage </h2>
require_once 'vendor/autoload.php';
$adapter = new \Gbowo\Adapter\Paystack\PaystackAdapter();
$response = $adapter->charge();
For the paystack and amplifypay adapters, the response received would be a string, which denotes an authorization__url. You are to make a redirect to the url to complete the transaction.
Other adapters implementation may do something much different like redirect internally ( from the adapter) but this isn't done for good reasons. This is because different systems may have different ways of performing redirects via Request or Response objects, or whatever have they. So as long as you can get the returned url, you can use the Adapter in your framework or whatever have you.
A basic example would be something like
header("Location : {$response}");
exit();
<h2 id="adapters">Adapters</h2>
Quick usage
$adapter = (new \Gbowo\GbowoFactory())->createAdapter("paystack"); //or "amplifypay"
return $adapter->charge();
Usage in depth
Gbowo ships with two adapters : one for paystack and the other for Amplifypay.
While both payment gateway offer similar features, there are a few subtle differences (obviously).
Gbowo requires some value to be present in the environment i.e $_ENV. For paystack, this is $_ENV['PAYSTACK_SECRET_KEY'] while the amplifypay adapter requires two values : your merchant id and an api key. This should be present in the following format : $_ENV['AMPLIFYPAY_MERCHANT_ID'] and $_ENV['AMPLIFYPAY_API_KEY'].
You are strongly advised to keep your keys and/or tokens out of your code and instead load them into
$_ENVby some other means. We don't enforce this but it is a best practice, 12 Factor App Guideline. A library that would help with this isvlucas/phpdotenv. All it needs is a.envfile and you are golden. Remember not to commit the.envelse it still isn't out of your "code". A sample.env.examplehas been provided in theresourcesdirectory. You can copy and rename that to.envin your root dir.
$paystack = new \Gbowo\Adapter\Paystack\PaystackAdapter();
$amplifyPay = new \Gbowo\Adapter\Amplifypay\AmplifypayAdapter()
A GuzzleHttp Client instance would be created automatically and values gotten from the $_ENV would be used to set the appropriate authorization headers where applicable.
You can prevent this "auto-wiring" by providing an instance of Guzzlehttp Client in the constructor.
$client = new \GuzzleHttp\Client(['key' => "value"]);
$amplifyPay = new \Gbowo\Adapter\Amplifypay\AmplifypayAdapter($client)
The payment flow for both adapters is pretty much the same. User initiates first time / one time transaction and is redirected to a secure page where payment details are to be inputted. After this (a successful payment request), the gateway would issue a redirect to a url you have supplied them as a callback. In this url, you should fetch the details of a user (who is now a customer) such as an authorization_code , transaction_reference among others. This is for recurrent transactions and should be persisted to a storage mechanism.
Initiating the transaction should be performed by calling the charge method on the adapter. And making a redirect where applicable to the response as described earlier.
To fetch the data from the url callback you have registered on your chosen gateway, you have to call the getPaymentData method on the adapter. It's response would contain some data about the customer.
//paystack adapter
var_dump($adapter->getPaymentData($_GET['trxref'])) ; //you should clean this up.
//amplifypay adapter
var_dump($adapter->getPaymentData($_GET['tran_response'])); // clean up
The
getPaymentDatamethod can also be called on some transaction reference you have stored in your db or some other form of storage mechanism.
When you call the
getPaymentDataon the paystack adapter. The reference is verified by paystack before a response is sent
Adapters Methods.
Paystack :
charge(array $data = [])getCustomer(int $id)getAllCustomers()chargeWithToken(array $userToken)// a token plus email address (or custom stuff)getPaymentData(string $transRef)fetchPlan($planIdentifier)fetchAllPlans()
Checkout gbowo-paystack . It contains an additional set of plugins for the paystack adapter.
charge(array $data = [])unsubcribeCustomerFromPlan(array $data)chargeWithToken(array $userToken)//a token in amplifypay is a key pair of values.getPaymentData(string $transRef)fetchPlan($planIdentifier)fetchAllPlans()
<h2 id="extend">Custom Adapters</h2>The
chargemethod parameter (array $data = []) should contain stuffs like amount, email, x, y, z). Those would be handed over to the payment gateway
Using laravel, please check out how to add your custom adapter
//let's assume it is an enterprisey app
$interswitch = new class implements \Gbowo\Contract\Adapter\AdapterInterface
{
protected $interswitch;
public function __construct()
{
$this->interswitch = new \stdClass(new \ArrayObject(new \stdClass())); // It wasn't me
}
public function charge(array $data = [])
{
return "charged by interswitch";
}
};
$adapter = new \Gbowo\GbowoFactory(["interswitch" => $interswitch]); //add the interswith adapter as a custom one.
$interswitchAdapter = $adapter->createAdapter("interswitch");
$interswitchAdapter->charge(['a' => 'b', 'c' => 'd']);
<h2 id="plugins">Extending Adapters via Plugins</h2>
Different gateways implement various features and there's no way we can support all of them without losing our sanity.
Supporting all features would lead to a bloat (an interface, class bloat). Take for instance : create InterfaceX to support feature X for AdapterE while AdapterE still makes use of features (and therefore interfaces) for AdapterA,AdapterQ and so on. Now imagine this scenario plays out for 4 -5 adapters.
Apart from the bloat, we cannot create a (visual) diagram of which interfaces are being used and it'd lead to a situation where we cannot remove a certain class or interface because we do not know who (what adapter) depends on them.
To prevent this, Gbowo implements a plugin architecture that eases extension or "adding new methods/behaviours" to an existing adapter without inheritance or touching core code. To achieve this, there is a Pluggable trait that contains the logic and MUST be imported by an adapter implementation.
A look at the paystack adapter and amplifypay would reveal that they do not have the methods described above in their public api. In fact they expose only 3 methods :
__construct(Client $client = null)// if it counts as onegetHttpClient()charge(array $data = [])//This is gotten from theAdapterInterfaceimplemented.
But a look at their registerPlugins method - which is gotten from the Pluggable trait - tells how the methods described in the Adapters method section above come about.
A plugin is a plain PHP class that MUST implement the PluginInterface. This interface exposes two methods :
getPluginAccessor() : stringsetAdapter(Adapter $adapter)handle(string $reference)//Typehint as much as you want. 2,3 args ? Your call.
I have written a detailed post about this here
namespace Vendor\AdapterName\Plugin;
use Gbowo/Contract/Plugin/PluginInterface;
use Gbowo\Exception\TransactionVerficationFailedException;
class ApiPinger implements PluginInterface
{
public function getPluginAccessor():string
{
return "pingApi"; //Oops.. Let's confirm if the api isn't dead before making any request. And it must be a string without parenthesis
}
/**
* You can also leave this method out but you must extend the `AbstractPlugin` class. Doing so, means you'd have to get rid of the plugin interface here as the abstract plugin already does that.
*/
public function setAdapter(AdapterInterface $adapter)
{
//useful for helpers like getting stuffs from "accessors" on the adapter instance like the already configured HttpClient object
$this->a
Related Skills
openhue
347.9kControl Philips Hue lights and scenes via the OpenHue CLI.
sag
347.9kElevenLabs text-to-speech with mac-style say UX.
weather
347.9kGet current weather and forecasts via wttr.in or Open-Meteo
tweakcc
1.6kCustomize Claude Code's system prompts, create custom toolsets, input pattern highlighters, themes/thinking verbs/spinners, customize input box & user message styling, support AGENTS.md, unlock private/unreleased features, and much more. Supports both native/npm installs on all platforms.
