Skip to content

Commit 99b8ef5

Browse files
committed
refacto model repository
1 parent aebf958 commit 99b8ef5

9 files changed

+237
-73
lines changed

config/stripe.php

+9-3
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,18 @@
33
// config for Finller/Stripe
44

55
use Finller\Stripe\Commands\CreateStripeWebhooksCommand;
6+
use Finller\Stripe\ModelRepository;
67

78
return [
89

9-
'tables' => [
10-
'accounts' => 'users',
11-
'customers' => 'users',
10+
'models' => [
11+
'accounts' => [
12+
\App\Models\User::class,
13+
],
14+
'customers' => [
15+
\App\Models\User::class,
16+
],
17+
'repository' => ModelRepository::class,
1218
],
1319

1420
'cache' => [
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,71 @@
11
<?php
22

3+
use Illuminate\Database\Eloquent\Model;
34
use Illuminate\Database\Migrations\Migration;
45
use Illuminate\Database\Schema\Blueprint;
6+
use Illuminate\Support\Arr;
57
use Illuminate\Support\Facades\Schema;
68

79
return new class extends Migration
810
{
911
public function up()
1012
{
11-
Schema::table(config('stripe.tables.accounts'), function (Blueprint $table) {
12-
$table->string('stripe_account_id')->nullable();
13-
});
13+
foreach (Arr::wrap(config('stripe.models.accounts')) as $modelClass) {
14+
/** @var Model $model */
15+
$model = new $modelClass;
1416

15-
Schema::table(config('stripe.tables.customers'), function (Blueprint $table) {
16-
$table->string('stripe_customer_id')->nullable();
17-
});
17+
Schema::table(
18+
$model->getTable(),
19+
function (Blueprint $table) {
20+
$table->string('stripe_account_id')->nullable();
21+
$table->boolean('stripe_charges_enabled')->default(false);
22+
$table->boolean('stripe_details_submitted')->default(false);
23+
$table->boolean('stripe_payouts_enabled')->default(false);
24+
}
25+
);
26+
}
27+
28+
foreach (Arr::wrap(config('stripe.models.customers')) as $modelClass) {
29+
/** @var Model $model */
30+
$model = new $modelClass;
31+
32+
Schema::table(
33+
$model->getTable(),
34+
function (Blueprint $table) {
35+
$table->string('stripe_customer_id')->nullable();
36+
}
37+
);
38+
}
1839
}
1940

2041
public function down(): void
2142
{
22-
Schema::table(config('stripe.tables.accounts'), function (Blueprint $table) {
23-
$table->dropColumn('stripe_account_id');
24-
});
2543

26-
Schema::table(config('stripe.tables.customers'), function (Blueprint $table) {
27-
$table->dropColumn('stripe_customer_id');
28-
});
44+
foreach (Arr::wrap(config('stripe.models.accounts')) as $modelClass) {
45+
/** @var Model $model */
46+
$model = new $modelClass;
47+
48+
Schema::table(
49+
$model->getTable(),
50+
function (Blueprint $table) {
51+
$table->dropColumn('stripe_account_id');
52+
$table->dropColumn('stripe_charges_enabled');
53+
$table->dropColumn('stripe_details_submitted');
54+
$table->dropColumn('stripe_payouts_enabled');
55+
}
56+
);
57+
}
58+
59+
foreach (Arr::wrap(config('stripe.models.customers')) as $modelClass) {
60+
/** @var Model $model */
61+
$model = new $modelClass;
62+
63+
Schema::table(
64+
$model->getTable(),
65+
function (Blueprint $table) {
66+
$table->dropColumn('stripe_customer_id');
67+
}
68+
);
69+
}
2970
}
3071
};

phpstan.neon.dist

+4
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,7 @@ parameters:
1212
checkModelProperties: true
1313
checkMissingIterableValueType: false
1414

15+
ignoreErrors:
16+
-
17+
message: '#Class App\\Models\\User not found.#'
18+
path: config/*

src/Listeners/AccountApplicationDeauthorized.php

+8-8
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace Finller\Stripe\Listeners;
44

5-
use Finller\Stripe\Traits\ListenAccountEvents;
5+
use Finller\Stripe\Traits\ListenAccountApplicationEvents;
66
use Illuminate\Contracts\Queue\ShouldQueue;
77
use Spatie\WebhookClient\Models\WebhookCall;
88
use Stripe\Account;
@@ -15,7 +15,7 @@
1515
*/
1616
class AccountApplicationDeauthorized implements ShouldQueue
1717
{
18-
use ListenAccountEvents;
18+
use ListenAccountApplicationEvents;
1919

2020
public function __construct()
2121
{
@@ -24,15 +24,15 @@ public function __construct()
2424

2525
public function handle(WebhookCall $event): void
2626
{
27-
$account = $this->getStripeAccountFromEvent($event);
27+
$model = $this->getModelFromEvent($event);
2828

29-
if (! $account) {
29+
if (! $model) {
3030
return;
3131
}
3232

33-
$model = $this->getModelFromAccount($account);
34-
35-
$model->importFromStripeAccount(null); // @phpstan-ignore-line
36-
$model->forgetStripeAccount(); // @phpstan-ignore-line
33+
// @phpstan-ignore-next-line
34+
$model
35+
->importFromStripeAccount(null)
36+
->forgetStripeAccount();
3737
}
3838
}

src/Listeners/AccountUpdated.php

+4
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ public function handle(WebhookCall $event): void
3232

3333
$model = $this->getModelFromAccount($account);
3434

35+
if (! $model) {
36+
return;
37+
}
38+
3539
$model->importFromStripeAccount($account); // @phpstan-ignore-line
3640

3741
if ($model->shouldCacheStripeAccount()) { // @phpstan-ignore-line

src/ModelRepository.php

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<?php
2+
3+
namespace Finller\Stripe;
4+
5+
use Exception;
6+
use Illuminate\Database\Eloquent\Model;
7+
use Illuminate\Support\Arr;
8+
use Stripe\Account;
9+
use Stripe\Customer;
10+
11+
class ModelRepository
12+
{
13+
public static function findAccount(string $stripeAccountId): ?Model
14+
{
15+
return static::findFromModels(
16+
models: Arr::wrap(config('stripe.models.accounts')),
17+
columnName: 'stripe_account_id',
18+
stripeId: $stripeAccountId
19+
);
20+
}
21+
22+
public static function findCustomer(string $stripeCustomerId): ?Model
23+
{
24+
return static::findFromModels(
25+
models: Arr::wrap(config('stripe.models.customers')),
26+
columnName: 'stripe_customer_id',
27+
stripeId: $stripeCustomerId
28+
);
29+
}
30+
31+
public static function findAccountFromStripeObject(Account $account): ?Model
32+
{
33+
$model = static::findFromStripeObject($account);
34+
35+
if (! $model) {
36+
return static::findAccount($account->id);
37+
}
38+
39+
$model_type = get_class($model);
40+
$model_id = $model->getKey();
41+
42+
/** @var ?string $model_stripe_account_id */
43+
$model_stripe_account_id = $model->stripe_account_id; // @phpstan-ignore-line
44+
45+
if ($model_stripe_account_id !== $account->id) {
46+
throw new Exception("[{$model_type}:{$model_id}] Conflict between Stripe account ID and Stripe account metadata: {$model_stripe_account_id} !== {$account->id}", 500);
47+
}
48+
49+
return $model;
50+
}
51+
52+
public static function findCustomerFromStripeObject(Customer $customer): ?Model
53+
{
54+
$model = static::findFromStripeObject($customer);
55+
56+
if (! $model) {
57+
return static::findCustomer($customer->id);
58+
}
59+
60+
$model_type = get_class($model);
61+
$model_id = $model->getKey();
62+
63+
/** @var ?string $model_stripe_customer_id */
64+
$model_stripe_customer_id = $model->stripe_customer_id; // @phpstan-ignore-line
65+
66+
if ($model_stripe_customer_id !== $customer->id) {
67+
throw new Exception("[{$model_type}:{$model_id}] Conflict between Stripe customer ID and Stripe customer metadata: {$model_stripe_customer_id} !== {$customer->id}", 500);
68+
}
69+
70+
return $model;
71+
}
72+
73+
protected static function findFromStripeObject(Account|Customer $object): ?Model
74+
{
75+
$model_type = data_get($object->metadata, 'model_type');
76+
$model_id = data_get($object->metadata, 'model_id');
77+
78+
if (! $model_type || ! $model_id) {
79+
return null;
80+
}
81+
82+
return $model_type::find($model_id);
83+
}
84+
85+
protected static function findFromModels(
86+
array $models,
87+
string $columnName,
88+
string $stripeId
89+
): ?Model {
90+
foreach ($models as $model) {
91+
$instance = $model::query()
92+
->where($columnName, $stripeId)
93+
->first();
94+
95+
if ($instance) {
96+
return $instance;
97+
}
98+
}
99+
100+
return null;
101+
}
102+
}

src/Traits/ListenAccountEvents.php

+11-25
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,28 @@
22

33
namespace Finller\Stripe\Traits;
44

5-
use Exception;
5+
use Finller\Stripe\ModelRepository;
66
use Illuminate\Database\Eloquent\Model;
77
use Spatie\WebhookClient\Models\WebhookCall;
88
use Stripe\Account;
99
use Stripe\Event;
10-
use Stripe\StripeObject;
1110

1211
trait ListenAccountEvents
1312
{
14-
/**
15-
* @return ?Account
16-
*/
17-
public function getStripeAccountFromEvent(WebhookCall $event): ?StripeObject
13+
public function getStripeEvent(WebhookCall $event): ?Event
1814
{
19-
return Event::constructFrom($event->payload)->data?->object; // @phpstan-ignore-line
15+
return $event->payload ?
16+
Event::constructFrom($event->payload) :
17+
null;
2018
}
2119

22-
public function getModelFromAccount(Account $account): ?Model
20+
public function getStripeAccountFromEvent(WebhookCall $event): ?Account
2321
{
24-
$model_type = data_get($account->metadata, 'model_type');
25-
$model_id = data_get($account->metadata, 'model_id');
26-
27-
/** @var ?Model $model */
28-
$model = $model_type::find($model_id);
29-
30-
if (! $model) {
31-
return null;
32-
}
33-
34-
/** @var ?string $model_stripe_account_id */
35-
$model_stripe_account_id = $model->stripe_account_id; // @phpstan-ignore-line
36-
37-
if ($model_stripe_account_id !== $account->id) {
38-
throw new Exception("[{$model_type}:{$model_id}] Conflict between Stripe account ID and Stripe account metadata: {$model_stripe_account_id} !== {$account->id}", 500);
39-
}
22+
return $this->getStripeEvent($event)?->data?->object; // @phpstan-ignore-line
23+
}
4024

41-
return $model;
25+
public function getModelFromAccount(Account $account): ?Model
26+
{
27+
return ModelRepository::findAccountFromStripeObject($account);
4228
}
4329
}
+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
namespace Finller\Stripe\Traits;
4+
5+
use Finller\Stripe\ModelRepository;
6+
use Illuminate\Database\Eloquent\Model;
7+
use Spatie\WebhookClient\Models\WebhookCall;
8+
use Stripe\Application;
9+
use Stripe\Event;
10+
11+
trait ListenAccountApplicationEvents
12+
{
13+
public function getStripeEvent(WebhookCall $event): ?Event
14+
{
15+
return $event->payload ?
16+
Event::constructFrom($event->payload) :
17+
null;
18+
}
19+
20+
public function getStripeApplicationFromEvent(WebhookCall $event): ?Application
21+
{
22+
return $this->getStripeEvent($event)?->data?->object; // @phpstan-ignore-line
23+
}
24+
25+
public function getModelFromEvent(WebhookCall $event): ?Model
26+
{
27+
$stripeEvent = $this->getStripeEvent($event);
28+
29+
if (! $stripeEvent?->account) {
30+
return null;
31+
}
32+
33+
return ModelRepository::findAccount($stripeEvent->account);
34+
}
35+
}

0 commit comments

Comments
 (0)