From a42f9828e00c786e567ecf5d733cb21a26a0de4d Mon Sep 17 00:00:00 2001 From: Jakub Theimer <5587309+theimerj@users.noreply.github.com> Date: Wed, 7 Feb 2024 19:26:05 +0100 Subject: [PATCH 1/7] fix event name --- src/Actions/AuthorizeStripePayment.php | 4 ++-- tests/HandleStripeWebhookTest.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Actions/AuthorizeStripePayment.php b/src/Actions/AuthorizeStripePayment.php index a75aed9..4178d87 100644 --- a/src/Actions/AuthorizeStripePayment.php +++ b/src/Actions/AuthorizeStripePayment.php @@ -2,7 +2,7 @@ namespace Dystcz\LunarApiStripeAdapter\Actions; -use Dystcz\LunarApi\Domain\Orders\Events\OrderPaid; +use Dystcz\LunarApi\Domain\Orders\Events\OrderPaymentSuccessful; use Dystcz\LunarApi\Domain\Payments\PaymentAdapters\PaymentIntent; use Illuminate\Support\Facades\Log; use Lunar\Base\DataTransferObjects\PaymentAuthorize; @@ -32,6 +32,6 @@ public function __invoke(Order $order, Cart $cart, PaymentIntent $intent): void return; } - OrderPaid::dispatch($order); + OrderPaymentSuccessful::dispatch($order); } } diff --git a/tests/HandleStripeWebhookTest.php b/tests/HandleStripeWebhookTest.php index e8a87a8..9ceeb58 100644 --- a/tests/HandleStripeWebhookTest.php +++ b/tests/HandleStripeWebhookTest.php @@ -2,9 +2,9 @@ use Dystcz\LunarApi\Domain\Carts\Events\CartCreated; use Dystcz\LunarApi\Domain\Carts\Models\Cart; -use Dystcz\LunarApi\Domain\Orders\Events\OrderPaid; use Dystcz\LunarApi\Domain\Orders\Events\OrderPaymentCanceled; use Dystcz\LunarApi\Domain\Orders\Events\OrderPaymentFailed; +use Dystcz\LunarApi\Domain\Orders\Events\OrderPaymentSuccessful; use Dystcz\LunarApiStripeAdapter\Jobs\Webhooks\HandlePaymentIntentSucceeded; use Dystcz\LunarApiStripeAdapter\StripePaymentAdapter; use Dystcz\LunarApiStripeAdapter\Tests\TestCase; @@ -75,7 +75,7 @@ public function constructEvent(string $jsonPayload, string $signature, string $s $response->assertSuccessful(); // Queue::assertPushed(HandlePaymentIntentSucceeded::class); - // Event::assertDispatched(OrderPaid::class); + // Event::assertDispatched(OrderPaymentSuccessful::class); }); it('can handle payment_intent.cancelled event', function () { From 5dbbe07772ad78a6b39f87d489f6a589975a7188 Mon Sep 17 00:00:00 2001 From: Jakub Theimer <5587309+theimerj@users.noreply.github.com> Date: Wed, 7 Feb 2024 19:26:12 +0100 Subject: [PATCH 2/7] fix arguments --- src/Jobs/Webhooks/HandlePaymentIntentSucceeded.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Jobs/Webhooks/HandlePaymentIntentSucceeded.php b/src/Jobs/Webhooks/HandlePaymentIntentSucceeded.php index c0d5170..70da0c7 100644 --- a/src/Jobs/Webhooks/HandlePaymentIntentSucceeded.php +++ b/src/Jobs/Webhooks/HandlePaymentIntentSucceeded.php @@ -40,6 +40,6 @@ public function handle(): void $this->fail($e); } - App::make(AuthorizeStripePayment::class)($order, $paymentIntent); + App::make(AuthorizeStripePayment::class)($order, $order->cart, $paymentIntent); } } From 869f1eeb8e6ca90b02ed5eb4d18ffd18316810ec Mon Sep 17 00:00:00 2001 From: Jakub Theimer <5587309+theimerj@users.noreply.github.com> Date: Wed, 7 Feb 2024 19:27:31 +0100 Subject: [PATCH 3/7] remove logging --- src/Actions/AuthorizeStripePayment.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Actions/AuthorizeStripePayment.php b/src/Actions/AuthorizeStripePayment.php index df3858d..cc90343 100644 --- a/src/Actions/AuthorizeStripePayment.php +++ b/src/Actions/AuthorizeStripePayment.php @@ -4,7 +4,6 @@ use Dystcz\LunarApi\Domain\Orders\Events\OrderPaymentSuccessful; use Dystcz\LunarApi\Domain\Payments\Contracts\PaymentIntent; -use Illuminate\Support\Facades\Log; use Lunar\Base\DataTransferObjects\PaymentAuthorize; use Lunar\Facades\Payments; use Lunar\Models\Cart; @@ -14,8 +13,6 @@ class AuthorizeStripePayment { public function __invoke(Order $order, Cart $cart, PaymentIntent $intent): void { - Log::info('Payment intent succeeded: '.$intent->id); - /** @var PaymentAuthorize $payment */ $payment = Payments::driver('stripe') ->order($order) From 414a8cdc3f8127bbf109728558ae7970cffe2232 Mon Sep 17 00:00:00 2001 From: Jakub Theimer <5587309+theimerj@users.noreply.github.com> Date: Wed, 7 Feb 2024 19:42:13 +0100 Subject: [PATCH 4/7] add docblocks --- src/Jobs/Webhooks/HandleChargeFailed.php | 7 ++++--- src/Jobs/Webhooks/HandleChargeableSource.php | 7 ++++--- src/Jobs/Webhooks/HandleOtherEvent.php | 3 +++ src/Jobs/Webhooks/HandlePaymentIntentCreated.php | 3 +++ src/Jobs/Webhooks/HandlePaymentIntentProcessing.php | 3 +++ src/Jobs/Webhooks/HandlePaymentIntentRequiresAction.php | 3 +++ src/Jobs/Webhooks/HandlePaymentIntentSucceeded.php | 3 +++ 7 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/Jobs/Webhooks/HandleChargeFailed.php b/src/Jobs/Webhooks/HandleChargeFailed.php index a18efd6..a40dc07 100644 --- a/src/Jobs/Webhooks/HandleChargeFailed.php +++ b/src/Jobs/Webhooks/HandleChargeFailed.php @@ -19,10 +19,11 @@ public function __construct(WebhookCall $webhookCall) $this->webhookCall = $webhookCall; } + /** + * Handle failed charge. + */ public function handle(): void { - // do your work here - - // you can access the payload of the webhook call with `$this->webhookCall->payload` + // } } diff --git a/src/Jobs/Webhooks/HandleChargeableSource.php b/src/Jobs/Webhooks/HandleChargeableSource.php index c9a869b..9215c97 100644 --- a/src/Jobs/Webhooks/HandleChargeableSource.php +++ b/src/Jobs/Webhooks/HandleChargeableSource.php @@ -19,10 +19,11 @@ public function __construct(WebhookCall $webhookCall) $this->webhookCall = $webhookCall; } + /** + * Handle chargeable source. + */ public function handle(): void { - // do your work here - - // you can access the payload of the webhook call with `$this->webhookCall->payload` + // } } diff --git a/src/Jobs/Webhooks/HandleOtherEvent.php b/src/Jobs/Webhooks/HandleOtherEvent.php index 9e1ab59..0323967 100644 --- a/src/Jobs/Webhooks/HandleOtherEvent.php +++ b/src/Jobs/Webhooks/HandleOtherEvent.php @@ -21,6 +21,9 @@ public function __construct(WebhookCall $webhookCall) $this->webhookCall = $webhookCall; } + /** + * Handle other events. + */ public function handle(): void { try { diff --git a/src/Jobs/Webhooks/HandlePaymentIntentCreated.php b/src/Jobs/Webhooks/HandlePaymentIntentCreated.php index d3a3fc0..2139682 100644 --- a/src/Jobs/Webhooks/HandlePaymentIntentCreated.php +++ b/src/Jobs/Webhooks/HandlePaymentIntentCreated.php @@ -21,6 +21,9 @@ public function __construct(WebhookCall $webhookCall) $this->webhookCall = $webhookCall; } + /** + * Handle created payment intent. + */ public function handle(): void { try { diff --git a/src/Jobs/Webhooks/HandlePaymentIntentProcessing.php b/src/Jobs/Webhooks/HandlePaymentIntentProcessing.php index f74949b..72a7f34 100644 --- a/src/Jobs/Webhooks/HandlePaymentIntentProcessing.php +++ b/src/Jobs/Webhooks/HandlePaymentIntentProcessing.php @@ -22,6 +22,9 @@ public function __construct(WebhookCall $webhookCall) $this->webhookCall = $webhookCall; } + /** + * Handle payment intent processing. + */ public function handle(): void { try { diff --git a/src/Jobs/Webhooks/HandlePaymentIntentRequiresAction.php b/src/Jobs/Webhooks/HandlePaymentIntentRequiresAction.php index c995f9c..969a9e3 100644 --- a/src/Jobs/Webhooks/HandlePaymentIntentRequiresAction.php +++ b/src/Jobs/Webhooks/HandlePaymentIntentRequiresAction.php @@ -22,6 +22,9 @@ public function __construct(WebhookCall $webhookCall) $this->webhookCall = $webhookCall; } + /** + * Handle payment intent requires action. + */ public function handle(): void { try { diff --git a/src/Jobs/Webhooks/HandlePaymentIntentSucceeded.php b/src/Jobs/Webhooks/HandlePaymentIntentSucceeded.php index 70da0c7..e27c65f 100644 --- a/src/Jobs/Webhooks/HandlePaymentIntentSucceeded.php +++ b/src/Jobs/Webhooks/HandlePaymentIntentSucceeded.php @@ -25,6 +25,9 @@ public function __construct(WebhookCall $webhookCall) $this->webhookCall = $webhookCall; } + /** + * Handle successful payment intent. + */ public function handle(): void { try { From 77f7e090ba002174350c648e40847ddac4b789cd Mon Sep 17 00:00:00 2001 From: Jakub Theimer <5587309+theimerj@users.noreply.github.com> Date: Wed, 7 Feb 2024 19:42:23 +0100 Subject: [PATCH 5/7] fix getting payment adapter --- src/Jobs/Webhooks/HandlePaymentIntentCancelled.php | 14 ++++++++++---- src/Jobs/Webhooks/HandlePaymentIntentFailed.php | 14 ++++++++++---- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/Jobs/Webhooks/HandlePaymentIntentCancelled.php b/src/Jobs/Webhooks/HandlePaymentIntentCancelled.php index 0ad0bb9..43ab776 100644 --- a/src/Jobs/Webhooks/HandlePaymentIntentCancelled.php +++ b/src/Jobs/Webhooks/HandlePaymentIntentCancelled.php @@ -5,12 +5,13 @@ use Dystcz\LunarApi\Domain\Orders\Actions\FindOrderByIntent; use Dystcz\LunarApi\Domain\Orders\Events\OrderPaymentCanceled; use Dystcz\LunarApi\Domain\Payments\Data\PaymentIntent; +use Dystcz\LunarApi\Domain\Payments\PaymentAdapters\PaymentAdaptersRegister; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; use Illuminate\Support\Facades\App; -use Lunar\Stripe\Facades\StripeFacade; +use Illuminate\Support\Facades\Config; use Spatie\WebhookClient\Models\WebhookCall; use Stripe\Event; use Throwable; @@ -21,11 +22,16 @@ class HandlePaymentIntentCancelled implements ShouldQueue public WebhookCall $webhookCall; - public function __construct(WebhookCall $webhookCall) - { + public function __construct( + WebhookCall $webhookCall, + protected PaymentAdaptersRegister $register + ) { $this->webhookCall = $webhookCall; } + /** + * Handle cancelled payment intent. + */ public function handle(): void { try { @@ -41,7 +47,7 @@ public function handle(): void $this->fail($e); } - $paymentAdapter = StripeFacade::getFacadeRoot(); + $paymentAdapter = $this->register->get(Config::get('lunar-api.stripe.driver', 'stripe')); OrderPaymentCanceled::dispatch($order, $paymentAdapter, $paymentIntent); } diff --git a/src/Jobs/Webhooks/HandlePaymentIntentFailed.php b/src/Jobs/Webhooks/HandlePaymentIntentFailed.php index 2617381..96bb6b1 100644 --- a/src/Jobs/Webhooks/HandlePaymentIntentFailed.php +++ b/src/Jobs/Webhooks/HandlePaymentIntentFailed.php @@ -5,12 +5,13 @@ use Dystcz\LunarApi\Domain\Orders\Actions\FindOrderByIntent; use Dystcz\LunarApi\Domain\Orders\Events\OrderPaymentFailed; use Dystcz\LunarApi\Domain\Payments\Data\PaymentIntent; +use Dystcz\LunarApi\Domain\Payments\PaymentAdapters\PaymentAdaptersRegister; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; use Illuminate\Support\Facades\App; -use Lunar\Stripe\Facades\StripeFacade; +use Illuminate\Support\Facades\Config; use Spatie\WebhookClient\Models\WebhookCall; use Stripe\Event; use Throwable; @@ -21,11 +22,16 @@ class HandlePaymentIntentFailed implements ShouldQueue public WebhookCall $webhookCall; - public function __construct(WebhookCall $webhookCall) - { + public function __construct( + WebhookCall $webhookCall, + protected PaymentAdaptersRegister $register + ) { $this->webhookCall = $webhookCall; } + /** + * Handle failed payment intent. + */ public function handle(): void { try { @@ -41,7 +47,7 @@ public function handle(): void $this->fail($e); } - $paymentAdapter = StripeFacade::getFacadeRoot(); + $paymentAdapter = $this->register->get(Config::get('lunar-api.stripe.driver', 'stripe')); OrderPaymentFailed::dispatch($order, $paymentAdapter, $paymentIntent); } From 4036683028689af1cee9f3d3c0a5cca56039bc49 Mon Sep 17 00:00:00 2001 From: Jakub Theimer <5587309+theimerj@users.noreply.github.com> Date: Wed, 7 Feb 2024 20:20:52 +0100 Subject: [PATCH 6/7] add abstract webhook handler --- src/Jobs/Webhooks/HandleChargeFailed.php | 21 +---- src/Jobs/Webhooks/HandleChargeableSource.php | 21 +---- src/Jobs/Webhooks/HandleOtherEvent.php | 31 ++----- .../Webhooks/HandlePaymentIntentCancelled.php | 41 ++------- .../Webhooks/HandlePaymentIntentCreated.php | 31 ++----- .../Webhooks/HandlePaymentIntentFailed.php | 39 +-------- .../HandlePaymentIntentProcessing.php | 31 ++----- .../HandlePaymentIntentRequiresAction.php | 33 ++----- .../Webhooks/HandlePaymentIntentSucceeded.php | 38 ++------- src/Jobs/Webhooks/WebhookHandler.php | 85 +++++++++++++++++++ 10 files changed, 138 insertions(+), 233 deletions(-) create mode 100644 src/Jobs/Webhooks/WebhookHandler.php diff --git a/src/Jobs/Webhooks/HandleChargeFailed.php b/src/Jobs/Webhooks/HandleChargeFailed.php index a40dc07..e028624 100644 --- a/src/Jobs/Webhooks/HandleChargeFailed.php +++ b/src/Jobs/Webhooks/HandleChargeFailed.php @@ -2,28 +2,13 @@ namespace Dystcz\LunarApiStripeAdapter\Jobs\Webhooks; -use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; -use Illuminate\Queue\InteractsWithQueue; -use Illuminate\Queue\SerializesModels; -use Spatie\WebhookClient\Models\WebhookCall; - -class HandleChargeFailed implements ShouldQueue +class HandleChargeFailed extends WebhookHandler { - use InteractsWithQueue, Queueable, SerializesModels; - - public WebhookCall $webhookCall; - - public function __construct(WebhookCall $webhookCall) - { - $this->webhookCall = $webhookCall; - } - /** - * Handle failed charge. + * Handle payment intent processing. */ public function handle(): void { - // + // $event = $this->constructStripeEvent(); } } diff --git a/src/Jobs/Webhooks/HandleChargeableSource.php b/src/Jobs/Webhooks/HandleChargeableSource.php index 9215c97..d484d94 100644 --- a/src/Jobs/Webhooks/HandleChargeableSource.php +++ b/src/Jobs/Webhooks/HandleChargeableSource.php @@ -2,28 +2,13 @@ namespace Dystcz\LunarApiStripeAdapter\Jobs\Webhooks; -use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; -use Illuminate\Queue\InteractsWithQueue; -use Illuminate\Queue\SerializesModels; -use Spatie\WebhookClient\Models\WebhookCall; - -class HandleChargeableSource implements ShouldQueue +class HandleChargeableSource extends WebhookHandler { - use InteractsWithQueue, Queueable, SerializesModels; - - public WebhookCall $webhookCall; - - public function __construct(WebhookCall $webhookCall) - { - $this->webhookCall = $webhookCall; - } - /** - * Handle chargeable source. + * Handle payment intent processing. */ public function handle(): void { - // + // $event = $this->constructStripeEvent(); } } diff --git a/src/Jobs/Webhooks/HandleOtherEvent.php b/src/Jobs/Webhooks/HandleOtherEvent.php index 0323967..93d416d 100644 --- a/src/Jobs/Webhooks/HandleOtherEvent.php +++ b/src/Jobs/Webhooks/HandleOtherEvent.php @@ -2,34 +2,19 @@ namespace Dystcz\LunarApiStripeAdapter\Jobs\Webhooks; -use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; -use Illuminate\Queue\InteractsWithQueue; -use Illuminate\Queue\SerializesModels; -use Spatie\WebhookClient\Models\WebhookCall; -use Stripe\Event; -use Throwable; +use Illuminate\Support\Facades\Config; -class HandleOtherEvent implements ShouldQueue +class HandleOtherEvent extends WebhookHandler { - use InteractsWithQueue, Queueable, SerializesModels; - - public WebhookCall $webhookCall; - - public function __construct(WebhookCall $webhookCall) - { - $this->webhookCall = $webhookCall; - } - /** - * Handle other events. + * Handle payment intent processing. */ public function handle(): void { - try { - $event = Event::constructFrom($this->webhookCall->payload); - } catch (Throwable $e) { - $this->fail($e); - } + // $event = $this->constructStripeEvent(); + // $paymentIntent = $this->getPaymentIntentFromEvent($event); + // $order = $this->findOrderByIntent($paymentIntent); + // + // $paymentAdapter = $this->register->get(Config::get('lunar-api.stripe.driver', 'stripe')); } } diff --git a/src/Jobs/Webhooks/HandlePaymentIntentCancelled.php b/src/Jobs/Webhooks/HandlePaymentIntentCancelled.php index 43ab776..43848b0 100644 --- a/src/Jobs/Webhooks/HandlePaymentIntentCancelled.php +++ b/src/Jobs/Webhooks/HandlePaymentIntentCancelled.php @@ -2,50 +2,19 @@ namespace Dystcz\LunarApiStripeAdapter\Jobs\Webhooks; -use Dystcz\LunarApi\Domain\Orders\Actions\FindOrderByIntent; use Dystcz\LunarApi\Domain\Orders\Events\OrderPaymentCanceled; -use Dystcz\LunarApi\Domain\Payments\Data\PaymentIntent; -use Dystcz\LunarApi\Domain\Payments\PaymentAdapters\PaymentAdaptersRegister; -use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; -use Illuminate\Queue\InteractsWithQueue; -use Illuminate\Queue\SerializesModels; -use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\Config; -use Spatie\WebhookClient\Models\WebhookCall; -use Stripe\Event; -use Throwable; -class HandlePaymentIntentCancelled implements ShouldQueue +class HandlePaymentIntentCancelled extends WebhookHandler { - use InteractsWithQueue, Queueable, SerializesModels; - - public WebhookCall $webhookCall; - - public function __construct( - WebhookCall $webhookCall, - protected PaymentAdaptersRegister $register - ) { - $this->webhookCall = $webhookCall; - } - /** - * Handle cancelled payment intent. + * Handle failed payment intent. */ public function handle(): void { - try { - $event = Event::constructFrom($this->webhookCall->payload); - $paymentIntent = new PaymentIntent(intent: $event->data->object); - } catch (Throwable $e) { - $this->fail($e); - } - - try { - $order = App::make(FindOrderByIntent::class)($paymentIntent); - } catch (Throwable $e) { - $this->fail($e); - } + $event = $this->constructStripeEvent(); + $paymentIntent = $this->getPaymentIntentFromEvent($event); + $order = $this->findOrderByIntent($paymentIntent); $paymentAdapter = $this->register->get(Config::get('lunar-api.stripe.driver', 'stripe')); diff --git a/src/Jobs/Webhooks/HandlePaymentIntentCreated.php b/src/Jobs/Webhooks/HandlePaymentIntentCreated.php index 2139682..65f8027 100644 --- a/src/Jobs/Webhooks/HandlePaymentIntentCreated.php +++ b/src/Jobs/Webhooks/HandlePaymentIntentCreated.php @@ -2,34 +2,19 @@ namespace Dystcz\LunarApiStripeAdapter\Jobs\Webhooks; -use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; -use Illuminate\Queue\InteractsWithQueue; -use Illuminate\Queue\SerializesModels; -use Spatie\WebhookClient\Models\WebhookCall; -use Stripe\Event; -use Throwable; +use Illuminate\Support\Facades\Config; -class HandlePaymentIntentCreated implements ShouldQueue +class HandlePaymentIntentCreated extends WebhookHandler { - use InteractsWithQueue, Queueable, SerializesModels; - - public WebhookCall $webhookCall; - - public function __construct(WebhookCall $webhookCall) - { - $this->webhookCall = $webhookCall; - } - /** - * Handle created payment intent. + * Handle payment intent processing. */ public function handle(): void { - try { - $event = Event::constructFrom($this->webhookCall->payload); - } catch (Throwable $e) { - $this->fail($e); - } + // $event = $this->constructStripeEvent(); + // $paymentIntent = $this->getPaymentIntentFromEvent($event); + // $order = $this->findOrderByIntent($paymentIntent); + // + // $paymentAdapter = $this->register->get(Config::get('lunar-api.stripe.driver', 'stripe')); } } diff --git a/src/Jobs/Webhooks/HandlePaymentIntentFailed.php b/src/Jobs/Webhooks/HandlePaymentIntentFailed.php index 96bb6b1..4ac5216 100644 --- a/src/Jobs/Webhooks/HandlePaymentIntentFailed.php +++ b/src/Jobs/Webhooks/HandlePaymentIntentFailed.php @@ -2,50 +2,19 @@ namespace Dystcz\LunarApiStripeAdapter\Jobs\Webhooks; -use Dystcz\LunarApi\Domain\Orders\Actions\FindOrderByIntent; use Dystcz\LunarApi\Domain\Orders\Events\OrderPaymentFailed; -use Dystcz\LunarApi\Domain\Payments\Data\PaymentIntent; -use Dystcz\LunarApi\Domain\Payments\PaymentAdapters\PaymentAdaptersRegister; -use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; -use Illuminate\Queue\InteractsWithQueue; -use Illuminate\Queue\SerializesModels; -use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\Config; -use Spatie\WebhookClient\Models\WebhookCall; -use Stripe\Event; -use Throwable; -class HandlePaymentIntentFailed implements ShouldQueue +class HandlePaymentIntentFailed extends WebhookHandler { - use InteractsWithQueue, Queueable, SerializesModels; - - public WebhookCall $webhookCall; - - public function __construct( - WebhookCall $webhookCall, - protected PaymentAdaptersRegister $register - ) { - $this->webhookCall = $webhookCall; - } - /** * Handle failed payment intent. */ public function handle(): void { - try { - $event = Event::constructFrom($this->webhookCall->payload); - $paymentIntent = new PaymentIntent(intent: $event->data->object); - } catch (Throwable $e) { - $this->fail($e); - } - - try { - $order = App::make(FindOrderByIntent::class)($paymentIntent); - } catch (Throwable $e) { - $this->fail($e); - } + $event = $this->constructStripeEvent(); + $paymentIntent = $this->getPaymentIntentFromEvent($event); + $order = $this->findOrderByIntent($paymentIntent); $paymentAdapter = $this->register->get(Config::get('lunar-api.stripe.driver', 'stripe')); diff --git a/src/Jobs/Webhooks/HandlePaymentIntentProcessing.php b/src/Jobs/Webhooks/HandlePaymentIntentProcessing.php index 72a7f34..17aa947 100644 --- a/src/Jobs/Webhooks/HandlePaymentIntentProcessing.php +++ b/src/Jobs/Webhooks/HandlePaymentIntentProcessing.php @@ -2,36 +2,19 @@ namespace Dystcz\LunarApiStripeAdapter\Jobs\Webhooks; -use Dystcz\LunarApi\Domain\Payments\Data\PaymentIntent; -use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; -use Illuminate\Queue\InteractsWithQueue; -use Illuminate\Queue\SerializesModels; -use Spatie\WebhookClient\Models\WebhookCall; -use Stripe\Event; -use Throwable; +use Illuminate\Support\Facades\Config; -class HandlePaymentIntentProcessing implements ShouldQueue +class HandlePaymentIntentProcessing extends WebhookHandler { - use InteractsWithQueue, Queueable, SerializesModels; - - public WebhookCall $webhookCall; - - public function __construct(WebhookCall $webhookCall) - { - $this->webhookCall = $webhookCall; - } - /** * Handle payment intent processing. */ public function handle(): void { - try { - $event = Event::constructFrom($this->webhookCall->payload); - $paymentIntent = new PaymentIntent(intent: $event->data->object); - } catch (Throwable $e) { - $this->fail($e); - } + // $event = $this->constructStripeEvent(); + // $paymentIntent = $this->getPaymentIntentFromEvent($event); + // $order = $this->findOrderByIntent($paymentIntent); + // + // $paymentAdapter = $this->register->get(Config::get('lunar-api.stripe.driver', 'stripe')); } } diff --git a/src/Jobs/Webhooks/HandlePaymentIntentRequiresAction.php b/src/Jobs/Webhooks/HandlePaymentIntentRequiresAction.php index 969a9e3..24724f2 100644 --- a/src/Jobs/Webhooks/HandlePaymentIntentRequiresAction.php +++ b/src/Jobs/Webhooks/HandlePaymentIntentRequiresAction.php @@ -2,36 +2,19 @@ namespace Dystcz\LunarApiStripeAdapter\Jobs\Webhooks; -use Dystcz\LunarApi\Domain\Payments\Data\PaymentIntent; -use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; -use Illuminate\Queue\InteractsWithQueue; -use Illuminate\Queue\SerializesModels; -use Spatie\WebhookClient\Models\WebhookCall; -use Stripe\Event; -use Throwable; +use Illuminate\Support\Facades\Config; -class HandlePaymentIntentRequiresAction implements ShouldQueue +class HandlePaymentIntentRequiresAction extends WebhookHandler { - use InteractsWithQueue, Queueable, SerializesModels; - - public WebhookCall $webhookCall; - - public function __construct(WebhookCall $webhookCall) - { - $this->webhookCall = $webhookCall; - } - /** - * Handle payment intent requires action. + * Handle payment intent processing. */ public function handle(): void { - try { - $event = Event::constructFrom($this->webhookCall->payload); - $paymentIntent = new PaymentIntent(intent: $event->data->object); - } catch (Throwable $e) { - $this->fail($e); - } + // $event = $this->constructStripeEvent(); + // $paymentIntent = $this->getPaymentIntentFromEvent($event); + // $order = $this->findOrderByIntent($paymentIntent); + // + // $paymentAdapter = $this->register->get(Config::get('lunar-api.stripe.driver', 'stripe')); } } diff --git a/src/Jobs/Webhooks/HandlePaymentIntentSucceeded.php b/src/Jobs/Webhooks/HandlePaymentIntentSucceeded.php index e27c65f..f7fd6de 100644 --- a/src/Jobs/Webhooks/HandlePaymentIntentSucceeded.php +++ b/src/Jobs/Webhooks/HandlePaymentIntentSucceeded.php @@ -2,46 +2,22 @@ namespace Dystcz\LunarApiStripeAdapter\Jobs\Webhooks; -use Dystcz\LunarApi\Domain\Orders\Actions\FindOrderByIntent; -use Dystcz\LunarApi\Domain\Payments\Data\PaymentIntent; use Dystcz\LunarApiStripeAdapter\Actions\AuthorizeStripePayment; -use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; -use Illuminate\Queue\InteractsWithQueue; -use Illuminate\Queue\SerializesModels; use Illuminate\Support\Facades\App; -use Spatie\WebhookClient\Models\WebhookCall; -use Stripe\Event; -use Throwable; +use Illuminate\Support\Facades\Config; -class HandlePaymentIntentSucceeded implements ShouldQueue +class HandlePaymentIntentSucceeded extends WebhookHandler { - use InteractsWithQueue, Queueable, SerializesModels; - - public WebhookCall $webhookCall; - - public function __construct(WebhookCall $webhookCall) - { - $this->webhookCall = $webhookCall; - } - /** - * Handle successful payment intent. + * Handle failed payment intent. */ public function handle(): void { - try { - $event = Event::constructFrom($this->webhookCall->payload); - $paymentIntent = new PaymentIntent(intent: $event->data->object); - } catch (Throwable $e) { - $this->fail($e); - } + $event = $this->constructStripeEvent(); + $paymentIntent = $this->getPaymentIntentFromEvent($event); + $order = $this->findOrderByIntent($paymentIntent); - try { - $order = App::make(FindOrderByIntent::class)($paymentIntent); - } catch (Throwable $e) { - $this->fail($e); - } + $paymentAdapter = $this->register->get(Config::get('lunar-api.stripe.driver', 'stripe')); App::make(AuthorizeStripePayment::class)($order, $order->cart, $paymentIntent); } diff --git a/src/Jobs/Webhooks/WebhookHandler.php b/src/Jobs/Webhooks/WebhookHandler.php new file mode 100644 index 0000000..1a14ef7 --- /dev/null +++ b/src/Jobs/Webhooks/WebhookHandler.php @@ -0,0 +1,85 @@ +webhookCall = $webhookCall; + } + + /** + * Handle the webhook. + */ + abstract public function handle(): void; + + /** + * Construct Stripe event. + */ + protected function constructStripeEvent(): Event + { + try { + $event = Event::constructFrom($this->webhookCall->payload); + } catch (Throwable $e) { + $this->fail($e); + } + + return $event; + } + + /** + * Get payment intent from event. + */ + protected function getPaymentIntentFromEvent(Event $event): PaymentIntentContract + { + return new PaymentIntent(intent: $event->data->object); + } + + /** + * Get payment adapter. + */ + protected function getPaymentAdapter(): PaymentAdapter + { + return $this->register->get(Config::get('lunar-api.stripe.driver', 'stripe')); + } + + /** + * Find order by payment intent. + * + * @throws ModelNotFoundException + */ + protected function findOrderByIntent(PaymentIntentContract $paymentIntent): Order + { + try { + $order = App::make(FindOrderByIntent::class)($paymentIntent); + } catch (Throwable $e) { + $this->fail($e); + } + + return $order; + } +} From b2d4a6314870e13a2a551816a0dcc6934a04232f Mon Sep 17 00:00:00 2001 From: Jakub Theimer <5587309+theimerj@users.noreply.github.com> Date: Wed, 7 Feb 2024 21:14:10 +0100 Subject: [PATCH 7/7] update tests --- .../CreatePaymentIntentTest.php} | 42 ++++++++++++++++++- .../{ => Feature}/HandleStripeWebhookTest.php | 16 +++---- tests/Feature/WebhookHandlerTest.php | 6 +++ tests/TestCase.php | 35 ++++++++++++---- 4 files changed, 82 insertions(+), 17 deletions(-) rename tests/{CreatePaymentTest.php => Feature/CreatePaymentIntentTest.php} (50%) rename tests/{ => Feature}/HandleStripeWebhookTest.php (87%) create mode 100644 tests/Feature/WebhookHandlerTest.php diff --git a/tests/CreatePaymentTest.php b/tests/Feature/CreatePaymentIntentTest.php similarity index 50% rename from tests/CreatePaymentTest.php rename to tests/Feature/CreatePaymentIntentTest.php index 6dea934..97e98a8 100644 --- a/tests/CreatePaymentTest.php +++ b/tests/Feature/CreatePaymentIntentTest.php @@ -26,7 +26,7 @@ $this->cart = $cart; }); -test('a payment intent can be created', function (string $paymentMethod) { +test('can create a payment intent', function (string $paymentMethod) { /** @var TestCase $this */ $url = URL::signedRoute( 'v1.orders.createPaymentIntent', @@ -47,6 +47,44 @@ $response->assertSuccessful(); + // Stores the payment intent in the cart expect($response->json('meta.payment_intent.id')) ->toBe($this->cart->fresh()->meta['payment_intent']); -})->with(['stripe']); + + // Stores the payment intent in the order + expect($response->json('meta.payment_intent.id')) + ->toBe($this->order->fresh()->meta['payment_intent']); + +})->group('payments-intents')->with(['stripe']); + +it('creates a transaction when creating a payement intent', function (string $paymentMethod) { + /** @var TestCase $this */ + $url = URL::signedRoute( + 'v1.orders.createPaymentIntent', + ['order' => $this->order->getRouteKey()], + ); + + $response = $this + ->jsonApi() + ->expects('orders') + ->withData([ + 'type' => 'orders', + 'id' => (string) $this->order->getRouteKey(), + 'attributes' => [ + 'payment_method' => $paymentMethod, + ], + ]) + ->post($url); + + $response->assertSuccessful(); + + $this->assertDatabaseHas('transactions', [ + 'order_id' => $this->order->getRouteKey(), + 'success' => true, + 'type' => 'intent', + 'driver' => 'stripe', + 'amount' => $this->order->total, + 'reference' => $response->json('meta.payment_intent.id'), + ]); + +})->group('payments-intents')->with(['stripe'])->todo(); diff --git a/tests/HandleStripeWebhookTest.php b/tests/Feature/HandleStripeWebhookTest.php similarity index 87% rename from tests/HandleStripeWebhookTest.php rename to tests/Feature/HandleStripeWebhookTest.php index 9ceeb58..00b7614 100644 --- a/tests/HandleStripeWebhookTest.php +++ b/tests/Feature/HandleStripeWebhookTest.php @@ -53,7 +53,7 @@ public function constructEvent(string $jsonPayload, string $signature, string $s Event::fake(); Queue::fake(); - $data = json_decode(file_get_contents(__DIR__.'/Stubs/Stripe/payment_intent.succeeded.json'), true); + $data = json_decode(file_get_contents(__DIR__.'/../Stubs/Stripe/payment_intent.succeeded.json'), true); $data['data']['object']['id'] = $this->cart->meta['payment_intent']; @@ -76,14 +76,14 @@ public function constructEvent(string $jsonPayload, string $signature, string $s // Queue::assertPushed(HandlePaymentIntentSucceeded::class); // Event::assertDispatched(OrderPaymentSuccessful::class); -}); +})->group('webhooks'); it('can handle payment_intent.cancelled event', function () { /** @var TestCase $this */ Event::fake(); Queue::fake(); - $data = json_decode(file_get_contents(__DIR__.'/Stubs/Stripe/payment_intent.canceled.json'), true); + $data = json_decode(file_get_contents(__DIR__.'/../Stubs/Stripe/payment_intent.canceled.json'), true); $paymentIntentId = $this->cart->meta['payment_intent']; $data['data']['object']['id'] = $paymentIntentId; @@ -98,14 +98,14 @@ public function constructEvent(string $jsonPayload, string $signature, string $s $response->assertSuccessful(); // Event::assertDispatched(OrderPaymentCanceled::class); -}); +})->group('webhooks'); it('can handle payment_intent.failed event', function () { /** @var TestCase $this */ Event::fake(); Queue::fake(); - $data = json_decode(file_get_contents(__DIR__.'/Stubs/Stripe/payment_intent.payment_failed.json'), true); + $data = json_decode(file_get_contents(__DIR__.'/../Stubs/Stripe/payment_intent.payment_failed.json'), true); $data['data']['object']['id'] = $this->cart->meta['payment_intent']; @@ -119,14 +119,14 @@ public function constructEvent(string $jsonPayload, string $signature, string $s $response->assertSuccessful(); // Event::assertDispatched(OrderPaymentFailed::class); -}); +})->group('webhooks'); it('can handle any other event', function () { /** @var TestCase $this */ Event::fake(); Queue::fake(); - $data = json_decode(file_get_contents(__DIR__.'/Stubs/Stripe/charge.succeeded.json'), true); + $data = json_decode(file_get_contents(__DIR__.'/../Stubs/Stripe/charge.succeeded.json'), true); $data['data']['object']['id'] = $this->cart->meta['payment_intent']; @@ -138,4 +138,4 @@ public function constructEvent(string $jsonPayload, string $signature, string $s ); $response->assertSuccessful(); -}); +})->group('webhooks'); diff --git a/tests/Feature/WebhookHandlerTest.php b/tests/Feature/WebhookHandlerTest.php new file mode 100644 index 0000000..68ccdc0 --- /dev/null +++ b/tests/Feature/WebhookHandlerTest.php @@ -0,0 +1,6 @@ +make(TestTaxDriver::class); - }); + Taxes::extend( + 'test', + fn (Application $app) => $app->make(TestTaxDriver::class), + ); Currency::factory()->create([ 'code' => 'EUR', @@ -62,13 +65,17 @@ protected function setUp(): void activity()->disableLogging(); } + /** + * Get package providers. + * + * @param \Illuminate\Foundation\Application $app + * @return array> + */ protected function getPackageProviders($app): array { return [ // Ray \Spatie\LaravelRay\RayServiceProvider::class, - \Spatie\WebhookClient\WebhookClientServiceProvider::class, - \Spatie\StripeWebhooks\StripeWebhooksServiceProvider::class, // Laravel JsonApi \LaravelJsonApi\Encoder\Neomerx\ServiceProvider::class, @@ -93,6 +100,10 @@ protected function getPackageProviders($app): array \Dystcz\LunarApi\LunarApiServiceProvider::class, \Dystcz\LunarApi\JsonApiServiceProvider::class, + // Stripe webhooks + \Spatie\WebhookClient\WebhookClientServiceProvider::class, + \Spatie\StripeWebhooks\StripeWebhooksServiceProvider::class, + // Lunar API Stripe Adapter \Dystcz\LunarApiStripeAdapter\LunarApiStripeAdapterServiceProvider::class, ]; @@ -122,7 +133,6 @@ public function getEnvironmentSetUp($app): void */ Config::set('database.default', 'sqlite'); Config::set('database.migrations', 'migrations'); - Config::set('database.connections.sqlite', [ 'driver' => 'sqlite', 'database' => ':memory:', @@ -175,4 +185,15 @@ protected function defineDatabaseMigrations(): void $this->loadMigrationsFrom(__DIR__.'/../database/migrations'); $this->loadLaravelMigrations(); } + + /** + * Resolve application HTTP exception handler implementation. + */ + protected function resolveApplicationExceptionHandler($app): void + { + $app->singleton( + ExceptionHandler::class, + TestExceptionHandler::class + ); + } }