mirror of
				https://github.com/invoiceninja/invoiceninja.git
				synced 2025-10-31 14:07:32 -04:00 
			
		
		
		
	Merge pull request #6806 from LarsK1/Przelewy24
Stripe: Add Przelewy24 payment integration
This commit is contained in:
		
						commit
						26bb30e44e
					
				| @ -105,6 +105,7 @@ class Gateway extends StaticModel | |||||||
|                     GatewayType::APPLE_PAY => ['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' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded']], |                     GatewayType::SEPA => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded']], | ||||||
|  |                     GatewayType::PRZELEWY24 => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded']], | ||||||
|                     GatewayType::GIROPAY => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded']], |                     GatewayType::GIROPAY => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded']], | ||||||
|                     GatewayType::IDEAL => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded']]]; |                     GatewayType::IDEAL => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded']]]; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -30,6 +30,7 @@ class GatewayType extends StaticModel | |||||||
|     const IDEAL = 13; |     const IDEAL = 13; | ||||||
|     const HOSTED_PAGE = 14; // For gateways that contain multiple methods.
 |     const HOSTED_PAGE = 14; // For gateways that contain multiple methods.
 | ||||||
|     const GIROPAY = 15; |     const GIROPAY = 15; | ||||||
|  |     const PRZELEWY24 = 16; | ||||||
| 
 | 
 | ||||||
|     public function gateway() |     public function gateway() | ||||||
|     { |     { | ||||||
| @ -70,6 +71,8 @@ class GatewayType extends StaticModel | |||||||
|                 return ctrans('texts.ideal'); |                 return ctrans('texts.ideal'); | ||||||
|             case self::HOSTED_PAGE: |             case self::HOSTED_PAGE: | ||||||
|                 return ctrans('texts.aio_checkout'); |                 return ctrans('texts.aio_checkout'); | ||||||
|  |             case self::PRZELEWY24: | ||||||
|  |                 return ctrans('texts.przelewy24'); | ||||||
|             case self::GIROPAY: |             case self::GIROPAY: | ||||||
|                 return ctrans('texts.giropay'); |                 return ctrans('texts.giropay'); | ||||||
|             default: |             default: | ||||||
|  | |||||||
| @ -48,6 +48,8 @@ class PaymentType extends StaticModel | |||||||
|     const IDEAL = 37; |     const IDEAL = 37; | ||||||
|     const HOSTED_PAGE = 38; |     const HOSTED_PAGE = 38; | ||||||
|     const GIROPAY = 39; |     const GIROPAY = 39; | ||||||
|  |     const PRZELEWY24 = 40; | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
|     public static function parseCardType($cardName) |     public static function parseCardType($cardName) | ||||||
|     { |     { | ||||||
|  | |||||||
							
								
								
									
										141
									
								
								app/PaymentDrivers/Stripe/PRZELEWY24.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								app/PaymentDrivers/Stripe/PRZELEWY24.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,141 @@ | |||||||
|  | <?php | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * 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://www.elastic.co/licensing/elastic-license | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | namespace App\PaymentDrivers\Stripe; | ||||||
|  | 
 | ||||||
|  | use App\Exceptions\PaymentFailed; | ||||||
|  | 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; | ||||||
|  | 
 | ||||||
|  | class PRZELEWY24 | ||||||
|  | { | ||||||
|  |     /** @var StripePaymentDriver */ | ||||||
|  |     public StripePaymentDriver $stripe; | ||||||
|  | 
 | ||||||
|  |     public function __construct(StripePaymentDriver $stripe) | ||||||
|  |     { | ||||||
|  |         $this->stripe = $stripe; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public function authorizeView($data) | ||||||
|  |     { | ||||||
|  |         return render('gateways.stripe.przelewy24.authorize', $data); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     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; | ||||||
|  | 
 | ||||||
|  |         $intent = \Stripe\PaymentIntent::create([ | ||||||
|  |             'amount' => $data['stripe_amount'], | ||||||
|  |             'currency' => 'eur', | ||||||
|  |             'payment_method_types' => ['p24'], | ||||||
|  |             'customer' => $this->stripe->findOrCreateCustomer(), | ||||||
|  |             'description' => $this->stripe->decodeUnicodeString(ctrans('texts.invoices') . ': ' . collect($data['invoices'])->pluck('invoice_number')), | ||||||
|  | 
 | ||||||
|  |         ]); | ||||||
|  | 
 | ||||||
|  |         $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.przelewy24.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::PRZELEWY24, | ||||||
|  |         ]); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public function paymentResponse($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) | ||||||
|  |     { | ||||||
|  |         /* @todo: https://github.com/invoiceninja/invoiceninja/pull/3789/files#r436175798 */ | ||||||
|  | 
 | ||||||
|  |         $this->stripe->init(); | ||||||
|  | 
 | ||||||
|  |         $data = [ | ||||||
|  |             'payment_method' => $payment_intent, | ||||||
|  |             'payment_type' => PaymentType::PRZELEWY24, | ||||||
|  |             '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::PRZELEWY24, | ||||||
|  |         ]; | ||||||
|  | 
 | ||||||
|  |         $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); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -33,6 +33,7 @@ use App\PaymentDrivers\Stripe\CreditCard; | |||||||
| use App\PaymentDrivers\Stripe\ImportCustomers; | use App\PaymentDrivers\Stripe\ImportCustomers; | ||||||
| use App\PaymentDrivers\Stripe\SOFORT; | use App\PaymentDrivers\Stripe\SOFORT; | ||||||
| use App\PaymentDrivers\Stripe\SEPA; | use App\PaymentDrivers\Stripe\SEPA; | ||||||
|  | use App\PaymentDrivers\Stripe\PRZELEWY24; | ||||||
| use App\PaymentDrivers\Stripe\GIROPAY; | use App\PaymentDrivers\Stripe\GIROPAY; | ||||||
| use App\PaymentDrivers\Stripe\iDeal; | use App\PaymentDrivers\Stripe\iDeal; | ||||||
| use App\PaymentDrivers\Stripe\UpdatePaymentMethods; | use App\PaymentDrivers\Stripe\UpdatePaymentMethods; | ||||||
| @ -79,9 +80,9 @@ class StripePaymentDriver extends BaseDriver | |||||||
|         GatewayType::SOFORT => SOFORT::class, |         GatewayType::SOFORT => SOFORT::class, | ||||||
|         GatewayType::APPLE_PAY => ApplePay::class, |         GatewayType::APPLE_PAY => ApplePay::class, | ||||||
|         GatewayType::SEPA => SEPA::class, |         GatewayType::SEPA => SEPA::class, | ||||||
|  |         GatewayType::PRZELEWY24 => PRZELEWY24::class, | ||||||
|         GatewayType::GIROPAY => GIROPAY::class, |         GatewayType::GIROPAY => GIROPAY::class, | ||||||
|         GatewayType::IDEAL => iDeal::class, |         GatewayType::IDEAL => iDeal::class, | ||||||
| 
 |  | ||||||
|     ]; |     ]; | ||||||
| 
 | 
 | ||||||
|     const SYSTEM_LOG_TYPE = SystemLog::TYPE_STRIPE; |     const SYSTEM_LOG_TYPE = SystemLog::TYPE_STRIPE; | ||||||
| @ -160,12 +161,19 @@ class StripePaymentDriver extends BaseDriver | |||||||
|             $types[] = GatewayType::SEPA; |             $types[] = GatewayType::SEPA; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         if ($this->client | ||||||
|  |             && isset($this->client->country) | ||||||
|  |             && in_array($this->client->country->iso_3166_3, ['POL'])){ | ||||||
|  |             $types[] = GatewayType::PRZELEWY24; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         if($this->client |         if($this->client | ||||||
|             && $this->client->currency() |             && $this->client->currency() | ||||||
|             && ($this->client->currency()->code == 'EUR') |             && ($this->client->currency()->code == 'EUR') | ||||||
|             && isset($this->client->country) |             && isset($this->client->country) | ||||||
|             && in_array($this->client->country->iso_3166_3, ["DEU"])) |             && in_array($this->client->country->iso_3166_3, ["DEU"])){ | ||||||
|             $types[] = GatewayType::GIROPAY; |             $types[] = GatewayType::GIROPAY; | ||||||
|  |         } | ||||||
|        |        | ||||||
|         if ($this->client |         if ($this->client | ||||||
|             && $this->client->currency() |             && $this->client->currency() | ||||||
| @ -192,6 +200,9 @@ class StripePaymentDriver extends BaseDriver | |||||||
|             case GatewayType::SEPA: |             case GatewayType::SEPA: | ||||||
|                 return 'gateways.stripe.sepa'; |                 return 'gateways.stripe.sepa'; | ||||||
|                 break; |                 break; | ||||||
|  |             case GatewayType::PRZELEWY24: | ||||||
|  |                 return 'gateways.stripe.przelewy24'; | ||||||
|  |                 break; | ||||||
|             case GatewayType::CRYPTO: |             case GatewayType::CRYPTO: | ||||||
|             case GatewayType::ALIPAY: |             case GatewayType::ALIPAY: | ||||||
|             case GatewayType::APPLE_PAY: |             case GatewayType::APPLE_PAY: | ||||||
|  | |||||||
							
								
								
									
										1
									
								
								public/js/clients/payments/stripe-przelewy24.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								public/js/clients/payments/stripe-przelewy24.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | !function(n){var o={};function r(e){if(o[e])return o[e].exports;var t=o[e]={i:e,l:!1,exports:{}};return n[e].call(t.exports,t,t.exports,r),t.l=!0,t.exports}r.m=n,r.c=o,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(t,e){if(1&e&&(t=r(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)r.d(n,o,function(e){return t[e]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="/",r(r.s=6)}({6:function(e,t,n){e.exports=n("RFiP")},RFiP:function(e,t){var n;function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var o=null!==(n=null===(o=document.querySelector('meta[name="stripe-publishable-key"]'))||void 0===o?void 0:o.content)&&void 0!==n?n:"",a=null!==(n=null===(n=document.querySelector('meta[name="stripe-account-id"]'))||void 0===n?void 0:n.content)&&void 0!==n?n:"";new function t(e,n){var o=this;!function(e){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this),r(this,"setupStripe",function(){o.stripe=Stripe(o.key),o.stripeConnect&&(o.stripe.stripeAccount=a);let e=o.stripe.elements();return o.p24bank=e.create("p24Bank",{style:{base:{padding:"10px 12px",color:"#32325d",fontSize:"16px","::placeholder":{color:"#aab7c4"}}}}),o.p24bank.mount("#p24-bank-element"),o}),r(this,"handle",function(){document.getElementById("pay-now").addEventListener("click",function(e){let t=document.getElementById("errors");return""===document.getElementById("p24-name").value?(document.getElementById("p24-name").focus(),t.textContent="Name required.",void(t.hidden=!1)):""===document.getElementById("p24-email-address").value?(document.getElementById("p24-email-address").focus(),t.textContent="Email required.",void(t.hidden=!1)):document.getElementById("p24-mandate-acceptance").checked?(document.getElementById("pay-now").disabled=!0,document.querySelector("#pay-now > svg").classList.remove("hidden"),document.querySelector("#pay-now > span").classList.add("hidden"),void o.stripe.confirmP24Payment(document.querySelector("meta[name=pi-client-secret").content,{payment_method:{p24:o.p24bank,billing_details:{name:document.getElementById("p24-name").value,email:document.getElementById("p24-email-address").value}},payment_method_options:{p24:{tos_shown_and_accepted:document.getElementById("p24-mandate-acceptance").checked}},return_url:document.querySelector('meta[name="return-url"]').content})):(document.getElementById("p24-mandate-acceptance").focus(),t.textContent="Accept Terms.",void(t.hidden=!1))})}),this.key=e,this.errors=document.getElementById("errors"),this.stripeConnect=n}(o,a).setupStripe().handle()}}),a; | ||||||
| @ -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 | ||||||
|  |  */ | ||||||
							
								
								
									
										98
									
								
								resources/js/clients/payments/stripe-przelewy24.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								resources/js/clients/payments/stripe-przelewy24.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,98 @@ | |||||||
|  | /** | ||||||
|  |  * 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 ProcessPRZELEWY24 { | ||||||
|  |     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; | ||||||
|  |         let elements = this.stripe.elements() | ||||||
|  |         var options = { | ||||||
|  |             // Custom styling can be passed to options when creating an Element
 | ||||||
|  |             style: { | ||||||
|  |                 base: { | ||||||
|  |                     padding: '10px 12px', | ||||||
|  |                     color: '#32325d', | ||||||
|  |                     fontSize: '16px', | ||||||
|  |                     '::placeholder': { | ||||||
|  |                         color: '#aab7c4' | ||||||
|  |                     }, | ||||||
|  |                 }, | ||||||
|  |             }, | ||||||
|  |         }; | ||||||
|  |         this.p24bank = elements.create('p24Bank', options) | ||||||
|  |         this.p24bank.mount('#p24-bank-element'); | ||||||
|  |         return this; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     handle = () => { | ||||||
|  |         document.getElementById('pay-now').addEventListener('click', (e) => { | ||||||
|  |             let errors = document.getElementById('errors'); | ||||||
|  | 
 | ||||||
|  |             if (document.getElementById('p24-name').value === "") { | ||||||
|  |                 document.getElementById('p24-name').focus(); | ||||||
|  |                 errors.textContent = "Name required."; | ||||||
|  |                 errors.hidden = false; | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             if (document.getElementById('p24-email-address').value === "") { | ||||||
|  |                 document.getElementById('p24-email-address').focus(); | ||||||
|  |                 errors.textContent = "Email required."; | ||||||
|  |                 errors.hidden = false; | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             if (!document.getElementById('p24-mandate-acceptance').checked) { | ||||||
|  |                 document.getElementById('p24-mandate-acceptance').focus(); | ||||||
|  |                 errors.textContent = "Accept Terms."; | ||||||
|  |                 errors.hidden = false; | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             document.getElementById('pay-now').disabled = true; | ||||||
|  |             document.querySelector('#pay-now > svg').classList.remove('hidden'); | ||||||
|  |             document.querySelector('#pay-now > span').classList.add('hidden'); | ||||||
|  | 
 | ||||||
|  |             this.stripe.confirmP24Payment( | ||||||
|  |                 document.querySelector('meta[name=pi-client-secret').content, | ||||||
|  |                 { | ||||||
|  |                     payment_method: { | ||||||
|  |                         p24: this.p24bank, | ||||||
|  |                         billing_details: { | ||||||
|  |                             name: document.getElementById('p24-name').value, | ||||||
|  |                             email: document.getElementById('p24-email-address').value, | ||||||
|  |                         }, | ||||||
|  |                     }, | ||||||
|  |                     payment_method_options: { | ||||||
|  |                         p24: { | ||||||
|  |                             tos_shown_and_accepted: document.getElementById('p24-mandate-acceptance').checked, | ||||||
|  |                         }, | ||||||
|  |                     }, | ||||||
|  |                     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 ProcessPRZELEWY24(publishableKey, stripeConnect).setupStripe().handle(); | ||||||
| @ -4320,6 +4320,8 @@ $LANG = array( | |||||||
|     'ideal' => 'iDEAL', |     'ideal' => 'iDEAL', | ||||||
|     'bank_account_holder' => 'Bank Account Holder', |     'bank_account_holder' => 'Bank Account Holder', | ||||||
|     'aio_checkout' => 'All-in-one checkout', |     'aio_checkout' => 'All-in-one checkout', | ||||||
|  |     'przelewy24' => 'Przelewy24', | ||||||
|  |     'przelewy24_accept' => 'I declare that I have familiarized myself with the regulations and information obligation of the Przelewy24 service.' | ||||||
|     'giropay' => 'GiroPay', |     'giropay' => 'GiroPay', | ||||||
|     'giropay_law' => 'By entering your Customer information (such as name, sort code and account number) you (the Customer) agree that this information is given voluntarily.' |     'giropay_law' => 'By entering your Customer information (such as name, sort code and account number) you (the Customer) agree that this information is given voluntarily.' | ||||||
| ); | ); | ||||||
|  | |||||||
| @ -4250,6 +4250,7 @@ $LANG = array( | |||||||
|     'contact_details' => 'Contact Details', |     'contact_details' => 'Contact Details', | ||||||
|     'download_backup_subject' => 'Your company backup is ready for download', |     'download_backup_subject' => 'Your company backup is ready for download', | ||||||
|     'account_passwordless_login' => 'Account passwordless login', |     'account_passwordless_login' => 'Account passwordless login', | ||||||
|  |     'przelewy24' => 'Przelewy24', | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
| return $LANG; | return $LANG; | ||||||
|  | |||||||
| @ -4249,6 +4249,8 @@ Gdy przelewy zostaną zaksięgowane na Twoim koncie, wróć do tej strony i klik | |||||||
|     'contact_details' => 'Contact Details', |     'contact_details' => 'Contact Details', | ||||||
|     'download_backup_subject' => 'Your company backup is ready for download', |     'download_backup_subject' => 'Your company backup is ready for download', | ||||||
|     'account_passwordless_login' => 'Account passwordless login', |     'account_passwordless_login' => 'Account passwordless login', | ||||||
|  |     'przelewy24' => 'Przelewy24', | ||||||
|  |     'przelewy24_accept' => 'Oświadczam, że zapoznałem się z regulaminem i obowiązkiem informacyjnym serwisu Przelewy24.' | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
| return $LANG; | return $LANG; | ||||||
|  | |||||||
| @ -0,0 +1,84 @@ | |||||||
|  | @extends('portal.ninja2020.layout.payments', ['gateway_title' => 'SEPA', 'card_title' => 'SEPA-Lastschrift']) | ||||||
|  | 
 | ||||||
|  | @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->company_gateway->getPublishableKey() }}"> | ||||||
|  |     @endif | ||||||
|  | @endsection | ||||||
|  | 
 | ||||||
|  | @section('gateway_content') | ||||||
|  |     @if(session()->has('sepa_error')) | ||||||
|  |         <div class="alert alert-failure mb-4"> | ||||||
|  |             <p>{{ session('sepa_error') }}</p> | ||||||
|  |         </div> | ||||||
|  |     @endif | ||||||
|  | 
 | ||||||
|  |     <form action="{{ route('client.payment_methods.store', ['method' => App\Models\GatewayType::SEPA]) }}" method="post" id="server_response"> | ||||||
|  |         @csrf | ||||||
|  | 
 | ||||||
|  |         <input type="hidden" name="company_gateway_id" value="{{ $gateway->company_gateway->id }}"> | ||||||
|  |         <input type="hidden" name="gateway_type_id" value="{{ $payment_method_id }}"> | ||||||
|  |         <input type="hidden" name="gateway_response" id="gateway_response"> | ||||||
|  |         <input type="hidden" name="payment_hash" value="{{ $payment_hash }}"> | ||||||
|  | 
 | ||||||
|  |         <input type="hidden" name="is_default" id="is_default"> | ||||||
|  |     </form> | ||||||
|  | 
 | ||||||
|  |     <div class="alert alert-failure mb-4" hidden id="errors"></div> | ||||||
|  | 
 | ||||||
|  |     @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.account_holder_type')]) | ||||||
|  |         <span class="flex items-center mr-4"> | ||||||
|  |             <input class="form-radio mr-2" type="radio" value="individual" name="account-holder-type" checked> | ||||||
|  |             <span>{{ __('texts.individual_account') }}</span> | ||||||
|  |         </span> | ||||||
|  |         <span class="flex items-center"> | ||||||
|  |             <input class="form-radio mr-2" type="radio" value="company" name="account-holder-type"> | ||||||
|  |             <span>{{ __('texts.company_account') }}</span> | ||||||
|  |         </span> | ||||||
|  |     @endcomponent | ||||||
|  | 
 | ||||||
|  |     @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.account_holder_name')]) | ||||||
|  |         <input class="input w-full" id="account-holder-name" type="text" placeholder="{{ ctrans('texts.name') }}" required> | ||||||
|  |     @endcomponent | ||||||
|  | 
 | ||||||
|  |     @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.country')]) | ||||||
|  |         <select name="countries" id="country" class="form-select input w-full" required> | ||||||
|  |             @foreach($countries as $country) | ||||||
|  |                 <option value="{{ $country->iso_3166_2 }}">{{ $country->iso_3166_2 }} ({{ $country->name }})</option> | ||||||
|  |             @endforeach | ||||||
|  |         </select> | ||||||
|  |     @endcomponent | ||||||
|  | 
 | ||||||
|  |     @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.currency')]) | ||||||
|  |         <select name="currencies" id="currency" class="form-select input w-full"> | ||||||
|  |             @foreach($currencies as $currency) | ||||||
|  |                 <option value="{{ $currency->code }}">{{ $currency->code }} ({{ $currency->name }})</option> | ||||||
|  |             @endforeach | ||||||
|  |         </select> | ||||||
|  |     @endcomponent | ||||||
|  | 
 | ||||||
|  |     @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.routing_number')]) | ||||||
|  |         <input class="input w-full" id="routing-number" type="text" required> | ||||||
|  |     @endcomponent | ||||||
|  | 
 | ||||||
|  |     @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.account_number')]) | ||||||
|  |         <input class="input w-full" id="account-number" type="text" required> | ||||||
|  |     @endcomponent | ||||||
|  | 
 | ||||||
|  |     @component('portal.ninja2020.components.general.card-element-single') | ||||||
|  |         <input type="checkbox" class="form-checkbox mr-1" id="accept-terms" required> | ||||||
|  |         <label for="accept-terms" class="cursor-pointer">{{ ctrans('texts.ach_authorization', ['company' => auth()->user()->company->present()->name, 'email' => auth('contact')->user()->client->company->settings->email]) }}</label> | ||||||
|  |     @endcomponent | ||||||
|  | 
 | ||||||
|  |     @component('portal.ninja2020.gateways.includes.pay_now', ['id' => 'save-button']) | ||||||
|  |         {{ ctrans('texts.add_payment_method') }} | ||||||
|  |     @endcomponent | ||||||
|  | @endsection | ||||||
|  | 
 | ||||||
|  | @section('gateway_footer') | ||||||
|  |     <script src="https://js.stripe.com/v3/"></script> | ||||||
|  |     <script src="{{ asset('js/clients/payments/stripe-sepa.js') }}"></script> | ||||||
|  | @endsection | ||||||
| @ -0,0 +1,30 @@ | |||||||
|  | @extends('portal.ninja2020.layout.payments', ['gateway_title' => 'Przelewy24', 'card_title' => 'Przelewy24']) | ||||||
|  | 
 | ||||||
|  | @section('gateway_head') | ||||||
|  |     <meta name="stripe-publishable-key" content="{{ $gateway->getPublishableKey() }}"> | ||||||
|  |     <meta name="stripe-account-id" content="{{ $gateway->company_gateway->getConfigField('account_id') }}"> | ||||||
|  |     <meta name="amount" content="{{ $stripe_amount }}"> | ||||||
|  |     <meta name="country" content="{{ $country }}"> | ||||||
|  |     <meta name="return-url" content="{{ $return_url }}"> | ||||||
|  |     <meta name="customer" content="{{ $customer }}"> | ||||||
|  |     <meta name="pi-client-secret" content="{{ $pi_client_secret }}"> | ||||||
|  | @endsection | ||||||
|  | 
 | ||||||
|  | @section('gateway_content') | ||||||
|  |     <div class="alert alert-failure mb-4" hidden id="errors"></div> | ||||||
|  | 
 | ||||||
|  |     @include('portal.ninja2020.gateways.includes.payment_details') | ||||||
|  | 
 | ||||||
|  |     @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.payment_type')]) | ||||||
|  |         {{ ctrans('texts.przelewy24') }} ({{ ctrans('texts.bank_transfer') }}) | ||||||
|  |     @endcomponent | ||||||
|  | 
 | ||||||
|  |     @include('portal.ninja2020.gateways.stripe.przelewy24.przelewy24') | ||||||
|  |     @include('portal.ninja2020.gateways.includes.save_card') | ||||||
|  |     @include('portal.ninja2020.gateways.includes.pay_now') | ||||||
|  | @endsection | ||||||
|  | 
 | ||||||
|  | @push('footer') | ||||||
|  |     <script src="https://js.stripe.com/v3/"></script> | ||||||
|  |     <script src="{{ asset('js/clients/payments/stripe-przelewy24.js') }}"></script> | ||||||
|  | @endpush | ||||||
| @ -0,0 +1,17 @@ | |||||||
|  | <div id="stripe--payment-container"> | ||||||
|  |     @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.name')]) | ||||||
|  |     <label for="p24-name"> | ||||||
|  |         <input class="input w-full" id="p24-name" type="text" placeholder="{{ ctrans('texts.bank_account_holder') }}"> | ||||||
|  |     </label> | ||||||
|  |     <label for="p24-email" > | ||||||
|  |         <input class="input w-full" id="p24-email-address" type="email" placeholder="{{ ctrans('texts.email') }}"> | ||||||
|  |     </label> | ||||||
|  |     <label for="p24-bank-element"></label> | ||||||
|  |     <div class="border p-4 rounded"><div id="p24-bank-element"></div> | ||||||
|  |     </div> | ||||||
|  |     <div id="mandate-acceptance"> | ||||||
|  |         <input type="checkbox" id="p24-mandate-acceptance" class="input mr-4"> | ||||||
|  |         <label for="p24-mandate-acceptance">{{ctrans('texts.przelewy24_accept')}}</label> | ||||||
|  |     </div> | ||||||
|  |     @endcomponent | ||||||
|  | </div> | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user