Skip to content

Commit d77514f

Browse files
authored
Merge pull request #129 from NativePHP/improve-stripe-handling
Improve stripe handling
2 parents 0d645be + 4379cb4 commit d77514f

File tree

3 files changed

+56
-4
lines changed

3 files changed

+56
-4
lines changed

app/Jobs/CreateUserFromStripeCustomer.php

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Illuminate\Queue\InteractsWithQueue;
1010
use Illuminate\Queue\SerializesModels;
1111
use Illuminate\Support\Facades\Hash;
12+
use Illuminate\Support\Facades\Log;
1213
use Illuminate\Support\Str;
1314
use Laravel\Cashier\Cashier;
1415
use Stripe\Customer;
@@ -21,14 +22,19 @@ public function __construct(public Customer $customer) {}
2122

2223
public function handle(): void
2324
{
24-
if (Cashier::findBillable($this->customer)) {
25-
$this->fail("A user already exists for Stripe customer [{$this->customer->id}].");
25+
/** @var User $user */
26+
if ($user = Cashier::findBillable($this->customer)) {
27+
Log::debug("A user [{$user->id} | {$user->email}] with stripe_id [{$this->customer->id}] already exists.");
2628

2729
return;
2830
}
2931

30-
if (User::query()->where('email', $this->customer->email)->exists()) {
31-
$this->fail("A user already exists for email [{$this->customer->email}].");
32+
if ($user = User::query()->where('email', $this->customer->email)->first()) {
33+
// This could occur if a user performs/attempts multiple checkouts with the same email address.
34+
// In the event all existing stripe customers for this email address do NOT have an active
35+
// subscription, we could theoretically update the stripe_id for the existing user
36+
// and continue. However, for now, we will throw an exception.
37+
$this->fail("A user with email [{$user->email}] already exists but the current stripe_id [{$user->stripe_id}] does not match the new customer id [{$this->customer->id}].");
3238

3339
return;
3440
}

app/Listeners/StripeWebhookReceivedListener.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
namespace App\Listeners;
44

55
use App\Jobs\CreateUserFromStripeCustomer;
6+
use Exception;
67
use Illuminate\Support\Facades\Log;
8+
use Laravel\Cashier\Cashier;
79
use Laravel\Cashier\Events\WebhookReceived;
810
use Stripe\Customer;
911

@@ -19,7 +21,25 @@ public function handle(WebhookReceived $event): void
1921
'customer.created' => dispatch_sync(new CreateUserFromStripeCustomer(
2022
Customer::constructFrom($event->payload['data']['object'])
2123
)),
24+
'customer.subscription.created' => $this->createUserIfNotExists($event->payload['data']['object']['customer']),
2225
default => null,
2326
};
2427
}
28+
29+
private function createUserIfNotExists(string $stripeCustomerId): void
30+
{
31+
if (Cashier::findBillable($stripeCustomerId)) {
32+
return;
33+
}
34+
35+
$customer = Customer::retrieve($stripeCustomerId);
36+
37+
if (! $customer) {
38+
throw new Exception(
39+
'A user needed to be created for customer.subscription.created but was unable to retrieve the customer from Stripe.'
40+
);
41+
}
42+
43+
dispatch_sync(new CreateUserFromStripeCustomer($customer));
44+
}
2545
}

app/Providers/AppServiceProvider.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,14 @@
33
namespace App\Providers;
44

55
use App\Support\GitHub;
6+
use Illuminate\Queue\Events\JobFailed;
7+
use Illuminate\Support\Facades\Queue;
68
use Illuminate\Support\Facades\View;
79
use Illuminate\Support\ServiceProvider;
10+
use Sentry\State\Scope;
11+
12+
use function Sentry\captureException;
13+
use function Sentry\configureScope;
814

915
class AppServiceProvider extends ServiceProvider
1016
{
@@ -22,6 +28,8 @@ public function register(): void
2228
public function boot(): void
2329
{
2430
$this->registerSharedViewVariables();
31+
32+
$this->sendFailingJobsToSentry();
2533
}
2634

2735
private function registerSharedViewVariables(): void
@@ -35,4 +43,22 @@ private function registerSharedViewVariables(): void
3543
View::share('openCollectiveLink', 'https://opencollective.com/nativephp');
3644
View::share('githubLink', 'https://github.com/NativePHP');
3745
}
46+
47+
private function sendFailingJobsToSentry(): void
48+
{
49+
Queue::failing(static function (JobFailed $event) {
50+
if (app()->bound('sentry')) {
51+
configureScope(function (Scope $scope) use ($event): void {
52+
$scope->setContext('job', [
53+
'connection' => $event->connectionName,
54+
'queue' => $event->job->getQueue(),
55+
'name' => $event->job->resolveName(),
56+
'payload' => $event->job->payload(),
57+
]);
58+
});
59+
60+
captureException($event->exception);
61+
}
62+
});
63+
}
3864
}

0 commit comments

Comments
 (0)