From f1dd68a737eef2a357ad99076462d1ee90f7fa35 Mon Sep 17 00:00:00 2001 From: Deon George Date: Sat, 10 Aug 2024 22:17:21 +1000 Subject: [PATCH] Fixes for cart and payment/paypal processing --- app/Http/Controllers/CheckoutController.php | 52 +++++-- app/Http/Controllers/PaymentController.php | 2 +- app/Http/Controllers/PaypalController.php | 84 +++++++---- app/Http/Requests/CheckoutAddEdit.php | 4 +- app/Http/Requests/PaymentAddEdit.php | 4 +- .../backend/adminlte/checkout/cart.blade.php | 140 ++++++++++++++++++ .../backend/adminlte/invoice/view.blade.php | 45 +++--- .../backend/adminlte/u/invoice/cart.blade.php | 109 -------------- routes/api.php | 5 +- routes/web.php | 15 +- 10 files changed, 271 insertions(+), 189 deletions(-) create mode 100644 resources/views/theme/backend/adminlte/checkout/cart.blade.php delete mode 100644 resources/views/theme/backend/adminlte/u/invoice/cart.blade.php diff --git a/app/Http/Controllers/CheckoutController.php b/app/Http/Controllers/CheckoutController.php index 76c0097..c9f82cb 100644 --- a/app/Http/Controllers/CheckoutController.php +++ b/app/Http/Controllers/CheckoutController.php @@ -42,27 +42,53 @@ class CheckoutController extends Controller ->with('success','Checkout saved'); } - public function cart_invoice(Request $request,Invoice $o=NULL) + /** + * Add an invoice to the cart + * + * @param Request $request + * @param Invoice $o + * @return \Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Foundation\Application + * @note The route validates that the user can see the invoice + */ + public function cart_invoice(Request $request,Invoice $o) { - if ($o) { - $request->session()->put('invoice.cart.'.$o->id,$o->id); + $request->session()->put('invoice.cart.'.$o->id,$o->id); + + return view('theme.backend.adminlte.checkout.cart'); + } + + /** + * Remove an item from the cart + * + * @param Request $request + * @return string + */ + public function cart_remove(Request $request): string + { + if ($id=$request->post('id')) { + $cart = $request->session()->pull('invoice.cart'); + unset($cart[$id]); + + $request->session()->put('invoice.cart',$cart); } - if (! $request->session()->get('invoice.cart')) - return redirect() - ->to('u/home'); - - return view('theme.backend.adminlte.u.invoice.cart') - ->with('invoices',Invoice::find(array_values($request->session()->get('invoice.cart')))); + return ''; } - public function fee(Request $request,Checkout $o): float + public function fee(Request $request): float { - return $o->fee($request->post('total',0)); + if ((! $request->post('checkout_id') || (! $request->post('total')))) + return 0; + + $co = Checkout::findOrFail($request->post('checkout_id')); + + return $co->fee($request->post('total')); } - public function pay(Request $request,Checkout $o) + public function pay() { - return redirect('pay/paypal/authorise'); + // @todo Currently sending all payments to paypal + return redirect() + ->action([PaypalController::class,'authorise']); } } \ No newline at end of file diff --git a/app/Http/Controllers/PaymentController.php b/app/Http/Controllers/PaymentController.php index d002f70..b245ad5 100644 --- a/app/Http/Controllers/PaymentController.php +++ b/app/Http/Controllers/PaymentController.php @@ -3,9 +3,9 @@ namespace App\Http\Controllers; use Illuminate\Http\RedirectResponse; +use Illuminate\Support\Arr; use App\Http\Requests\PaymentAddEdit; -use Illuminate\Support\Arr; use App\Models\{Payment,PaymentItem}; class PaymentController extends Controller diff --git a/app/Http/Controllers/PaypalController.php b/app/Http/Controllers/PaypalController.php index 02e83aa..3bba17c 100644 --- a/app/Http/Controllers/PaypalController.php +++ b/app/Http/Controllers/PaypalController.php @@ -2,8 +2,8 @@ namespace App\Http\Controllers; -use App\Models\PaymentItem; use Carbon\Carbon; +use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Support\Facades\Log; use PayPalCheckoutSdk\Core\PayPalHttpClient; @@ -13,14 +13,13 @@ use PayPalCheckoutSdk\Orders\OrdersCreateRequest; use PayPalCheckoutSdk\Orders\OrdersCaptureRequest; use PayPalHttp\HttpException; -use App\Models\Checkout; -use App\Models\Invoice; -use App\Models\Payment; +use App\Models\{Checkout,Invoice,Payment,PaymentItem}; class PaypalController extends Controller { - private $client; - private $o = NULL; + private PayPalHttpClient $client; + + protected const cart_url = 'u/checkout/cart'; // Create a new instance with our paypal credentials public function __construct() @@ -31,27 +30,30 @@ class PaypalController extends Controller $environment = new ProductionEnvironment(config('paypal.live_client_id'),config('paypal.live_secret')); $this->client = new PayPalHttpClient($environment); - $this->o = Checkout::where('name','paypal')->firstOrFail(); } - public function cancel(Request $request) + public function cancel() { - return redirect()->to('u/invoice/cart'); + return redirect() + ->to(self::cart_url); } /** * Authorize a paypal payment, and redirect the user to pay. * - * @param Request $request - * @return \Illuminate\Http\RedirectResponse + * @return RedirectResponse + * @throws \PayPalHttp\IOException */ - public function authorise(Request $request) + public function authorise() { + $co = Checkout::where('name','ilike','paypal')->firstOrFail(); + $currency = 'AUD'; // @todo TO determine from DB.; - $cart = $request->session()->get('invoice.cart'); + $cart = request()->session()->get('invoice.cart'); if (! $cart) - return redirect()->to('u/home'); + return redirect() + ->to('u/home'); $invoices = Invoice::find($cart); @@ -61,7 +63,7 @@ class PaypalController extends Controller // Paypal Purchase Units $items = collect(); foreach ($invoices as $io) { - $fee = $this->o->fee($io->due,count($cart)); + $fee = $co->fee($io->due,count($cart)); $total = round($io->due+$fee,2); $items->push([ @@ -100,7 +102,7 @@ class PaypalController extends Controller $data->put('application_context',[ 'return_url' => url('pay/paypal/capture'), - 'cancel_url' => url('u/invoice/cart'), + 'cancel_url' => url(self::cart_url), ]); $paypal->body = $data->toArray(); @@ -111,12 +113,16 @@ class PaypalController extends Controller } catch (HttpException $e) { Log::error('Paypal Exception',['request'=>$paypal,'response'=>$e->getMessage()]); - return redirect()->to('u/invoice/cart')->withErrors('Paypal Exception: '.$e->getCode()); + return redirect() + ->to(self::cart_url) + ->withErrors('Paypal Exception: '.$e->getCode()); } catch (\HttpException $e) { - Log::error('HTTP Exception',['request'=>$request,'response'=>$e->getMessage()]); + Log::error('HTTP Exception',['request'=>$this->client,'response'=>$e->getMessage()]); - return redirect()->to('u/invoice/cart')->withErrors('HTTP Exception: '.$e->getCode()); + return redirect() + ->to(self::cart_url) + ->withErrors('HTTP Exception: '.$e->getCode()); } // Get the approval link @@ -128,18 +134,21 @@ class PaypalController extends Controller } } - if ($redirect_url) { - return redirect()->away($redirect_url); - } + if ($redirect_url) + return redirect() + ->away($redirect_url); - return redirect()->to('u/invoice/cart')->withErrors('An error occurred with Paypal?'); + return redirect() + ->to(self::cart_url) + ->withErrors('An error occurred with Paypal?'); } /** * Capture a paypal payment * * @param Request $request - * @return \Illuminate\Http\RedirectResponse + * @return RedirectResponse + * @throws \PayPalHttp\IOException */ public function capture(Request $request) { @@ -179,23 +188,32 @@ class PaypalController extends Controller if ($redirect_url) { Log::error('Paypal Capture: Redirect back to Paypal.'); - return redirect()->away($redirect_url); + return redirect() + ->away($redirect_url); } - return redirect()->to('u/invoice/cart')->withErrors('An error occurred with Paypal?'); + return redirect() + ->to(self::cart_url) + ->withErrors('An error occurred with Paypal?'); } catch (\HttpException $e) { Log::error('HTTP Exception',['request'=>$paypal,'response'=>$e->getMessage()]); - return redirect()->to('u/invoice/cart')->withErrors('HTTP Exception: '.$e->getCode()); + return redirect() + ->to(self::cart_url) + ->withErrors('HTTP Exception: '.$e->getCode()); } - if (! $response OR ! $response->result->purchase_units) { + if ((! $response) || (! $response->result->purchase_units)) { Log::error('Paypal Capture: No Purchase Units?'); - return redirect()->to('u/invoice/cart')->withErrors('Paypal Exception: NPU'); + return redirect() + ->to(self::cart_url) + ->withErrors('Paypal Exception: NPU'); } + $co = Checkout::where('name','ilike','paypal')->firstOrFail(); + // If we got here, we got a payment foreach ($response->result->purchase_units as $pu) { foreach ($pu->payments->captures as $cap) { @@ -219,7 +237,7 @@ class PaypalController extends Controller } $po->paid_at = Carbon::parse($cap->create_time); - $po->checkout_id = $this->o->id; + $po->checkout_id = $co->id; $po->checkout_data = $cap->id; list($account_id,$fee) = explode(':',$cap->custom_id); @@ -246,7 +264,11 @@ class PaypalController extends Controller } $request->session()->forget('invoice.cart'); + Log::info('Paypal Payment Recorded',['po'=>$po->id]); - return redirect()->to('u/home')->with('success','Payment recorded thank you.'); + + return redirect() + ->to('u/home') + ->with('success','Payment recorded thank you.'); } } \ No newline at end of file diff --git a/app/Http/Requests/CheckoutAddEdit.php b/app/Http/Requests/CheckoutAddEdit.php index 8076a3c..1d3d124 100644 --- a/app/Http/Requests/CheckoutAddEdit.php +++ b/app/Http/Requests/CheckoutAddEdit.php @@ -3,7 +3,7 @@ namespace App\Http\Requests; use Illuminate\Foundation\Http\FormRequest; -use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Gate; use Illuminate\Validation\Rule; /** @@ -18,7 +18,7 @@ class CheckoutAddEdit extends FormRequest */ public function authorize() { - return Auth::user()->isWholesaler(); + return Gate::allows('wholesaler'); } /** diff --git a/app/Http/Requests/PaymentAddEdit.php b/app/Http/Requests/PaymentAddEdit.php index 4c8d3ee..eb13c2b 100644 --- a/app/Http/Requests/PaymentAddEdit.php +++ b/app/Http/Requests/PaymentAddEdit.php @@ -3,7 +3,7 @@ namespace App\Http\Requests; use Illuminate\Foundation\Http\FormRequest; -use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Gate; use App\Models\Invoice; @@ -19,7 +19,7 @@ class PaymentAddEdit extends FormRequest */ public function authorize() { - return Auth::user()->isWholesaler(); + return Gate::allows('wholesaler'); } /** diff --git a/resources/views/theme/backend/adminlte/checkout/cart.blade.php b/resources/views/theme/backend/adminlte/checkout/cart.blade.php new file mode 100644 index 0000000..c5e2e99 --- /dev/null +++ b/resources/views/theme/backend/adminlte/checkout/cart.blade.php @@ -0,0 +1,140 @@ +@use(App\Models\Checkout) +@use(App\Models\Invoice) + +@extends('adminlte::layouts.app') + +@section('htmlheader_title') + Payment Cart +@endsection +@section('page_title') + Payments +@endsection + +@section('contentheader_title') + Payment Cart +@endsection +@section('contentheader_description') +@endsection + +@section('main-content') +
+
+
+
+ Invoices to Pay +
+ +
+
+ @csrf + + + + + + + + + + + + + @foreach (($invoices=Invoice::whereIn('id',session('invoice.cart',[]))->get()) as $io) + + + + + + @endforeach + + + + + + + + + + + + + + + + + + +
InvoiceBalance Due
{{ $io->sid }}{{ number_format($io->due,2) }}
Sub Total{{ number_format($invoices->sum('due'),2) }}
Payment FeesTBA
Payment TotalTBA
+ + + Pay + Add Invoice +
+ +
+
+
+
+ + +@endsection + +@section('page-scripts') + +@append \ No newline at end of file diff --git a/resources/views/theme/backend/adminlte/invoice/view.blade.php b/resources/views/theme/backend/adminlte/invoice/view.blade.php index c3a7979..30de294 100644 --- a/resources/views/theme/backend/adminlte/invoice/view.blade.php +++ b/resources/views/theme/backend/adminlte/invoice/view.blade.php @@ -18,9 +18,7 @@ @endsection @section('main-content') -
-

@@ -31,10 +29,8 @@

Tax Invoice

-

-
@@ -84,12 +80,10 @@
- -
-
- +
+
@@ -144,15 +138,11 @@
Qty
-
- -
-

Payment Methods:

@@ -172,7 +162,6 @@

-
@@ -213,18 +202,14 @@ @endif
-
-
- +@endsection -
-@endsection \ No newline at end of file +@section('page-styles') + +@append +@section('page-scripts') + +@append \ No newline at end of file diff --git a/resources/views/theme/backend/adminlte/u/invoice/cart.blade.php b/resources/views/theme/backend/adminlte/u/invoice/cart.blade.php deleted file mode 100644 index ec3ab60..0000000 --- a/resources/views/theme/backend/adminlte/u/invoice/cart.blade.php +++ /dev/null @@ -1,109 +0,0 @@ -@extends('adminlte::layouts.app') - -@section('htmlheader_title') - Payment Cart -@endsection -@section('page_title') - Payments -@endsection - -@section('contentheader_title') - Payment Cart -@endsection -@section('contentheader_description') -@endsection - -@section('main-content') -
-
-
-
- Invoices to Pay -
- -
-
- @csrf - - - -
-
- Payment Method -
- - -
- - - - - - - - @foreach ($invoices as $io) - - - - - - @endforeach - - - - - - - - - - - - - - - - - - -
InvoiceBalance Due
{{ $io->sid }}{{ number_format($io->due,2) }}
Sub Total{{ number_format($invoices->sum('due'),2) }}
Payment FeesTBA
Payment TotalTBA
- - - Add Invoice -
-
-
-
-
-
-@endsection - -@section('page-scripts') - -@append \ No newline at end of file diff --git a/routes/api.php b/routes/api.php index 3241dbc..0dd8e8a 100644 --- a/routes/api.php +++ b/routes/api.php @@ -25,10 +25,7 @@ Route::group(['middleware'=>['auth:api','role:wholesaler']], function() { }); Route::group(['middleware'=>'auth:api'], function() { - Route::post('/u/checkout/fee/{o}',[CheckoutController::class,'fee']) - ->where('o','[0-9]+'); - - Route::any('/intuit/accounting/list',[AccountingController::class,'list']); + Route::any('/intuit/accounting/list',[AccountingController::class,'list']); }); Route::any('/intuit/webhook',[Webhook::class,'webhook']); \ No newline at end of file diff --git a/routes/web.php b/routes/web.php index eb1c682..8a97d16 100644 --- a/routes/web.php +++ b/routes/web.php @@ -180,17 +180,22 @@ Route::group(['middleware'=>['auth'],'prefix'=>'u'],function() { Route::get('home/{o}',[HomeController::class,'home']) ->where('o','[0-9]+') ->middleware('can:view,o'); - Route::redirect('checkout/pay','pay/paypal/authorise'); + + Route::view('checkout/cart','theme.backend.adminlte.checkout.cart'); + Route::get('checkout/cart/{o}',[CheckoutController::class,'cart_invoice']) + ->where('o','[0-9]+') + ->middleware('can:view,o'); + Route::post('checkout/cart/remove',[CheckoutController::class,'cart_remove']); + Route::post('checkout/fee',[CheckoutController::class,'fee']); + Route::post('checkout/pay',[CheckoutController::class,'pay']); + Route::get('invoice/{o}',[InvoiceController::class,'view']) ->where('o','[0-9]+') ->middleware('can:view,o'); Route::get('invoice/{o}/pdf',[InvoiceController::class,'pdf']) ->where('o','[0-9]+') ->middleware('can:view,o'); - Route::get('invoice/cart',[CheckoutController::class,'cart_invoice']); - Route::get('invoice/cart/{o}',[CheckoutController::class,'cart_invoice']) - ->where('o','[0-9]+') - ->middleware('can:view,o'); + Route::get('service/{o}',[ServiceController::class,'home']) ->where('o','[0-9]+') ->middleware('can:view,o');