Add Stripe integration: webhook controller, service, sync command, Connect account
- Create StripeService: webhook sync, signature verification, save secret to .env.local - Create StripeWebhookController with signature verification (400 on invalid) - Create stripe:sync command to auto-create webhook endpoint via Stripe API - Webhook listens to all events (configurable later) - Save webhook secret automatically to .env.local on creation - Add stripeAccountId field to User entity for Stripe Connect + migration - Tests: StripeServiceTest (5), StripeWebhookControllerTest (2), StripeSyncCommandTest (1), UserTest updated Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
19
tests/Command/StripeSyncCommandTest.php
Normal file
19
tests/Command/StripeSyncCommandTest.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Tests\Command;
|
||||
|
||||
use App\Command\StripeSyncCommand;
|
||||
use App\Service\StripeService;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class StripeSyncCommandTest extends TestCase
|
||||
{
|
||||
public function testCommandIsConfigured(): void
|
||||
{
|
||||
$stripeService = $this->createMock(StripeService::class);
|
||||
$command = new StripeSyncCommand($stripeService);
|
||||
|
||||
self::assertSame('stripe:sync', $command->getName());
|
||||
self::assertSame('Create or update the Stripe webhook endpoint', $command->getDescription());
|
||||
}
|
||||
}
|
||||
41
tests/Controller/StripeWebhookControllerTest.php
Normal file
41
tests/Controller/StripeWebhookControllerTest.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Tests\Controller;
|
||||
|
||||
use App\Service\StripeService;
|
||||
use Stripe\Event;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||
|
||||
class StripeWebhookControllerTest extends WebTestCase
|
||||
{
|
||||
public function testWebhookWithValidSignature(): void
|
||||
{
|
||||
$client = static::createClient();
|
||||
|
||||
$stripeService = $this->createMock(StripeService::class);
|
||||
$stripeService->method('verifyWebhookSignature')->willReturn(new Event());
|
||||
static::getContainer()->set(StripeService::class, $stripeService);
|
||||
|
||||
$client->request('POST', '/stripe/webhook', [], [], [
|
||||
'HTTP_STRIPE_SIGNATURE' => 'valid',
|
||||
], '{}');
|
||||
|
||||
self::assertResponseIsSuccessful();
|
||||
self::assertSame('OK', $client->getResponse()->getContent());
|
||||
}
|
||||
|
||||
public function testWebhookWithInvalidSignature(): void
|
||||
{
|
||||
$client = static::createClient();
|
||||
|
||||
$stripeService = $this->createMock(StripeService::class);
|
||||
$stripeService->method('verifyWebhookSignature')->willReturn(null);
|
||||
static::getContainer()->set(StripeService::class, $stripeService);
|
||||
|
||||
$client->request('POST', '/stripe/webhook', [], [], [
|
||||
'HTTP_STRIPE_SIGNATURE' => 'invalid',
|
||||
], '{}');
|
||||
|
||||
self::assertResponseStatusCodeSame(400);
|
||||
}
|
||||
}
|
||||
@@ -146,6 +146,17 @@ class UserTest extends TestCase
|
||||
self::assertSame(1.5, $user->getCommissionRate());
|
||||
}
|
||||
|
||||
public function testStripeAccountIdField(): void
|
||||
{
|
||||
$user = new User();
|
||||
|
||||
self::assertNull($user->getStripeAccountId());
|
||||
|
||||
$result = $user->setStripeAccountId('acct_1234567890');
|
||||
self::assertSame($user, $result);
|
||||
self::assertSame('acct_1234567890', $user->getStripeAccountId());
|
||||
}
|
||||
|
||||
public function testEmailVerificationFields(): void
|
||||
{
|
||||
$user = new User();
|
||||
|
||||
63
tests/Service/StripeServiceTest.php
Normal file
63
tests/Service/StripeServiceTest.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace App\Tests\Service;
|
||||
|
||||
use App\Service\StripeService;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class StripeServiceTest extends TestCase
|
||||
{
|
||||
public function testGetWebhookUrl(): void
|
||||
{
|
||||
$service = new StripeService('sk_test', 'whsec_test', 'https://example.com', '/tmp');
|
||||
|
||||
self::assertSame('https://example.com/stripe/webhook', $service->getWebhookUrl());
|
||||
}
|
||||
|
||||
public function testGetWebhookUrlTrimsTrailingSlash(): void
|
||||
{
|
||||
$service = new StripeService('sk_test', 'whsec_test', 'https://example.com/', '/tmp');
|
||||
|
||||
self::assertSame('https://example.com/stripe/webhook', $service->getWebhookUrl());
|
||||
}
|
||||
|
||||
public function testVerifyWebhookSignatureReturnsNullOnInvalid(): void
|
||||
{
|
||||
$service = new StripeService('sk_test', 'whsec_test', 'https://example.com', '/tmp');
|
||||
|
||||
self::assertNull($service->verifyWebhookSignature('{}', 'invalid'));
|
||||
}
|
||||
|
||||
public function testSaveWebhookSecretCreatesEntry(): void
|
||||
{
|
||||
$tmpDir = sys_get_temp_dir().'/stripe_test_'.uniqid();
|
||||
mkdir($tmpDir);
|
||||
file_put_contents($tmpDir.'/.env.local', "APP_ENV=test\n");
|
||||
|
||||
$service = new StripeService('sk_test', 'whsec_test', 'https://example.com', $tmpDir);
|
||||
$service->saveWebhookSecret('whsec_new123');
|
||||
|
||||
$content = file_get_contents($tmpDir.'/.env.local');
|
||||
self::assertStringContainsString('STRIPE_WEBHOOK_SECRET=whsec_new123', $content);
|
||||
|
||||
unlink($tmpDir.'/.env.local');
|
||||
rmdir($tmpDir);
|
||||
}
|
||||
|
||||
public function testSaveWebhookSecretUpdatesExisting(): void
|
||||
{
|
||||
$tmpDir = sys_get_temp_dir().'/stripe_test_'.uniqid();
|
||||
mkdir($tmpDir);
|
||||
file_put_contents($tmpDir.'/.env.local', "APP_ENV=test\nSTRIPE_WEBHOOK_SECRET=old_secret\n");
|
||||
|
||||
$service = new StripeService('sk_test', 'whsec_test', 'https://example.com', $tmpDir);
|
||||
$service->saveWebhookSecret('whsec_updated');
|
||||
|
||||
$content = file_get_contents($tmpDir.'/.env.local');
|
||||
self::assertStringContainsString('STRIPE_WEBHOOK_SECRET=whsec_updated', $content);
|
||||
self::assertStringNotContainsString('old_secret', $content);
|
||||
|
||||
unlink($tmpDir.'/.env.local');
|
||||
rmdir($tmpDir);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user