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();
});