Merge pull request #4054 from turbo124/v2

Gateway fees and payments.
This commit is contained in:
David Bomba 2020-09-11 16:15:53 +10:00 committed by GitHub
commit f0bd089acb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 89 additions and 16 deletions

View File

@ -71,6 +71,7 @@ class CreateInvoicePdf implements ShouldQueue
public function handle() public function handle()
{ {
if (config('ninja.phantomjs_key')) { if (config('ninja.phantomjs_key')) {
return (new Phantom)->generate($this->invitation); return (new Phantom)->generate($this->invitation);
} }
@ -110,8 +111,6 @@ class CreateInvoicePdf implements ShouldQueue
//todo - move this to the client creation stage so we don't keep hitting this unnecessarily //todo - move this to the client creation stage so we don't keep hitting this unnecessarily
Storage::makeDirectory($path, 0775); Storage::makeDirectory($path, 0775);
//info($maker->getCompiledHTML(true));
$pdf = $this->makePdf(null, null, $maker->getCompiledHTML(true)); $pdf = $this->makePdf(null, null, $maker->getCompiledHTML(true));
$instance = Storage::disk($this->disk)->put($file_path, $pdf); $instance = Storage::disk($this->disk)->put($file_path, $pdf);

View File

@ -45,6 +45,8 @@ class InvoicePaidActivity implements ShouldQueue
{ {
MultiDB::setDb($event->company->db); MultiDB::setDb($event->company->db);
$event->invoice->service()->touchPdf();
$fields = new \stdClass; $fields = new \stdClass;
$fields->invoice_id = $event->invoice->id; $fields->invoice_id = $event->invoice->id;

View File

@ -136,6 +136,9 @@ class AuthorizeCreditCard
$response = $data['response']; $response = $data['response'];
if ($response != null && $response->getMessages()->getResultCode() == 'Ok') { if ($response != null && $response->getMessages()->getResultCode() == 'Ok') {
$this->authorize->confirmGatewayFee($request);
return $this->processSuccessfulResponse($data, $request); return $this->processSuccessfulResponse($data, $request);
} }

View File

@ -194,6 +194,24 @@ class BaseDriver extends AbstractPaymentDriver
}); });
} }
/**
* In case of a payment failure we should always
* return the invoice to its original state
*
* @param PaymentHash $payment_hash The payment hash containing the list of invoices
* @return void
*/
public function unWindGatewayFees(PaymentHash $payment_hash)
{
$invoices = Invoice::whereIn('id', $this->transformKeys(array_column($payment_hash->invoices(), 'invoice_id')))->get();
$invoices->each(function ($invoice) {
$invoice->service()->removeUnpaidGatewayFees();
});
}
/** /**
* Return the contact if possible. * Return the contact if possible.
* *

View File

@ -182,17 +182,28 @@ class CheckoutComPaymentDriver extends BaseDriver
$state['payment_response'] = $response; $state['payment_response'] = $response;
if ($response->status === 'Authorized') { if ($response->status === 'Authorized') {
$this->confirmGatewayFee($request);
return $this->processSuccessfulPayment($state); return $this->processSuccessfulPayment($state);
} }
if ($response->status === 'Pending') { if ($response->status === 'Pending') {
$this->confirmGatewayFee($request);
return $this->processPendingPayment($state); return $this->processPendingPayment($state);
} }
if ($response->status === 'Declined') { if ($response->status === 'Declined') {
$this->unWindGatewayFees($request->payment_hash);
return $this->processUnsuccessfulPayment($state); return $this->processUnsuccessfulPayment($state);
} }
} catch (CheckoutHttpException $e) { } catch (CheckoutHttpException $e) {
$this->unWindGatewayFees($request->payment_hash);
return $this->processInternallyFailedPayment($e, $state); return $this->processInternallyFailedPayment($e, $state);
} }
} }
@ -253,7 +264,7 @@ class CheckoutComPaymentDriver extends BaseDriver
$payment = $this->createPayment($data, Payment::STATUS_PENDING); $payment = $this->createPayment($data, Payment::STATUS_PENDING);
$this->attachInvoices($payment, $state['hashed_ids']); $this->attachInvoices($payment, $state['payment_hash']);
$payment->service()->updateInvoicePayment(); $payment->service()->updateInvoicePayment();
@ -269,9 +280,16 @@ class CheckoutComPaymentDriver extends BaseDriver
try { try {
return redirect($state['payment_response']->_links['redirect']['href']); return redirect($state['payment_response']->_links['redirect']['href']);
} catch (\Exception $e) { } catch (\Exception $e) {
SystemLogger::dispatch($logger_message, SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::TYPE_CHECKOUT, $this->client); SystemLogger::dispatch($logger_message, SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::TYPE_CHECKOUT, $this->client);
throw new \Exception('Failed to process the payment.', 1); $this->unWindGatewayFees($state['payment_hash']);
return render('gateways.unsuccessful', [
'code' => $state['payment_response']->response_code,
'message' => ctrans('texts.payment_error'),
]);
} }
} }
@ -290,6 +308,7 @@ class CheckoutComPaymentDriver extends BaseDriver
return render('gateways.unsuccessful', [ return render('gateways.unsuccessful', [
'code' => $state['payment_response']->response_code, 'code' => $state['payment_response']->response_code,
'message' => ctrans('texts.payment_error'),
]); ]);
} }
@ -308,7 +327,12 @@ class CheckoutComPaymentDriver extends BaseDriver
//todo push to a error page with the exception message. //todo push to a error page with the exception message.
throw new \Exception('Failed to process the payment.', 1); //throw new \Exception('Failed to process the payment.', 1);
return render('gateways.unsuccessful', [
'code' => '500',
'message' => ctrans('texts.payment_error'),
]);
} }
public function createPayment($data, $status = Payment::STATUS_COMPLETED): Payment public function createPayment($data, $status = Payment::STATUS_COMPLETED): Payment

View File

@ -11,6 +11,7 @@
namespace App\Services\Invoice; namespace App\Services\Invoice;
use App\Jobs\Invoice\CreateInvoicePdf;
use App\Models\CompanyGateway; use App\Models\CompanyGateway;
use App\Models\Invoice; use App\Models\Invoice;
use App\Models\Payment; use App\Models\Payment;
@ -200,6 +201,14 @@ class InvoiceService
return $this; return $this;
} }
public function updateStatus()
{
if($this->invoice->balance == 0)
$this->setStatus(Invoice::STATUS_PAID);
return $this;
}
public function toggleFeesPaid() public function toggleFeesPaid()
{ {
$this->invoice->line_items = collect($this->invoice->line_items) $this->invoice->line_items = collect($this->invoice->line_items)
@ -211,6 +220,8 @@ class InvoiceService
return $item; return $item;
})->toArray(); })->toArray();
$this->invoice = $this->invoice->calc()->getInvoice();
return $this; return $this;
} }
@ -221,6 +232,8 @@ class InvoiceService
return $item->type_id == '3'; return $item->type_id == '3';
})->toArray(); })->toArray();
$this->invoice = $this->invoice->calc()->getInvoice();
return $this; return $this;
} }
@ -241,6 +254,20 @@ class InvoiceService
return $this; return $this;
} }
/**
* Sometimes we need to refresh the
* PDF when it is updated etc.
* @return void
*/
public function touchPdf()
{
$this->invoice->invitations->each(function ($invitation){
CreateInvoicePdf::dispatch($invitation);
});
return $this;
}
/*When a reminder is sent we want to touch the dates they were sent*/ /*When a reminder is sent we want to touch the dates they were sent*/
public function touchReminder(string $reminder_template) public function touchReminder(string $reminder_template)
{ {

View File

@ -73,11 +73,11 @@ class UpdateInvoicePayment
$invoice->service() //caution what if we amount paid was less than partial - we wipe it! $invoice->service() //caution what if we amount paid was less than partial - we wipe it!
->clearPartial() ->clearPartial()
->updateBalance($paid_amount * -1) ->updateBalance($paid_amount * -1)
->updateStatus()
->save(); ->save();
info("firing invoice was updated event");
event(new InvoiceWasUpdated($invoice, $invoice->company, Ninja::eventVars())); event(new InvoiceWasUpdated($invoice, $invoice->company, Ninja::eventVars()));
info("fired invoice was updated event");
}); });
return $this->payment; return $this->payment;

View File

@ -141,8 +141,6 @@ class HtmlEngine
} }
$data['$entity_number'] = &$data['$number']; $data['$entity_number'] = &$data['$number'];
//$data['$paid_to_date'] = ;
$data['$invoice.discount'] = ['value' => Number::formatMoney($this->entity_calc->getTotalDiscount(), $this->client) ?: ' ', 'label' => ctrans('texts.discount')]; $data['$invoice.discount'] = ['value' => Number::formatMoney($this->entity_calc->getTotalDiscount(), $this->client) ?: ' ', 'label' => ctrans('texts.discount')];
$data['$discount'] = &$data['$invoice.discount']; $data['$discount'] = &$data['$invoice.discount'];
$data['$subtotal'] = ['value' => Number::formatMoney($this->entity_calc->getSubTotal(), $this->client) ?: ' ', 'label' => ctrans('texts.subtotal')]; $data['$subtotal'] = ['value' => Number::formatMoney($this->entity_calc->getSubTotal(), $this->client) ?: ' ', 'label' => ctrans('texts.subtotal')];
@ -236,9 +234,8 @@ class HtmlEngine
$data['$client.country'] = &$data['$country']; $data['$client.country'] = &$data['$country'];
$data['$client.email'] = &$data['$email']; $data['$client.email'] = &$data['$email'];
$data['$client.balance'] = ['value' => Number::formatMoney($this->client->balance, $this->client), 'label' => ctrans('texts.account_balance')];
$data['$client.balance'] = ['value' => $this->client->balance, 'label' => ctrans('texts.balance')]; $data['$paid_to_date'] = ['value' => Number::formatMoney($this->client->paid_to_date, $this->client), 'label' => ctrans('texts.paid_to_date')];
$data['$paid_to_date'] = ['value' => $this->client->paid_to_date, 'label' => ctrans('texts.paid_to_date')];
$data['$contact.full_name'] = ['value' => $this->contact->present()->name(), 'label' => ctrans('texts.name')]; $data['$contact.full_name'] = ['value' => $this->contact->present()->name(), 'label' => ctrans('texts.name')];
$data['$contact.email'] = ['value' => $this->contact->email, 'label' => ctrans('texts.email')]; $data['$contact.email'] = ['value' => $this->contact->email, 'label' => ctrans('texts.email')];

View File

@ -3268,4 +3268,5 @@ return [
'no_items_selected' => 'No items selected.', 'no_items_selected' => 'No items selected.',
'payment_due' => 'Payment due', 'payment_due' => 'Payment due',
'account_balance' => 'Account balance',
]; ];

View File

@ -6,8 +6,10 @@
{{ ctrans('texts.payment_error_code', ['code' => isset($code) ? $code : '']) }} {{ ctrans('texts.payment_error_code', ['code' => isset($code) ? $code : '']) }}
</span> </span>
<span class="mt-6 block">{{ ctrans('texts.common_codes') }}:</span> @if($message)
<ul> <span class="mt-6 block">{{ ctrans('texts.message') }}:</span>
<li>{{ ctrans('texts.payment_error_code_20087') }}.</li> <ul>
</ul> <li>{{ $message }}.</li>
</ul>
@endif
@endsection @endsection