1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-09-20 16:31:33 +02:00

Merge pull request #6803 from turbo124/v5-develop

Fixes for Stripe SEPA
This commit is contained in:
David Bomba 2021-10-09 12:30:44 +11:00 committed by GitHub
commit 5169e0587e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 265 additions and 202 deletions

View File

@ -72,7 +72,7 @@ class Kernel extends ConsoleKernel
$schedule->call(function () {
Account::whereNotNull('id')->update(['is_scheduler_running' => true]);
})->everyFiveMinutes()->withoutOverlapping();
})->everyFiveMinutes();
/* Run hosted specific jobs */
if (Ninja::isHosted()) {

View File

@ -1,5 +1,4 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
@ -39,11 +38,12 @@ class SEPA
public function paymentView(array $data) {
$data['gateway'] = $this->stripe;
$data['return_url'] = $this->buildReturnUrl();
$data['payment_method_id'] = GatewayType::SEPA;
$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;
$data['payment_hash'] = $this->stripe->payment_hash->hash;
$intent = \Stripe\PaymentIntent::create([
'amount' => $data['stripe_amount'],
@ -63,25 +63,24 @@ class SEPA
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)
{
$gateway_response = json_decode($request->gateway_response);
$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);
if (property_exists($gateway_response, 'status') && $gateway_response->status == 'processing') {
$this->stripe->init();
$this->storePaymentMethod($gateway_response);
return $this->processSuccessfulPayment($gateway_response->id);
}
return $this->processUnsuccessfulPayment();
}
public function processSuccessfulPayment(string $payment_intent)
@ -137,4 +136,29 @@ class SEPA
throw new PaymentFailed('Failed to process the payment.', 500);
}
private function storePaymentMethod($intent)
{
try {
$method = $this->stripe->getStripePaymentMethod($intent->payment_method);
$payment_meta = new \stdClass;
$payment_meta->brand = (string) \sprintf('%s (%s)', $method->sepa_debit->bank_code, ctrans('texts.sepa'));
$payment_meta->last4 = (string) $method->sepa_debit->last4;
$payment_meta->state = 'authorized';
$payment_meta->type = GatewayType::SEPA;
$data = [
'payment_meta' => $payment_meta,
'token' => $intent->payment_method,
'payment_method_id' => GatewayType::SEPA,
];
$this->stripe->storeGatewayToken($data, ['gateway_customer_reference' => $method->customer]);
} catch (\Exception $e) {
return $this->stripe->processInternallyFailedPayment($this->stripe, $e);
}
}
}

234
composer.lock generated
View File

@ -323,16 +323,16 @@
},
{
"name": "aws/aws-sdk-php",
"version": "3.196.1",
"version": "3.198.1",
"source": {
"type": "git",
"url": "https://github.com/aws/aws-sdk-php.git",
"reference": "2845899d05c66a00d88eabbf7cf5d3dbae2da58a"
"reference": "79bf3298bd2893eb0b4614c2463e9f675d07118b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/2845899d05c66a00d88eabbf7cf5d3dbae2da58a",
"reference": "2845899d05c66a00d88eabbf7cf5d3dbae2da58a",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/79bf3298bd2893eb0b4614c2463e9f675d07118b",
"reference": "79bf3298bd2893eb0b4614c2463e9f675d07118b",
"shasum": ""
},
"require": {
@ -408,9 +408,9 @@
"support": {
"forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
"issues": "https://github.com/aws/aws-sdk-php/issues",
"source": "https://github.com/aws/aws-sdk-php/tree/3.196.1"
"source": "https://github.com/aws/aws-sdk-php/tree/3.198.1"
},
"time": "2021-10-01T18:23:06+00:00"
"time": "2021-10-08T18:28:30+00:00"
},
{
"name": "bacon/bacon-qr-code",
@ -1049,16 +1049,16 @@
},
{
"name": "composer/composer",
"version": "2.1.8",
"version": "2.1.9",
"source": {
"type": "git",
"url": "https://github.com/composer/composer.git",
"reference": "24d38e9686092de05214cafa187dc282a5d89497"
"reference": "e558c88f28d102d497adec4852802c0dc14c7077"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/composer/zipball/24d38e9686092de05214cafa187dc282a5d89497",
"reference": "24d38e9686092de05214cafa187dc282a5d89497",
"url": "https://api.github.com/repos/composer/composer/zipball/e558c88f28d102d497adec4852802c0dc14c7077",
"reference": "e558c88f28d102d497adec4852802c0dc14c7077",
"shasum": ""
},
"require": {
@ -1127,7 +1127,7 @@
"support": {
"irc": "ircs://irc.libera.chat:6697/composer",
"issues": "https://github.com/composer/composer/issues",
"source": "https://github.com/composer/composer/tree/2.1.8"
"source": "https://github.com/composer/composer/tree/2.1.9"
},
"funding": [
{
@ -1143,7 +1143,7 @@
"type": "tidelift"
}
],
"time": "2021-09-15T11:55:15+00:00"
"time": "2021-10-05T07:47:38+00:00"
},
{
"name": "composer/metadata-minifier",
@ -3045,16 +3045,16 @@
},
{
"name": "guzzlehttp/promises",
"version": "1.4.1",
"version": "1.5.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/promises.git",
"reference": "8e7d04f1f6450fef59366c399cfad4b9383aa30d"
"reference": "136a635e2b4a49b9d79e9c8fee267ffb257fdba0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/promises/zipball/8e7d04f1f6450fef59366c399cfad4b9383aa30d",
"reference": "8e7d04f1f6450fef59366c399cfad4b9383aa30d",
"url": "https://api.github.com/repos/guzzle/promises/zipball/136a635e2b4a49b9d79e9c8fee267ffb257fdba0",
"reference": "136a635e2b4a49b9d79e9c8fee267ffb257fdba0",
"shasum": ""
},
"require": {
@ -3066,7 +3066,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
"dev-master": "1.5-dev"
}
},
"autoload": {
@ -3082,10 +3082,25 @@
"MIT"
],
"authors": [
{
"name": "Graham Campbell",
"email": "hello@gjcampbell.co.uk",
"homepage": "https://github.com/GrahamCampbell"
},
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "Tobias Nyholm",
"email": "tobias.nyholm@gmail.com",
"homepage": "https://github.com/Nyholm"
},
{
"name": "Tobias Schultze",
"email": "webmaster@tubo-world.de",
"homepage": "https://github.com/Tobion"
}
],
"description": "Guzzle promises library",
@ -3094,22 +3109,36 @@
],
"support": {
"issues": "https://github.com/guzzle/promises/issues",
"source": "https://github.com/guzzle/promises/tree/1.4.1"
"source": "https://github.com/guzzle/promises/tree/1.5.0"
},
"time": "2021-03-07T09:25:29+00:00"
"funding": [
{
"url": "https://github.com/GrahamCampbell",
"type": "github"
},
{
"url": "https://github.com/Nyholm",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises",
"type": "tidelift"
}
],
"time": "2021-10-07T13:05:22+00:00"
},
{
"name": "guzzlehttp/psr7",
"version": "1.8.2",
"version": "1.8.3",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "dc960a912984efb74d0a90222870c72c87f10c91"
"reference": "1afdd860a2566ed3c2b0b4a3de6e23434a79ec85"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/dc960a912984efb74d0a90222870c72c87f10c91",
"reference": "dc960a912984efb74d0a90222870c72c87f10c91",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/1afdd860a2566ed3c2b0b4a3de6e23434a79ec85",
"reference": "1afdd860a2566ed3c2b0b4a3de6e23434a79ec85",
"shasum": ""
},
"require": {
@ -3146,13 +3175,34 @@
"MIT"
],
"authors": [
{
"name": "Graham Campbell",
"email": "hello@gjcampbell.co.uk",
"homepage": "https://github.com/GrahamCampbell"
},
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "George Mponos",
"email": "gmponos@gmail.com",
"homepage": "https://github.com/gmponos"
},
{
"name": "Tobias Nyholm",
"email": "tobias.nyholm@gmail.com",
"homepage": "https://github.com/Nyholm"
},
{
"name": "Márk Sági-Kazár",
"email": "mark.sagikazar@gmail.com",
"homepage": "https://github.com/sagikazarmark"
},
{
"name": "Tobias Schultze",
"email": "webmaster@tubo-world.de",
"homepage": "https://github.com/Tobion"
}
],
@ -3169,9 +3219,23 @@
],
"support": {
"issues": "https://github.com/guzzle/psr7/issues",
"source": "https://github.com/guzzle/psr7/tree/1.8.2"
"source": "https://github.com/guzzle/psr7/tree/1.8.3"
},
"time": "2021-04-26T09:17:50+00:00"
"funding": [
{
"url": "https://github.com/GrahamCampbell",
"type": "github"
},
{
"url": "https://github.com/Nyholm",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7",
"type": "tidelift"
}
],
"time": "2021-10-05T13:56:00+00:00"
},
{
"name": "halaxa/json-machine",
@ -3411,16 +3475,16 @@
},
{
"name": "intervention/image",
"version": "2.6.1",
"version": "2.7.0",
"source": {
"type": "git",
"url": "https://github.com/Intervention/image.git",
"reference": "0925f10b259679b5d8ca58f3a2add9255ffcda45"
"reference": "9a8cc99d30415ec0b3f7649e1647d03a55698545"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Intervention/image/zipball/0925f10b259679b5d8ca58f3a2add9255ffcda45",
"reference": "0925f10b259679b5d8ca58f3a2add9255ffcda45",
"url": "https://api.github.com/repos/Intervention/image/zipball/9a8cc99d30415ec0b3f7649e1647d03a55698545",
"reference": "9a8cc99d30415ec0b3f7649e1647d03a55698545",
"shasum": ""
},
"require": {
@ -3479,7 +3543,7 @@
],
"support": {
"issues": "https://github.com/Intervention/image/issues",
"source": "https://github.com/Intervention/image/tree/2.6.1"
"source": "https://github.com/Intervention/image/tree/2.7.0"
},
"funding": [
{
@ -3491,7 +3555,7 @@
"type": "github"
}
],
"time": "2021-07-22T14:31:53+00:00"
"time": "2021-10-03T14:17:12+00:00"
},
{
"name": "invoiceninja/inspector",
@ -3558,16 +3622,16 @@
},
{
"name": "jean85/pretty-package-versions",
"version": "2.0.4",
"version": "2.0.5",
"source": {
"type": "git",
"url": "https://github.com/Jean85/pretty-package-versions.git",
"reference": "694492c653c518456af2805f04eec445b997ed1f"
"reference": "ae547e455a3d8babd07b96966b17d7fd21d9c6af"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/694492c653c518456af2805f04eec445b997ed1f",
"reference": "694492c653c518456af2805f04eec445b997ed1f",
"url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/ae547e455a3d8babd07b96966b17d7fd21d9c6af",
"reference": "ae547e455a3d8babd07b96966b17d7fd21d9c6af",
"shasum": ""
},
"require": {
@ -3611,9 +3675,9 @@
],
"support": {
"issues": "https://github.com/Jean85/pretty-package-versions/issues",
"source": "https://github.com/Jean85/pretty-package-versions/tree/2.0.4"
"source": "https://github.com/Jean85/pretty-package-versions/tree/2.0.5"
},
"time": "2021-05-26T08:46:42+00:00"
"time": "2021-10-08T21:21:46+00:00"
},
{
"name": "justinrainbow/json-schema",
@ -3737,16 +3801,16 @@
},
{
"name": "laravel/framework",
"version": "v8.62.0",
"version": "v8.63.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
"reference": "60a7e00488167ce2babf3a2aeb3677e48aaf39be"
"reference": "8f3d280f36a427730c8c8fa34316c79eed38781e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/60a7e00488167ce2babf3a2aeb3677e48aaf39be",
"reference": "60a7e00488167ce2babf3a2aeb3677e48aaf39be",
"url": "https://api.github.com/repos/laravel/framework/zipball/8f3d280f36a427730c8c8fa34316c79eed38781e",
"reference": "8f3d280f36a427730c8c8fa34316c79eed38781e",
"shasum": ""
},
"require": {
@ -3904,20 +3968,20 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2021-09-28T13:30:25+00:00"
"time": "2021-10-05T14:04:25+00:00"
},
{
"name": "laravel/serializable-closure",
"version": "v1.0.2",
"version": "v1.0.3",
"source": {
"type": "git",
"url": "https://github.com/laravel/serializable-closure.git",
"reference": "679e24d36ff8b9be0e36f5222244ec8602e18867"
"reference": "6cfc678735f22ccedad761b8cae2bab14c3d8e5b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/serializable-closure/zipball/679e24d36ff8b9be0e36f5222244ec8602e18867",
"reference": "679e24d36ff8b9be0e36f5222244ec8602e18867",
"url": "https://api.github.com/repos/laravel/serializable-closure/zipball/6cfc678735f22ccedad761b8cae2bab14c3d8e5b",
"reference": "6cfc678735f22ccedad761b8cae2bab14c3d8e5b",
"shasum": ""
},
"require": {
@ -3963,7 +4027,7 @@
"issues": "https://github.com/laravel/serializable-closure/issues",
"source": "https://github.com/laravel/serializable-closure"
},
"time": "2021-09-29T13:25:52+00:00"
"time": "2021-10-07T14:00:57+00:00"
},
{
"name": "laravel/slack-notification-channel",
@ -4416,16 +4480,16 @@
},
{
"name": "league/csv",
"version": "9.7.1",
"version": "9.7.2",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/csv.git",
"reference": "0ec57e8264ec92565974ead0d1724cf1026e10c1"
"reference": "8544655c460fd01eed0ad258e514488d4b388645"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/csv/zipball/0ec57e8264ec92565974ead0d1724cf1026e10c1",
"reference": "0ec57e8264ec92565974ead0d1724cf1026e10c1",
"url": "https://api.github.com/repos/thephpleague/csv/zipball/8544655c460fd01eed0ad258e514488d4b388645",
"reference": "8544655c460fd01eed0ad258e514488d4b388645",
"shasum": ""
},
"require": {
@ -4436,10 +4500,10 @@
"require-dev": {
"ext-curl": "*",
"ext-dom": "*",
"friendsofphp/php-cs-fixer": "^2.16",
"phpstan/phpstan": "^0.12.0",
"phpstan/phpstan-phpunit": "^0.12.0",
"phpstan/phpstan-strict-rules": "^0.12.0",
"friendsofphp/php-cs-fixer": "^3.0",
"phpstan/phpstan": "^0.12.99",
"phpstan/phpstan-phpunit": "^0.12.22",
"phpstan/phpstan-strict-rules": "^0.12.11",
"phpunit/phpunit": "^9.5"
},
"suggest": {
@ -4496,7 +4560,7 @@
"type": "github"
}
],
"time": "2021-04-17T16:32:08+00:00"
"time": "2021-10-05T19:41:46+00:00"
},
{
"name": "league/flysystem",
@ -7021,16 +7085,16 @@
},
{
"name": "predis/predis",
"version": "v1.1.8",
"version": "v1.1.9",
"source": {
"type": "git",
"url": "https://github.com/predis/predis.git",
"reference": "cf5c118a077fbab8b9af1482c20952173125c041"
"reference": "c50c3393bb9f47fa012d0cdfb727a266b0818259"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/predis/predis/zipball/cf5c118a077fbab8b9af1482c20952173125c041",
"reference": "cf5c118a077fbab8b9af1482c20952173125c041",
"url": "https://api.github.com/repos/predis/predis/zipball/c50c3393bb9f47fa012d0cdfb727a266b0818259",
"reference": "c50c3393bb9f47fa012d0cdfb727a266b0818259",
"shasum": ""
},
"require": {
@ -7075,7 +7139,7 @@
],
"support": {
"issues": "https://github.com/predis/predis/issues",
"source": "https://github.com/predis/predis/tree/v1.1.8"
"source": "https://github.com/predis/predis/tree/v1.1.9"
},
"funding": [
{
@ -7083,7 +7147,7 @@
"type": "github"
}
],
"time": "2021-09-29T17:48:39+00:00"
"time": "2021-10-05T19:02:38+00:00"
},
{
"name": "psr/cache",
@ -7791,16 +7855,16 @@
},
{
"name": "razorpay/razorpay",
"version": "2.7.1",
"version": "2.8.0",
"source": {
"type": "git",
"url": "https://github.com/razorpay/razorpay-php.git",
"reference": "f562c919d153c343428c9a4e8d4e0848f334aef4"
"reference": "3e70e7ccb0bcb77daa8eaa1f80091906e5a3416e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/razorpay/razorpay-php/zipball/f562c919d153c343428c9a4e8d4e0848f334aef4",
"reference": "f562c919d153c343428c9a4e8d4e0848f334aef4",
"url": "https://api.github.com/repos/razorpay/razorpay-php/zipball/3e70e7ccb0bcb77daa8eaa1f80091906e5a3416e",
"reference": "3e70e7ccb0bcb77daa8eaa1f80091906e5a3416e",
"shasum": ""
},
"require": {
@ -7849,7 +7913,7 @@
"issues": "https://github.com/Razorpay/razorpay-php/issues",
"source": "https://github.com/Razorpay/razorpay-php"
},
"time": "2021-09-16T06:18:12+00:00"
"time": "2021-10-08T05:54:41+00:00"
},
{
"name": "react/promise",
@ -8359,16 +8423,16 @@
},
{
"name": "sentry/sentry-laravel",
"version": "2.8.0",
"version": "2.9.0",
"source": {
"type": "git",
"url": "https://github.com/getsentry/sentry-laravel.git",
"reference": "21dd07bdd2956e182ffde32d22872ce1a4b3eca9"
"reference": "3acb930f1abeb67046097c3912c7b4b9b4303f08"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/getsentry/sentry-laravel/zipball/21dd07bdd2956e182ffde32d22872ce1a4b3eca9",
"reference": "21dd07bdd2956e182ffde32d22872ce1a4b3eca9",
"url": "https://api.github.com/repos/getsentry/sentry-laravel/zipball/3acb930f1abeb67046097c3912c7b4b9b4303f08",
"reference": "3acb930f1abeb67046097c3912c7b4b9b4303f08",
"shasum": ""
},
"require": {
@ -8434,7 +8498,7 @@
],
"support": {
"issues": "https://github.com/getsentry/sentry-laravel/issues",
"source": "https://github.com/getsentry/sentry-laravel/tree/2.8.0"
"source": "https://github.com/getsentry/sentry-laravel/tree/2.9.0"
},
"funding": [
{
@ -8446,7 +8510,7 @@
"type": "custom"
}
],
"time": "2021-08-08T09:03:08+00:00"
"time": "2021-10-06T13:08:08+00:00"
},
{
"name": "square/square",
@ -8507,16 +8571,16 @@
},
{
"name": "stripe/stripe-php",
"version": "v7.97.0",
"version": "v7.98.0",
"source": {
"type": "git",
"url": "https://github.com/stripe/stripe-php.git",
"reference": "ae41c309ce113362706f8d5f19cf0cf2c730bc4a"
"reference": "87f27d3da4a72c93da49d81011cb675c2847a7c0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/stripe/stripe-php/zipball/ae41c309ce113362706f8d5f19cf0cf2c730bc4a",
"reference": "ae41c309ce113362706f8d5f19cf0cf2c730bc4a",
"url": "https://api.github.com/repos/stripe/stripe-php/zipball/87f27d3da4a72c93da49d81011cb675c2847a7c0",
"reference": "87f27d3da4a72c93da49d81011cb675c2847a7c0",
"shasum": ""
},
"require": {
@ -8562,9 +8626,9 @@
],
"support": {
"issues": "https://github.com/stripe/stripe-php/issues",
"source": "https://github.com/stripe/stripe-php/tree/v7.97.0"
"source": "https://github.com/stripe/stripe-php/tree/v7.98.0"
},
"time": "2021-09-16T21:28:33+00:00"
"time": "2021-10-07T22:39:44+00:00"
},
{
"name": "swiftmailer/swiftmailer",
@ -12694,16 +12758,16 @@
},
{
"name": "facade/ignition",
"version": "2.14.0",
"version": "2.14.1",
"source": {
"type": "git",
"url": "https://github.com/facade/ignition.git",
"reference": "c6126e291bd44ad3fe482537a145fc70e3320598"
"reference": "6d89c4c99537f487ad29f646d57ebf107ef714ed"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/facade/ignition/zipball/c6126e291bd44ad3fe482537a145fc70e3320598",
"reference": "c6126e291bd44ad3fe482537a145fc70e3320598",
"url": "https://api.github.com/repos/facade/ignition/zipball/6d89c4c99537f487ad29f646d57ebf107ef714ed",
"reference": "6d89c4c99537f487ad29f646d57ebf107ef714ed",
"shasum": ""
},
"require": {
@ -12766,7 +12830,7 @@
"issues": "https://github.com/facade/ignition/issues",
"source": "https://github.com/facade/ignition"
},
"time": "2021-10-01T12:58:45+00:00"
"time": "2021-10-08T12:34:52+00:00"
},
{
"name": "facade/ignition-contracts",
@ -16084,5 +16148,5 @@
"platform-dev": {
"php": "^7.3|^7.4|^8.0"
},
"plugin-api-version": "2.1.0"
"plugin-api-version": "2.0.0"
}

View File

@ -15,7 +15,7 @@ class AddHostedPageToPaymentTypes extends Migration
{
$type = new PaymentType();
$type->id = 35;
$type->id = 38;
$type->name = 'Hosted Page';
$type->gateway_type_id = GatewayType::HOSTED_PAGE;

2
public/css/app.css vendored

File diff suppressed because one or more lines are too long

View File

@ -1,91 +1,2 @@
/**
* 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();
/*! For license information please see stripe-sepa.js.LICENSE.txt */
!function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},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 o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},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=28)}({28:function(e,t,n){e.exports=n("guV3")},guV3:function(e,t){var n,o,r,a;function i(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}function u(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var l=function(){function e(t,n){var o=this;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),u(this,"setupStripe",(function(){o.stripe=Stripe(o.key),o.stripeConnect&&(o.stripe.stripeAccount=d);var e=o.stripe.elements(),t={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"}}},supportedCountries:["SEPA"],placeholderCountry:document.querySelector('meta[name="country"]').content};return o.iban=e.create("iban",t),o.iban.mount("#sepa-iban"),o})),u(this,"handle",(function(){document.getElementById("pay-now").addEventListener("click",(function(e){var t=document.getElementById("errors");return""===document.getElementById("sepa-name").value?(document.getElementById("sepa-name").focus(),t.textContent="Name required.",void(t.hidden=!1)):""===document.getElementById("sepa-email-address").value?(document.getElementById("sepa-email-address").focus(),t.textContent="Email required.",void(t.hidden=!1)):document.getElementById("sepa-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.confirmSepaDebitPayment(document.querySelector("meta[name=pi-client-secret").content,{payment_method:{sepa_debit:o.iban,billing_details:{name:document.getElementById("sepa-name").value,email:document.getElementById("sepa-email-address").value}}}).then((function(e){return e.error?o.handleFailure(e.error.message):o.handleSuccess(e)}))):(t.textContent="Accept Terms",t.hidden=!1,void console.log("Terms"))}))})),this.key=t,this.errors=document.getElementById("errors"),this.stripeConnect=n}var t,n,o;return t=e,(n=[{key:"handleSuccess",value:function(e){document.querySelector('input[name="gateway_response"]').value=JSON.stringify(e.paymentIntent),document.getElementById("server-response").submit()}},{key:"handleFailure",value:function(e){var t=document.getElementById("errors");t.textContent="",t.textContent=e,t.hidden=!1,document.getElementById("pay-now").disabled=!1,document.querySelector("#pay-now > svg").classList.add("hidden"),document.querySelector("#pay-now > span").classList.remove("hidden")}}])&&i(t.prototype,n),o&&i(t,o),e}(),c=null!==(n=null===(o=document.querySelector('meta[name="stripe-publishable-key"]'))||void 0===o?void 0:o.content)&&void 0!==n?n:"",d=null!==(r=null===(a=document.querySelector('meta[name="stripe-account-id"]'))||void 0===a?void 0:a.content)&&void 0!==r?r:"";new l(c,d).setupStripe().handle()}});

View File

@ -1,6 +1,6 @@
{
"/js/app.js": "/js/app.js?id=696e8203d5e8e7cf5ff5",
"/css/app.css": "/css/app.css?id=ad5ff55c9ef56ede1726",
"/css/app.css": "/css/app.css?id=f7f7b35aa3f417a3eca3",
"/js/clients/invoices/action-selectors.js": "/js/clients/invoices/action-selectors.js?id=a09bb529b8e1826f13b4",
"/js/clients/invoices/payment.js": "/js/clients/invoices/payment.js?id=8ce8955ba775ea5f47d1",
"/js/clients/linkify-urls.js": "/js/clients/linkify-urls.js?id=0dc8c34010d09195d2f7",
@ -20,6 +20,7 @@
"/js/clients/payments/stripe-ach.js": "/js/clients/payments/stripe-ach.js?id=81c2623fc1e5769b51c7",
"/js/clients/payments/stripe-alipay.js": "/js/clients/payments/stripe-alipay.js?id=665ddf663500767f1a17",
"/js/clients/payments/stripe-credit-card.js": "/js/clients/payments/stripe-credit-card.js?id=a30464874dee84678344",
"/js/clients/payments/stripe-sepa.js": "/js/clients/payments/stripe-sepa.js?id=e7dc964c85085314b12c",
"/js/clients/payments/stripe-sofort.js": "/js/clients/payments/stripe-sofort.js?id=231571942310348aa616",
"/js/clients/payments/wepay-credit-card.js": "/js/clients/payments/wepay-credit-card.js?id=f51400e03c5fdb6cdabe",
"/js/clients/quotes/action-selectors.js": "/js/clients/quotes/action-selectors.js?id=1b8f9325aa6e8595e7fa",

View File

@ -49,7 +49,7 @@ class ProcessSEPA {
// 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"
placeholderCountry: document.querySelector('meta[name="country"]').content
};
this.iban = elements.create("iban", options);
this.iban.mount("#sepa-iban");
@ -58,6 +58,31 @@ class ProcessSEPA {
handle = () => {
document.getElementById('pay-now').addEventListener('click', (e) => {
let errors = document.getElementById('errors');
if (document.getElementById('sepa-name').value === "") {
document.getElementById('sepa-name').focus();
errors.textContent = "Name required.";
errors.hidden = false;
return;
}
if (document.getElementById('sepa-email-address').value === "") {
document.getElementById('sepa-email-address').focus();
errors.textContent = "Email required.";
errors.hidden = false;
return ;
}
if (!document.getElementById('sepa-mandate-acceptance').checked) {
errors.textContent = "Accept Terms";
errors.hidden = false;
console.log("Terms");
return ;
}
document.getElementById('pay-now').disabled = true;
document.querySelector('#pay-now > svg').classList.remove('hidden');
document.querySelector('#pay-now > span').classList.add('hidden');
@ -72,13 +97,36 @@ class ProcessSEPA {
email: document.getElementById("sepa-email-address").value,
},
},
return_url: document.querySelector(
'meta[name="return-url"]'
).content,
}
);
).then((result) => {
if (result.error) {
return this.handleFailure(result.error.message);
}
return this.handleSuccess(result);
});
});
};
handleSuccess(result) {
document.querySelector(
'input[name="gateway_response"]'
).value = JSON.stringify(result.paymentIntent);
document.getElementById('server-response').submit();
}
handleFailure(message) {
let errors = document.getElementById('errors');
errors.textContent = '';
errors.textContent = message;
errors.hidden = false;
document.getElementById('pay-now').disabled = false;
document.querySelector('#pay-now > svg').classList.add('hidden');
document.querySelector('#pay-now > span').classList.remove('hidden');
}
}
const publishableKey = document.querySelector(

View File

@ -4316,7 +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.',
'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.',
'ideal' => 'iDEAL',
'bank_account_holder' => 'Bank Account Holder',
'aio_checkout' => 'All-in-one checkout',

View File

@ -20,8 +20,10 @@
@csrf
<input type="hidden" name="company_gateway_id" value="{{ $gateway->company_gateway->id }}">
<input type="hidden" name="gateway_type_id" value="9">
<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>

View File

@ -3,7 +3,6 @@
@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="return-url" content="{{ $return_url }}">
<meta name="amount" content="{{ $stripe_amount }}">
<meta name="country" content="{{ $country }}">
<meta name="customer" content="{{ $customer }}">
@ -20,7 +19,7 @@
@endcomponent
@include('portal.ninja2020.gateways.stripe.sepa.sepa_debit')
@include('portal.ninja2020.gateways.includes.save_card')
@include('portal.ninja2020.gateways.includes.pay_now')
@endsection

View File

@ -1,5 +1,14 @@
<div id="stripe--payment-container">
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.name')])
<form action="{{ route('client.payments.response') }}" method="post" id="server-response">
@csrf
<input type="hidden" name="gateway_response">
<input type="hidden" name="company_gateway_id" value="{{ $gateway->getCompanyGatewayId() }}">
<input type="hidden" name="payment_method_id" value="{{ $payment_method_id }}">
<input type="hidden" name="payment_hash" value="{{ $payment_hash }}">
<input type="hidden" name="store_card">
<label for="sepa-name">
<input class="input w-full" id="sepa-name" type="text" placeholder="{{ ctrans('texts.bank_account_holder') }}">
</label>
@ -15,5 +24,6 @@
<input type="checkbox" id="sepa-mandate-acceptance" class="input mr-4">
<label for="sepa-mandate-acceptance">{{ctrans('texts.sepa_mandat', ['company' => auth('contact')->user()->company->present()->name()])}}</label>
</div>
</form>
@endcomponent
</div>

4
webpack.mix.js vendored
View File

@ -110,6 +110,10 @@ mix.js("resources/js/app.js", "public/js")
"resources/js/clients/payments/razorpay-aio.js",
"public/js/clients/payments/razorpay-aio.js"
)
.js(
"resources/js/clients/payments/stripe-sepa.js",
"public/js/clients/payments/stripe-sepa.js"
)
mix.copyDirectory('node_modules/card-js/card-js.min.css', 'public/css/card-js.min.css');