mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Bank Transfers
This commit is contained in:
parent
6496b99379
commit
885ee633d7
@ -104,6 +104,7 @@ class Gateway extends StaticModel
|
||||
return [
|
||||
GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true, 'webhooks' => ['payment_intent.succeeded']],
|
||||
GatewayType::BANK_TRANSFER => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded', 'customer.source.updated','payment_intent.processing']],
|
||||
GatewayType::DIRECT_DEBIT => ['refund' => false, 'token_billing' => false, 'webhooks' => ['payment_intent.processing','payment_intent.succeeded','payment_intent.partially_funded']],
|
||||
GatewayType::ALIPAY => ['refund' => false, 'token_billing' => false],
|
||||
GatewayType::APPLE_PAY => ['refund' => false, 'token_billing' => false],
|
||||
GatewayType::SOFORT => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded', 'payment_intent.succeeded']],
|
||||
@ -141,6 +142,7 @@ class Gateway extends StaticModel
|
||||
return [
|
||||
GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true, 'webhooks' => ['payment_intent.succeeded']],
|
||||
GatewayType::BANK_TRANSFER => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded', 'customer.source.updated','payment_intent.processing']],
|
||||
GatewayType::DIRECT_DEBIT => ['refund' => false, 'token_billing' => false, 'webhooks' => ['payment_intent.processing','payment_intent.succeeded','payment_intent.partially_funded']],
|
||||
GatewayType::ALIPAY => ['refund' => false, 'token_billing' => false],
|
||||
GatewayType::APPLE_PAY => ['refund' => false, 'token_billing' => false],
|
||||
GatewayType::SOFORT => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded', 'payment_intent.succeeded']],
|
||||
|
211
app/PaymentDrivers/Stripe/BankTransfer.php
Normal file
211
app/PaymentDrivers/Stripe/BankTransfer.php
Normal file
@ -0,0 +1,211 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\PaymentDrivers\Stripe;
|
||||
|
||||
use App\Models\Payment;
|
||||
use App\Models\SystemLog;
|
||||
use Stripe\PaymentIntent;
|
||||
use App\Models\GatewayType;
|
||||
use App\Models\PaymentType;
|
||||
use App\Jobs\Util\SystemLogger;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use App\Exceptions\PaymentFailed;
|
||||
use App\PaymentDrivers\StripePaymentDriver;
|
||||
use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest;
|
||||
|
||||
class BankTransfer
|
||||
{
|
||||
use MakesHash;
|
||||
|
||||
/** @var StripePaymentDriver */
|
||||
public $stripe;
|
||||
|
||||
public function __construct(StripePaymentDriver $stripe)
|
||||
{
|
||||
$this->stripe = $stripe;
|
||||
}
|
||||
|
||||
public function paymentView(array $data)
|
||||
{
|
||||
$this->stripe->init();
|
||||
|
||||
$intent = \Stripe\PaymentIntent::create([
|
||||
'amount' => $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency()),
|
||||
'currency' => $this->stripe->client->currency()->code,
|
||||
'customer' => $this->stripe->findOrCreateCustomer()->id,
|
||||
'description' => $this->stripe->getDescription(false),
|
||||
'payment_method_types' => ['customer_balance'],
|
||||
'payment_method_data' => [
|
||||
'type' => 'customer_balance',
|
||||
],
|
||||
'payment_method_options' => [
|
||||
'customer_balance' => [
|
||||
'funding_type' => 'bank_transfer',
|
||||
'bank_transfer' => $this->resolveBankType()
|
||||
],
|
||||
],
|
||||
'metadata' => [
|
||||
'payment_hash' => $this->stripe->payment_hash->hash,
|
||||
'gateway_type_id' => GatewayType::DIRECT_DEBIT,
|
||||
],
|
||||
], $this->stripe->stripe_connect_auth);
|
||||
|
||||
|
||||
$this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, ['stripe_amount' => $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency())]);
|
||||
$this->stripe->payment_hash->save();
|
||||
|
||||
$data = [];
|
||||
$data['return_url'] = $this->buildReturnUrl();
|
||||
$data['gateway'] = $this->stripe;
|
||||
$data['client_secret'] = $intent ? $intent->client_secret : false;
|
||||
|
||||
return render('gateways.stripe.bank_transfer.pay', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the bank type based on the currency
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function resolveBankType()
|
||||
{
|
||||
|
||||
return match($this->stripe->client->currency()->code){
|
||||
'GBP' => ['type' => 'gb_bank_transfer'],
|
||||
'EUR' => ['type' => 'eu_bank_transfer', 'eu_bank_transfer' => ['country' => $this->stripe->client->country->iso_3166_2]],
|
||||
'JPY' => ['type' => 'jp_bank_transfer'],
|
||||
'MXN' => ['type' =>'mx_bank_transfer'],
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Return URL
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function buildReturnUrl(): string
|
||||
{
|
||||
return route('client.payments.response.get', [
|
||||
'company_gateway_id' => $this->stripe->company_gateway->id,
|
||||
'payment_hash' => $this->stripe->payment_hash->hash,
|
||||
'payment_method_id' => GatewayType::DIRECT_DEBIT,
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
public function paymentResponse(PaymentResponseRequest $request)
|
||||
{
|
||||
|
||||
$this->stripe->init();
|
||||
|
||||
$this->stripe->setPaymentHash($request->getPaymentHash());
|
||||
$this->stripe->client = $this->stripe->payment_hash->fee_invoice->client;
|
||||
|
||||
if($request->payment_intent){
|
||||
|
||||
$pi = \Stripe\PaymentIntent::retrieve(
|
||||
$request->payment_intent,
|
||||
$this->stripe->stripe_connect_auth
|
||||
);
|
||||
|
||||
nlog($pi);
|
||||
|
||||
if (in_array($pi->status, ['succeeded', 'processing'])) {
|
||||
return $this->processSuccesfulRedirect($pi);
|
||||
}
|
||||
|
||||
/* Create a pending payment */
|
||||
if($pi->status == 'requires_action') {
|
||||
|
||||
$data = [
|
||||
'payment_method' => $pi->payment_method,
|
||||
'payment_type' => PaymentType::DIRECT_DEBIT,
|
||||
'amount' => $this->stripe->convertFromStripeAmount($this->stripe->payment_hash->data->stripe_amount, $this->stripe->client->currency()->precision, $this->stripe->client->currency()),
|
||||
'transaction_reference' => $pi->id,
|
||||
'gateway_type_id' => GatewayType::DIRECT_DEBIT,
|
||||
|
||||
];
|
||||
|
||||
$payment = $this->stripe->createPayment($data, Payment::STATUS_PENDING);
|
||||
|
||||
SystemLogger::dispatch(
|
||||
['response' => $this->stripe->payment_hash->data, 'data' => $data],
|
||||
SystemLog::CATEGORY_GATEWAY_RESPONSE,
|
||||
SystemLog::EVENT_GATEWAY_SUCCESS,
|
||||
SystemLog::TYPE_STRIPE,
|
||||
$this->stripe->client,
|
||||
$this->stripe->client->company,
|
||||
);
|
||||
|
||||
return redirect($pi->next_action->display_bank_transfer_instructions->hosted_instructions_url);
|
||||
|
||||
}
|
||||
return $this->processUnsuccesfulRedirect();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function processSuccesfulRedirect($payment_intent)
|
||||
{
|
||||
$this->stripe->init();
|
||||
|
||||
$data = [
|
||||
'payment_method' => $payment_intent->payment_method,
|
||||
'payment_type' => PaymentType::DIRECT_DEBIT,
|
||||
'amount' => $this->stripe->convertFromStripeAmount($this->stripe->payment_hash->data->stripe_amount, $this->stripe->client->currency()->precision, $this->stripe->client->currency()),
|
||||
'transaction_reference' => $payment_intent->id,
|
||||
'gateway_type_id' => GatewayType::DIRECT_DEBIT,
|
||||
|
||||
];
|
||||
|
||||
$payment = $this->stripe->createPayment($data, $payment_intent->status == 'processing' ? Payment::STATUS_PENDING : Payment::STATUS_COMPLETED);
|
||||
|
||||
SystemLogger::dispatch(
|
||||
['response' => $this->stripe->payment_hash->data, 'data' => $data],
|
||||
SystemLog::CATEGORY_GATEWAY_RESPONSE,
|
||||
SystemLog::EVENT_GATEWAY_SUCCESS,
|
||||
SystemLog::TYPE_STRIPE,
|
||||
$this->stripe->client,
|
||||
$this->stripe->client->company,
|
||||
);
|
||||
|
||||
return redirect()->route('client.payments.show', ['payment' => $this->stripe->encodePrimaryKey($payment->id)]);
|
||||
}
|
||||
|
||||
public function processUnsuccesfulRedirect()
|
||||
{
|
||||
$server_response = $this->stripe->payment_hash->data;
|
||||
|
||||
$this->stripe->sendFailureMail($server_response->redirect_status);
|
||||
|
||||
$message = [
|
||||
'server_response' => $server_response,
|
||||
'data' => $this->stripe->payment_hash->data,
|
||||
];
|
||||
|
||||
SystemLogger::dispatch(
|
||||
$message,
|
||||
SystemLog::CATEGORY_GATEWAY_RESPONSE,
|
||||
SystemLog::EVENT_GATEWAY_FAILURE,
|
||||
SystemLog::TYPE_STRIPE,
|
||||
$this->stripe->client,
|
||||
$this->stripe->client->company,
|
||||
);
|
||||
|
||||
throw new PaymentFailed('Failed to process the payment.', 500);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\PaymentDrivers\Stripe\Jobs;
|
||||
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\Company;
|
||||
use App\Models\CompanyGateway;
|
||||
use App\Models\Payment;
|
||||
use App\Models\PaymentHash;
|
||||
use App\PaymentDrivers\Stripe\Utilities;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class PaymentIntentPartiallyFundedWebhook implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, Utilities;
|
||||
|
||||
public $tries = 1;
|
||||
|
||||
public $deleteWhenMissingModels = true;
|
||||
|
||||
public function __construct(public array $stripe_request, public string $company_key, public int $company_gateway_id)
|
||||
{
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
MultiDB::findAndSetDbByCompanyKey($this->company_key);
|
||||
|
||||
$company = Company::where('company_key', $this->company_key)->first();
|
||||
|
||||
foreach ($this->stripe_request as $transaction) {
|
||||
$payment_intent = false;
|
||||
|
||||
if (array_key_exists('payment_intent', $transaction)) {
|
||||
$payment_intent = $transaction['payment_intent'];
|
||||
} else {
|
||||
$payment_intent = $transaction['id'];
|
||||
}
|
||||
|
||||
if(!$payment_intent){
|
||||
nlog("payment intent not found");
|
||||
nlog($transaction);
|
||||
return;
|
||||
}
|
||||
|
||||
$payment = Payment::query()
|
||||
->where('company_id', $company->id)
|
||||
->where('transaction_reference', $payment_intent)
|
||||
->first();
|
||||
|
||||
if(!$payment){
|
||||
nlog("paymentintent found but no payment");
|
||||
}
|
||||
|
||||
$company_gateway = CompanyGateway::find($this->company_gateway_id);
|
||||
$stripe_driver = $company_gateway->driver()->init();
|
||||
|
||||
$hash = isset($transaction['metadata']['payment_hash']) ? $transaction['metadata']['payment_hash'] : false;
|
||||
|
||||
if (!$hash) {
|
||||
nlog("no hash found");
|
||||
return;
|
||||
}
|
||||
|
||||
$payment_hash = PaymentHash::where('hash', $hash)->first();
|
||||
|
||||
if (!$payment_hash) {
|
||||
nlog("no payment hash found");
|
||||
return;
|
||||
}
|
||||
|
||||
$stripe_driver->client = $payment_hash->fee_invoice->client;
|
||||
|
||||
$pi = \Stripe\PaymentIntent::retrieve($payment_intent, $stripe_driver->stripe_connect_auth);
|
||||
|
||||
$amount = $stripe_driver->convertFromStripeAmount($pi->amount, $stripe_driver->client->currency()->precision, $stripe_driver->client->currency()->precision);
|
||||
$amount_received = $stripe_driver->convertFromStripeAmount($pi->amount_received, $stripe_driver->client->currency()->precision, $stripe_driver->client->currency()->precision);
|
||||
|
||||
//at this point we just send notification emails to the client and advise of over/under payments.
|
||||
}
|
||||
}
|
||||
}
|
@ -260,39 +260,6 @@ class PaymentIntentWebhook implements ShouldQueue
|
||||
}
|
||||
}
|
||||
|
||||
// private function updateSepaPayment($payment_hash, $client, $meta)
|
||||
// {
|
||||
|
||||
// $company_gateway = CompanyGateway::find($this->company_gateway_id);
|
||||
// $payment_method_type = GatewayType::SEPA;
|
||||
// $driver = $company_gateway->driver($client)->init()->setPaymentMethod($payment_method_type);
|
||||
|
||||
// $payment_hash->data = array_merge((array) $payment_hash->data, $this->stripe_request);
|
||||
// $payment_hash->save();
|
||||
// $driver->setPaymentHash($payment_hash);
|
||||
|
||||
// $data = [
|
||||
// 'payment_method' => $payment_hash->data->object->payment_method,
|
||||
// 'payment_type' => PaymentType::parseCardType(strtolower($meta['card_details'])) ?: PaymentType::CREDIT_CARD_OTHER,
|
||||
// 'amount' => $payment_hash->data->amount_with_fee,
|
||||
// 'transaction_reference' => $meta['transaction_reference'],
|
||||
// 'gateway_type_id' => GatewayType::CREDIT_CARD,
|
||||
// ];
|
||||
|
||||
// $payment = $driver->createPayment($data, Payment::STATUS_COMPLETED);
|
||||
|
||||
// SystemLogger::dispatch(
|
||||
// ['response' => $this->stripe_request, 'data' => $data],
|
||||
// SystemLog::CATEGORY_GATEWAY_RESPONSE,
|
||||
// SystemLog::EVENT_GATEWAY_SUCCESS,
|
||||
// SystemLog::TYPE_STRIPE,
|
||||
// $client,
|
||||
// $client->company,
|
||||
// );
|
||||
|
||||
|
||||
// }
|
||||
|
||||
|
||||
private function updateCreditCardPayment($payment_hash, $client, $meta)
|
||||
{
|
||||
|
@ -12,51 +12,53 @@
|
||||
|
||||
namespace App\PaymentDrivers;
|
||||
|
||||
use App\Exceptions\PaymentFailed;
|
||||
use App\Exceptions\StripeConnectFailure;
|
||||
use App\Http\Requests\Payments\PaymentWebhookRequest;
|
||||
use App\Http\Requests\Request;
|
||||
use App\Jobs\Util\SystemLogger;
|
||||
use App\Models\ClientGatewayToken;
|
||||
use App\Models\GatewayType;
|
||||
use App\Models\Payment;
|
||||
use App\Models\PaymentHash;
|
||||
use App\Models\SystemLog;
|
||||
use App\PaymentDrivers\Stripe\ACH;
|
||||
use App\PaymentDrivers\Stripe\ACSS;
|
||||
use App\PaymentDrivers\Stripe\Alipay;
|
||||
use App\PaymentDrivers\Stripe\Bancontact;
|
||||
use App\PaymentDrivers\Stripe\BECS;
|
||||
use App\PaymentDrivers\Stripe\BrowserPay;
|
||||
use App\PaymentDrivers\Stripe\Charge;
|
||||
use App\PaymentDrivers\Stripe\Connect\Verify;
|
||||
use App\PaymentDrivers\Stripe\CreditCard;
|
||||
use App\PaymentDrivers\Stripe\EPS;
|
||||
use App\PaymentDrivers\Stripe\FPX;
|
||||
use App\PaymentDrivers\Stripe\GIROPAY;
|
||||
use App\PaymentDrivers\Stripe\iDeal;
|
||||
use App\PaymentDrivers\Stripe\ImportCustomers;
|
||||
use App\PaymentDrivers\Stripe\Jobs\PaymentIntentFailureWebhook;
|
||||
use App\PaymentDrivers\Stripe\Jobs\PaymentIntentProcessingWebhook;
|
||||
use App\PaymentDrivers\Stripe\Jobs\PaymentIntentWebhook;
|
||||
use App\PaymentDrivers\Stripe\Klarna;
|
||||
use App\PaymentDrivers\Stripe\PRZELEWY24;
|
||||
use App\PaymentDrivers\Stripe\SEPA;
|
||||
use App\PaymentDrivers\Stripe\SOFORT;
|
||||
use App\PaymentDrivers\Stripe\UpdatePaymentMethods;
|
||||
use App\PaymentDrivers\Stripe\Utilities;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Exception;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Laracasts\Presenter\Exceptions\PresenterException;
|
||||
use Stripe\Stripe;
|
||||
use Stripe\Account;
|
||||
use Stripe\Customer;
|
||||
use Stripe\Exception\ApiErrorException;
|
||||
use App\Models\Payment;
|
||||
use Stripe\SetupIntent;
|
||||
use Stripe\StripeClient;
|
||||
use App\Models\SystemLog;
|
||||
use Stripe\PaymentIntent;
|
||||
use Stripe\PaymentMethod;
|
||||
use Stripe\SetupIntent;
|
||||
use Stripe\Stripe;
|
||||
use Stripe\StripeClient;
|
||||
use App\Models\GatewayType;
|
||||
use App\Models\PaymentHash;
|
||||
use App\Http\Requests\Request;
|
||||
use App\Jobs\Util\SystemLogger;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use App\Exceptions\PaymentFailed;
|
||||
use App\Models\ClientGatewayToken;
|
||||
use App\PaymentDrivers\Stripe\ACH;
|
||||
use App\PaymentDrivers\Stripe\EPS;
|
||||
use App\PaymentDrivers\Stripe\FPX;
|
||||
use App\PaymentDrivers\Stripe\ACSS;
|
||||
use App\PaymentDrivers\Stripe\BECS;
|
||||
use App\PaymentDrivers\Stripe\SEPA;
|
||||
use App\PaymentDrivers\Stripe\iDeal;
|
||||
use App\PaymentDrivers\Stripe\Alipay;
|
||||
use App\PaymentDrivers\Stripe\Charge;
|
||||
use App\PaymentDrivers\Stripe\Klarna;
|
||||
use App\PaymentDrivers\Stripe\SOFORT;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use App\PaymentDrivers\Stripe\GIROPAY;
|
||||
use Stripe\Exception\ApiErrorException;
|
||||
use App\Exceptions\StripeConnectFailure;
|
||||
use App\PaymentDrivers\Stripe\Utilities;
|
||||
use App\PaymentDrivers\Stripe\Bancontact;
|
||||
use App\PaymentDrivers\Stripe\BrowserPay;
|
||||
use App\PaymentDrivers\Stripe\CreditCard;
|
||||
use App\PaymentDrivers\Stripe\PRZELEWY24;
|
||||
use App\PaymentDrivers\Stripe\BankTransfer;
|
||||
use App\PaymentDrivers\Stripe\Connect\Verify;
|
||||
use App\PaymentDrivers\Stripe\ImportCustomers;
|
||||
use App\PaymentDrivers\Stripe\UpdatePaymentMethods;
|
||||
use App\Http\Requests\Payments\PaymentWebhookRequest;
|
||||
use Laracasts\Presenter\Exceptions\PresenterException;
|
||||
use App\PaymentDrivers\Stripe\Jobs\PaymentIntentWebhook;
|
||||
use App\PaymentDrivers\Stripe\Jobs\PaymentIntentFailureWebhook;
|
||||
use App\PaymentDrivers\Stripe\Jobs\PaymentIntentProcessingWebhook;
|
||||
use App\PaymentDrivers\Stripe\Jobs\PaymentIntentPartiallyFundedWebhook;
|
||||
|
||||
class StripePaymentDriver extends BaseDriver
|
||||
{
|
||||
@ -95,6 +97,7 @@ class StripePaymentDriver extends BaseDriver
|
||||
GatewayType::ACSS => ACSS::class,
|
||||
GatewayType::FPX => FPX::class,
|
||||
GatewayType::KLARNA => Klarna::class,
|
||||
GatewayType::DIRECT_DEBIT => BankTransfer::class,
|
||||
];
|
||||
|
||||
const SYSTEM_LOG_TYPE = SystemLog::TYPE_STRIPE;
|
||||
@ -255,6 +258,14 @@ class StripePaymentDriver extends BaseDriver
|
||||
$types[] = GatewayType::APPLE_PAY;
|
||||
}
|
||||
|
||||
if (
|
||||
$this->client
|
||||
&& isset($this->client->country)
|
||||
&& in_array($this->client->country->iso_3166_2, ['FR', 'IE', 'NL', 'GB', 'DE', 'ES', 'JP', 'MX'])
|
||||
) {
|
||||
$types[] = GatewayType::DIRECT_DEBIT;
|
||||
}
|
||||
|
||||
return $types;
|
||||
}
|
||||
|
||||
@ -657,6 +668,12 @@ class StripePaymentDriver extends BaseDriver
|
||||
return response()->json([], 200);
|
||||
}
|
||||
|
||||
if ($request->type === 'payment_intent.partially_funded') {
|
||||
PaymentIntentPartiallyFundedWebhook::dispatch($request->data, $request->company_key, $this->company_gateway->id)->delay(now()->addSeconds(rand(5, 10)));
|
||||
|
||||
return response()->json([], 200);
|
||||
}
|
||||
|
||||
if (in_array($request->type, ['payment_intent.payment_failed', 'charge.failed'])) {
|
||||
PaymentIntentFailureWebhook::dispatch($request->data, $request->company_key, $this->company_gateway->id)->delay(now()->addSeconds(rand(5, 10)));
|
||||
|
||||
|
@ -0,0 +1,93 @@
|
||||
@extends('portal.ninja2020.layout.payments', ['gateway_title' => 'Bank Transfer', 'card_title' => 'Bank Transfer'])
|
||||
|
||||
@section('gateway_head')
|
||||
@if($gateway->company_gateway->getConfigField('account_id'))
|
||||
<meta name="stripe-account-id" content="{{ $gateway->company_gateway->getConfigField('account_id') }}">
|
||||
<meta name="stripe-publishable-key" content="{{ config('ninja.ninja_stripe_publishable_key') }}">
|
||||
@else
|
||||
<meta name="stripe-publishable-key" content="{{ $gateway->getPublishableKey() }}">
|
||||
@endif
|
||||
<meta name="viewport" content="width=device-width, minimum-scale=1" />
|
||||
|
||||
@endsection
|
||||
|
||||
@section('gateway_content')
|
||||
<div class="alert alert-failure mb-4" hidden id="errors"></div>
|
||||
|
||||
<form action="{{ route('client.payments.response') }}" method="post" id="payment-form">
|
||||
@csrf
|
||||
|
||||
<div id="payment-element">
|
||||
<!-- Elements will create form elements here -->
|
||||
</div>
|
||||
|
||||
<div class="bg-white px-4 py-5 flex justify-end">
|
||||
<button
|
||||
@isset($form) form="{{ $form }}" @endisset
|
||||
type="submit"
|
||||
id="{{ $id ?? 'pay-now' }}"
|
||||
@isset($data) @foreach($data as $prop => $value) data-{{ $prop }}="{{ $value }}" @endforeach @endisset
|
||||
class="button button-primary bg-primary {{ $class ?? '' }}"
|
||||
{{ isset($disabled) && $disabled === true ? 'disabled' : '' }}>
|
||||
<svg class="animate-spin h-5 w-5 text-white hidden" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
||||
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||
</svg>
|
||||
<span>{{ $slot ?? ctrans('texts.pay_now') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@endsection
|
||||
|
||||
@push('footer')
|
||||
<script src="https://js.stripe.com/v3/"></script>
|
||||
|
||||
<script>
|
||||
const options = {
|
||||
clientSecret: '{{ $client_secret }}',
|
||||
// Fully customizable with appearance API.
|
||||
appearance: {/*...*/},
|
||||
};
|
||||
|
||||
const stripe = Stripe(document.querySelector('meta[name="stripe-publishable-key"]').getAttribute('content'));
|
||||
const stripeConnect = document.querySelector('meta[name="stripe-account-id"]')?.content ?? '';
|
||||
|
||||
if(stripeConnect)
|
||||
stripe.stripeAccount = stripeConnect;
|
||||
|
||||
// Set up Stripe.js and Elements to use in checkout form, passing the client secret obtained in step 3
|
||||
const elements = stripe.elements(options);
|
||||
// Create and mount the Payment Element
|
||||
const paymentElement = elements.create('payment');
|
||||
paymentElement.mount('#payment-element');
|
||||
|
||||
|
||||
const form = document.getElementById('payment-form');
|
||||
|
||||
form.addEventListener('submit', async (event) => {
|
||||
event.preventDefault();
|
||||
document.getElementById('pay-now').disabled = true;
|
||||
document.querySelector('#pay-now > svg').classList.add('hidden');
|
||||
document.querySelector('#pay-now > span').classList.remove('hidden');
|
||||
|
||||
const {error} = await stripe.confirmPayment({
|
||||
//`Elements` instance that was used to create the Payment Element
|
||||
elements,
|
||||
confirmParams: {
|
||||
return_url: '{!! $return_url !!}',
|
||||
},
|
||||
});
|
||||
|
||||
if (error) {
|
||||
|
||||
const messageContainer = document.querySelector('#errors');
|
||||
messageContainer.textContent = error.message;
|
||||
} else {
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
@endpush
|
Loading…
x
Reference in New Issue
Block a user