'Create Payment Booking', 'message' => 'You have successfully created a payment booking' ]; } /** @var FetchesBookingQuotation */ private $fetchBookingQuotation; /** @var FetchesCompanyPaymentAttemptLimit */ private $fetchesCompanyPaymentAttemptLimit; /** @var GeneratesTransactionBillNumber */ private $generatesTransactionBillNumber; /** @var CreatesTransaction */ private $createsTransaction; /** @var CalculatesBookingOutstanding */ private $calculatesBookingOutstanding; /** @var CreatesBillplzBill */ private $createsBillplzBill; /** @var UpdatesWalletBalance */ private $updatesWalletBalance; /** @var UpdatesTransactionStatus */ private $updatesTransactionStatus; /** @var RecalculatesWalletBalance */ private $recalculatesWalletBalance; /** @var BookingToVoucherifyProcessor */ private $bookingToVoucherifyProcessor; /** @var CalculatesBookingRefundAmount */ private $calculatesBookingRefundAmount; /** * @param FetchesBookingQuotation $fetchBookingQuotation * @param FetchesCompanyPaymentAttemptLimit $fetchesCompanyPaymentAttemptLimit * @param GeneratesTransactionBillNumber $generatesTransactionBillNumber * @param CreatesTransaction $createsTransaction * @param CalculatesBookingOutstanding $calculatesBookingOutstanding * @param CreatesBillplzBill $createsBillplzBill * @param UpdatesWalletBalance $updatesWalletBalance * @param UpdatesTransactionStatus $updatesTransactionStatus * @param RecalculatesWalletBalance $recalculatesWalletBalance * @param BookingToVoucherifyProcessor $bookingToVoucherifyProcessor * @param CalculatesBookingRefundAmount $calculatesBookingRefundAmount */ public function __construct(FetchesBookingQuotation $fetchBookingQuotation, FetchesCompanyPaymentAttemptLimit $fetchesCompanyPaymentAttemptLimit, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatesTransaction $createsTransaction, CalculatesBookingOutstanding $calculatesBookingOutstanding, CreatesBillplzBill $createsBillplzBill, UpdatesWalletBalance $updatesWalletBalance, UpdatesTransactionStatus $updatesTransactionStatus, CreateCashBackTransactionProcessor $createCashBackTransactionProcessor, RecalculatesWalletBalance $recalculatesWalletBalance, BookingToVoucherifyProcessor $bookingToVoucherifyProcessor, CalculatesBookingRefundAmount $calculatesBookingRefundAmount) { $this->fetchBookingQuotation = $fetchBookingQuotation; $this->fetchesCompanyPaymentAttemptLimit = $fetchesCompanyPaymentAttemptLimit; $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; $this->createsTransaction = $createsTransaction; $this->calculatesBookingOutstanding = $calculatesBookingOutstanding; $this->createsBillplzBill = $createsBillplzBill; $this->updatesWalletBalance = $updatesWalletBalance; $this->updatesTransactionStatus = $updatesTransactionStatus; $this->recalculatesWalletBalance = $recalculatesWalletBalance; $this->bookingToVoucherifyProcessor = $bookingToVoucherifyProcessor; $this->calculatesBookingRefundAmount = $calculatesBookingRefundAmount; } public function logic(Request $request) : JsonResponse { $voucherCode = $request->input('voucher_code'); $booking = Booking::find($request->route('id')); $conversionObject = $this->createConversionObject($request, $booking); $this->validatePayment($request, $booking, $conversionObject); $configurations = $this->fetchBookingQuotation->execute($booking->company, $conversionObject, $request->input('voucher_code')); $billNumber = $this->generatesTransactionBillNumber->execute('PYMT-'); $paymentReference = $this->handlePaymentMethods($request, $booking, $configurations, $billNumber); $billNumber = $this->generatesTransactionBillNumber->execute('PYMT-'); $object = $this->createTransactionObject($booking, $configurations, $billNumber, $paymentReference); /** @var Transaction $transaction */ $transaction = $this->createsTransaction->execute($booking, $object); $this->bookingToVoucherifyProcessor->execute($booking->company->employees()->first(), $transaction, $booking->company->id, $configurations->getSubTotal(), $configurations->getVoucherDiscountAmount(), $voucherCode); if(PaymentMethodType::PAYMENT_METHODS[$request->input('payment_method')] == PaymentMethodType::PAYMENT_GATEWAY){ $this->updatesTransactionStatus->execute($transaction, ApprovalStatus::PENDING_VERIFICATION); } if(PaymentMethodType::PAYMENT_METHODS[$request->input('payment_method')] == PaymentMethodType::WALLET){ $this->updatesTransactionStatus->execute($transaction, ApprovalStatus::APPROVED); } return $this->resourceResponse(new TransactionResource($transaction)); } private function createConversionObject(Request $request, Booking $booking): CurrencyConversionObject { return new CurrencyConversionObject( floatval(str_replace(',', '', $request->input('amount'))), $booking->convertible_currency_id, $booking->service_id, $booking->fix_currency_id === 1 ? 0:1, PaymentMethodType::PAYMENT_METHODS[$request->input('payment_method')] ); } private function validatePayment(Request $request, Booking $booking, CurrencyConversionObject $conversionObject): void { $outstanding = $this->calculatesBookingOutstanding->execute($booking) + $this->calculatesBookingRefundAmount->execute($booking, $booking->fix_currency_id); if($conversionObject->getAmount() > round($outstanding, 2)) throw new MalformedRequestException('Your payment must not be greater than '. $outstanding .'.'); } private function handlePaymentMethods(Request $request, Booking $booking, CalculationObject $configurations, string $billNumber): ?string { $paymentReference = null; if(PaymentMethodType::PAYMENT_METHODS[$request->input('payment_method')] == PaymentMethodType::PAYMENT_GATEWAY) $paymentReference = $this->handlePaymentGateway($request, $booking, $configurations, $billNumber); if(PaymentMethodType::PAYMENT_METHODS[$request->input('payment_method')] == PaymentMethodType::WALLET) $paymentReference = $this->handleWalletPayment($request, $booking, $configurations, $billNumber); return $paymentReference; } private function handlePaymentGateway(Request $request, Booking $booking, CalculationObject $configurations, string $billNumber): string { $billPlzBill = $this->createsBillplzBill->execute( $booking->company->name, $request->user()->email, 'This payment is made for transfer ref. '.$booking->marking, $configurations->getTotal(), $billNumber, $request->input('bank_code') ); return $billPlzBill->id; } private function handleWalletPayment(Request $request, Booking $booking, CalculationObject $configurations, string $billNumber): string { $wallet = $booking->company->wallets()->first(); $amount = $configurations->getTotal(); if((float) number_format(($wallet->amount - $amount),2) < 0) throw new MalformedRequestException('Insufficient wallet balance. Please Top up your wallet.'); $transactionObject = new TransactionObject($billNumber, TransactionType::PAYMENT, 1, $booking->company->id, 1, PaymentMethodType::WALLET, $amount, $amount, 1, 1, 1, 0, 0, null, ApprovalStatus::APPROVED, [], ''); $this->createsTransaction->execute($wallet, $transactionObject); $walletBalance = $this->recalculatesWalletBalance->execute($wallet); $this->updatesWalletBalance->execute($wallet, $walletBalance); return $billNumber; } private function createTransactionObject(Booking $booking, CalculationObject $configurations, string $billNumber, ?string $paymentReference): TransactionObject { return 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($this->fetchesCompanyPaymentAttemptLimit->execute($booking->company)), ApprovalStatus::PENDING_SUBMISSION, [], $paymentReference ); } // private function handleVoucherCode(Request $request, Booking $booking, CalculationObject $configurations, Transaction $transaction): void // { // $voucherCode = $request->input('voucher_code'); // if($voucherCode){ // $employee = $booking->company->employees()->first(); // $result = $this->redeemsVoucher->execute($voucherCode, $configurations->getSubTotal(), $employee); // $voucher = $result->voucher; // $redemptionId = $result->id; // $voucherValue = $voucher->discount->amount_off ?? ($voucher->discount->percent_off ?? 0.00); // $voucherObject = new VoucherObject($voucher->code, $voucher->metadata->name ?? "", $voucher->discount->type, $voucherValue); // $voucher = $this->createsVoucher->execute($voucherObject); // if(!$voucher) // $voucher = $this->fetchesVoucher->execute(['code' => $voucherObject->getCode()]); // $this->createsVoucherRedemption->execute($redemptionId, $voucher->id, $employee->id, $configurations->getVoucherDiscountAmount()); // } // } }