feat: implement comprehensive multi-provider payment processing system
- Add unified payment provider architecture with contract-based design - Implement 6 payment providers: Stripe, Lemon Squeezy, Polar, Oxapay, Crypto, Activation Keys - Create subscription management with lifecycle handling (create, cancel, pause, resume, update) - Add coupon system with usage tracking and trial extensions - Build Filament admin resources for payment providers, subscriptions, coupons, and trials - Implement payment orchestration service with provider registry and configuration management - Add comprehensive payment logging and webhook handling for all providers - Create customer analytics dashboard with revenue, churn, and lifetime value metrics - Add subscription migration service for provider switching - Include extensive test coverage for all payment functionality
This commit is contained in:
227
tests/Unit/PaymentConfigurationManagerTest.php
Normal file
227
tests/Unit/PaymentConfigurationManagerTest.php
Normal file
@@ -0,0 +1,227 @@
|
||||
<?php
|
||||
|
||||
use App\Services\Payments\PaymentConfigurationManager;
|
||||
use App\Services\Payments\ProviderRegistry;
|
||||
|
||||
test('can initialize payment providers', function () {
|
||||
$registry = new ProviderRegistry;
|
||||
$manager = new PaymentConfigurationManager($registry);
|
||||
|
||||
$manager->initializeProviders();
|
||||
|
||||
// Check that activation key provider is always registered
|
||||
expect($registry->has('activation_key'))->toBeTrue();
|
||||
|
||||
// Other providers should only be registered if configured
|
||||
$providers = $registry->getAllProviders();
|
||||
expect($providers)->toHaveKey('activation_key');
|
||||
});
|
||||
|
||||
test('can get provider configuration', function () {
|
||||
$registry = new ProviderRegistry;
|
||||
$manager = new PaymentConfigurationManager($registry);
|
||||
|
||||
$config = $manager->getProviderConfig('activation_key');
|
||||
|
||||
expect($config)->toBeArray();
|
||||
expect($config)->toHaveKey('key_prefix');
|
||||
expect($config)->toHaveKey('key_length');
|
||||
});
|
||||
|
||||
test('can update provider configuration', function () {
|
||||
$registry = new ProviderRegistry;
|
||||
$manager = new PaymentConfigurationManager($registry);
|
||||
|
||||
$newConfig = ['key_prefix' => 'TEST-'];
|
||||
$manager->updateProviderConfig('activation_key', $newConfig);
|
||||
|
||||
$config = $manager->getProviderConfig('activation_key');
|
||||
expect($config['key_prefix'])->toBe('TEST-');
|
||||
});
|
||||
|
||||
test('can validate stripe configuration', function () {
|
||||
$registry = new ProviderRegistry;
|
||||
$manager = new PaymentConfigurationManager($registry);
|
||||
|
||||
// Invalid configuration
|
||||
$result = $manager->validateProviderConfig('stripe', []);
|
||||
expect($result['valid'])->toBeFalse();
|
||||
expect($result['errors'])->toContain('Stripe secret key is required');
|
||||
|
||||
// Valid configuration
|
||||
$result = $manager->validateProviderConfig('stripe', [
|
||||
'secret_key' => 'sk_test_123',
|
||||
'publishable_key' => 'pk_test_123',
|
||||
]);
|
||||
expect($result['valid'])->toBeTrue();
|
||||
expect($result['errors'])->toBeEmpty();
|
||||
});
|
||||
|
||||
test('can validate lemon squeezy configuration', function () {
|
||||
$registry = new ProviderRegistry;
|
||||
$manager = new PaymentConfigurationManager($registry);
|
||||
|
||||
// Invalid configuration
|
||||
$result = $manager->validateProviderConfig('lemon_squeezy', []);
|
||||
expect($result['valid'])->toBeFalse();
|
||||
expect($result['errors'])->toContain('Lemon Squeezy API key is required');
|
||||
|
||||
// Valid configuration
|
||||
$result = $manager->validateProviderConfig('lemon_squeezy', [
|
||||
'api_key' => 'test_key',
|
||||
'store_id' => 'test_store',
|
||||
]);
|
||||
expect($result['valid'])->toBeTrue();
|
||||
expect($result['errors'])->toBeEmpty();
|
||||
});
|
||||
|
||||
test('can validate crypto configuration', function () {
|
||||
$registry = new ProviderRegistry;
|
||||
$manager = new PaymentConfigurationManager($registry);
|
||||
|
||||
// Invalid configuration
|
||||
$result = $manager->validateProviderConfig('crypto', []);
|
||||
expect($result['valid'])->toBeFalse();
|
||||
expect($result['errors'])->toContain('Crypto webhook secret is required');
|
||||
|
||||
// Valid configuration
|
||||
$result = $manager->validateProviderConfig('crypto', [
|
||||
'webhook_secret' => 'test_secret',
|
||||
]);
|
||||
expect($result['valid'])->toBeTrue();
|
||||
expect($result['errors'])->toBeEmpty();
|
||||
});
|
||||
|
||||
test('activation key configuration is always valid', function () {
|
||||
$registry = new ProviderRegistry;
|
||||
$manager = new PaymentConfigurationManager($registry);
|
||||
|
||||
$result = $manager->validateProviderConfig('activation_key', []);
|
||||
expect($result['valid'])->toBeTrue();
|
||||
expect($result['errors'])->toBeEmpty();
|
||||
});
|
||||
|
||||
test('can get provider status', function () {
|
||||
$registry = new ProviderRegistry;
|
||||
$manager = new PaymentConfigurationManager($registry);
|
||||
|
||||
$manager->initializeProviders();
|
||||
$status = $manager->getProviderStatus();
|
||||
|
||||
expect($status)->toBeArray();
|
||||
expect($status)->toHaveKey('activation_key');
|
||||
|
||||
$activationKeyStatus = $status['activation_key'];
|
||||
expect($activationKeyStatus)->toHaveKey('name');
|
||||
expect($activationKeyStatus)->toHaveKey('active');
|
||||
expect($activationKeyStatus)->toHaveKey('supports_recurring');
|
||||
expect($activationKeyStatus)->toHaveKey('supports_one_time');
|
||||
expect($activationKeyStatus)->toHaveKey('supported_currencies');
|
||||
});
|
||||
|
||||
test('can sanitize configuration for display', function () {
|
||||
$registry = new ProviderRegistry;
|
||||
$manager = new PaymentConfigurationManager($registry);
|
||||
|
||||
$manager->updateProviderConfig('test', [
|
||||
'secret_key' => 'sk_test_1234567890',
|
||||
'public_key' => 'pk_test_1234567890',
|
||||
'other_field' => 'visible_value',
|
||||
]);
|
||||
|
||||
$status = $manager->getProviderStatus();
|
||||
|
||||
// Since 'test' is not a real provider, we need to check the sanitize logic indirectly
|
||||
$config = $manager->getProviderConfig('test');
|
||||
expect($config['secret_key'])->toBe('sk_test_1234567890'); // Original is preserved
|
||||
});
|
||||
|
||||
test('can get default provider', function () {
|
||||
$registry = new ProviderRegistry;
|
||||
$manager = new PaymentConfigurationManager($registry);
|
||||
|
||||
$manager->initializeProviders();
|
||||
$defaultProvider = $manager->getDefaultProvider();
|
||||
|
||||
expect($defaultProvider)->toBe('activation_key'); // Should fallback to activation key
|
||||
});
|
||||
|
||||
test('can test provider connectivity', function () {
|
||||
$registry = new ProviderRegistry;
|
||||
$manager = new PaymentConfigurationManager($registry);
|
||||
|
||||
$manager->initializeProviders();
|
||||
|
||||
// Test existing provider
|
||||
$result = $manager->testProviderConnectivity('activation_key');
|
||||
expect($result['success'])->toBeTrue();
|
||||
expect($result['details']['name'])->toBe('activation_key');
|
||||
|
||||
// Test non-existing provider
|
||||
$result = $manager->testProviderConnectivity('non_existent');
|
||||
expect($result['success'])->toBeFalse();
|
||||
expect($result['error'])->toBe('Provider not registered');
|
||||
});
|
||||
|
||||
test('can toggle provider', function () {
|
||||
$registry = new ProviderRegistry;
|
||||
$manager = new PaymentConfigurationManager($registry);
|
||||
|
||||
$manager->initializeProviders();
|
||||
|
||||
// Activation key should be registered
|
||||
expect($registry->has('activation_key'))->toBeTrue();
|
||||
|
||||
// Disable activation key
|
||||
$result = $manager->toggleProvider('activation_key', false);
|
||||
expect($result)->toBeTrue();
|
||||
expect($registry->has('activation_key'))->toBeFalse();
|
||||
|
||||
// Re-enable activation key
|
||||
$result = $manager->toggleProvider('activation_key', true);
|
||||
expect($result)->toBeTrue();
|
||||
expect($registry->has('activation_key'))->toBeTrue();
|
||||
});
|
||||
|
||||
test('can refresh configurations', function () {
|
||||
$registry = new ProviderRegistry;
|
||||
$manager = new PaymentConfigurationManager($registry);
|
||||
|
||||
// Update a configuration
|
||||
$manager->updateProviderConfig('activation_key', ['key_prefix' => 'REFRESH-']);
|
||||
|
||||
// Refresh configurations
|
||||
$manager->refreshConfigurations();
|
||||
|
||||
// Configuration should still be available
|
||||
$config = $manager->getProviderConfig('activation_key');
|
||||
expect($config)->toHaveKey('key_prefix');
|
||||
});
|
||||
|
||||
test('handles unknown provider validation', function () {
|
||||
$registry = new ProviderRegistry;
|
||||
$manager = new PaymentConfigurationManager($registry);
|
||||
|
||||
$result = $manager->validateProviderConfig('unknown_provider', []);
|
||||
expect($result['valid'])->toBeFalse();
|
||||
expect($result['errors'])->toContain('Unknown provider: unknown_provider');
|
||||
});
|
||||
|
||||
test('handles unknown provider toggle', function () {
|
||||
$registry = new ProviderRegistry;
|
||||
$manager = new PaymentConfigurationManager($registry);
|
||||
|
||||
$result = $manager->toggleProvider('unknown_provider', true);
|
||||
expect($result)->toBeFalse();
|
||||
});
|
||||
|
||||
test('activation key provider is always available', function () {
|
||||
$registry = new ProviderRegistry;
|
||||
$manager = new PaymentConfigurationManager($registry);
|
||||
|
||||
$manager->initializeProviders();
|
||||
|
||||
// Even without any configuration, activation key should be available
|
||||
expect($registry->has('activation_key'))->toBeTrue();
|
||||
expect($registry->get('activation_key')->isActive())->toBeTrue();
|
||||
});
|
||||
Reference in New Issue
Block a user