feat: clean credits users
CI / 🧪 Tests Laravel (push) Successful in 2m0s
CI / 🐳 Build & Push Image (push) Successful in 35s

This commit is contained in:
2026-08-07 15:32:40 +02:00
parent eac86afa53
commit 68560655f3
44 changed files with 417 additions and 661 deletions
@@ -0,0 +1,96 @@
<?php
namespace App\Services;
use App\Enums\BillingProductPurpose;
use App\Models\BillingProduct;
use Laravel\Cashier\Cashier;
class StripeBillingProductSyncer
{
public function sync(BillingProduct $product): BillingProduct
{
throw_if(
$product->purpose === null,
\InvalidArgumentException::class,
'A billing product purpose is required before syncing with Stripe.',
);
$stripe = Cashier::stripe();
$stripeProductId = $product->stripe_product_id;
if (! $stripeProductId) {
$stripeProduct = $stripe->products->create([
'name' => $product->name,
'description' => $product->description,
'metadata' => [
'billing_product_id' => $product->getKey(),
'billing_product_purpose' => $product->purpose?->value,
],
]);
$stripeProductId = $stripeProduct->id;
} else {
$stripe->products->update($stripeProductId, [
'name' => $product->name,
'description' => $product->description,
'active' => (bool) $product->is_active,
'metadata' => [
'billing_product_id' => $product->getKey(),
'billing_product_purpose' => $product->purpose?->value,
],
]);
}
$needsNewPrice = false;
if (! $product->stripe_price_id) {
$needsNewPrice = true;
} elseif ($product->wasChanged(['amount', 'currency', 'purpose'])) {
$needsNewPrice = true;
}
$stripePriceId = $product->stripe_price_id;
if ($needsNewPrice) {
$priceData = [
'product' => $stripeProductId,
'unit_amount' => $product->amount,
'currency' => strtolower($product->currency),
'metadata' => [
'billing_product_id' => $product->getKey(),
'billing_product_purpose' => $product->purpose?->value,
],
];
if ($product->purpose === BillingProductPurpose::SUBSCRIPTION) {
$priceData['recurring'] = [
'interval' => 'month',
];
}
$stripePrice = $stripe->prices->create($priceData);
$stripePriceId = $stripePrice->id;
// Archive the old price if it exists
if ($product->stripe_price_id && $product->stripe_price_id !== $stripePriceId) {
try {
$stripe->prices->update($product->stripe_price_id, [
'active' => false,
]);
} catch (\Exception $e) {
// Ignore error if price not found
}
}
}
if ($product->stripe_product_id !== $stripeProductId || $product->stripe_price_id !== $stripePriceId) {
$product->forceFill([
'stripe_product_id' => $stripeProductId,
'stripe_price_id' => $stripePriceId,
])->saveQuietly();
}
return $product;
}
}