mirror of
				https://github.com/invoiceninja/invoiceninja.git
				synced 2025-10-31 12:17:32 -04:00 
			
		
		
		
	Implement Stripe Giropay
This commit is contained in:
		
							parent
							
								
									5169e0587e
								
							
						
					
					
						commit
						f41b49ad7e
					
				| @ -104,7 +104,8 @@ 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' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded']]]; | ||||
|                     GatewayType::SEPA => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded']], | ||||
|                     GatewayType::GIROPAY => ['refund' => true, 'token_billing' => true, 'webhooks' => ['source.chargeable', 'charge.succeeded']]]; | ||||
|             case 39: | ||||
|                 return [GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true]]; //Checkout
 | ||||
|                 break; | ||||
|  | ||||
| @ -29,7 +29,8 @@ class GatewayType extends StaticModel | ||||
|     const BANCONTACT = 12; | ||||
|     const IDEAL = 13; | ||||
|     const HOSTED_PAGE = 14; // For gateways that contain multiple methods.
 | ||||
|      | ||||
|     const GIROPAY = 15; | ||||
| 
 | ||||
|     public function gateway() | ||||
|     { | ||||
|         return $this->belongsTo(Gateway::class); | ||||
| @ -69,6 +70,8 @@ class GatewayType extends StaticModel | ||||
|                 return ctrans('texts.ideal'); | ||||
|             case self::HOSTED_PAGE: | ||||
|                 return ctrans('texts.aio_checkout'); | ||||
|             case self::GIROPAY: | ||||
|                 return ctrans('texts.giropay'); | ||||
|             default: | ||||
|                 return 'Undefined.'; | ||||
|                 break; | ||||
|  | ||||
							
								
								
									
										141
									
								
								app/PaymentDrivers/Stripe/GIROPAY.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								app/PaymentDrivers/Stripe/GIROPAY.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 GIROPAY | ||||
| { | ||||
|     /** @var StripePaymentDriver */ | ||||
|     public StripePaymentDriver $stripe; | ||||
| 
 | ||||
|     public function __construct(StripePaymentDriver $stripe) | ||||
|     { | ||||
|         $this->stripe = $stripe; | ||||
|     } | ||||
| 
 | ||||
|     public function authorizeView($data) | ||||
|     { | ||||
|         return render('gateways.stripe.giropay.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' => ['giropay'], | ||||
|             '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.giropay.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::GIROPAY, | ||||
|         ]); | ||||
|     } | ||||
| 
 | ||||
|     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::GIROPAY, | ||||
|             '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::GIROPAY, | ||||
|         ]; | ||||
| 
 | ||||
|         $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\SOFORT; | ||||
| use App\PaymentDrivers\Stripe\SEPA; | ||||
| use App\PaymentDrivers\Stripe\GIROPAY; | ||||
| use App\PaymentDrivers\Stripe\UpdatePaymentMethods; | ||||
| use App\PaymentDrivers\Stripe\Utilities; | ||||
| use App\Utils\Traits\MakesHash; | ||||
| @ -77,6 +78,7 @@ class StripePaymentDriver extends BaseDriver | ||||
|         GatewayType::SOFORT => SOFORT::class, | ||||
|         GatewayType::APPLE_PAY => ApplePay::class, | ||||
|         GatewayType::SEPA => SEPA::class, | ||||
|         GatewayType::GIROPAY => GIROPAY::class, | ||||
|     ]; | ||||
| 
 | ||||
|     const SYSTEM_LOG_TYPE = SystemLog::TYPE_STRIPE; | ||||
| @ -153,6 +155,11 @@ class StripePaymentDriver extends BaseDriver | ||||
|             $types[] = GatewayType::SEPA; | ||||
|         } | ||||
| 
 | ||||
|         if ($this -> client | ||||
|             && isset($this->client->country) | ||||
|             && in_array($this->client->country->iso_3166_3, ["DEU"])) | ||||
|             $types[] = GatewayType::GIROPAY; | ||||
| 
 | ||||
|         return $types; | ||||
|     } | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										57
									
								
								resources/js/clients/payments/stripe-giropay.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								resources/js/clients/payments/stripe-giropay.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,57 @@ | ||||
| /** | ||||
|  * 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 ProcessGiroPay { | ||||
|     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.confirmGiropayPayment( | ||||
|                 document.querySelector('meta[name=pi-client-secret').content, | ||||
|                 { | ||||
|                     payment_method: { | ||||
|                         billing_details: { | ||||
|                             name: "", | ||||
|                         }, | ||||
|                     }, | ||||
|                     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 ProcessGiroPay(publishableKey, stripeConnect).setupStripe().handle(); | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user