Add paypal payments
This commit is contained in:
34
app/Http/Controllers/CheckoutController.php
Normal file
34
app/Http/Controllers/CheckoutController.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Invoice;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
use App\Models\Checkout;
|
||||
|
||||
class CheckoutController extends Controller
|
||||
{
|
||||
public function cart_invoice(Request $request,Invoice $o=NULL)
|
||||
{
|
||||
if ($o) {
|
||||
$request->session()->put('invoice.cart.'.$o->id,$o->id);
|
||||
}
|
||||
|
||||
if (! $request->session()->get('invoice.cart'))
|
||||
return redirect()->to('u/home');
|
||||
|
||||
return View('u.invoice.cart')
|
||||
->with('invoices',Invoice::find(array_values($request->session()->get('invoice.cart'))));
|
||||
}
|
||||
|
||||
public function fee(Request $request,Checkout $o): float
|
||||
{
|
||||
return $o->fee($request->post('total',0));
|
||||
}
|
||||
|
||||
public function pay(Request $request,Checkout $o)
|
||||
{
|
||||
return redirect('pay/paypal/authorise');
|
||||
}
|
||||
}
|
251
app/Http/Controllers/PaypalController.php
Normal file
251
app/Http/Controllers/PaypalController.php
Normal file
@@ -0,0 +1,251 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\PaymentItem;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use PayPalCheckoutSdk\Core\PayPalHttpClient;
|
||||
use PayPalCheckoutSdk\Core\ProductionEnvironment;
|
||||
use PayPalCheckoutSdk\Core\SandboxEnvironment;
|
||||
use PayPalCheckoutSdk\Orders\OrdersCreateRequest;
|
||||
use PayPalCheckoutSdk\Orders\OrdersCaptureRequest;
|
||||
use PayPalHttp\HttpException;
|
||||
|
||||
use App\Models\Checkout;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Payment;
|
||||
|
||||
class PaypalController extends Controller
|
||||
{
|
||||
private $client;
|
||||
private $o = NULL;
|
||||
|
||||
// Create a new instance with our paypal credentials
|
||||
public function __construct()
|
||||
{
|
||||
if (config('paypal.settings.mode') == 'sandbox')
|
||||
$environment = new SandboxEnvironment(config('paypal.sandbox_client_id'),config('paypal.sandbox_secret'));
|
||||
else
|
||||
$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)
|
||||
{
|
||||
return redirect()->to('u/invoice/cart');
|
||||
}
|
||||
|
||||
/**
|
||||
* Authorize a paypal payment, and redirect the user to pay.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function authorise(Request $request)
|
||||
{
|
||||
$currency = 'AUD'; // @todo TO determine from DB.;
|
||||
$cart = $request->session()->get('invoice.cart');
|
||||
|
||||
if (! $cart)
|
||||
return redirect()->to('u/home');
|
||||
|
||||
$invoices = Invoice::find($cart);
|
||||
|
||||
$paypal = new OrdersCreateRequest();
|
||||
$paypal->prefer('return=minimal');
|
||||
|
||||
// Paypal Purchase Units
|
||||
$items = collect();
|
||||
foreach ($invoices as $io) {
|
||||
$fee = $this->o->fee($io->due,count($cart));
|
||||
$total = round($io->due+$fee,2);
|
||||
|
||||
$items->push([
|
||||
'reference_id'=>$io->id,
|
||||
'invoice_id'=>$io->id,
|
||||
'description'=>'Invoice Payment',
|
||||
'custom_id'=>sprintf('%s:%s',$io->account_id,$fee*100),
|
||||
'amount'=>[
|
||||
'value'=>$total,
|
||||
'currency_code'=>$currency,
|
||||
'breakdown'=>[
|
||||
'item_total'=>[
|
||||
'value'=>$total,
|
||||
'currency_code'=>$currency,
|
||||
]
|
||||
],
|
||||
],
|
||||
'items'=>[
|
||||
[
|
||||
'name'=>'Invoice: '.$io->id,
|
||||
'unit_amount'=>[
|
||||
'value'=>$total,
|
||||
'currency_code'=>$currency,
|
||||
],
|
||||
'quantity'=>1,
|
||||
'description'=>'Invoice Payment',
|
||||
'category'=>'DIGITAL_GOODS',
|
||||
],
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
$data = collect();
|
||||
$data->put('intent','CAPTURE');
|
||||
$data->put('purchase_units',$items->toArray());
|
||||
|
||||
$data->put('application_context',[
|
||||
'return_url' => url('pay/paypal/capture'),
|
||||
'cancel_url' => url('u/invoice/cart'),
|
||||
]);
|
||||
|
||||
$paypal->body = $data->toArray();
|
||||
|
||||
try {
|
||||
$response = $this->client->execute($paypal);
|
||||
|
||||
} catch (HttpException $e) {
|
||||
Log::error('Paypal Exception',['request'=>$paypal,'response'=>$e->getMessage()]);
|
||||
|
||||
return redirect()->to('u/invoice/cart')->withErrors('Paypal Exception: '.$e->getCode());
|
||||
|
||||
} catch (\HttpException $e) {
|
||||
Log::error('HTTP Exception',['request'=>$request,'response'=>$e->getMessage()]);
|
||||
|
||||
return redirect()->to('u/invoice/cart')->withErrors('HTTP Exception: '.$e->getCode());
|
||||
}
|
||||
|
||||
// Get the approval link
|
||||
$redirect_url = '';
|
||||
foreach ($response->result->links as $link) {
|
||||
if ($link->rel == 'approve') {
|
||||
$redirect_url = $link->href;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($redirect_url) {
|
||||
return redirect()->away($redirect_url);
|
||||
}
|
||||
|
||||
return redirect()->to('u/invoice/cart')->withErrors('An error occurred with Paypal?');
|
||||
}
|
||||
|
||||
/**
|
||||
* Capture a paypal payment
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function capture(Request $request)
|
||||
{
|
||||
$paypal = new OrdersCaptureRequest($request->query('token'));
|
||||
$paypal->prefer('return=representation');
|
||||
|
||||
$redirect_url = '';
|
||||
|
||||
try {
|
||||
$response = $this->client->execute($paypal);
|
||||
|
||||
} catch (HttpException $e) {
|
||||
$result = json_decode($e->getMessage());
|
||||
|
||||
Log::error(sprintf('Paypal Declined: Code: %s, DebugID: %s, Name: %s,Message: %s',$e->getCode(),$result->debug_id,$result->name,$result->message));
|
||||
|
||||
switch ($result->name) {
|
||||
case 'UNPROCESSABLE_ENTITY':
|
||||
foreach ($result->details as $detail)
|
||||
Log::error(sprintf('Paypal Declined: Issue: %s Message: %s',$detail->issue,$detail->description));
|
||||
|
||||
// If we got a redirect link, lets redirect
|
||||
foreach ($result->links as $link) {
|
||||
if ($link->rel == 'redirect') {
|
||||
$redirect_url = $link->href;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
Log::error(sprintf('Paypal Unhandled: %s',$result));
|
||||
}
|
||||
|
||||
// If we got a redirect.
|
||||
if ($redirect_url) {
|
||||
Log::error('Paypal Capture: Redirect back to Paypal.');
|
||||
|
||||
return redirect()->away($redirect_url);
|
||||
}
|
||||
|
||||
return redirect()->to('u/invoice/cart')->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());
|
||||
}
|
||||
|
||||
if (! $response OR ! $response->result->purchase_units) {
|
||||
Log::error('Paypal Capture: No Purchase Units?');
|
||||
|
||||
return redirect()->to('u/invoice/cart')->withErrors('Paypal Exception: NPU');
|
||||
}
|
||||
|
||||
// If we got here, we got a payment
|
||||
foreach ($response->result->purchase_units as $pu) {
|
||||
foreach ($pu->payments->captures as $cap) {
|
||||
$po = new Payment;
|
||||
|
||||
switch ($cap->status) {
|
||||
case 'PENDING':
|
||||
$po->pending_status = TRUE;
|
||||
$po->pending = $cap->status_details->reason;
|
||||
break;
|
||||
|
||||
case 'FAILED':
|
||||
Log::error(sprintf('Paypal Payment Failed: Invoice: %s (%s).',$pu->invoice_id,$cap->error->details[0]->description));
|
||||
continue 2;
|
||||
|
||||
default:
|
||||
$po->pending_status = TRUE;
|
||||
$po->pending = $cap->status_details->reason ?? 'Unknown Status';
|
||||
break;
|
||||
}
|
||||
|
||||
$po->date_payment = Carbon::parse($cap->create_time);
|
||||
$po->checkout_id = $this->o->id;
|
||||
$po->checkout_data = $cap->id;
|
||||
|
||||
list($account_id,$fee) = explode(':',$cap->custom_id);
|
||||
$po->fees_amt = $fee/100;
|
||||
$po->total_amt = $cap->amount->value-$po->fees_amt;
|
||||
$po->account_id = $account_id;
|
||||
|
||||
$pio = new PaymentItem;
|
||||
$pio->site_id = 1; // @todo To implement
|
||||
$pio->invoice_id = $cap->invoice_id;
|
||||
$pio->alloc_amt = $cap->amount->value-$po->fees_amt;
|
||||
|
||||
$po->items->push($pio);
|
||||
|
||||
// @todo To store payment fees on invoice
|
||||
|
||||
try {
|
||||
$po->pushNew();
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Error recording payment',['po'=>$po,'e'=>$e->getMessage(),'token'=>$request->query('token')]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$request->session()->forget('invoice.cart');
|
||||
Log::info('Paypal Payment Recorded',['po'=>$po->id]);
|
||||
return redirect()->to('u/home')->with('success','Payment recorded thank you.');
|
||||
}
|
||||
}
|
@@ -38,6 +38,6 @@ class AccountController extends Controller
|
||||
$io->items->push($o);
|
||||
}
|
||||
|
||||
return View('u.invoice',['o'=>$io]);
|
||||
return View('u.invoice.home',['o'=>$io]);
|
||||
}
|
||||
}
|
@@ -55,7 +55,7 @@ class UserHomeController extends Controller
|
||||
*/
|
||||
public function invoice(Invoice $o): View
|
||||
{
|
||||
return View('u.invoice',['o'=>$o]);
|
||||
return View('u.invoice.home',['o'=>$o]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,7 +66,7 @@ class UserHomeController extends Controller
|
||||
*/
|
||||
public function invoice_pdf(Invoice $o)
|
||||
{
|
||||
return PDF::loadView('u.invoice', ['o'=>$o])->stream(sprintf('%s.pdf',$o->invoice_account_id));
|
||||
return PDF::loadView('u.invoice.home',['o'=>$o])->stream(sprintf('%s.pdf',$o->invoice_account_id));
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user