From 2856f36a8677dd4fe937b304d7a3a5f362c789ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Beganovi=C4=87?= Date: Fri, 27 Aug 2021 17:00:32 +0200 Subject: [PATCH] Payment page with token --- app/PaymentDrivers/Braintree/ACH.php | 100 +++++++++++++++++- .../gateways/braintree/ach/pay.blade.php | 5 +- 2 files changed, 102 insertions(+), 3 deletions(-) diff --git a/app/PaymentDrivers/Braintree/ACH.php b/app/PaymentDrivers/Braintree/ACH.php index e50778176b30..1b400e61ddec 100644 --- a/app/PaymentDrivers/Braintree/ACH.php +++ b/app/PaymentDrivers/Braintree/ACH.php @@ -11,13 +11,24 @@ namespace App\PaymentDrivers\Braintree; +use App\Exceptions\PaymentFailed; +use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest; use App\Http\Requests\Request; +use App\Jobs\Mail\PaymentFailureMailer; +use App\Jobs\Util\SystemLogger; +use App\Models\ClientGatewayToken; use App\Models\GatewayType; +use App\Models\Payment; +use App\Models\PaymentType; +use App\Models\SystemLog; use App\PaymentDrivers\BraintreePaymentDriver; use App\PaymentDrivers\Common\MethodInterface; +use App\Utils\Traits\MakesHash; class ACH implements MethodInterface { + use MakesHash; + protected BraintreePaymentDriver $braintree; public function __construct(BraintreePaymentDriver $braintree) @@ -70,7 +81,7 @@ class ACH implements MethodInterface $this->braintree->storeGatewayToken($data, ['gateway_customer_reference' => $customer->id]); - return redirect()->route('client.payment_methods.index'); + return redirect()->route('client.payment_methods.index')->withMessage(ctrans('texts.payment_method_added')); } catch (\Exception $e) { return $this->braintree->processInternallyFailedPayment($this->braintree, $e); } @@ -80,7 +91,94 @@ class ACH implements MethodInterface public function paymentView(array $data) { $data['gateway'] = $this->braintree; + $data['currency'] = $this->braintree->client->getCurrencyCode(); + $data['payment_method_id'] = GatewayType::BANK_TRANSFER; + $data['amount'] = $this->braintree->payment_hash->data->amount_with_fee; return render('gateways.braintree.ach.pay', $data); } + + public function paymentResponse(PaymentResponseRequest $request) + { + $request->validate([ + 'source' => ['required'], + 'payment_hash' => ['required'], + ]); + + $customer = $this->braintree->findOrCreateCustomer(); + + $token = ClientGatewayToken::query() + ->where('client_id', auth('contact')->user()->client->id) + ->where('id', $this->decodePrimaryKey($request->source)) + ->firstOrFail(); + + $result = $this->braintree->gateway->transaction()->sale([ + 'amount' => $this->braintree->payment_hash->data->amount_with_fee, + 'paymentMethodToken' => $token->token, + 'options' => [ + 'submitForSettlement' => true + ], + ]); + + if ($result->success) { + $this->braintree->logSuccessfulGatewayResponse(['response' => $request->server_response, 'data' => $this->braintree->payment_hash], SystemLog::TYPE_BRAINTREE); + + return $this->processSuccessfulPayment($result); + } + + return $this->processUnsuccessfulPayment($result); + } + + private function processSuccessfulPayment($response) + { + $state = $this->braintree->payment_hash->data; + + $data = [ + 'payment_type' => PaymentType::ACH, + 'amount' => $this->braintree->payment_hash->data->amount_with_fee, + 'transaction_reference' => $response->transaction->id, + 'gateway_type_id' => GatewayType::BANK_TRANSFER, + ]; + + $payment = $this->braintree->createPayment($data, Payment::STATUS_COMPLETED); + + SystemLogger::dispatch( + ['response' => $response, 'data' => $data], + SystemLog::CATEGORY_GATEWAY_RESPONSE, + SystemLog::EVENT_GATEWAY_SUCCESS, + SystemLog::TYPE_BRAINTREE, + $this->braintree->client, + $this->braintree->client->company, + ); + + return redirect()->route('client.payments.show', ['payment' => $this->braintree->encodePrimaryKey($payment->id)]); + } + + private function processUnsuccessfulPayment($response) + { + PaymentFailureMailer::dispatch($this->braintree->client, $response->transaction->additionalProcessorResponse, $this->braintree->client->company, $this->braintree->payment_hash->data->amount_with_fee); + + PaymentFailureMailer::dispatch( + $this->braintree->client, + $response, + $this->braintree->client->company, + $this->braintree->payment_hash->data->amount_with_fee, + ); + + $message = [ + 'server_response' => $response, + 'data' => $this->braintree->payment_hash->data, + ]; + + SystemLogger::dispatch( + $message, + SystemLog::CATEGORY_GATEWAY_RESPONSE, + SystemLog::EVENT_GATEWAY_FAILURE, + SystemLog::TYPE_BRAINTREE, + $this->braintree->client, + $this->braintree->client->company, + ); + + throw new PaymentFailed($response->transaction->additionalProcessorResponse, $response->transaction->processorResponseCode); + } } diff --git a/resources/views/portal/ninja2020/gateways/braintree/ach/pay.blade.php b/resources/views/portal/ninja2020/gateways/braintree/ach/pay.blade.php index d6ccfb98519f..50f87edcd4bb 100644 --- a/resources/views/portal/ninja2020/gateways/braintree/ach/pay.blade.php +++ b/resources/views/portal/ninja2020/gateways/braintree/ach/pay.blade.php @@ -13,7 +13,6 @@ - @@ -51,7 +50,9 @@ document.querySelector('input[name=source]').value = element.target.dataset.token; })); - document.getElementById('pay-now').addEventListener('click', function () { + document.getElementById('pay-now').addEventListener('click', function (e) { + e.target.parentElement.disabled = true; + document.getElementById('server-response').submit(); });