integrate create billplz bill with create booking payment, and a new billplz callback url

This commit is contained in:
ahmedsophyudden
2021-10-04 15:09:36 +08:00
parent 376d2dd686
commit fb84e47d43
11 changed files with 262 additions and 6 deletions
+3 -1
View File
@@ -54,5 +54,7 @@ IS_PRODUCTION=false
BILLPLZ_BASE_URL="https://www.billplz-sandbox.com"
BILLPLZ_API_KEY="0fa4c710-761b-4a7a-a501-c2c2d02643d5"
BILLPLZ_X_SIGNATURE_KEY="S-pbNVthVRsvnPfZlgLwqqOg"
BILLPLZ_COLLECTION_ID="hev2wdjy"
BILLPLZ_CALLBACK_URL="localhost:9003"
BILLPLZ_REDIRECT_URL="localhost:9003"
BILLPLZ_CALLBACK_URL="localhost:9003/api/v1/billplz/callback"
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class PaymentReference implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('payment_reference', $value);
}
}
@@ -0,0 +1,71 @@
<?php
namespace App\Classes\Modules\Billplzs\ControllersLogic;
use ErrorException;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\Modules\Billplzs\Services\GetBillplzBill;
use App\Classes\Modules\Billplzs\DataTransferObjects\BillplzXSignatureObject;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
class CallbackBillplzLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Callback Billplz',
'message' => 'You have successfully receive Billplz callback'
];
}
/** @var GetBillplzBill */
private $getBillplzBill;
/** @var UpdatesTransactionStatus */
private $updatesTransactionStatus;
/**
* CreateBookingLogic constructor.
* @param CreateGetBillplzBillsBillplzBill $getBillplzBill
* @param UpdatesTransactionStatus $updatesTransactionStatus
*/
public function __construct(GetBillplzBill $getBillplzBill, UpdatesTransactionStatus $updatesTransactionStatus)
{
$this->getBillplzBill = $getBillplzBill;
$this->updatesTransactionStatus = $updatesTransactionStatus;
}
/**
* @param Request $request
* @return JsonResponse
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function logic(Request $request) : JsonResponse
{
$billplzXSignatureObject = new BillplzXSignatureObject($request);
if(!$billplzXSignatureObject->isValidSignature()) throw new MalformedRequestException('Unable to get correct response from billplz server.');
$billPlz = $this->getBillplzBill->execute($request->input('id'));
if(!$billPlz) throw new MalformedRequestException('Unable to get correct response from billplz server.');
if($billPlz->state == 'paid') $this->updatesTransactionStatus->execute($transaction, ApprovalStatus::PENDING_VERIFICATION);
return $this->response(['data' => $billPlz]);
}
}
@@ -0,0 +1,88 @@
<?php
namespace App\Classes\Modules\Billplzs\DataTransferObjects;
use Illuminate\Http\Request;
use App\Classes\General\Interfaces\DataTransferObject;
class BillplzXSignatureObject implements DataTransferObject
{
/** @var array */
private $billPlzConstructArray;
/** @var string */
private $billPlzConstructString;
/** @var string */
private $billPlzComputedXSignature;
/** @var Request */
private $request;
public function __construct(Request $request)
{
$this->request = $request;
$this->_constructBillplzArray()->_natSortBillplzArray()->_constructBillplzString()->_computeBillplzXSignature();
}
private function _constructBillplzArray(){
foreach($this->request->all() as $key => $value){
if($key != 'x_signature'){
$this->billPlzConstructArray[] = $key.$value;
}
}
return $this;
}
private function _natCaseSortBillplzArray(){
natcasesort($this->billPlzConstructArray);
return $this;
}
private function _natSortBillplzArray(){
natsort($this->billPlzConstructArray);
return $this;
}
private function _constructBillplzString(){
$this->billPlzConstructString = implode('|', $this->billPlzConstructArray);
return $this;
}
private function _computeBillplzXSignature(){
$this->billPlzComputedXSignature = hash_hmac('sha256', $this->billPlzConstructString, config('billplz.x_signature_key'));
return $this;
}
/**
* @return array
*/
public function getBillPlzConstructArray(): array
{
return $this->billPlzConstructArray;
}
/**
* @return string
*/
public function getBillPlzConstructString(): string
{
return $this->billPlzConstructString;
}
/**
* @return string
*/
public function getBillPlzComputedXSignature(): string
{
return $this->billPlzComputedXSignature;
}
public function isValidSignature(): bool
{
return $this->billPlzComputedXSignature == $this->request->x_signature ? true : false;
}
}
@@ -10,7 +10,7 @@ class CreatesBillplzBill
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(string $name, string $email, string $description, float $amount, string $bank_code) {
public function execute(string $name, string $email, string $description, float $amount, string $bankCode, string $billNumber) {
try{
$response = Http::withBasicAuth(config('billplz.api_key').':', '')->post(config('billplz.base_url').'/api/v3/bills', [
'collection_id' => config('billplz.collection_id'),
@@ -18,9 +18,12 @@ class CreatesBillplzBill
'email' => $email,
'description' => $description,
'amount' => $amount,
'redirect_url' => config('billplz.redirect_url'),
'callback_url' => config('billplz.callback_url'),
'reference_1_label' => 'Bank Code',
'reference_1' => config('billplz.'.strtolower($bank_code))
'reference_1' => $bankCode,
'reference_2_label' => 'Bill Number',
'reference_2' => $billNumber
]);
if($response->successful()){
@@ -28,7 +31,7 @@ class CreatesBillplzBill
$data['url'] = $data['url'].'?auto_submit=true';
return $data;
return (object) $data;
}else{
return null;
}
@@ -0,0 +1,28 @@
<?php
namespace App\Classes\Modules\Billplzs\Services;
use Illuminate\Support\Facades\Http;
class GetBillplzBill
{
/**
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(string $billPlzId) {
try{
$response = Http::withBasicAuth(config('billplz.api_key').':', '')->get(config('billplz.base_url').'/api/v3/bills/'.$billPlzId);
if($response->successful()){
$data = $response->json();
return (object) $data;
}else{
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from billplz server');
}
}
}
@@ -11,7 +11,9 @@ use App\Classes\Modules\Companies\Services\FetchesCompanyPaymentAttemptLimit;
use App\Classes\Modules\Currencies\DataTransferObjects\CurrencyConversionObject;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject;
use App\Classes\Modules\Transactions\Services\CreatesTransaction;
use App\Classes\Modules\Transactions\Services\UpdatesTransaction;
use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber;
use App\Classes\Modules\Billplzs\Services\CreatesBillplzBill;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\ValueObjects\Constants\TransactionType;
@@ -46,9 +48,15 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic
/** @var CreatesTransaction */
private $createsTransaction;
/** @var UpdatesTransaction */
private $updatesTransaction;
/** @var CalculatesBookingOutstanding */
private $calculatesBookingOutstanding;
/** @var CreatesBillplzBill */
private $createsBillplzBill;
/**
* CreateBookingPaymentLogic constructor.
* @param FetchesBookingQuotation $fetchBookingQuotation
@@ -56,14 +64,17 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic
* @param GeneratesTransactionBillNumber $generatesTransactionBillNumber
* @param CreatesTransaction $createsTransaction
* @param CalculatesBookingOutstanding $calculatesBookingOutstanding
* @param CreatesBillplzBill $createsBillplzBill
*/
public function __construct(FetchesBookingQuotation $fetchBookingQuotation, FetchesCompanyPaymentAttemptLimit $fetchesCompanyPaymentAttemptLimit, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatesTransaction $createsTransaction, CalculatesBookingOutstanding $calculatesBookingOutstanding)
public function __construct(FetchesBookingQuotation $fetchBookingQuotation, FetchesCompanyPaymentAttemptLimit $fetchesCompanyPaymentAttemptLimit, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatesTransaction $createsTransaction, UpdatesTransaction $updatesTransaction, CalculatesBookingOutstanding $calculatesBookingOutstanding, CreatesBillplzBill $createsBillplzBill)
{
$this->fetchBookingQuotation = $fetchBookingQuotation;
$this->fetchesCompanyPaymentAttemptLimit = $fetchesCompanyPaymentAttemptLimit;
$this->generatesTransactionBillNumber = $generatesTransactionBillNumber;
$this->createsTransaction = $createsTransaction;
$this->updatesTransaction = $updatesTransaction;
$this->calculatesBookingOutstanding = $calculatesBookingOutstanding;
$this->createsBillplzBill = $createsBillplzBill;
}
/**
@@ -88,11 +99,15 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic
$billNumber = $this->generatesTransactionBillNumber->execute('PYMT-');
if(PaymentMethodType::PAYMENT_METHODS[$request->input('payment_method')] == PaymentMethodType::PAYMENT_GATEWAY){
$billPlzBill = $this->createsBillplzBill->execute($request->user()->name, $request->user()->email, 'This payment is made on behave '.$booking->company->name, $configurations->getTotal(), $request->input('bank_code'), $billNumber);
}
$object = new TransactionObject($billNumber, TransactionType::PAYMENT, 1, $booking->company->id,
$configurations->getConfigurations()->getBankId(), $configurations->getConversionObject()->getPaymentMethod(),
$configurations->getTotal(), $configurations->getForeignTotal(), 1,
$configurations->getConversionObject()->getCurrencyId(), $configurations->getConfigurations()->getRate(),
$configurations->getTax(), $configurations->getServiceCharge(), Carbon::now()->addMinutes($paymentAttemptLimit), ApprovalStatus::PENDING_SUBMISSION);
$configurations->getTax(), $configurations->getServiceCharge(), Carbon::now()->addMinutes($paymentAttemptLimit), ApprovalStatus::PENDING_SUBMISSION, [], isset($billPlzBill) ? $billPlzBill->id : NULL);
$transaction = $this->createsTransaction->execute($booking, $object);
@@ -0,0 +1,20 @@
<?php
namespace App\Http\Controllers\Billplzs;
use App\Classes\Modules\Billplzs\ControllersLogic\CallbackBillplzLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class CallbackBillplzController
{
/**
* @param Request $request
* @param BillplzBillLogic $logic
* @return JsonResponse
*/
public function callback(Request $request, CallbackBillplzLogic $logic): JsonResponse {
return $logic->execute($request);
}
}
+1
View File
@@ -23,6 +23,7 @@ class BookingResource extends JsonResource
*/
public function toArray($request)
{
// dd($this->service);
return [
'id' => $this->id,
'company' => new CompanyResource($this->company),
+2
View File
@@ -3,7 +3,9 @@
return [
'base_url' => env('BILLPLZ_BASE_URL', 'https://www.billplz-sandbox.com'),
'api_key' => env('BILLPLZ_API_KEY', '0fa4c710-761b-4a7a-a501-c2c2d02643d5'),
'x_signature_key' => env('BILLPLZ_X_SIGNATURE_KEY', 'S-pbNVthVRsvnPfZlgLwqqOg'),
'collection_id' => env('BILLPLZ_COLLECTION_ID', 'hev2wdjy'),
'redirect_url' => env('BILLPLZ_REDIRECT_URL', 'localhost'),
'callback_url' => env('BILLPLZ_CALLBACK_URL', 'localhost'),
'maybank' => 'MB2U0227',
'cimb' => 'BCBB0235'
+6
View File
@@ -23,6 +23,12 @@ Route::group(['middleware' => 'api', 'prefix' => 'v1', 'as' => 'api.'], function
Route::get('countries/list', 'Services\CountriesListController@index')->name('list.countries');
});
Route::group(['prefix' => 'billplz', 'as' => 'billplz.', 'namespace' => 'Billplzs'], function () {
Route::group(['prefix' => 'bill', 'as' => 'bill.'], function () {
Route::post('/callback', 'CallbackBillplzController@callback')->name('callback');
});
});
Route::group(['middleware' => 'valid.token'], function () {