From 96750d5fdb48188638dc0ee4da345d45b3f586c9 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Tue, 13 Oct 2020 21:32:15 +1100 Subject: [PATCH] Refactor for payments via client portal --- .../ClientPortal/PaymentController.php | 62 ++++++++++--------- app/Models/Client.php | 2 +- app/Models/CompanyGateway.php | 2 +- app/Models/GatewayType.php | 37 +++++++++++ app/Services/Invoice/AutoBillInvoice.php | 4 +- app/Transformers/ExpenseTransformer.php | 3 +- .../gateways/stripe/credit_card.blade.php | 8 ++- routes/client.php | 2 + tests/MockAccountData.php | 2 +- 9 files changed, 84 insertions(+), 38 deletions(-) diff --git a/app/Http/Controllers/ClientPortal/PaymentController.php b/app/Http/Controllers/ClientPortal/PaymentController.php index 26f458ff17fe..a2ade63eeeac 100644 --- a/app/Http/Controllers/ClientPortal/PaymentController.php +++ b/app/Http/Controllers/ClientPortal/PaymentController.php @@ -71,18 +71,25 @@ class PaymentController extends Controller { $gateway = CompanyGateway::findOrFail(request()->input('company_gateway_id')); - /*find invoices*/ + /** + * find invoices + * + * ['invoice_id' => xxx, 'amount' => 22.00] + * + */ - $payable_invoices = request()->payable_invoices; - $invoices = Invoice::whereIn('id', $this->transformKeys(array_column($payable_invoices, 'invoice_id')))->get(); + $payable_invoices = collect(request()->payable_invoices); + $invoices = Invoice::whereIn('id', $this->transformKeys($payable_invoices->pluck('invoice_id')->toArray()))->get(); + + /* pop non payable invoice from the $payable_invoices array */ + $payable_invoices = $payable_invoices->filter(function ($payable_invoice) use ($invoices){ + + return $invoices->where('hashed_id', $payable_invoice['invoice_id'])->first()->isPayable(); - /*filter only payable invoices*/ - $invoices = $invoices->filter(function ($invoice) { - return $invoice->isPayable(); }); /*return early if no invoices*/ - if ($invoices->count() == 0) { + if ($payable_invoices->count() == 0) { return redirect() ->route('client.invoices.index') ->with(['warning' => 'No payable invoices selected.']); @@ -91,10 +98,10 @@ class PaymentController extends Controller $settings = auth()->user()->client->getMergedSettings(); /*iterate through invoices and add gateway fees and other payment metadata*/ - foreach ($payable_invoices as $key => $payable_invoice) { + $payable_invoices = $payable_invoices->map(function($payable_invoice) use($invoices, $settings){ - $payable_invoices[$key]['amount'] = Number::parseFloat($payable_invoice['amount']); - $payable_invoice['amount'] = $payable_invoices[$key]['amount']; + + $payable_invoice['amount'] = Number::parseFloat($payable_invoice['amount']); $invoice = $invoices->first(function ($inv) use ($payable_invoice) { return $payable_invoice['invoice_id'] == $inv->hashed_id; @@ -135,8 +142,8 @@ class PaymentController extends Controller } } // Make sure 'amount' from form is not higher than 'amount' from invoice. - $payable_invoices[$key]['due_date'] = $this->formatDate($invoice->due_date, $invoice->client->date_format()); - $payable_invoices[$key]['invoice_number'] = $invoice->number; + $payable_invoice['due_date'] = $this->formatDate($invoice->due_date, $invoice->client->date_format()); + $payable_invoice['invoice_number'] = $invoice->number; if (isset($invoice->po_number)) { $additional_info = $invoice->po_number; @@ -146,8 +153,13 @@ class PaymentController extends Controller $additional_info = $invoice->date; } - $payable_invoices[$key]['additional_info'] = $additional_info; - } + $payable_invoice['additional_info'] = $additional_info; + + return $payable_invoice; + + }); + + if ((bool) request()->signature) { $invoices->each(function ($invoice) { @@ -157,7 +169,7 @@ class PaymentController extends Controller $payment_method_id = request()->input('payment_method_id'); - $invoice_totals = array_sum(array_column($payable_invoices, 'amount')); + $invoice_totals = $payable_invoices->sum('amount'); $first_invoice = $invoices->first(); @@ -209,24 +221,14 @@ class PaymentController extends Controller /*Payment Gateway*/ $gateway = CompanyGateway::find($request->input('company_gateway_id'))->firstOrFail(); - //REFACTOR - Entry point for the gateway response - we don't need to do anything at this point. - // - // - Inside each gateway driver, we should use have a generic code path (in BaseDriver.php)for successful/failed payment - // - // Success workflow - // - // - Rehydrate the hash and iterate through the invoices and update the balances - // - Update the type_id of the gateway fee to type_id 4 - // - Link invoices to payment - // - // Failure workflow - // - // - Rehydrate hash, iterate through invoices and remove type_id 3's - // - Recalcuate invoice totals - return $gateway ->driver(auth()->user()->client) ->setPaymentMethod($request->input('payment_method_id')) ->processPaymentResponse($request); } + + public function credit_response(Request $request) + { + $payment_hash = PaymentHash::find($request->input('payment_hash')); + } } diff --git a/app/Models/Client.php b/app/Models/Client.php index f4af6cee2fab..e02fd1b5c898 100644 --- a/app/Models/Client.php +++ b/app/Models/Client.php @@ -517,7 +517,7 @@ class Client extends BaseModel implements HasLocalePreference $fee_label = $gateway->calcGatewayFeeLabel($amount, $this); $payment_urls[] = [ - 'label' => ctrans('texts.'.$gateway->getTypeAlias($gateway_type_id)).$fee_label, + 'label' => $gateway->getTypeAlias($gateway_type_id) . $fee_label, 'company_gateway_id' => $gateway_id, 'gateway_type_id' => $gateway_type_id, ]; diff --git a/app/Models/CompanyGateway.php b/app/Models/CompanyGateway.php index b05d20a94b05..fbf065fd19d8 100644 --- a/app/Models/CompanyGateway.php +++ b/app/Models/CompanyGateway.php @@ -79,7 +79,7 @@ class CompanyGateway extends BaseModel public function getTypeAlias($gateway_type_id) { - return GatewayType::find($gateway_type_id)->alias; + return GatewayType::getAlias($gateway_type_id); } /* This is the public entry point into the payment superclass */ diff --git a/app/Models/GatewayType.php b/app/Models/GatewayType.php index 058fd116e8f5..5ed2e80c2fc5 100644 --- a/app/Models/GatewayType.php +++ b/app/Models/GatewayType.php @@ -37,4 +37,41 @@ class GatewayType extends StaticModel { return $this->hasMany(PaymentType::class); } + + public static function getAlias($type) + { + switch ($type) { + case self::CREDIT_CARD: + return ctrans('texts.credit_card'); + break; + case self::BANK_TRANSFER: + return ctrans('texts.bank_transfer'); + break; + case self::PAYPAL: + return ctrans('texts.paypal'); + break; + case self::CRYPTO: + return ctrans('texts.crypto'); + break; + case self::CUSTOM: + return ctrans('texts.custom'); + break; + case self::ALIPAY: + return ctrans('texts.alipay'); + break; + case self::SOFORT: + return ctrans('texts.sofort'); + break; + case self::APPLE_PAY: + return ctrans('texts.apple_pay'); + break; + case self::SEPA: + return ctrans('texts.sepa'); + break; + + default: + return 'Undefined.'; + break; + } + } } diff --git a/app/Services/Invoice/AutoBillInvoice.php b/app/Services/Invoice/AutoBillInvoice.php index 42bc0498e094..02f553022821 100644 --- a/app/Services/Invoice/AutoBillInvoice.php +++ b/app/Services/Invoice/AutoBillInvoice.php @@ -104,10 +104,8 @@ class AutoBillInvoice extends AbstractService */ private function finalizePaymentUsingCredits() { - info("finalizing"); - info(print_r($this->used_credit,1)); + $amount = array_sum(array_column($this->used_credit, 'amount')); - info("amount {$amount}"); $payment = PaymentFactory::create($this->invoice->company_id, $this->invoice->user_id); $payment->amount = $amount; diff --git a/app/Transformers/ExpenseTransformer.php b/app/Transformers/ExpenseTransformer.php index f096c829e7f8..e1d6c9ca6a17 100644 --- a/app/Transformers/ExpenseTransformer.php +++ b/app/Transformers/ExpenseTransformer.php @@ -77,7 +77,8 @@ class ExpenseTransformer extends EntityTransformer 'public_notes' => (string) $expense->public_notes ?: '', 'transaction_reference' => (string) $expense->transaction_reference ?: '', 'transaction_id' => (string) $expense->transaction_id ?: '', - 'date' => $expense->date ?: '', + //'date' => $expense->date ?: '', + 'expense_date' => $expense->date ?: '', 'payment_date' => $expense->payment_date ?: '', 'custom_value1' => $expense->custom_value1 ?: '', 'custom_value2' => $expense->custom_value2 ?: '', diff --git a/resources/views/portal/ninja2020/gateways/stripe/credit_card.blade.php b/resources/views/portal/ninja2020/gateways/stripe/credit_card.blade.php index 37aa836f5133..6248f80a52eb 100644 --- a/resources/views/portal/ninja2020/gateways/stripe/credit_card.blade.php +++ b/resources/views/portal/ninja2020/gateways/stripe/credit_card.blade.php @@ -16,6 +16,10 @@ +
+ @csrf + +
@@ -64,7 +68,9 @@
@if((int)$total['amount_with_fee'] == 0) - +
+ +
@elseif($token)
diff --git a/routes/client.php b/routes/client.php index a7be93d29df2..685482d0ed5b 100644 --- a/routes/client.php +++ b/routes/client.php @@ -35,6 +35,8 @@ Route::group(['middleware' => ['auth:contact', 'locale'], 'prefix' => 'client', Route::get('recurring_invoices/{recurring_invoice}/request_cancellation', 'ClientPortal\RecurringInvoiceController@requestCancellation')->name('recurring_invoices.request_cancellation'); Route::post('payments/process', 'ClientPortal\PaymentController@process')->name('payments.process'); + Route::post('payments/credit_response', 'ClientPortal\PaymentController@credit_response')->name('payments.credit_response'); + Route::get('payments', 'ClientPortal\PaymentController@index')->name('payments.index')->middleware('portal_enabled'); Route::get('payments/{payment}', 'ClientPortal\PaymentController@show')->name('payments.show'); Route::post('payments/process/response', 'ClientPortal\PaymentController@response')->name('payments.response'); diff --git a/tests/MockAccountData.php b/tests/MockAccountData.php index 3c36bf758ac9..5ae73d2f8820 100644 --- a/tests/MockAccountData.php +++ b/tests/MockAccountData.php @@ -154,7 +154,7 @@ trait MockAccountData $cu->is_admin = true; $cu->save(); - $this->token = \Illuminate\Support\Str::random(64); + $this->token = 'TOKEN'; $company_token = new CompanyToken; $company_token->user_id = $this->user->id;