Optimize academy
This commit is contained in:
@@ -5,8 +5,11 @@ declare(strict_types=1);
|
||||
namespace App\Services\Academy;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Str;
|
||||
use RuntimeException;
|
||||
use Stripe\Exception\InvalidRequestException;
|
||||
use Stripe\StripeClient;
|
||||
|
||||
final class AcademyBillingPlanService
|
||||
{
|
||||
@@ -64,6 +67,7 @@ final class AcademyBillingPlanService
|
||||
$plan['stripe_price_id'] = trim((string) ($plan['stripe_price_id'] ?? ''));
|
||||
$plan['configured'] = $plan['stripe_price_id'] !== '';
|
||||
$plan['price_id_valid'] = $this->isValidPriceId($plan['stripe_price_id']);
|
||||
$plan['remote_price_exists'] = $this->remotePriceExists($plan['stripe_price_id']);
|
||||
$plan['price_display'] = $plan['amount'] !== '' ? $plan['amount'].' '.$plan['currency'] : null;
|
||||
|
||||
return $plan;
|
||||
@@ -145,4 +149,86 @@ final class AcademyBillingPlanService
|
||||
|
||||
return preg_match('/^price_[A-Za-z0-9]+$/', $priceId) === 1;
|
||||
}
|
||||
}
|
||||
|
||||
public function remotePriceExists(?string $priceId): ?bool
|
||||
{
|
||||
$priceId = trim((string) $priceId);
|
||||
|
||||
if ($priceId === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Avoid calling Stripe in local/testing environments — assume exists there.
|
||||
if (app()->environment(['local', 'testing'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$cacheKey = 'academy.remote_price_exists:'.md5($priceId);
|
||||
|
||||
return Cache::remember($cacheKey, 300, function () use ($priceId): ?bool {
|
||||
try {
|
||||
$secret = $this->stripeSecret();
|
||||
|
||||
if ($secret === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$client = new StripeClient($secret);
|
||||
$price = $client->prices->retrieve($priceId, []);
|
||||
|
||||
// If Stripe returned an object with an id, it exists. Also ensure product exists where possible.
|
||||
if (is_object($price) && ! empty($price->id)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
} catch (InvalidRequestException $e) {
|
||||
report($e);
|
||||
|
||||
return false;
|
||||
} catch (\Throwable $e) {
|
||||
report($e);
|
||||
|
||||
// Auth, network, or transient Stripe failures should not make
|
||||
// public pricing look fully misconfigured.
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private function stripeSecret(): ?string
|
||||
{
|
||||
foreach ([config('cashier.secret'), env('STRIPE_SECRET')] as $candidate) {
|
||||
if (! is_string($candidate)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$candidate = trim($candidate);
|
||||
|
||||
if ($candidate !== '') {
|
||||
return $candidate;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, string>
|
||||
*/
|
||||
public function missingRemotePriceIds(?string $planKey = null): array
|
||||
{
|
||||
if ($planKey !== null) {
|
||||
$plan = $this->plan($planKey);
|
||||
|
||||
return $plan !== null && $this->remotePriceExists($plan['stripe_price_id'] ?? '') === false
|
||||
? [$this->normalizePlanKey($planKey)]
|
||||
: [];
|
||||
}
|
||||
|
||||
return collect(array_keys($this->plans()))
|
||||
->filter(fn (string $key): bool => $this->remotePriceExists($this->plan($key)['stripe_price_id'] ?? '') === false)
|
||||
->values()
|
||||
->all();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user