From 539e584cff6acde7ae122daeb393ad4f5189e805 Mon Sep 17 00:00:00 2001 From: Lars Kusch Date: Mon, 4 Oct 2021 17:33:35 +0200 Subject: [PATCH 01/27] Add support for SEPA --- app/PaymentDrivers/StripePaymentDriver.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/PaymentDrivers/StripePaymentDriver.php b/app/PaymentDrivers/StripePaymentDriver.php index 62537689be..e60422a94a 100644 --- a/app/PaymentDrivers/StripePaymentDriver.php +++ b/app/PaymentDrivers/StripePaymentDriver.php @@ -32,6 +32,7 @@ use App\PaymentDrivers\Stripe\Connect\Verify; use App\PaymentDrivers\Stripe\CreditCard; use App\PaymentDrivers\Stripe\ImportCustomers; use App\PaymentDrivers\Stripe\SOFORT; +use APP\PaymentDrivers\Stripe\SEPA; use App\PaymentDrivers\Stripe\UpdatePaymentMethods; use App\PaymentDrivers\Stripe\Utilities; use App\Utils\Traits\MakesHash; @@ -75,7 +76,7 @@ class StripePaymentDriver extends BaseDriver GatewayType::ALIPAY => Alipay::class, GatewayType::SOFORT => SOFORT::class, GatewayType::APPLE_PAY => ApplePay::class, - GatewayType::SEPA => 1, // TODO + GatewayType::SEPA => 1, SEPA::class, ]; const SYSTEM_LOG_TYPE = SystemLog::TYPE_STRIPE; @@ -145,6 +146,12 @@ class StripePaymentDriver extends BaseDriver && in_array($this->client->country->iso_3166_3, ['AUS', 'DNK', 'DEU', 'ITA', 'LUX', 'NOR', 'SVN', 'GBR', 'AUT', 'EST', 'GRC', 'JPN', 'MYS', 'PRT', 'ESP', 'USA', 'BEL', 'FIN', 'HKG', 'LVA', 'NLD', 'SGP', 'SWE', 'CAN', 'FRA', 'IRL', 'LTU', 'NZL', 'SVK', 'CHE'])) { $types[] = GatewayType::ALIPAY; } + + if ($this->client + && isset($this->client->country) + && in_array($this->client->country->iso_3166_3, ['DEU', 'USA'])) { + $types[] = GateWayType::SEPA; + } return $types; } From 5d2c66486ba010afadacb9af1b4a021506a66ee0 Mon Sep 17 00:00:00 2001 From: Lars Kusch Date: Mon, 4 Oct 2021 17:34:21 +0200 Subject: [PATCH 02/27] Add SEPA-Payment --- app/PaymentDrivers/StripeConnectPaymentDriver.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/PaymentDrivers/StripeConnectPaymentDriver.php b/app/PaymentDrivers/StripeConnectPaymentDriver.php index 2a64438271..9199391185 100644 --- a/app/PaymentDrivers/StripeConnectPaymentDriver.php +++ b/app/PaymentDrivers/StripeConnectPaymentDriver.php @@ -28,6 +28,7 @@ use App\PaymentDrivers\Stripe\Alipay; use App\PaymentDrivers\Stripe\Charge; use App\PaymentDrivers\Stripe\CreditCard; use App\PaymentDrivers\Stripe\SOFORT; +use App\PaymentDrivers\Stripe\SEPA; use App\PaymentDrivers\Stripe\Utilities; use App\Utils\Traits\MakesHash; use Exception; From e48a5fe8c4daf3fb7d748c1f4534e9deba0d6b18 Mon Sep 17 00:00:00 2001 From: Lars Kusch Date: Mon, 4 Oct 2021 17:49:18 +0200 Subject: [PATCH 03/27] Update SEPA.php --- app/PaymentDrivers/Stripe/SEPA.php | 32 +++++++++++++++--------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/app/PaymentDrivers/Stripe/SEPA.php b/app/PaymentDrivers/Stripe/SEPA.php index 74b564f6ed..58ff1c8793 100644 --- a/app/PaymentDrivers/Stripe/SEPA.php +++ b/app/PaymentDrivers/Stripe/SEPA.php @@ -56,32 +56,32 @@ class SEPA public function paymentResponse(PaymentResponseRequest $request) { - // $this->stripe_driver->init(); + $this->stripe_driver->init(); - // $state = [ - // 'server_response' => json_decode($request->gateway_response), - // 'payment_hash' => $request->payment_hash, - // ]; + $state = [ + 'server_response' => json_decode($request->gateway_response), + 'payment_hash' => $request->payment_hash, + ]; - // $state['payment_intent'] = \Stripe\PaymentIntent::retrieve($state['server_response']->id, $this->stripe_driver->stripe_connect_auth); + $state['payment_intent'] = \Stripe\PaymentIntent::retrieve($state['server_response']->id, $this->stripe_driver->stripe_connect_auth); - // $state['customer'] = $state['payment_intent']->customer; + $state['customer'] = $state['payment_intent']->customer; - // $this->stripe_driver->payment_hash->data = array_merge((array) $this->stripe_driver->payment_hash->data, $state); - // $this->stripe_driver->payment_hash->save(); + $this->stripe_driver->payment_hash->data = array_merge((array) $this->stripe_driver->payment_hash->data, $state); + $this->stripe_driver->payment_hash->save(); - // $server_response = $this->stripe_driver->payment_hash->data->server_response; + $server_response = $this->stripe_driver->payment_hash->data->server_response; - // $response_handler = new CreditCard($this->stripe_driver); + $response_handler = new SEPAAccount($this->stripe_driver); - // if ($server_response->status == 'succeeded') { + if ($server_response->status == 'succeeded') { - // $this->stripe_driver->logSuccessfulGatewayResponse(['response' => json_decode($request->gateway_response), 'data' => $this->stripe_driver->payment_hash], SystemLog::TYPE_STRIPE); + $this->stripe_driver->logSuccessfulGatewayResponse(['response' => json_decode($request->gateway_response), 'data' => $this->stripe_driver->payment_hash], SystemLog::TYPE_STRIPE); - // return $response_handler->processSuccessfulPayment(); - // } + return $response_handler->processSuccessfulPayment(); + } - // return $response_handler->processUnsuccessfulPayment($server_response); + return $response_handler->processUnsuccessfulPayment($server_response); } From 36a62111467b58480820e6e23a41faae1e76aa8c Mon Sep 17 00:00:00 2001 From: Lars Kusch Date: Mon, 4 Oct 2021 18:09:10 +0200 Subject: [PATCH 04/27] Added more allowed states --- app/PaymentDrivers/StripePaymentDriver.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app/PaymentDrivers/StripePaymentDriver.php b/app/PaymentDrivers/StripePaymentDriver.php index e60422a94a..06cdccccc8 100644 --- a/app/PaymentDrivers/StripePaymentDriver.php +++ b/app/PaymentDrivers/StripePaymentDriver.php @@ -126,7 +126,7 @@ class StripePaymentDriver extends BaseDriver $types = [ // GatewayType::CRYPTO, GatewayType::CREDIT_CARD - ]; + ]; if ($this->client && isset($this->client->country) @@ -146,10 +146,10 @@ class StripePaymentDriver extends BaseDriver && in_array($this->client->country->iso_3166_3, ['AUS', 'DNK', 'DEU', 'ITA', 'LUX', 'NOR', 'SVN', 'GBR', 'AUT', 'EST', 'GRC', 'JPN', 'MYS', 'PRT', 'ESP', 'USA', 'BEL', 'FIN', 'HKG', 'LVA', 'NLD', 'SGP', 'SWE', 'CAN', 'FRA', 'IRL', 'LTU', 'NZL', 'SVK', 'CHE'])) { $types[] = GatewayType::ALIPAY; } - + if ($this->client && isset($this->client->country) - && in_array($this->client->country->iso_3166_3, ['DEU', 'USA'])) { + && in_array($this->client->country->iso_3166_3, ['AUS', 'DNK', 'DEU', 'ITA', 'LUX', 'NOR', 'SVN', 'GBR', 'EST', 'GRC', 'JPN', 'PRT', 'ESP', 'USA', 'BEL', 'FIN'])) { // TODO: More has to be added https://stripe.com/docs/payments/sepa-debit $types[] = GateWayType::SEPA; } @@ -333,7 +333,7 @@ class StripePaymentDriver extends BaseDriver if($customer) return $customer; - } + } //Search by email $searchResults = \Stripe\Customer::all([ @@ -344,11 +344,11 @@ class StripePaymentDriver extends BaseDriver if(count($searchResults) == 1) return $searchResults->data[0]; - + //Else create a new record $data['name'] = $this->client->present()->name(); $data['phone'] = $this->client->present()->phone(); - + if (filter_var($this->client->present()->email(), FILTER_VALIDATE_EMAIL)) { $data['email'] = $this->client->present()->email(); } @@ -377,7 +377,7 @@ class StripePaymentDriver extends BaseDriver // ->create(['charge' => $payment->transaction_reference, 'amount' => $this->convertToStripeAmount($amount, $this->client->currency()->precision, $this->client->currency())], $meta); $response = \Stripe\Refund::create([ - 'charge' => $payment->transaction_reference, + 'charge' => $payment->transaction_reference, 'amount' => $this->convertToStripeAmount($amount, $this->client->currency()->precision, $this->client->currency()) ], $meta); From fc9dcd135da4c6dfd27ee919b33d4f9b8b9366e1 Mon Sep 17 00:00:00 2001 From: Lars Kusch Date: Mon, 4 Oct 2021 18:38:32 +0200 Subject: [PATCH 05/27] Added SEPA-Payment --- app/PaymentDrivers/Stripe/SEPA.php | 104 +++++++++++++++++++---------- 1 file changed, 70 insertions(+), 34 deletions(-) diff --git a/app/PaymentDrivers/Stripe/SEPA.php b/app/PaymentDrivers/Stripe/SEPA.php index 58ff1c8793..2c7043586a 100644 --- a/app/PaymentDrivers/Stripe/SEPA.php +++ b/app/PaymentDrivers/Stripe/SEPA.php @@ -12,22 +12,20 @@ namespace App\PaymentDrivers\Stripe; -use App\Exceptions\PaymentFailed; -use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest; -use App\Jobs\Mail\PaymentFailureMailer; -use App\Jobs\Util\SystemLogger; use App\Models\GatewayType; -use App\Models\Payment; -use App\Models\PaymentType; use App\Models\SystemLog; use App\PaymentDrivers\StripePaymentDriver; -use App\PaymentDrivers\Stripe\CreditCard; -use App\Utils\Ninja; +use Stripe\PaymentMethod; +use App\Exceptions\PaymentFailed; +use App\Jobs\Mail\PaymentFailureMailer; +use App\Jobs\Util\SystemLogger; +use App\Models\Payment; +use Stripe\PaymentIntent; class SEPA { /** @var StripePaymentDriver */ - public $stripe_driver; + public StripePaymentDriver $stripe; public function __construct(StripePaymentDriver $stripe_driver) { @@ -46,18 +44,18 @@ class SEPA $client_secret = $setup_intent->client_secret; // Pass the client secret to the client - $data['gateway'] = $this->stripe; return render('gateways.stripe.sepa.authorize', array_merge($data)); } - - public function paymentResponse(PaymentResponseRequest $request) + public function paymentView(array $data) { + // TODO: implement paymentView + } - $this->stripe_driver->init(); - + public function paymentResponse($request) + { $state = [ 'server_response' => json_decode($request->gateway_response), 'payment_hash' => $request->payment_hash, @@ -72,38 +70,76 @@ class SEPA $server_response = $this->stripe_driver->payment_hash->data->server_response; - $response_handler = new SEPAAccount($this->stripe_driver); + $response_handler = new SEPA($this->stripe_driver); if ($server_response->status == 'succeeded') { - $this->stripe_driver->logSuccessfulGatewayResponse(['response' => json_decode($request->gateway_response), 'data' => $this->stripe_driver->payment_hash], SystemLog::TYPE_STRIPE); + $this->stripe_driver->logSuccessfulGatewayResponse(['response' => json_decode($request->gateway_response), 'data' => $this->stripe_driver->payment_hash], SystemLog::TYPE_STRIPE); - return $response_handler->processSuccessfulPayment(); - } + return $response_handler->processSuccessfulPayment($state); + } - return $response_handler->processUnsuccessfulPayment($server_response); + return $response_handler->processUnsuccessfulPayment($state); + } + public function processSuccessfulPayment($server_response) + { + $stripe_method = $this->stripe->getStripePaymentMethod($this->stripe->payment_hash->data->server_response->payment_method); + $data = [ + 'payment_method' => $this->stripe->payment_hash->data->server_response->payment_method, + 'amount' => $this->stripe->convertFromStripeAmount($this->stripe->payment_hash->data->server_response->amount, $this->stripe->client->currency()->precision, $this->stripe->client->currency()), + 'transaction_reference' => optional($this->stripe->payment_hash->data->payment_intent->charges->data[0])->id, + 'gateway_type_id' => GatewayType::SEPA, + ]; + $this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, ['amount' => $data['amount']]); + $this->stripe->payment_hash->save(); + + $payment = $this->stripe->createPayment($data, Payment::STATUS_COMPLETED); + + SystemLogger::dispatch( + ['response' => $this->stripe->payment_hash->data->server_response, '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)]); } - /* Searches for a stripe customer by email - otherwise searches by gateway tokens in StripePaymentdriver - finally creates a new customer if none found - */ - private function getCustomer() + public function processUnsuccessfullyPayment($server_response) { - $searchResults = \Stripe\Customer::all([ - "email" => $this->stripe_driver->client->present()->email(), - "limit" => 1, - "starting_after" => null - ], $this->stripe_driver->stripe_connect_auth); - + PaymentFailureMailer::dispatch($this->stripe->client, $server_response->cancellation_reason, $this->stripe->client->company, $server_response->amount); - if(count($searchResults) >= 1) - return $searchResults[0]; + PaymentFailureMailer::dispatch( + $this->stripe->client, + $server_response, + $this->stripe->client->company, + $server_response->amount + ); - return $this->stripe_driver->findOrCreateCustomer(); + $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); + } + + private function storePaymentMethod(PaymentMethod $method, $payment_method_id, $customer) + { + // TODO: implement storePaymentMethod + } } From c6cb5697cd0ef1535b58483a9d817a0584fb658a Mon Sep 17 00:00:00 2001 From: Lars Kusch Date: Tue, 5 Oct 2021 16:19:38 +0200 Subject: [PATCH 06/27] Implement basic structure --- app/PaymentDrivers/Stripe/SEPA.php | 135 ++--------------------------- 1 file changed, 9 insertions(+), 126 deletions(-) diff --git a/app/PaymentDrivers/Stripe/SEPA.php b/app/PaymentDrivers/Stripe/SEPA.php index 2c7043586a..a17bbe43aa 100644 --- a/app/PaymentDrivers/Stripe/SEPA.php +++ b/app/PaymentDrivers/Stripe/SEPA.php @@ -7,139 +7,22 @@ * * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com) * - * @license https://www.elastic.co/licensing/elastic-license + * @license https://opensource.org/licenses/AAL */ namespace App\PaymentDrivers\Stripe; -use App\Models\GatewayType; -use App\Models\SystemLog; -use App\PaymentDrivers\StripePaymentDriver; -use Stripe\PaymentMethod; -use App\Exceptions\PaymentFailed; -use App\Jobs\Mail\PaymentFailureMailer; -use App\Jobs\Util\SystemLogger; -use App\Models\Payment; -use Stripe\PaymentIntent; +use App\Http\Requests\Request; +use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest; +use App\PaymentDrivers\Common\MethodInterface; -class SEPA +class SEPA implements MethodInterface { - /** @var StripePaymentDriver */ - public StripePaymentDriver $stripe; + public function authorizeView(array $data) { } - public function __construct(StripePaymentDriver $stripe_driver) - { - $this->stripe_driver = $stripe_driver; - } + public function authorizeResponse(Request $request) { } - public function authorizeView(array $data) - { - $customer = $this->stripe_driver->findOrCreateCustomer(); + public function paymentView(array $data) { } - $setup_intent = \Stripe\SetupIntent::create([ - 'payment_method_types' => ['sepa_debit'], - 'customer' => $customer->id, - ], $this->stripe_driver->stripe_connect_auth); - - $client_secret = $setup_intent->client_secret; - // Pass the client secret to the client - - $data['gateway'] = $this->stripe; - - return render('gateways.stripe.sepa.authorize', array_merge($data)); - } - - public function paymentView(array $data) - { - // TODO: implement paymentView - } - - public function paymentResponse($request) - { - $state = [ - 'server_response' => json_decode($request->gateway_response), - 'payment_hash' => $request->payment_hash, - ]; - - $state['payment_intent'] = \Stripe\PaymentIntent::retrieve($state['server_response']->id, $this->stripe_driver->stripe_connect_auth); - - $state['customer'] = $state['payment_intent']->customer; - - $this->stripe_driver->payment_hash->data = array_merge((array) $this->stripe_driver->payment_hash->data, $state); - $this->stripe_driver->payment_hash->save(); - - $server_response = $this->stripe_driver->payment_hash->data->server_response; - - $response_handler = new SEPA($this->stripe_driver); - - if ($server_response->status == 'succeeded') { - - $this->stripe_driver->logSuccessfulGatewayResponse(['response' => json_decode($request->gateway_response), 'data' => $this->stripe_driver->payment_hash], SystemLog::TYPE_STRIPE); - - return $response_handler->processSuccessfulPayment($state); - } - - return $response_handler->processUnsuccessfulPayment($state); - } - public function processSuccessfulPayment($server_response) - { - $stripe_method = $this->stripe->getStripePaymentMethod($this->stripe->payment_hash->data->server_response->payment_method); - - $data = [ - 'payment_method' => $this->stripe->payment_hash->data->server_response->payment_method, - 'amount' => $this->stripe->convertFromStripeAmount($this->stripe->payment_hash->data->server_response->amount, $this->stripe->client->currency()->precision, $this->stripe->client->currency()), - 'transaction_reference' => optional($this->stripe->payment_hash->data->payment_intent->charges->data[0])->id, - 'gateway_type_id' => GatewayType::SEPA, - ]; - - $this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, ['amount' => $data['amount']]); - $this->stripe->payment_hash->save(); - - $payment = $this->stripe->createPayment($data, Payment::STATUS_COMPLETED); - - SystemLogger::dispatch( - ['response' => $this->stripe->payment_hash->data->server_response, '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 processUnsuccessfullyPayment($server_response) - { - PaymentFailureMailer::dispatch($this->stripe->client, $server_response->cancellation_reason, $this->stripe->client->company, $server_response->amount); - - PaymentFailureMailer::dispatch( - $this->stripe->client, - $server_response, - $this->stripe->client->company, - $server_response->amount - ); - - $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); - } - - private function storePaymentMethod(PaymentMethod $method, $payment_method_id, $customer) - { - // TODO: implement storePaymentMethod - } + public function paymentResponse(PaymentResponseRequest $request) { } } - From 58d2e4b1743a10e35bb6cf49a10bbcfe9e56b737 Mon Sep 17 00:00:00 2001 From: Lars Kusch Date: Tue, 5 Oct 2021 16:31:33 +0200 Subject: [PATCH 07/27] Add payment method to gateway model --- app/Models/Gateway.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/Models/Gateway.php b/app/Models/Gateway.php index e8808b943e..d49429baf8 100644 --- a/app/Models/Gateway.php +++ b/app/Models/Gateway.php @@ -102,7 +102,8 @@ class Gateway extends StaticModel GatewayType::BANK_TRANSFER => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable','charge.succeeded']], 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']]]; //Stripe + GatewayType::SOFORT => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded']], //Stripe + GatewayType::SEPA => ['refund' => true, 'token_billing' => false]]; case 39: return [GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true]]; //Checkout break; From 6cc30a24544116f361410e2ffadc74acf24b4bd4 Mon Sep 17 00:00:00 2001 From: Lars Kusch Date: Tue, 5 Oct 2021 16:31:48 +0200 Subject: [PATCH 08/27] Add gateway initialization --- app/PaymentDrivers/Stripe/SEPA.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/PaymentDrivers/Stripe/SEPA.php b/app/PaymentDrivers/Stripe/SEPA.php index a17bbe43aa..dd373571f9 100644 --- a/app/PaymentDrivers/Stripe/SEPA.php +++ b/app/PaymentDrivers/Stripe/SEPA.php @@ -15,9 +15,17 @@ namespace App\PaymentDrivers\Stripe; use App\Http\Requests\Request; use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest; use App\PaymentDrivers\Common\MethodInterface; +use App\PaymentDrivers\StripePaymentDriver; class SEPA implements MethodInterface { + /** @var StripePaymentDriver */ + public StripePaymentDriver $stripe; + + public function __construct(StripePaymentDriver $stripe) + { + $this->stripe = $stripe; + } public function authorizeView(array $data) { } public function authorizeResponse(Request $request) { } From b727a07476ea4c489368e4ec4b51ba5f0a6e1091 Mon Sep 17 00:00:00 2001 From: Lars Kusch Date: Tue, 5 Oct 2021 16:34:19 +0200 Subject: [PATCH 09/27] Added authorisation --- app/PaymentDrivers/Stripe/SEPA.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/PaymentDrivers/Stripe/SEPA.php b/app/PaymentDrivers/Stripe/SEPA.php index dd373571f9..f2525f938b 100644 --- a/app/PaymentDrivers/Stripe/SEPA.php +++ b/app/PaymentDrivers/Stripe/SEPA.php @@ -26,7 +26,11 @@ class SEPA implements MethodInterface { $this->stripe = $stripe; } - public function authorizeView(array $data) { } + + public function authorizeView($data) + { + return render('gateways.stripe.sofort.authorize', $data); + } public function authorizeResponse(Request $request) { } From 125250f62c564f36d50c299fb48636e0e1694e67 Mon Sep 17 00:00:00 2001 From: Lars Kusch Date: Tue, 5 Oct 2021 16:39:01 +0200 Subject: [PATCH 10/27] Added views --- app/PaymentDrivers/Stripe/SEPA.php | 2 +- resources/js/clients/payments/stripe-sepa.js | 59 +++++++++++++++++++ .../gateways/stripe/sepa/authorize.blade.php | 6 +- 3 files changed, 63 insertions(+), 4 deletions(-) create mode 100644 resources/js/clients/payments/stripe-sepa.js diff --git a/app/PaymentDrivers/Stripe/SEPA.php b/app/PaymentDrivers/Stripe/SEPA.php index f2525f938b..7f618e2a0c 100644 --- a/app/PaymentDrivers/Stripe/SEPA.php +++ b/app/PaymentDrivers/Stripe/SEPA.php @@ -29,7 +29,7 @@ class SEPA implements MethodInterface public function authorizeView($data) { - return render('gateways.stripe.sofort.authorize', $data); + return render('gateways.stripe.sepa.authorize', $data); } public function authorizeResponse(Request $request) { } diff --git a/resources/js/clients/payments/stripe-sepa.js b/resources/js/clients/payments/stripe-sepa.js new file mode 100644 index 0000000000..6a2f36894e --- /dev/null +++ b/resources/js/clients/payments/stripe-sepa.js @@ -0,0 +1,59 @@ +/** + * Invoice Ninja (https://invoiceninja.com) + * + * @link https://github.com/invoiceninja/invoiceninja source repository + * + * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com) + * + * @license https://opensource.org/licenses/AAL + */ + +class ProcessSEPA { + constructor(key, stripeConnect) { + this.key = key; + this.errors = document.getElementById('errors'); + this.stripeConnect = stripeConnect; + } + + setupStripe = () => { + this.stripe = Stripe(this.key); + + if(this.stripeConnect) + this.stripe.stripeAccount = stripeConnect; + + return this; + }; + + handle = () => { + document.getElementById('pay-now').addEventListener('click', (e) => { + document.getElementById('pay-now').disabled = true; + document.querySelector('#pay-now > svg').classList.remove('hidden'); + document.querySelector('#pay-now > span').classList.add('hidden'); + + this.stripe.confirmSEPAPayment( + document.querySelector('meta[name=pi-client-secret').content, + { + payment_method: { + sofort: { + country: document.querySelector( + 'meta[name="country"]' + ).content, + }, + }, + return_url: document.querySelector( + 'meta[name="return-url"]' + ).content, + } + ); + }); + }; +} + +const publishableKey = document.querySelector( + 'meta[name="stripe-publishable-key"]' +)?.content ?? ''; + +const stripeConnect = + document.querySelector('meta[name="stripe-account-id"]')?.content ?? ''; + +new ProcessSEPA(publishableKey, stripeConnect).setupStripe().handle(); diff --git a/resources/views/portal/ninja2020/gateways/stripe/sepa/authorize.blade.php b/resources/views/portal/ninja2020/gateways/stripe/sepa/authorize.blade.php index def2150fb3..6a5c4bc09c 100644 --- a/resources/views/portal/ninja2020/gateways/stripe/sepa/authorize.blade.php +++ b/resources/views/portal/ninja2020/gateways/stripe/sepa/authorize.blade.php @@ -10,9 +10,9 @@ @endsection @section('gateway_content') - @if(session()->has('ach_error')) + @if(session()->has('sepa_error'))
-

{{ session('ach_error') }}

+

{{ session('sepa_error') }}

@endif @@ -78,5 +78,5 @@ @section('gateway_footer') - + @endsection From d709041ff935585f1ed966e03de13f3d521dd2c9 Mon Sep 17 00:00:00 2001 From: Lars Kusch Date: Tue, 5 Oct 2021 16:54:34 +0200 Subject: [PATCH 11/27] Added views and implement payment --- app/PaymentDrivers/Stripe/SEPA.php | 107 +++++++++++++++++- .../gateways/stripe/sepa/pay.blade.php | 28 +++++ 2 files changed, 132 insertions(+), 3 deletions(-) create mode 100644 resources/views/portal/ninja2020/gateways/stripe/sepa/pay.blade.php diff --git a/app/PaymentDrivers/Stripe/SEPA.php b/app/PaymentDrivers/Stripe/SEPA.php index 7f618e2a0c..a623c4ffa4 100644 --- a/app/PaymentDrivers/Stripe/SEPA.php +++ b/app/PaymentDrivers/Stripe/SEPA.php @@ -16,6 +16,13 @@ use App\Http\Requests\Request; use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest; use App\PaymentDrivers\Common\MethodInterface; use App\PaymentDrivers\StripePaymentDriver; +use App\Jobs\Mail\PaymentFailureMailer; +use App\Jobs\Util\SystemLogger; +use App\Models\GatewayType; +use App\Models\Payment; +use App\Models\PaymentType; +use App\Models\SystemLog; +use App\Exceptions\PaymentFailed; class SEPA implements MethodInterface { @@ -32,9 +39,103 @@ class SEPA implements MethodInterface return render('gateways.stripe.sepa.authorize', $data); } - public function authorizeResponse(Request $request) { } + public function paymentView(array $data) { + $data['gateway'] = $this->stripe; + $data['return_url'] = $this->buildReturnUrl(); + $data['stripe_amount'] = $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency()); + $data['client'] = $this->stripe->client; + $data['customer'] = $this->stripe->findOrCreateCustomer()->id; + $data['country'] = $this->stripe->client->country->iso_3166_2; - public function paymentView(array $data) { } + $intent = \Stripe\PaymentIntent::create([ + 'amount' => $data['stripe_amount'], + 'currency' => 'eur', + 'payment_method_types' => ['sepa'], + 'customer' => $this->stripe->findOrCreateCustomer(), + 'description' => $this->stripe->decodeUnicodeString(ctrans('texts.invoices') . ': ' . collect($data['invoices'])->pluck('invoice_number')), - public function paymentResponse(PaymentResponseRequest $request) { } + ]); + + $data['pi_client_secret'] = $intent->client_secret; + + $this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, ['stripe_amount' => $data['stripe_amount']]); + $this->stripe->payment_hash->save(); + + return render('gateways.stripe.sepa.pay', $data); + } + + private function buildReturnUrl(): string + { + return route('client.payments.response', [ + 'company_gateway_id' => $this->stripe->company_gateway->id, + 'payment_hash' => $this->stripe->payment_hash->hash, + 'payment_method_id' => GatewayType::SEPA, + ]); + } + + public function paymentResponse(PaymentResponseRequest $request) + { + $this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, $request->all()); + $this->stripe->payment_hash->save(); + + if ($request->redirect_status == 'succeeded') { + return $this->processSuccessfulPayment($request->payment_intent); + } + + return $this->processUnsuccessfulPayment(); + } + + public function processSuccessfulPayment(string $payment_intent) + { + $this->stripe->init(); + + $data = [ + 'payment_method' => $payment_intent, + 'payment_type' => PaymentType::SOFORT, + 'amount' => $this->stripe->convertFromStripeAmount($this->stripe->payment_hash->data->stripe_amount, $this->stripe->client->currency()->precision, $this->stripe->client->currency()), + 'transaction_reference' => $payment_intent, + 'gateway_type_id' => GatewayType::SOFORT, + ]; + + $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()->route('client.payments.index'); + } + + public function processUnsuccessfulPayment() + { + $server_response = $this->stripe->payment_hash->data; + + PaymentFailureMailer::dispatch( + $this->stripe->client, + $server_response, + $this->stripe->client->company, + $this->stripe->convertFromStripeAmount($this->stripe->payment_hash->data->stripe_amount, $this->stripe->client->currency()->precision, $this->stripe->client->currency()) + ); + + $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); + } } diff --git a/resources/views/portal/ninja2020/gateways/stripe/sepa/pay.blade.php b/resources/views/portal/ninja2020/gateways/stripe/sepa/pay.blade.php new file mode 100644 index 0000000000..926e254e35 --- /dev/null +++ b/resources/views/portal/ninja2020/gateways/stripe/sepa/pay.blade.php @@ -0,0 +1,28 @@ +@extends('portal.ninja2020.layout.payments', ['gateway_title' => 'SEPA', 'card_title' => 'SEPA']) + +@section('gateway_head') + + + + + + + +@endsection + +@section('gateway_content') + + + @include('portal.ninja2020.gateways.includes.payment_details') + + @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.payment_type')]) + {{ ctrans('texts.sepa') }} ({{ ctrans('texts.bank_transfer') }}) + @endcomponent + + @include('portal.ninja2020.gateways.includes.pay_now') +@endsection + +@push('footer') + + +@endpush From e9537b4d807204fa84ed19c4a06270d67ca11568 Mon Sep 17 00:00:00 2001 From: Lars Kusch Date: Tue, 5 Oct 2021 16:56:18 +0200 Subject: [PATCH 12/27] fix little bug --- app/PaymentDrivers/Stripe/SEPA.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/PaymentDrivers/Stripe/SEPA.php b/app/PaymentDrivers/Stripe/SEPA.php index a623c4ffa4..2153f3c50a 100644 --- a/app/PaymentDrivers/Stripe/SEPA.php +++ b/app/PaymentDrivers/Stripe/SEPA.php @@ -24,7 +24,7 @@ use App\Models\PaymentType; use App\Models\SystemLog; use App\Exceptions\PaymentFailed; -class SEPA implements MethodInterface +class SEPA { /** @var StripePaymentDriver */ public StripePaymentDriver $stripe; From 96fda7164cef015a21e126674b3ced796e7feed5 Mon Sep 17 00:00:00 2001 From: Lars Kusch Date: Wed, 6 Oct 2021 07:54:58 +0200 Subject: [PATCH 13/27] fixed small typos --- app/PaymentDrivers/StripePaymentDriver.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/PaymentDrivers/StripePaymentDriver.php b/app/PaymentDrivers/StripePaymentDriver.php index 06cdccccc8..120776940a 100644 --- a/app/PaymentDrivers/StripePaymentDriver.php +++ b/app/PaymentDrivers/StripePaymentDriver.php @@ -76,7 +76,7 @@ class StripePaymentDriver extends BaseDriver GatewayType::ALIPAY => Alipay::class, GatewayType::SOFORT => SOFORT::class, GatewayType::APPLE_PAY => ApplePay::class, - GatewayType::SEPA => 1, SEPA::class, + GatewayType::SEPA => SEPA::class, ]; const SYSTEM_LOG_TYPE = SystemLog::TYPE_STRIPE; @@ -150,7 +150,7 @@ class StripePaymentDriver extends BaseDriver if ($this->client && isset($this->client->country) && in_array($this->client->country->iso_3166_3, ['AUS', 'DNK', 'DEU', 'ITA', 'LUX', 'NOR', 'SVN', 'GBR', 'EST', 'GRC', 'JPN', 'PRT', 'ESP', 'USA', 'BEL', 'FIN'])) { // TODO: More has to be added https://stripe.com/docs/payments/sepa-debit - $types[] = GateWayType::SEPA; + $types[] = GatewayType::SEPA; } return $types; From ebdc5865545bebe810d1fdf68c5d4669fb91864f Mon Sep 17 00:00:00 2001 From: Lars Kusch Date: Wed, 6 Oct 2021 08:49:59 +0200 Subject: [PATCH 14/27] fixed small typos --- app/PaymentDrivers/Stripe/SEPA.php | 4 +--- app/PaymentDrivers/StripePaymentDriver.php | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/app/PaymentDrivers/Stripe/SEPA.php b/app/PaymentDrivers/Stripe/SEPA.php index 2153f3c50a..4350377223 100644 --- a/app/PaymentDrivers/Stripe/SEPA.php +++ b/app/PaymentDrivers/Stripe/SEPA.php @@ -7,14 +7,12 @@ * * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com) * - * @license https://opensource.org/licenses/AAL + * @license https://www.elastic.co/licensing/elastic-license */ namespace App\PaymentDrivers\Stripe; -use App\Http\Requests\Request; use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest; -use App\PaymentDrivers\Common\MethodInterface; use App\PaymentDrivers\StripePaymentDriver; use App\Jobs\Mail\PaymentFailureMailer; use App\Jobs\Util\SystemLogger; diff --git a/app/PaymentDrivers/StripePaymentDriver.php b/app/PaymentDrivers/StripePaymentDriver.php index 120776940a..604a4a89c5 100644 --- a/app/PaymentDrivers/StripePaymentDriver.php +++ b/app/PaymentDrivers/StripePaymentDriver.php @@ -32,7 +32,7 @@ use App\PaymentDrivers\Stripe\Connect\Verify; use App\PaymentDrivers\Stripe\CreditCard; use App\PaymentDrivers\Stripe\ImportCustomers; use App\PaymentDrivers\Stripe\SOFORT; -use APP\PaymentDrivers\Stripe\SEPA; +use App\PaymentDrivers\Stripe\SEPA; use App\PaymentDrivers\Stripe\UpdatePaymentMethods; use App\PaymentDrivers\Stripe\Utilities; use App\Utils\Traits\MakesHash; From 71d5ba0c785197beb079d7afa4151ee0b2c6c675 Mon Sep 17 00:00:00 2001 From: Lars Kusch Date: Wed, 6 Oct 2021 08:53:36 +0200 Subject: [PATCH 15/27] fixed wrong payment type --- app/PaymentDrivers/Stripe/SEPA.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/PaymentDrivers/Stripe/SEPA.php b/app/PaymentDrivers/Stripe/SEPA.php index 4350377223..0833e65a20 100644 --- a/app/PaymentDrivers/Stripe/SEPA.php +++ b/app/PaymentDrivers/Stripe/SEPA.php @@ -48,7 +48,7 @@ class SEPA $intent = \Stripe\PaymentIntent::create([ 'amount' => $data['stripe_amount'], 'currency' => 'eur', - 'payment_method_types' => ['sepa'], + 'payment_method_types' => ['sepa_debit'], 'customer' => $this->stripe->findOrCreateCustomer(), 'description' => $this->stripe->decodeUnicodeString(ctrans('texts.invoices') . ': ' . collect($data['invoices'])->pluck('invoice_number')), @@ -89,10 +89,10 @@ class SEPA $data = [ 'payment_method' => $payment_intent, - 'payment_type' => PaymentType::SOFORT, + 'payment_type' => PaymentType::SEPA, 'amount' => $this->stripe->convertFromStripeAmount($this->stripe->payment_hash->data->stripe_amount, $this->stripe->client->currency()->precision, $this->stripe->client->currency()), 'transaction_reference' => $payment_intent, - 'gateway_type_id' => GatewayType::SOFORT, + 'gateway_type_id' => GatewayType::SEPA, ]; $this->stripe->createPayment($data, Payment::STATUS_PENDING); From 330b405f890888a67a3c7c6957a9733f1525f429 Mon Sep 17 00:00:00 2001 From: Lars Kusch Date: Wed, 6 Oct 2021 09:14:14 +0200 Subject: [PATCH 16/27] Added javascript files --- public/js/clients/payments/stripe-sepa.js | 2 ++ public/js/clients/payments/stripe-sepa.js.LICENSE.txt | 9 +++++++++ .../ninja2020/gateways/stripe/sepa/authorize.blade.php | 2 +- 3 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 public/js/clients/payments/stripe-sepa.js create mode 100644 public/js/clients/payments/stripe-sepa.js.LICENSE.txt diff --git a/public/js/clients/payments/stripe-sepa.js b/public/js/clients/payments/stripe-sepa.js new file mode 100644 index 0000000000..9f4a85924a --- /dev/null +++ b/public/js/clients/payments/stripe-sepa.js @@ -0,0 +1,2 @@ +/*! For license information please see stripe-sofort.js.LICENSE.txt */ +!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=6)}({6:function(e,t,n){e.exports=n("RFiP")},RFiP:function(e,t){var n,r,o,u;function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var c=null!==(n=null===(r=document.querySelector('meta[name="stripe-publishable-key"]'))||void 0===r?void 0:r.content)&&void 0!==n?n:"",l=null!==(o=null===(u=document.querySelector('meta[name="stripe-account-id"]'))||void 0===u?void 0:u.content)&&void 0!==o?o:"";new function e(t,n){var r=this;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),i(this,"setupStripe",(function(){return r.stripe=Stripe(r.key),r.stripeConnect&&(r.stripe.stripeAccount=l),r})),i(this,"handle",(function(){document.getElementById("pay-now").addEventListener("click",(function(e){document.getElementById("pay-now").disabled=!0,document.querySelector("#pay-now > svg").classList.remove("hidden"),document.querySelector("#pay-now > span").classList.add("hidden"),r.stripe.confirmSEPAPayment(document.querySelector("meta[name=pi-client-secret").content,{payment_method:{sepa_debit:{country:document.querySelector('meta[name="country"]').content}},return_url:document.querySelector('meta[name="return-url"]').content})}))})),this.key=t,this.errors=document.getElementById("errors"),this.stripeConnect=n}(c,l).setupStripe().handle()}}); diff --git a/public/js/clients/payments/stripe-sepa.js.LICENSE.txt b/public/js/clients/payments/stripe-sepa.js.LICENSE.txt new file mode 100644 index 0000000000..585c6ab0e4 --- /dev/null +++ b/public/js/clients/payments/stripe-sepa.js.LICENSE.txt @@ -0,0 +1,9 @@ +/** + * Invoice Ninja (https://invoiceninja.com) + * + * @link https://github.com/invoiceninja/invoiceninja source repository + * + * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com) + * + * @license https://opensource.org/licenses/AAL + */ diff --git a/resources/views/portal/ninja2020/gateways/stripe/sepa/authorize.blade.php b/resources/views/portal/ninja2020/gateways/stripe/sepa/authorize.blade.php index 6a5c4bc09c..539346205b 100644 --- a/resources/views/portal/ninja2020/gateways/stripe/sepa/authorize.blade.php +++ b/resources/views/portal/ninja2020/gateways/stripe/sepa/authorize.blade.php @@ -1,4 +1,4 @@ -@extends('portal.ninja2020.layout.payments', ['gateway_title' => 'SEPA', 'card_title' => 'SEPA']) +@extends('portal.ninja2020.layout.payments', ['gateway_title' => 'SEPA', 'card_title' => 'SEPA-Lastschrift']) @section('gateway_head') @if($gateway->company_gateway->getConfigField('account_id')) From a461ca47fcafd927d8dc0911c959a1054a819be0 Mon Sep 17 00:00:00 2001 From: Lars Kusch Date: Wed, 6 Oct 2021 14:08:26 +0200 Subject: [PATCH 17/27] Adjust javascript file --- public/js/clients/payments/stripe-sepa.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/js/clients/payments/stripe-sepa.js b/public/js/clients/payments/stripe-sepa.js index 9f4a85924a..5af10e060b 100644 --- a/public/js/clients/payments/stripe-sepa.js +++ b/public/js/clients/payments/stripe-sepa.js @@ -1,2 +1,2 @@ /*! For license information please see stripe-sofort.js.LICENSE.txt */ -!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=6)}({6:function(e,t,n){e.exports=n("RFiP")},RFiP:function(e,t){var n,r,o,u;function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var c=null!==(n=null===(r=document.querySelector('meta[name="stripe-publishable-key"]'))||void 0===r?void 0:r.content)&&void 0!==n?n:"",l=null!==(o=null===(u=document.querySelector('meta[name="stripe-account-id"]'))||void 0===u?void 0:u.content)&&void 0!==o?o:"";new function e(t,n){var r=this;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),i(this,"setupStripe",(function(){return r.stripe=Stripe(r.key),r.stripeConnect&&(r.stripe.stripeAccount=l),r})),i(this,"handle",(function(){document.getElementById("pay-now").addEventListener("click",(function(e){document.getElementById("pay-now").disabled=!0,document.querySelector("#pay-now > svg").classList.remove("hidden"),document.querySelector("#pay-now > span").classList.add("hidden"),r.stripe.confirmSEPAPayment(document.querySelector("meta[name=pi-client-secret").content,{payment_method:{sepa_debit:{country:document.querySelector('meta[name="country"]').content}},return_url:document.querySelector('meta[name="return-url"]').content})}))})),this.key=t,this.errors=document.getElementById("errors"),this.stripeConnect=n}(c,l).setupStripe().handle()}}); +!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=6)}({6:function(e,t,n){e.exports=n("RFiP")},RFiP:function(e,t){var n,r,o,u;function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var c=null!==(n=null===(r=document.querySelector('meta[name="stripe-publishable-key"]'))||void 0===r?void 0:r.content)&&void 0!==n?n:"",l=null!==(o=null===(u=document.querySelector('meta[name="stripe-account-id"]'))||void 0===u?void 0:u.content)&&void 0!==o?o:"";new function e(t,n){var r=this;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),i(this,"setupStripe",(function(){return r.stripe=Stripe(r.key),r.stripeConnect&&(r.stripe.stripeAccount=l),r})),i(this,"handle",(function(){document.getElementById("pay-now").addEventListener("click",(function(e){document.getElementById("pay-now").disabled=!0,document.querySelector("#pay-now > svg").classList.remove("hidden"),document.querySelector("#pay-now > span").classList.add("hidden"),r.stripe.confirmSepaDebitPayment(document.querySelector("meta[name=pi-client-secret").content,{payment_method:{sepa_debit:{country:document.querySelector('meta[name="country"]').content}},return_url:document.querySelector('meta[name="return-url"]').content})}))})),this.key=t,this.errors=document.getElementById("errors"),this.stripeConnect=n}(c,l).setupStripe().handle()}}); From 391a58664525a2e5018646ed5a5048446cbede6a Mon Sep 17 00:00:00 2001 From: Lars Kusch Date: Wed, 6 Oct 2021 14:35:16 +0200 Subject: [PATCH 18/27] Added offline usage token --- app/PaymentDrivers/Stripe/SEPA.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/PaymentDrivers/Stripe/SEPA.php b/app/PaymentDrivers/Stripe/SEPA.php index 0833e65a20..cba8c6bdcc 100644 --- a/app/PaymentDrivers/Stripe/SEPA.php +++ b/app/PaymentDrivers/Stripe/SEPA.php @@ -49,6 +49,7 @@ class SEPA 'amount' => $data['stripe_amount'], 'currency' => 'eur', 'payment_method_types' => ['sepa_debit'], + 'setup_future_usage' => 'off_session', 'customer' => $this->stripe->findOrCreateCustomer(), 'description' => $this->stripe->decodeUnicodeString(ctrans('texts.invoices') . ': ' . collect($data['invoices'])->pluck('invoice_number')), From 80c06f68490ede7b7e337dd82de24f3fc1f5f015 Mon Sep 17 00:00:00 2001 From: Lars Kusch Date: Wed, 6 Oct 2021 14:51:05 +0200 Subject: [PATCH 19/27] Added sepa debit field to views --- .../ninja2020/gateways/stripe/sepa/sepa_debit.blade.php | 7 +++++++ .../portal/ninja2020/gateways/stripe/sofort/pay.blade.php | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 resources/views/portal/ninja2020/gateways/stripe/sepa/sepa_debit.blade.php diff --git a/resources/views/portal/ninja2020/gateways/stripe/sepa/sepa_debit.blade.php b/resources/views/portal/ninja2020/gateways/stripe/sepa/sepa_debit.blade.php new file mode 100644 index 0000000000..e000216d27 --- /dev/null +++ b/resources/views/portal/ninja2020/gateways/stripe/sepa/sepa_debit.blade.php @@ -0,0 +1,7 @@ +
+ @unless(isset($show_name) && $show_name == false) + @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.name')]) + + @endcomponent + @endunless +
diff --git a/resources/views/portal/ninja2020/gateways/stripe/sofort/pay.blade.php b/resources/views/portal/ninja2020/gateways/stripe/sofort/pay.blade.php index 9fcec3e1c9..01a152f5a7 100644 --- a/resources/views/portal/ninja2020/gateways/stripe/sofort/pay.blade.php +++ b/resources/views/portal/ninja2020/gateways/stripe/sofort/pay.blade.php @@ -18,7 +18,7 @@ @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.payment_type')]) {{ ctrans('texts.sofort') }} ({{ ctrans('texts.bank_transfer') }}) @endcomponent - + @include('portal.ninja2020.gateways.stripe.sepa.sepa_debit') @include('portal.ninja2020.gateways.includes.pay_now') @endsection From 789f2bfa0a0ca1b8e16ba996e910e3e0f2f1f552 Mon Sep 17 00:00:00 2001 From: Lars Kusch Date: Wed, 6 Oct 2021 15:01:21 +0200 Subject: [PATCH 20/27] Small changes --- .../ninja2020/gateways/stripe/sepa/sepa_debit.blade.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/resources/views/portal/ninja2020/gateways/stripe/sepa/sepa_debit.blade.php b/resources/views/portal/ninja2020/gateways/stripe/sepa/sepa_debit.blade.php index e000216d27..ada051bfe3 100644 --- a/resources/views/portal/ninja2020/gateways/stripe/sepa/sepa_debit.blade.php +++ b/resources/views/portal/ninja2020/gateways/stripe/sepa/sepa_debit.blade.php @@ -1,7 +1,5 @@
- @unless(isset($show_name) && $show_name == false) - @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.name')]) - - @endcomponent - @endunless + @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.name')]) + + @endcomponent
From 5e0aaa45b53516caa2f128e9d52992148486ddd2 Mon Sep 17 00:00:00 2001 From: Lars Kusch Date: Wed, 6 Oct 2021 15:23:19 +0200 Subject: [PATCH 21/27] Added required input views --- resources/lang/en/texts.php | 3 ++- .../gateways/stripe/sepa/sepa_debit.blade.php | 13 ++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php index 14df4963a7..ec22a578e3 100644 --- a/resources/lang/en/texts.php +++ b/resources/lang/en/texts.php @@ -1779,7 +1779,7 @@ $LANG = array( 'lang_Bulgarian' => 'Bulgarian', 'lang_Russian (Russia)' => 'Russian (Russia)', - + // Industries 'industry_Accounting & Legal' => 'Accounting & Legal', 'industry_Advertising' => 'Advertising', @@ -4316,6 +4316,7 @@ $LANG = array( 'payment_method_cannot_be_preauthorized' => 'This payment method cannot be preauthorized.', 'kbc_cbc' => 'KBC/CBC', 'bancontact' => 'Bancontact', + 'sepa_mandat' => 'By providing your IBAN and confirming this payment, you are authorizing Rocketship Inc. and Stripe, our payment service provider, to send instructions to your bank to debit your account and your bank to debit your account in accordance with those instructions. You are entitled to a refund from your bank under the terms and conditions of your agreement with your bank. A refund must be claimed within 8 weeks starting from the date on which your account was debited.', ); return $LANG; diff --git a/resources/views/portal/ninja2020/gateways/stripe/sepa/sepa_debit.blade.php b/resources/views/portal/ninja2020/gateways/stripe/sepa/sepa_debit.blade.php index ada051bfe3..ede181c99b 100644 --- a/resources/views/portal/ninja2020/gateways/stripe/sepa/sepa_debit.blade.php +++ b/resources/views/portal/ninja2020/gateways/stripe/sepa/sepa_debit.blade.php @@ -1,5 +1,16 @@
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.name')]) - + + + +
+ {{ctrans('texts.sepa_mandat')}} +
@endcomponent
From 2f26114110abd1cc117538adde624e8cb2d959dd Mon Sep 17 00:00:00 2001 From: Lars Kusch Date: Wed, 6 Oct 2021 15:36:14 +0200 Subject: [PATCH 22/27] Added real payment to js --- resources/js/clients/payments/stripe-sepa.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/resources/js/clients/payments/stripe-sepa.js b/resources/js/clients/payments/stripe-sepa.js index 6a2f36894e..fd53d52654 100644 --- a/resources/js/clients/payments/stripe-sepa.js +++ b/resources/js/clients/payments/stripe-sepa.js @@ -30,14 +30,16 @@ class ProcessSEPA { document.querySelector('#pay-now > svg').classList.remove('hidden'); document.querySelector('#pay-now > span').classList.add('hidden'); - this.stripe.confirmSEPAPayment( + this.stripe.confirmSepaDebitPayment( document.querySelector('meta[name=pi-client-secret').content, { payment_method: { - sofort: { - country: document.querySelector( - 'meta[name="country"]' - ).content, + sepa_debit: { + sepa_debit: document.getElementById("sepa-iban").value, + billing_details: { + name: document.getElementById("sepa-email-addres").value, + email: document.getElementById("sepa-name").value, + }, }, }, return_url: document.querySelector( From 93dfe178e0eaa600db3f77b7742b538a2600fd94 Mon Sep 17 00:00:00 2001 From: Lars Kusch Date: Wed, 6 Oct 2021 16:50:36 +0200 Subject: [PATCH 23/27] Adapted fields --- .../ninja2020/gateways/stripe/sepa/pay.blade.php | 2 ++ .../gateways/stripe/sepa/sepa_debit.blade.php | 11 +++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/resources/views/portal/ninja2020/gateways/stripe/sepa/pay.blade.php b/resources/views/portal/ninja2020/gateways/stripe/sepa/pay.blade.php index 926e254e35..508ccf57aa 100644 --- a/resources/views/portal/ninja2020/gateways/stripe/sepa/pay.blade.php +++ b/resources/views/portal/ninja2020/gateways/stripe/sepa/pay.blade.php @@ -19,6 +19,8 @@ {{ ctrans('texts.sepa') }} ({{ ctrans('texts.bank_transfer') }}) @endcomponent + @include('portal.ninja2020.gateways.stripe.sepa.sepa_debit') + @include('portal.ninja2020.gateways.includes.pay_now') @endsection diff --git a/resources/views/portal/ninja2020/gateways/stripe/sepa/sepa_debit.blade.php b/resources/views/portal/ninja2020/gateways/stripe/sepa/sepa_debit.blade.php index ede181c99b..de193956f2 100644 --- a/resources/views/portal/ninja2020/gateways/stripe/sepa/sepa_debit.blade.php +++ b/resources/views/portal/ninja2020/gateways/stripe/sepa/sepa_debit.blade.php @@ -1,16 +1,19 @@
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.name')]) +
- {{ctrans('texts.sepa_mandat')}} + +
+ @endcomponent
From 6e1e8d528e9ec4051bde97f9db394c59b320c91a Mon Sep 17 00:00:00 2001 From: Lars Kusch Date: Thu, 7 Oct 2021 15:20:20 +0200 Subject: [PATCH 24/27] Fixed bug in js and implemented stripe iban element --- public/js/clients/payments/stripe-sepa.js | 93 ++++++++++++++++++- resources/js/clients/payments/stripe-sepa.js | 44 +++++++-- .../gateways/stripe/sepa/sepa_debit.blade.php | 12 ++- 3 files changed, 136 insertions(+), 13 deletions(-) diff --git a/public/js/clients/payments/stripe-sepa.js b/public/js/clients/payments/stripe-sepa.js index 5af10e060b..1fdf03776a 100644 --- a/public/js/clients/payments/stripe-sepa.js +++ b/public/js/clients/payments/stripe-sepa.js @@ -1,2 +1,91 @@ -/*! For license information please see stripe-sofort.js.LICENSE.txt */ -!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=6)}({6:function(e,t,n){e.exports=n("RFiP")},RFiP:function(e,t){var n,r,o,u;function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var c=null!==(n=null===(r=document.querySelector('meta[name="stripe-publishable-key"]'))||void 0===r?void 0:r.content)&&void 0!==n?n:"",l=null!==(o=null===(u=document.querySelector('meta[name="stripe-account-id"]'))||void 0===u?void 0:u.content)&&void 0!==o?o:"";new function e(t,n){var r=this;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),i(this,"setupStripe",(function(){return r.stripe=Stripe(r.key),r.stripeConnect&&(r.stripe.stripeAccount=l),r})),i(this,"handle",(function(){document.getElementById("pay-now").addEventListener("click",(function(e){document.getElementById("pay-now").disabled=!0,document.querySelector("#pay-now > svg").classList.remove("hidden"),document.querySelector("#pay-now > span").classList.add("hidden"),r.stripe.confirmSepaDebitPayment(document.querySelector("meta[name=pi-client-secret").content,{payment_method:{sepa_debit:{country:document.querySelector('meta[name="country"]').content}},return_url:document.querySelector('meta[name="return-url"]').content})}))})),this.key=t,this.errors=document.getElementById("errors"),this.stripeConnect=n}(c,l).setupStripe().handle()}}); +/** + * Invoice Ninja (https://invoiceninja.com) + * + * @link https://github.com/invoiceninja/invoiceninja source repository + * + * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com) + * + * @license https://opensource.org/licenses/AAL + */ + +class ProcessSEPA { + constructor(key, stripeConnect) { + this.key = key; + this.errors = document.getElementById('errors'); + this.stripeConnect = stripeConnect; + } + + setupStripe = () => { + this.stripe = Stripe(this.key); + + if(this.stripeConnect) + this.stripe.stripeAccount = stripeConnect; + const elements = this.stripe.elements(); + var style = { + base: { + color: "#32325d", + fontFamily: + '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif', + fontSmoothing: "antialiased", + fontSize: "16px", + "::placeholder": { + color: "#aab7c4" + }, + ":-webkit-autofill": { + color: "#32325d" + } + }, + invalid: { + color: "#fa755a", + iconColor: "#fa755a", + ":-webkit-autofill": { + color: "#fa755a" + } + } + }; + var options = { + style: style, + supportedCountries: ["SEPA"], + // If you know the country of the customer, you can optionally pass it to + // the Element as placeholderCountry. The example IBAN that is being used + // as placeholder reflects the IBAN format of that country. + placeholderCountry: "DE" + }; + this.iban = elements.create("iban", options); + this.iban.mount("#sepa-iban"); + return this; + }; + + handle = () => { + document.getElementById('pay-now').addEventListener('click', (e) => { + document.getElementById('pay-now').disabled = true; + document.querySelector('#pay-now > svg').classList.remove('hidden'); + document.querySelector('#pay-now > span').classList.add('hidden'); + + this.stripe.confirmSepaDebitPayment( + document.querySelector('meta[name=pi-client-secret').content, + { + payment_method: { + sepa_debit: this.iban, + billing_details: { + name: document.getElementById("sepa-name").value, + email: document.getElementById("sepa-email-address").value, + }, + }, + return_url: document.querySelector( + 'meta[name="return-url"]' + ).content, + } + ); + }); + }; +} + +const publishableKey = document.querySelector( + 'meta[name="stripe-publishable-key"]' +)?.content ?? ''; + +const stripeConnect = + document.querySelector('meta[name="stripe-account-id"]')?.content ?? ''; + +new ProcessSEPA(publishableKey, stripeConnect).setupStripe().handle(); diff --git a/resources/js/clients/payments/stripe-sepa.js b/resources/js/clients/payments/stripe-sepa.js index fd53d52654..5a216d81c2 100644 --- a/resources/js/clients/payments/stripe-sepa.js +++ b/resources/js/clients/payments/stripe-sepa.js @@ -20,7 +20,39 @@ class ProcessSEPA { if(this.stripeConnect) this.stripe.stripeAccount = stripeConnect; - + const elements = this.stripe.elements(); + var style = { + base: { + color: "#32325d", + fontFamily: + '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif', + fontSmoothing: "antialiased", + fontSize: "16px", + "::placeholder": { + color: "#aab7c4" + }, + ":-webkit-autofill": { + color: "#32325d" + } + }, + invalid: { + color: "#fa755a", + iconColor: "#fa755a", + ":-webkit-autofill": { + color: "#fa755a" + } + } + }; + var options = { + style: style, + supportedCountries: ["SEPA"], + // If you know the country of the customer, you can optionally pass it to + // the Element as placeholderCountry. The example IBAN that is being used + // as placeholder reflects the IBAN format of that country. + placeholderCountry: "DE" + }; + this.iban = elements.create("iban", options); + this.iban.mount("#sepa-iban"); return this; }; @@ -34,12 +66,10 @@ class ProcessSEPA { document.querySelector('meta[name=pi-client-secret').content, { payment_method: { - sepa_debit: { - sepa_debit: document.getElementById("sepa-iban").value, - billing_details: { - name: document.getElementById("sepa-email-addres").value, - email: document.getElementById("sepa-name").value, - }, + sepa_debit: this.iban, + billing_details: { + name: document.getElementById("sepa-name").value, + email: document.getElementById("sepa-email-address").value, }, }, return_url: document.querySelector( diff --git a/resources/views/portal/ninja2020/gateways/stripe/sepa/sepa_debit.blade.php b/resources/views/portal/ninja2020/gateways/stripe/sepa/sepa_debit.blade.php index de193956f2..7694428c2d 100644 --- a/resources/views/portal/ninja2020/gateways/stripe/sepa/sepa_debit.blade.php +++ b/resources/views/portal/ninja2020/gateways/stripe/sepa/sepa_debit.blade.php @@ -6,10 +6,14 @@ - -
+
+ +
+ +
+
From 7f6537d3b6e7f92217e866a8ee6428fe1b3494d6 Mon Sep 17 00:00:00 2001 From: Lars Kusch Date: Thu, 7 Oct 2021 15:46:36 +0200 Subject: [PATCH 25/27] fixed minor issues --- app/Models/Gateway.php | 2 +- .../ninja2020/gateways/stripe/sepa/sepa_debit.blade.php | 5 +---- .../portal/ninja2020/gateways/stripe/sofort/pay.blade.php | 1 - 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/app/Models/Gateway.php b/app/Models/Gateway.php index d49429baf8..add21c73e5 100644 --- a/app/Models/Gateway.php +++ b/app/Models/Gateway.php @@ -103,7 +103,7 @@ class Gateway extends StaticModel 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']], //Stripe - GatewayType::SEPA => ['refund' => true, 'token_billing' => false]]; + GatewayType::SEPA => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded']]]; case 39: return [GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true]]; //Checkout break; diff --git a/resources/views/portal/ninja2020/gateways/stripe/sepa/sepa_debit.blade.php b/resources/views/portal/ninja2020/gateways/stripe/sepa/sepa_debit.blade.php index 7694428c2d..73795895a4 100644 --- a/resources/views/portal/ninja2020/gateways/stripe/sepa/sepa_debit.blade.php +++ b/resources/views/portal/ninja2020/gateways/stripe/sepa/sepa_debit.blade.php @@ -6,10 +6,7 @@ -
- +
diff --git a/resources/views/portal/ninja2020/gateways/stripe/sofort/pay.blade.php b/resources/views/portal/ninja2020/gateways/stripe/sofort/pay.blade.php index 01a152f5a7..85c223516e 100644 --- a/resources/views/portal/ninja2020/gateways/stripe/sofort/pay.blade.php +++ b/resources/views/portal/ninja2020/gateways/stripe/sofort/pay.blade.php @@ -18,7 +18,6 @@ @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.payment_type')]) {{ ctrans('texts.sofort') }} ({{ ctrans('texts.bank_transfer') }}) @endcomponent - @include('portal.ninja2020.gateways.stripe.sepa.sepa_debit') @include('portal.ninja2020.gateways.includes.pay_now') @endsection From abd8a635206842ab39356973be7a1ef990f31079 Mon Sep 17 00:00:00 2001 From: Lars Kusch Date: Fri, 8 Oct 2021 14:48:17 +0200 Subject: [PATCH 26/27] fixed minor issues --- resources/lang/en/texts.php | 3 ++- .../gateways/stripe/sepa/sepa_debit.blade.php | 19 +++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php index ec22a578e3..2a94cbfb34 100644 --- a/resources/lang/en/texts.php +++ b/resources/lang/en/texts.php @@ -4316,7 +4316,8 @@ $LANG = array( 'payment_method_cannot_be_preauthorized' => 'This payment method cannot be preauthorized.', 'kbc_cbc' => 'KBC/CBC', 'bancontact' => 'Bancontact', - 'sepa_mandat' => 'By providing your IBAN and confirming this payment, you are authorizing Rocketship Inc. and Stripe, our payment service provider, to send instructions to your bank to debit your account and your bank to debit your account in accordance with those instructions. You are entitled to a refund from your bank under the terms and conditions of your agreement with your bank. A refund must be claimed within 8 weeks starting from the date on which your account was debited.', + 'sepa_mandat' => 'By providing your IBAN and confirming this payment, you are authorizing :company and Stripe, our payment service provider, to send instructions to your bank to debit your account and your bank to debit your account in accordance with those instructions. You are entitled to a refund from your bank under the terms and conditions of your agreement with your bank. A refund must be claimed within 8 weeks starting from the date on which your account was debited.', + 'bank_account_holder' => 'Bank Account Holder', ); return $LANG; diff --git a/resources/views/portal/ninja2020/gateways/stripe/sepa/sepa_debit.blade.php b/resources/views/portal/ninja2020/gateways/stripe/sepa/sepa_debit.blade.php index 73795895a4..126c5b48bd 100644 --- a/resources/views/portal/ninja2020/gateways/stripe/sepa/sepa_debit.blade.php +++ b/resources/views/portal/ninja2020/gateways/stripe/sepa/sepa_debit.blade.php @@ -1,20 +1,19 @@
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.name')]) -