dammyammy / lara-pay-ng
Payment Solution For Laravel 5 (Nigerian Specific Providers eg. GTPay, SimplePay, CashEnvoy, VoguePay, WebPay)
Requires
- php: >=5.5.9
- guzzlehttp/guzzle: ~5.0
- illuminate/support: 5.1.*
- nesbot/carbon: ~1.19
This package is not auto-updated.
Last update: 2024-12-07 18:45:46 UTC
README
Supports Multiple Gateways with a single API approach, meaning Integration is the same across board in code.
Note: Do Not Use In Production, Currently being developed to be compatible with the latest version of Laravel.
The Aim is to Integrate as many Payment Gateways As Possible.
Requirements
Currently Supported
- VoguePay
- GTPay
- CashEnvoy
- SimplePay
Gateways Currently In development
- WebPay
Installation
Simply Run
composer require dammyammy/lara-pay-ng
Next Add the Service Provider into your Providers Array in config/app.php
'providers' => [ /* * Laravel Framework Service Providers... */ 'Illuminate\Foundation\Providers\ArtisanServiceProvider', 'Illuminate\Auth\AuthServiceProvider', .... 'LaraPayNG\Providers\LaraPayNGServiceProvider', ],
Next Publish All Package Files
php artisan vendor:publish
This Would create the following:
- A PaymentController in app/Http/Controllers/PaymentController.php
- Note: This is a working Sample, you may need to change Namespace to match your Projects namespace
- Migrations would be published to folder database/migrations
- 4 Views, matching the Controller
- one with a simulated checkout out button
- one is the proceed to pay page (Pay Now Button)
- one is a success notification Url, Showing a Successful Transaction
- one is a failure notification Url, Showing a Failed Transaction
Next Add the following to your routes page in app/Http/routes.php and edit as you seem fit, But be sure specified values match Your Config file
Route::get('orders', [ 'as' => 'orders', 'uses' => 'PaymentController@orders' ]); Route::get('checkout', [ 'as' => 'checkout', 'uses' => 'PaymentController@checkout' ]); $successUrl = config('lara-pay-ng.gateways.routes.success_route'); $successName = config('lara-pay-ng.gateways.routes.success_route_name'); $failureUrl = config('lara-pay-ng.gateways.routes.failure_route'); $failureName = config('lara-pay-ng.gateways.routes.failure_route_name'); Route::post('/' . $successUrl . '/{mert_id}', [ 'as' => $successName, 'uses' => 'PaymentController@success' ]); Route::post('/' . $failureUrl . '/{mert_id}', [ 'as' => $failureName, 'uses' => 'PaymentController@failed' ]); Route::post('/payment-notification/{mert_id}', [ 'as' => 'payment-notification', 'uses' => 'PaymentController@notification' ]);
Remember to Disallow CSRF Token Verification for your payment routes
This is perhaps one of the use cases in which u need to absolutely do this. If this is not done, When a Transaction Id is been sent back your site would throw a TokenMismatchException, as the Gateway Provider is posting back, and doesn't have a token Generated from your app.
Use the appropriate route endpoints if you did change the default names and urls.
<?php namespace App\Http\Middleware; use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier; class VerifyCsrfToken extends BaseVerifier { /** * The URIs that should be excluded from CSRF verification. * * @var array */ protected $except = [ 'transaction-failed/*', 'transaction-successful/*', 'payment-notification/*', ]; }
Next Migrate the Package Tables.
php artisan migrate
Next, Test the default Controller by visiting /Orders and follow through.
The Important thing to note is, to Inject the Payment Functionality into a controller, all you need do is to Inject the PaymentGatewayManager Class into that controller, and you instantly gain access to all the methods provided by the facades below.
use LaraPayNG\Exceptions\UnknownPaymentGatewayException; use LaraPayNG\Managers\PaymentGatewayManager; class PaymentController extends Controller { /** * @var PaymentGateway */ private $paymentGateway; /** * @param PaymentGatewayManager $paymentGateway */ public function __construct(PaymentGatewayManager $paymentGateway) { $this->paymentGateway = $paymentGateway; } .... }
Facades
Methods Available Via Facades / PaymentGatewayManager Injection
Events
Throwing this Events are optional, but helps serve as a hook for how you handle Completed Transactions.Take these Example Scenarios When you would Like to
- Send A customer an Email to notify them of their recent Transaction Status.
- You want to Set a person's account to active in the User's Table after a successful Transaction.
- You Want to add Paying Customer's to your Paying Customer's Mailer List.
The possibilities are endless, All you have to do is to Pull in the \LaraPayNG\Traits\DetermineTransactionStatus Trait and call the dispatchAppropriateEvents($result); method within your controller. e.g.
public function notification($mert_id, Request $request) { $result = $this->handleTransactionResponse($mert_id, $request); $this->dispatchAppropriateEvents($result); return $this->determineViewToPresent($result); }
Then Simply Create Event Listeners in app/Providers/EventServiceProvider.php
<?php namespace App\Providers; use Illuminate\Contracts\Events\Dispatcher as DispatcherContract; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; class EventServiceProvider extends ServiceProvider { /** * The event listener mappings for the application. * * @var array */ protected $listen = [ 'LaraPayNG\Events\TransactionSuccessful' => [ // 'App\Listeners\SendEmailForSuccessfulTransactions', // 'App\Listeners\ActivateUser', ], 'LaraPayNG\Events\TransactionUnsuccessful' => [ // 'App\Listeners\DeactivateUser', ], ]; .... }
Finally, Create Your Listener Implementations Knowing you have access to an array result containing values needed. An example implementation is written below:
File: app/Listeners/ActivateUser.php
<?php namespace App\Listeners; use LaraPayNG\Events\TransactionSuccessful; use App\User; class ActivateUser { /** * Handle the event. * * @param ActivateUser $event * @return void */ public function handle(ActivateUser $event) { // All Values Below are available // $event['status'], // $event['items'], // $event['transaction_id'], // $event['merchant_ref'], // $event['amount'], // $event['customer_id'], // $event['payer_id'], $user = User::find($event['customer_id']); $user->activate = true; $user->save(); return true; } }
Exceptions
All Exceptions Exist Under This Namespace;
namespace \LaraPayNG\Exceptions;
Commands
There is a Command to Help Clear Stale Records That have been logged within a set number of days. To Use Simply Type in your terminal
# php artisan lara-pay-ng:purge-database gatewayname --days=3 --with-failed=false
php artisan lara-pay-ng:purge-database
You can Pass the gatewayname attribute to the Command eg. gtpay, voguepay. This is particularly useful for Multi-gateway Setups.
In the event of not passing the option, the default gateway driver from set config would be used.
It also can be passed a --with-failed option which accepts true/false. True means all Transactions that failed should be included in the deletion, as well as a --days option specifying how many days back data is considered old.
Tips
Add Methods Like These to Your Helpers.php File then Autoload It In Your composer.json
public function generateTransactionData($dessert, $transactionId) { return 'name=' . $dessert->present()->name . ';pre=' . $dessert->present()->buyPrice . ';buyer=' . currentUserName() . '; transactionId=' . $transactionId; } public function generateTransactionMemo($product) { return 'Name: ' . $product->name . '; Price: ' . $product->price . '; Buyer: ' . Auth::user()->email; }
then You can easily Do
$product = Product::get('2'); $transactionData = [ 'ce_amount' => $product->price, 'ce_memo' => generateTransactionMemo($product), ... ]; CashEnvoy::button($product->id, $transactionData, 'btn btn-success', '<i class="fa fa-currency"></i> Pay');
TODO
- Refactor Code
- Ability to Handle Transaction From Start to Finish
- Back everything up with Tests.