Skip to content

Commit

Permalink
- Added Invoice
Browse files Browse the repository at this point in the history
- Updated Monnify Documentation link
- Updated README.md
  • Loading branch information
henryejemuta committed Nov 18, 2021
1 parent ed84361 commit 1f64ddf
Show file tree
Hide file tree
Showing 6 changed files with 266 additions and 11 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

All notable changes to `laravel-monnify` will be documented in this file

- Release 2.1.0
## 2.1.0 2021-11-18 Added Invoice, Updated README.md, other cleanup

- Release 2.0.0
## 1.0.2 2021-03-02 Added PHP 8 support, Webhook Event now include a boolean for transaction hash validity, decoupled Monnify class into abstract classes

Expand Down
66 changes: 58 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Monnify is a leading payment technology that powers seamless transactions for bu

Create a Monnify Account [Sign Up](https://app.monnify.com/create-account).

Look up Monnify API Documentation [API Documentation](https://docs.teamapt.com/display/MON/Monnify).
Look up Monnify API Documentation [API Documentation](https://teamapt.atlassian.net/wiki/spaces/MON/overview).

## Installation

Expand Down Expand Up @@ -53,24 +53,74 @@ php artisan monnify:init
> To use the monnify package you must import the Monnify Facades with the import statement below; Other Classes import is based on your specific usage and would be highlighted in their corresponding sections.
> You'll also need to import the MonnifyFailedRequestException and handle the exception as all failed request will throw this exception the with the corresponding monnify message and code [Learn More](https://docs.teamapt.com/display/MON/Transaction+Responses)
>
``` php
...
use HenryEjemuta\LaravelMonnify\Facades\Monnify;
use HenryEjemuta\LaravelMonnify\Exceptions\MonnifyFailedRequestException;
...
```php
//...
use HenryEjemuta\LaravelMonnify\Facades\Monnify;
use HenryEjemuta\LaravelMonnify\Exceptions\MonnifyFailedRequestException;
//...

```

# Important Notice!!!
### Major Change from Previous Version Monnify Facades Overview
### Migrating from Previous Version of Laravel Monnify
This new changes reflect my concern for modular code base, I'm certain you should not have any issues migrating and refactoring your codebase, but if you do, kindly contact me or use the issues tab, and I will make sure your concerns are all attended to.
The Monnify class has been broken down grouping all actions into five(5) classes, Banks, CustomerReservedAccounts, Disbursements, SubAccounts, and Transactions
see example usage below:
``` php
```php

//...
use HenryEjemuta\LaravelMonnify\Facades\Monnify;
//...

$responseBody = Monnify::Transactions()->initializeTransaction(float $amount, string $customerName, string $customerEmail, string $paymentReference, string $paymentDescription, string $redirectUrl, MonnifyPaymentMethods $monnifyPaymentMethods, MonnifyIncomeSplitConfig $incomeSplitConfig = null, string $currencyCode = null);
$responseBody = Monnify::Transactions()->getAllTransactions(array $queryParams);
$responseBody = Monnify::Transactions()->calculateHash(string $paymentReference, $amountPaid, string $paidOn, string $transactionReference);
$responseBody = Monnify::Transactions()->getTransactionStatus(string $transactions);
$responseBody = Monnify::Transactions()->payWithBankTransfer(string $transactionReference, string $bankCode);

```
## Before
```php
//...
use HenryEjemuta\LaravelMonnify\Facades\Monnify;
use HenryEjemuta\LaravelMonnify\Classes\MonnifyPaymentMethod;
use HenryEjemuta\LaravelMonnify\Classes\MonnifyPaymentMethods;
//...

Monnify::initializeTransaction(
15000, "Customer Name", "[email protected]", "transaction_ref", "Transaction Description",
"https://youdomain.com/afterpaymentendpoint", new MonnifyPaymentMethods(MonnifyPaymentMethod::CARD(), MonnifyPaymentMethod::ACCOUNT_TRANSFER()));
```
## Now

```php
//...
use HenryEjemuta\LaravelMonnify\Facades\Monnify;
use HenryEjemuta\LaravelMonnify\Classes\MonnifyPaymentMethod;
use HenryEjemuta\LaravelMonnify\Classes\MonnifyPaymentMethods;
//...

Monnify::Transactions()->initializeTransaction(
15000, "Customer Name", "[email protected]", "transaction_ref", "Transaction Description",
"https://youdomain.com/afterpaymentendpoint", new MonnifyPaymentMethods(MonnifyPaymentMethod::CARD(), MonnifyPaymentMethod::ACCOUNT_TRANSFER()));

```

Similar implementation applies to other sections (i.e. Banks, CustomerReservedAccounts, Disbursements, and SubAccounts)

```php
//...
use HenryEjemuta\LaravelMonnify\Facades\Monnify;
//...
$responseBody = Monnify::Banks()->getBanks();
$responseBody = Monnify::Banks()->getBanksWithUSSDShortCode();
$responseBody = Monnify::Banks()->validateBankAccount(MonnifyBankAccount $bankAccount);

$responseBody = Monnify::Disbursements()->initiateTransferSingle(float $amount, string $reference, string $narration, MonnifyBankAccount $bankAccount, string $currencyCode = null);
$responseBody = Monnify::Disbursements()->initiateTransferSingleWithMonnifyTransaction(MonnifyTransaction $monnifyTransaction);
$responseBody = Monnify::Disbursements()->initiateTransferBulk(string $title, string $batchReference, string $narration, MonnifyOnFailureValidate $onFailureValidate, int $notificationInterval, MonnifyTransactionList $transactionList);
$responseBody = Monnify::Disbursements()->authorizeTransfer2FA(string $authorizationCode, string $reference, string $path);


$responseBody = Monnify::SubAccounts()->createSubAccount(string $bankCode, string $accountNumber, string $email, string $currencyCode = null, string $splitPercentage = null);
$responseBody = Monnify::SubAccounts()->createSubAccounts(array $accounts);
Expand Down
2 changes: 0 additions & 2 deletions src/Classes/MonnifyPaymentMethod.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,6 @@ public static function findPaymentMethod(int $id): MonnifyPaymentMethod
return self::CARD();
case 2:
return self::ACCOUNT_TRANSFER();
default:
return null;
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/Facades/Monnify.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

/**
* @method static Banks Banks()
* @method static CustomerReservedAccount ReservedAccount()
* @method static CustomerReservedAccount ReservedAccounts()
* @method static Disbursements Disbursements()
* @method static SubAccounts SubAccounts()
* @method static Transactions Transactions()
Expand Down
194 changes: 194 additions & 0 deletions src/Invoice.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
<?php
/**
* Created By: Henry Ejemuta
* PC: Enrico Systems
* Project: laravel-monnify
* Company: Stimolive Technologies Limited
* Class Name: Banks.php
* Date Created: 3/2/21
* Time Created: 4:11 PM
*/

namespace HenryEjemuta\LaravelMonnify;


use HenryEjemuta\LaravelMonnify\Classes\MonnifyIncomeSplitConfig;
use HenryEjemuta\LaravelMonnify\Classes\MonnifyPaymentMethods;
use HenryEjemuta\LaravelMonnify\Exceptions\MonnifyFailedRequestException;

abstract class Invoice
{
private $monnify;

/**
* Flexible handle to the Monnify Configuration
*
* @var
*/
private $config;

public function __construct(Monnify $monnify, $config)
{
$this->config = $config;
$this->monnify = $monnify;
}

/**
* You can get details of all your invoices by using this handle
* Monnify will return a paginated list of all your invoices. Here's a sample response
* @return object
*
* @throws MonnifyFailedRequestException
* @see https://teamapt.atlassian.net/wiki/spaces/MON/pages/212008979/Get+All+Invoices
*
*/
public function getAllInvoice()
{
$endpoint = "{$this->monnify->baseUrl}{$this->monnify->v1}invoice/all";
$response = $this->monnify->withOAuth2()->get($endpoint);

$responseObject = json_decode($response->body());
if (!$response->successful())
throw new MonnifyFailedRequestException($responseObject->responseMessage ?? "Path '{$responseObject->path}' {$responseObject->error}", $responseObject->responseCode ?? $responseObject->status);

return $responseObject->responseBody;
}


/**
* Allows you create an invoice on Monnify. When the request is sent, an account number will be returned.
* You should include that account number (and bank) on the invoice being sent to your customer. We also return a checkout URL which can be included on your invoices. This way customers who want to pay using their debit cards can simply click on the link and pay using the Monnify payment interface.
*
* @param float $amount The amount to be paid by the customer
* @param string $expiryDateTime Invoice Expiry date in this format "2019-10-30 12:00:00"
* @param string $customerName Full name of the customer
* @param string $customerEmail Email address of the customer
* @param string $invoiceReference Merchant's Unique reference for the invoice.
* @param string $invoiceDescription Description for the invoce. Will be returned as part of the account name on name enquiry for transfer payments.
* @param string $redirectUrl A URL which user will be redirected to, on completion of the payment.
* @param MonnifyPaymentMethods $monnifyPaymentMethods
* @param MonnifyIncomeSplitConfig $incomeSplitConfig
* @param string|null $currencyCode
* @return array
*
* @throws MonnifyFailedRequestException
* @link https://teamapt.atlassian.net/wiki/spaces/MON/pages/212008946/Create+an+Invoice
*/
public function createAnInvoice(float $amount, $expiryDateTime, string $customerName, string $customerEmail, string $invoiceReference, string $invoiceDescription, string $redirectUrl, MonnifyPaymentMethods $monnifyPaymentMethods, MonnifyIncomeSplitConfig $incomeSplitConfig = null, string $currencyCode = null)
{
$endpoint = "{$this->monnify->baseUrl}{$this->monnify->v1}invoice/create";

$formData = [
"amount" => $amount,
"expiryDate" => trim($expiryDateTime),
"customerName" => trim($customerName),
"customerEmail" => $customerEmail,
"invoiceReference" => $invoiceReference,
"description" => trim($invoiceDescription),
"currencyCode" => $currencyCode ?? $this->config['default_currency_code'],
"contractCode" => $this->config['contract_code'],
"redirectUrl" => trim($redirectUrl),
"paymentMethods" => $monnifyPaymentMethods->toArray(),
];
if ($incomeSplitConfig !== null)
$formData["incomeSplitConfig"] = $incomeSplitConfig->toArray();
$response = $this->monnify->withBasicAuth()->post($endpoint, $formData);

$responseObject = json_decode($response->body());
if (!$response->successful())
throw new MonnifyFailedRequestException($responseObject->responseMessage ?? "Path '{$responseObject->path}' {$responseObject->error}", $responseObject->responseCode ?? $responseObject->status);

return $responseObject->responseBody;
}


/**
* To view the details of an invoice you need to use this handle
* Once you send the request, Monnify will return all the details attached to the invoice
*
* @param string $invoiceReference Unique invoice reference provide while creating invoice
* @return object
*
* @throws MonnifyFailedRequestException
* @link https://teamapt.atlassian.net/wiki/spaces/MON/pages/212008971/View+Invoice+Details
*/
public function viewInvoiceDetails(string $invoiceReference)
{
$endpoint = "{$this->monnify->baseUrl}{$this->monnify->v1}invoice/$invoiceReference/details";

$response = $this->monnify->withOAuth2()->get($endpoint);

$responseObject = json_decode($response->body());
if (!$response->successful())
throw new MonnifyFailedRequestException($responseObject->responseMessage ?? "Path '{$responseObject->path}' {$responseObject->error}", $responseObject->responseCode ?? $responseObject->status);

return $responseObject->responseBody;
}

/**
* To cancel an invoice you need to use this handle
* Once the invoice is canceled, the customer can no longer pay for that invoice. For the customer reserved invoice, the customer's account number becomes inactive.
*
* @param string $invoiceReference Unique invoice reference provide while creating invoice
* @return object
*
* @throws MonnifyFailedRequestException
* @link https://teamapt.atlassian.net/wiki/spaces/MON/pages/213909772/Cancel+an+Invoice
*/
public function cancelAnInvoice(string $invoiceReference)
{
$endpoint = "{$this->monnify->baseUrl}{$this->monnify->v1}invoice/$invoiceReference/cancel";

$response = $this->monnify->withOAuth2()->delete($endpoint);

$responseObject = json_decode($response->body());
if (!$response->successful())
throw new MonnifyFailedRequestException($responseObject->responseMessage ?? "Path '{$responseObject->path}' {$responseObject->error}", $responseObject->responseCode ?? $responseObject->status);

return $responseObject->responseBody;
}


/**
* Monnify allows you Reserve an Account for your customers who you send invoices to.
* You can then attach these accounts to invoices being generated so the customer always receives the same account number for any invoice he receives.
* These accounts are slightly different from regular customer reserved accounts as customers cannot pay into these accounts until they are attached to an invoice.
* Basically, the account number is only active when attached to an invoice.
*
* <strong>NB</strong>
* <em>Only one invoice can be attached to a Reserved Account at a time.</em>
*
* @param string $accountName Reserved Account Name
* @param string $customerName Full name of the customer
* @param string $customerEmail Email address of the customer
* @param string $accountReference Merchant's Unique reference for the Account.
* @param string|null $currencyCode
*
* @return object
*
* @throws MonnifyFailedRequestException
* @link https://teamapt.atlassian.net/wiki/spaces/MON/pages/212008993/Reserved+Account+Invoicing
*/
public function reservedAccountInvoicing(string $accountName, string $customerName, string $customerEmail, string $accountReference, string $currencyCode = null)
{
$endpoint = "{$this->monnify->baseUrl}{$this->monnify->v1}bank-transfer/reserved-accounts";

$response = $this->monnify->withBasicAuth()->post($endpoint, [
"contractCode" => $this->config['contract_code'],
"accountName" => trim($accountName),
"currencyCode" => $currencyCode ?? $this->config['default_currency_code'],
"accountReference" => $accountReference,
"customerEmail" => $customerEmail,
"customerName" => trim($customerName),
"reservedAccountType" => "INVOICE",
]);

$responseObject = json_decode($response->body());
if (!$response->successful())
throw new MonnifyFailedRequestException($responseObject->responseMessage ?? "Path '{$responseObject->path}' {$responseObject->error}", $responseObject->responseCode ?? $responseObject->status);

return $responseObject->responseBody;
}


}
10 changes: 10 additions & 0 deletions src/Monnify.php
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,16 @@ public function Disbursements(): Disbursements
return $this->disbursements;
}

private $invoice;

public function Invoice(): Invoice
{
if (is_null($this->invoice))
$this->invoice = new class($this, $this->config) extends Invoice {
};
return $this->invoice;
}

private $subAccounts;

public function SubAccounts(): SubAccounts
Expand Down

0 comments on commit 1f64ddf

Please sign in to comment.