Intégration fonctionnalites V1

This commit is contained in:
bastien
2026-07-04 22:30:18 +02:00
parent 55a558b536
commit 10ee859602
54 changed files with 4802 additions and 1018 deletions
+151
View File
@@ -0,0 +1,151 @@
<?php
namespace App\Services;
use App\Models\PaymentTransaction;
use App\Models\User;
use Stripe\Exception\SignatureVerificationException;
use Stripe\PaymentIntent;
use Stripe\Stripe;
use Stripe\Webhook;
use UnexpectedValueException;
class StripePaymentService
{
private bool $configured = false;
private function ensureConfigured(): void
{
if ($this->configured) {
return;
}
if (! class_exists(Stripe::class)) {
throw new \RuntimeException(
'SDK Stripe manquant. Exécutez : composer require stripe/stripe-php',
);
}
Stripe::setApiKey(config('services.stripe.secret'));
$this->configured = true;
}
public function isEnabled(): bool
{
return class_exists(Stripe::class)
&& filled(config('services.stripe.secret'))
&& filled(config('services.stripe.key'));
}
public function publishableKey(): string
{
return (string) config('services.stripe.key');
}
public function createPaymentIntent(
User $user,
PaymentTransaction $payment,
float $amount,
): PaymentIntent {
$this->ensureConfigured();
return PaymentIntent::create([
'amount' => (int) round($amount * 100),
'currency' => strtolower($payment->currency),
'metadata' => [
'payment_uuid' => $payment->uuid,
'user_id' => (string) $user->id,
'idempotency_key' => $payment->idempotency_key,
],
]);
}
public function retrievePaymentIntent(string $paymentIntentId): PaymentIntent
{
$this->ensureConfigured();
return PaymentIntent::retrieve($paymentIntentId, [
'expand' => ['payment_method'],
]);
}
/**
* @return array<string, mixed>
*/
public function summarizePaymentIntent(PaymentIntent $intent): array
{
$summary = [
'payment_intent_id' => $intent->id,
'status' => $intent->status,
'amount' => $intent->amount / 100,
'currency' => strtoupper($intent->currency),
];
$paymentMethod = $intent->payment_method;
if (is_object($paymentMethod)) {
$summary['payment_method_type'] = $paymentMethod->type ?? null;
if (isset($paymentMethod->card)) {
$summary['card_brand'] = $paymentMethod->card->brand ?? null;
$summary['card_last4'] = $paymentMethod->card->last4 ?? null;
$summary['card_exp_month'] = $paymentMethod->card->exp_month ?? null;
$summary['card_exp_year'] = $paymentMethod->card->exp_year ?? null;
}
}
return $summary;
}
public function isPaymentSucceeded(PaymentIntent $paymentIntent): bool
{
return $paymentIntent->status === 'succeeded';
}
/**
* @return array{provider_payment_id: string, status: string, payload: array<string, mixed>}
*/
public function parseWebhook(string $payload, string $signature): array
{
$this->ensureConfigured();
$secret = config('services.stripe.webhook_secret');
if (blank($secret)) {
throw new \RuntimeException('Webhook Stripe non configuré.');
}
try {
$event = Webhook::constructEvent($payload, $signature, $secret);
} catch (UnexpectedValueException|SignatureVerificationException $e) {
throw new \InvalidArgumentException('Signature webhook Stripe invalide.', 0, $e);
}
$type = $event->type;
$object = $event->data->object;
if (! in_array($type, [
'payment_intent.succeeded',
'payment_intent.payment_failed',
'payment_intent.canceled',
], true)) {
return [
'provider_payment_id' => $object->id ?? '',
'status' => 'ignored',
'payload' => $event->toArray(),
];
}
$status = match ($type) {
'payment_intent.succeeded' => 'succeeded',
'payment_intent.payment_failed' => 'failed',
'payment_intent.canceled' => 'cancelled',
default => 'ignored',
};
return [
'provider_payment_id' => $object->id,
'status' => $status,
'payload' => $event->toArray(),
];
}
}