diff --git a/Boot.php b/Boot.php index 89aa105..8684c5b 100644 --- a/Boot.php +++ b/Boot.php @@ -8,11 +8,32 @@ use Core\Events\AdminPanelBooting; use Core\Events\ApiRoutesRegistering; use Core\Events\ConsoleBooting; use Core\Events\WebRoutesRegistering; +use Core\Mod\Commerce\Events\OrderPaid; +use Core\Mod\Commerce\Events\SubscriptionCreated; +use Core\Mod\Commerce\Events\SubscriptionRenewed; use Core\Mod\Commerce\Listeners\ProvisionSocialHostSubscription; use Core\Mod\Commerce\Listeners\RewardAgentReferralOnSubscription; +use Core\Mod\Commerce\Services\CheckoutRateLimiter; +use Core\Mod\Commerce\Services\CommerceService; +use Core\Mod\Commerce\Services\ContentOverrideService; +use Core\Mod\Commerce\Services\CouponService; +use Core\Mod\Commerce\Services\CreditNoteService; +use Core\Mod\Commerce\Services\CurrencyService; +use Core\Mod\Commerce\Services\DunningService; +use Core\Mod\Commerce\Services\FraudService; +use Core\Mod\Commerce\Services\InvoiceService; use Core\Mod\Commerce\Services\PaymentGateway\BTCPayGateway; use Core\Mod\Commerce\Services\PaymentGateway\PaymentGatewayContract; use Core\Mod\Commerce\Services\PaymentGateway\StripeGateway; +use Core\Mod\Commerce\Services\PaymentMethodService; +use Core\Mod\Commerce\Services\PermissionMatrixService; +use Core\Mod\Commerce\Services\ReferralService; +use Core\Mod\Commerce\Services\SkuBuilderService; +use Core\Mod\Commerce\Services\SkuParserService; +use Core\Mod\Commerce\Services\SubscriptionService; +use Core\Mod\Commerce\Services\TaxService; +use Core\Mod\Commerce\Services\UsageBillingService; +use Core\Mod\Commerce\Services\WebhookRateLimiter; use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Route; use Illuminate\Support\ServiceProvider; @@ -46,9 +67,9 @@ class Boot extends ServiceProvider // Laravel event listeners (not lifecycle events) Event::subscribe(ProvisionSocialHostSubscription::class); - Event::listen(\Core\Mod\Commerce\Events\SubscriptionCreated::class, RewardAgentReferralOnSubscription::class); - Event::listen(\Core\Mod\Commerce\Events\SubscriptionRenewed::class, Listeners\ResetUsageOnRenewal::class); - Event::listen(\Core\Mod\Commerce\Events\OrderPaid::class, Listeners\CreateReferralCommission::class); + Event::listen(SubscriptionCreated::class, RewardAgentReferralOnSubscription::class); + Event::listen(SubscriptionRenewed::class, Listeners\ResetUsageOnRenewal::class); + Event::listen(OrderPaid::class, Listeners\CreateReferralCommission::class); } public function register(): void @@ -59,24 +80,24 @@ class Boot extends ServiceProvider ); // Core Services - $this->app->singleton(\Core\Mod\Commerce\Services\CommerceService::class); - $this->app->singleton(\Core\Mod\Commerce\Services\SubscriptionService::class); - $this->app->singleton(\Core\Mod\Commerce\Services\InvoiceService::class); - $this->app->singleton(\Core\Mod\Commerce\Services\PermissionMatrixService::class); - $this->app->singleton(\Core\Mod\Commerce\Services\CouponService::class); - $this->app->singleton(\Core\Mod\Commerce\Services\TaxService::class); - $this->app->singleton(\Core\Mod\Commerce\Services\CurrencyService::class); - $this->app->singleton(\Core\Mod\Commerce\Services\ContentOverrideService::class); - $this->app->singleton(\Core\Mod\Commerce\Services\DunningService::class); - $this->app->singleton(\Core\Mod\Commerce\Services\SkuParserService::class); - $this->app->singleton(\Core\Mod\Commerce\Services\SkuBuilderService::class); - $this->app->singleton(\Core\Mod\Commerce\Services\CreditNoteService::class); - $this->app->singleton(\Core\Mod\Commerce\Services\PaymentMethodService::class); - $this->app->singleton(\Core\Mod\Commerce\Services\UsageBillingService::class); - $this->app->singleton(\Core\Mod\Commerce\Services\ReferralService::class); - $this->app->singleton(\Core\Mod\Commerce\Services\FraudService::class); - $this->app->singleton(\Core\Mod\Commerce\Services\CheckoutRateLimiter::class); - $this->app->singleton(\Core\Mod\Commerce\Services\WebhookRateLimiter::class); + $this->app->singleton(CommerceService::class); + $this->app->singleton(SubscriptionService::class); + $this->app->singleton(InvoiceService::class); + $this->app->singleton(PermissionMatrixService::class); + $this->app->singleton(CouponService::class); + $this->app->singleton(TaxService::class); + $this->app->singleton(CurrencyService::class); + $this->app->singleton(ContentOverrideService::class); + $this->app->singleton(DunningService::class); + $this->app->singleton(SkuParserService::class); + $this->app->singleton(SkuBuilderService::class); + $this->app->singleton(CreditNoteService::class); + $this->app->singleton(PaymentMethodService::class); + $this->app->singleton(UsageBillingService::class); + $this->app->singleton(ReferralService::class); + $this->app->singleton(FraudService::class); + $this->app->singleton(CheckoutRateLimiter::class); + $this->app->singleton(WebhookRateLimiter::class); // Payment Gateways $this->app->singleton('commerce.gateway.btcpay', function ($app) { diff --git a/Console/CleanupExpiredOrders.php b/Console/CleanupExpiredOrders.php index 6b843b5..c06ed7b 100644 --- a/Console/CleanupExpiredOrders.php +++ b/Console/CleanupExpiredOrders.php @@ -1,5 +1,7 @@ copy()->startOfMonth(); $endOfMonth = $date->copy()->endOfMonth(); diff --git a/Console/ProcessDunning.php b/Console/ProcessDunning.php index 85fac5d..ba6d7cc 100644 --- a/Console/ProcessDunning.php +++ b/Console/ProcessDunning.php @@ -1,7 +1,10 @@ info('Stage 5: Expired Subscriptions'); if ($dryRun) { - $count = \Core\Mod\Commerce\Models\Subscription::query() + $count = Subscription::query() ->active() ->whereNotNull('cancelled_at') ->where('current_period_end', '<=', now()) diff --git a/Console/RefreshExchangeRates.php b/Console/RefreshExchangeRates.php index 9dcbb14..c75da5e 100644 --- a/Console/RefreshExchangeRates.php +++ b/Console/RefreshExchangeRates.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Core\Mod\Commerce\Console; +use Core\Mod\Commerce\Models\ExchangeRate; use Core\Mod\Commerce\Services\CurrencyService; use Illuminate\Console\Command; @@ -30,7 +31,7 @@ class RefreshExchangeRates extends Command $this->line("Provider: {$provider}"); // Check if rates need refresh - if (! $this->option('force') && ! \Core\Mod\Commerce\Models\ExchangeRate::needsRefresh()) { + if (! $this->option('force') && ! ExchangeRate::needsRefresh()) { $this->info('Rates are still fresh. Use --force to refresh anyway.'); return self::SUCCESS; diff --git a/Console/SendRenewalReminders.php b/Console/SendRenewalReminders.php index 5b5b3e0..0d5746d 100644 --- a/Console/SendRenewalReminders.php +++ b/Console/SendRenewalReminders.php @@ -1,5 +1,7 @@ json(['error' => 'No workspace found'], 404); } - $entitlements = app(\Core\Tenant\Services\EntitlementService::class); + $entitlements = app(EntitlementService::class); $summary = $entitlements->getUsageSummary($workspace); return response()->json([ diff --git a/Data/CouponValidationResult.php b/Data/CouponValidationResult.php index e7cdc6f..805683e 100644 --- a/Data/CouponValidationResult.php +++ b/Data/CouponValidationResult.php @@ -1,5 +1,7 @@ $duration, 'max_uses' => $maxUses, 'max_uses_per_workspace' => 1, - 'valid_until' => $validUntil ? \Carbon\Carbon::parse($validUntil) : null, + 'valid_until' => $validUntil ? Carbon::parse($validUntil) : null, 'is_active' => true, 'applies_to' => 'all', ]); diff --git a/Mcp/Tools/GetBillingStatus.php b/Mcp/Tools/GetBillingStatus.php index 9ff0041..ede8194 100644 --- a/Mcp/Tools/GetBillingStatus.php +++ b/Mcp/Tools/GetBillingStatus.php @@ -1,5 +1,7 @@ issue_date; } diff --git a/Models/InvoiceItem.php b/Models/InvoiceItem.php index 84f7b2e..5f3fee2 100644 --- a/Models/InvoiceItem.php +++ b/Models/InvoiceItem.php @@ -1,5 +1,7 @@ format($this->total, $this->display_currency); } @@ -301,7 +306,7 @@ class Order extends Model */ public function getFormattedSubtotalAttribute(): string { - $currencyService = app(\Core\Mod\Commerce\Services\CurrencyService::class); + $currencyService = app(CurrencyService::class); return $currencyService->format($this->subtotal, $this->display_currency); } @@ -311,7 +316,7 @@ class Order extends Model */ public function getFormattedTaxAmountAttribute(): string { - $currencyService = app(\Core\Mod\Commerce\Services\CurrencyService::class); + $currencyService = app(CurrencyService::class); return $currencyService->format($this->tax_amount, $this->display_currency); } @@ -321,7 +326,7 @@ class Order extends Model */ public function getFormattedDiscountAmountAttribute(): string { - $currencyService = app(\Core\Mod\Commerce\Services\CurrencyService::class); + $currencyService = app(CurrencyService::class); return $currencyService->format($this->discount_amount, $this->display_currency); } @@ -341,7 +346,7 @@ class Order extends Model return $amount; } - return \Core\Mod\Commerce\Models\ExchangeRate::convert( + return ExchangeRate::convert( $amount, $this->display_currency, $baseCurrency @@ -363,7 +368,7 @@ class Order extends Model return $amount; } - return \Core\Mod\Commerce\Models\ExchangeRate::convert( + return ExchangeRate::convert( $amount, $baseCurrency, $this->display_currency diff --git a/Models/OrderItem.php b/Models/OrderItem.php index 207ff22..d94aa46 100644 --- a/Models/OrderItem.php +++ b/Models/OrderItem.php @@ -1,5 +1,7 @@ exp_year, $this->exp_month)->endOfMonth(); + $expiry = Carbon::createFromDate($this->exp_year, $this->exp_month)->endOfMonth(); return $expiry->isPast(); } diff --git a/Models/PermissionMatrix.php b/Models/PermissionMatrix.php index 9f457a0..d983cf9 100644 --- a/Models/PermissionMatrix.php +++ b/Models/PermissionMatrix.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Core\Mod\Commerce\Models; +use Carbon\Carbon; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -23,7 +24,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; * @property bool $locked * @property string $source * @property int|null $set_by_entity_id - * @property \Carbon\Carbon|null $trained_at + * @property Carbon|null $trained_at * @property string|null $trained_route */ class PermissionMatrix extends Model diff --git a/Models/PermissionRequest.php b/Models/PermissionRequest.php index 1685ab2..ab285b9 100644 --- a/Models/PermissionRequest.php +++ b/Models/PermissionRequest.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Core\Mod\Commerce\Models; +use Carbon\Carbon; use Core\Tenant\Models\User; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -27,7 +28,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; * @property int|null $user_id * @property string $status * @property bool $was_trained - * @property \Carbon\Carbon|null $trained_at + * @property Carbon|null $trained_at */ class PermissionRequest extends Model { diff --git a/Models/Product.php b/Models/Product.php index eb1457c..4e88092 100644 --- a/Models/Product.php +++ b/Models/Product.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace Core\Mod\Commerce\Models; use Core\Mod\Commerce\Concerns\HasContentOverrides; +use Core\Mod\Commerce\Services\CurrencyService; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -287,7 +288,7 @@ class Product extends Model public function formatPrice(int $amount, ?string $currency = null): string { $currency = $currency ?? $this->currency; - $currencyService = app(\Core\Mod\Commerce\Services\CurrencyService::class); + $currencyService = app(CurrencyService::class); return $currencyService->format($amount, $currency, isCents: true); } diff --git a/Models/Referral.php b/Models/Referral.php index e22679a..e7a7fb1 100644 --- a/Models/Referral.php +++ b/Models/Referral.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Core\Mod\Commerce\Models; +use Carbon\Carbon; use Core\Tenant\Models\User; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -30,13 +31,13 @@ use Spatie\Activitylog\Traits\LogsActivity; * @property string|null $ip_address * @property string|null $user_agent * @property string|null $tracking_id - * @property \Carbon\Carbon|null $clicked_at - * @property \Carbon\Carbon|null $signed_up_at - * @property \Carbon\Carbon|null $first_purchase_at - * @property \Carbon\Carbon|null $qualified_at - * @property \Carbon\Carbon|null $disqualified_at + * @property Carbon|null $clicked_at + * @property Carbon|null $signed_up_at + * @property Carbon|null $first_purchase_at + * @property Carbon|null $qualified_at + * @property Carbon|null $disqualified_at * @property string|null $disqualification_reason - * @property \Carbon\Carbon|null $matured_at + * @property Carbon|null $matured_at */ class Referral extends Model { diff --git a/Models/ReferralCode.php b/Models/ReferralCode.php index 2b0effc..eade293 100644 --- a/Models/ReferralCode.php +++ b/Models/ReferralCode.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Core\Mod\Commerce\Models; +use Carbon\Carbon; use Core\Tenant\Models\User; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -24,8 +25,8 @@ use Spatie\Activitylog\Traits\LogsActivity; * @property int $cookie_days * @property int|null $max_uses * @property int $uses_count - * @property \Carbon\Carbon|null $valid_from - * @property \Carbon\Carbon|null $valid_until + * @property Carbon|null $valid_from + * @property Carbon|null $valid_until * @property bool $is_active * @property string|null $campaign_name * @property array|null $metadata diff --git a/Models/ReferralCommission.php b/Models/ReferralCommission.php index e1c4c47..a1445ee 100644 --- a/Models/ReferralCommission.php +++ b/Models/ReferralCommission.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Core\Mod\Commerce\Models; +use Carbon\Carbon; use Core\Tenant\Models\User; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -26,10 +27,10 @@ use Spatie\Activitylog\Traits\LogsActivity; * @property float $commission_amount * @property string $currency * @property string $status - * @property \Carbon\Carbon|null $matures_at - * @property \Carbon\Carbon|null $matured_at + * @property Carbon|null $matures_at + * @property Carbon|null $matured_at * @property int|null $payout_id - * @property \Carbon\Carbon|null $paid_at + * @property Carbon|null $paid_at * @property string|null $notes */ class ReferralCommission extends Model diff --git a/Models/ReferralPayout.php b/Models/ReferralPayout.php index 0f71b2e..d959973 100644 --- a/Models/ReferralPayout.php +++ b/Models/ReferralPayout.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Core\Mod\Commerce\Models; +use Carbon\Carbon; use Core\Tenant\Models\User; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -27,10 +28,10 @@ use Spatie\Activitylog\Traits\LogsActivity; * @property float|null $btc_amount * @property float|null $btc_rate * @property string $status - * @property \Carbon\Carbon|null $requested_at - * @property \Carbon\Carbon|null $processed_at - * @property \Carbon\Carbon|null $completed_at - * @property \Carbon\Carbon|null $failed_at + * @property Carbon|null $requested_at + * @property Carbon|null $processed_at + * @property Carbon|null $completed_at + * @property Carbon|null $failed_at * @property string|null $notes * @property string|null $failure_reason * @property int|null $processed_by diff --git a/Models/Refund.php b/Models/Refund.php index bf0c01e..5aad0e6 100644 --- a/Models/Refund.php +++ b/Models/Refund.php @@ -1,5 +1,7 @@ update(['status' => 'past_due']); } - public function renew(\Carbon\Carbon $periodStart, \Carbon\Carbon $periodEnd): void + public function renew(Carbon $periodStart, Carbon $periodEnd): void { $this->update([ 'status' => 'active', diff --git a/Models/SubscriptionUsage.php b/Models/SubscriptionUsage.php index af006d9..25ddd67 100644 --- a/Models/SubscriptionUsage.php +++ b/Models/SubscriptionUsage.php @@ -1,5 +1,7 @@ get_class($orderable), 'orderable_id' => $orderable->id, - 'user_id' => $orderable instanceof \Core\Tenant\Models\User ? $orderable->id : null, + 'user_id' => $orderable instanceof User ? $orderable->id : null, 'order_number' => Order::generateOrderNumber(), 'status' => 'pending', 'billing_cycle' => $billingCycle, @@ -361,7 +365,7 @@ class CommerceService $order = Order::create([ 'orderable_type' => get_class($orderable), 'orderable_id' => $orderable->id, - 'user_id' => $orderable instanceof \Core\Tenant\Models\User ? $orderable->id : null, + 'user_id' => $orderable instanceof User ? $orderable->id : null, 'order_number' => Order::generateOrderNumber(), 'status' => 'pending', 'billing_cycle' => 'onetime', @@ -437,7 +441,7 @@ class CommerceService } // Provision boosts for user-level orders - if ($order->orderable instanceof \Core\Tenant\Models\User) { + if ($order->orderable instanceof User) { foreach ($order->items as $item) { if ($item->item_type === 'boost') { $quantity = $item->metadata['quantity'] ?? $item->quantity ?? 1; @@ -450,28 +454,28 @@ class CommerceService } // Dispatch OrderPaid event for referral tracking and other listeners - event(new \Core\Mod\Commerce\Events\OrderPaid($order, $payment)); + event(new OrderPaid($order, $payment)); }); } /** * Provision a boost for a user. */ - public function provisionBoostForUser(\Core\Tenant\Models\User $user, string $featureCode, int $quantity = 1, array $metadata = []): \Core\Tenant\Models\Boost + public function provisionBoostForUser(User $user, string $featureCode, int $quantity = 1, array $metadata = []): Boost { // Use ADD_LIMIT for quantity-based boosts, ENABLE for boolean boosts $boostType = $quantity > 1 || $this->isQuantityBasedFeature($featureCode) - ? \Core\Tenant\Models\Boost::BOOST_TYPE_ADD_LIMIT - : \Core\Tenant\Models\Boost::BOOST_TYPE_ENABLE; + ? Boost::BOOST_TYPE_ADD_LIMIT + : Boost::BOOST_TYPE_ENABLE; - return \Core\Tenant\Models\Boost::create([ + return Boost::create([ 'user_id' => $user->id, 'workspace_id' => null, 'feature_code' => $featureCode, 'boost_type' => $boostType, - 'duration_type' => \Core\Tenant\Models\Boost::DURATION_PERMANENT, - 'limit_value' => $boostType === \Core\Tenant\Models\Boost::BOOST_TYPE_ADD_LIMIT ? $quantity : null, - 'status' => \Core\Tenant\Models\Boost::STATUS_ACTIVE, + 'duration_type' => Boost::DURATION_PERMANENT, + 'limit_value' => $boostType === Boost::BOOST_TYPE_ADD_LIMIT ? $quantity : null, + 'status' => Boost::STATUS_ACTIVE, 'starts_at' => now(), 'metadata' => $metadata, ]); @@ -599,7 +603,7 @@ class CommerceService Payment $payment, ?float $amount = null, ?string $reason = null - ): \Core\Mod\Commerce\Models\Refund { + ): Refund { $amountCents = $amount ? (int) ($amount * 100) : (int) (($payment->amount - $payment->amount_refunded) * 100); @@ -660,7 +664,7 @@ class CommerceService // For BTCPay, payment will be 'pending' as it requires customer action // This is expected - automatic retry won't work for crypto payments if ($payment->status === 'pending' && $paymentMethod->gateway === 'btcpay') { - \Illuminate\Support\Facades\Log::info('BTCPay invoice created for retry - requires customer payment', [ + Log::info('BTCPay invoice created for retry - requires customer payment', [ 'invoice_id' => $invoice->id, 'payment_id' => $payment->id, ]); @@ -668,7 +672,7 @@ class CommerceService return false; } catch (\Exception $e) { - \Illuminate\Support\Facades\Log::error('Invoice payment retry failed', [ + Log::error('Invoice payment retry failed', [ 'invoice_id' => $invoice->id, 'error' => $e->getMessage(), ]); diff --git a/Services/CouponService.php b/Services/CouponService.php index 6a94f2b..45f3ecc 100644 --- a/Services/CouponService.php +++ b/Services/CouponService.php @@ -11,6 +11,7 @@ use Core\Mod\Commerce\Models\CouponUsage; use Core\Mod\Commerce\Models\Order; use Core\Tenant\Models\Package; use Core\Tenant\Models\Workspace; +use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Model; /** @@ -217,7 +218,7 @@ class CouponService /** * Get usage history for a coupon. */ - public function getUsageHistory(Coupon $coupon, int $limit = 50): \Illuminate\Database\Eloquent\Collection + public function getUsageHistory(Coupon $coupon, int $limit = 50): Collection { return $coupon->usages() ->with(['workspace', 'order']) diff --git a/Services/CreditNoteService.php b/Services/CreditNoteService.php index 6f30743..96ef936 100644 --- a/Services/CreditNoteService.php +++ b/Services/CreditNoteService.php @@ -1,5 +1,7 @@ getPdf($invoice); @@ -219,7 +224,7 @@ class InvoiceService /** * Get invoices for a workspace. */ - public function getForWorkspace(Workspace $workspace, int $limit = 25): \Illuminate\Pagination\LengthAwarePaginator + public function getForWorkspace(Workspace $workspace, int $limit = 25): LengthAwarePaginator { return $workspace->invoices() ->with('items') @@ -230,7 +235,7 @@ class InvoiceService /** * Get unpaid invoices for a workspace. */ - public function getUnpaidForWorkspace(Workspace $workspace): \Illuminate\Database\Eloquent\Collection + public function getUnpaidForWorkspace(Workspace $workspace): Collection { return $workspace->invoices() ->pending() @@ -241,7 +246,7 @@ class InvoiceService /** * Get overdue invoices for a workspace. */ - public function getOverdueForWorkspace(Workspace $workspace): \Illuminate\Database\Eloquent\Collection + public function getOverdueForWorkspace(Workspace $workspace): Collection { return $workspace->invoices() ->pending() diff --git a/Services/PaymentGateway/BTCPayGateway.php b/Services/PaymentGateway/BTCPayGateway.php index 5104927..bcc5482 100644 --- a/Services/PaymentGateway/BTCPayGateway.php +++ b/Services/PaymentGateway/BTCPayGateway.php @@ -10,6 +10,7 @@ use Core\Mod\Commerce\Models\Payment; use Core\Mod\Commerce\Models\PaymentMethod; use Core\Mod\Commerce\Models\Subscription; use Core\Tenant\Models\Workspace; +use Illuminate\Http\Client\Response; use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Log; use Illuminate\Support\Str; @@ -633,7 +634,7 @@ class BTCPayGateway implements PaymentGatewayContract /** * Extract a safe error message from a failed response. */ - protected function sanitiseErrorMessage(\Illuminate\Http\Client\Response $response): string + protected function sanitiseErrorMessage(Response $response): string { $json = $response->json(); diff --git a/Services/PaymentGateway/PaymentGatewayContract.php b/Services/PaymentGateway/PaymentGatewayContract.php index 03509ef..8177ae1 100644 --- a/Services/PaymentGateway/PaymentGatewayContract.php +++ b/Services/PaymentGateway/PaymentGatewayContract.php @@ -1,5 +1,7 @@ $session->id, 'checkout_url' => $session->url, ]; - } catch (\Stripe\Exception\CardException $e) { + } catch (CardException $e) { Log::warning('Stripe checkout failed: card error', [ 'order_id' => $order->id, 'error' => $e->getMessage(), 'code' => $e->getStripeCode(), ]); throw new \RuntimeException('Payment card error: '.$e->getMessage(), 0, $e); - } catch (\Stripe\Exception\RateLimitException $e) { + } catch (RateLimitException $e) { Log::error('Stripe checkout failed: rate limit', [ 'order_id' => $order->id, ]); throw new \RuntimeException('Payment service temporarily unavailable. Please try again.', 0, $e); - } catch (\Stripe\Exception\InvalidRequestException $e) { + } catch (InvalidRequestException $e) { Log::error('Stripe checkout failed: invalid request', [ 'order_id' => $order->id, 'error' => $e->getMessage(), 'param' => $e->getStripeParam(), ]); throw new \RuntimeException('Unable to create checkout session. Please contact support.', 0, $e); - } catch (\Stripe\Exception\AuthenticationException $e) { + } catch (AuthenticationException $e) { Log::critical('Stripe authentication failed - check API keys', [ 'order_id' => $order->id, ]); throw new \RuntimeException('Payment service configuration error. Please contact support.', 0, $e); - } catch (\Stripe\Exception\ApiConnectionException $e) { + } catch (ApiConnectionException $e) { Log::error('Stripe checkout failed: connection error', [ 'order_id' => $order->id, ]); throw new \RuntimeException('Unable to connect to payment service. Please try again.', 0, $e); - } catch (\Stripe\Exception\ApiErrorException $e) { + } catch (ApiErrorException $e) { Log::error('Stripe checkout failed: API error', [ 'order_id' => $order->id, 'error' => $e->getMessage(), @@ -338,10 +348,10 @@ class StripeGateway implements PaymentGatewayContract 'gateway_customer_id' => $customerId, 'gateway_price_id' => $priceId, 'status' => $this->mapSubscriptionStatus($stripeSubscription->status), - 'current_period_start' => \Carbon\Carbon::createFromTimestamp($stripeSubscription->current_period_start), - 'current_period_end' => \Carbon\Carbon::createFromTimestamp($stripeSubscription->current_period_end), + 'current_period_start' => Carbon::createFromTimestamp($stripeSubscription->current_period_start), + 'current_period_end' => Carbon::createFromTimestamp($stripeSubscription->current_period_end), 'trial_ends_at' => $stripeSubscription->trial_end - ? \Carbon\Carbon::createFromTimestamp($stripeSubscription->trial_end) + ? Carbon::createFromTimestamp($stripeSubscription->trial_end) : null, 'metadata' => ['stripe_subscription' => $stripeSubscription->toArray()], ]); @@ -376,8 +386,8 @@ class StripeGateway implements PaymentGatewayContract 'gateway_price_id' => $options['price_id'] ?? $subscription->gateway_price_id, 'status' => $this->mapSubscriptionStatus($stripeSubscription->status), 'cancel_at_period_end' => $stripeSubscription->cancel_at_period_end, - 'current_period_start' => \Carbon\Carbon::createFromTimestamp($stripeSubscription->current_period_start), - 'current_period_end' => \Carbon\Carbon::createFromTimestamp($stripeSubscription->current_period_end), + 'current_period_start' => Carbon::createFromTimestamp($stripeSubscription->current_period_start), + 'current_period_end' => Carbon::createFromTimestamp($stripeSubscription->current_period_end), ]); return $subscription->fresh(); @@ -544,7 +554,7 @@ class StripeGateway implements PaymentGatewayContract public function verifyWebhookSignature(string $payload, string $signature): bool { try { - \Stripe\Webhook::constructEvent($payload, $signature, $this->webhookSecret); + Webhook::constructEvent($payload, $signature, $this->webhookSecret); return true; } catch (\Exception $e) { diff --git a/Services/PaymentMethodService.php b/Services/PaymentMethodService.php index 172f10c..e6bc412 100644 --- a/Services/PaymentMethodService.php +++ b/Services/PaymentMethodService.php @@ -1,7 +1,10 @@ exp_year, $paymentMethod->exp_month )->endOfMonth(); diff --git a/Services/ProrationResult.php b/Services/ProrationResult.php index 662afb7..a66633a 100644 --- a/Services/ProrationResult.php +++ b/Services/ProrationResult.php @@ -1,5 +1,7 @@ refunds()->latest()->get(); } @@ -168,7 +171,7 @@ class RefundService /** * Get all refunds for a workspace. */ - public function getRefundsForWorkspace(int $workspaceId): \Illuminate\Database\Eloquent\Collection + public function getRefundsForWorkspace(int $workspaceId): Collection { return Refund::query() ->whereHas('payment', function ($query) use ($workspaceId) { diff --git a/Services/SubscriptionService.php b/Services/SubscriptionService.php index eba812e..aecfffa 100644 --- a/Services/SubscriptionService.php +++ b/Services/SubscriptionService.php @@ -1,5 +1,7 @@ active() @@ -428,7 +431,7 @@ class SubscriptionService /** * Get subscriptions that have failed payment and need dunning. */ - public function getFailedPayments(): \Illuminate\Database\Eloquent\Collection + public function getFailedPayments(): Collection { return Subscription::query() ->where('status', 'past_due') diff --git a/Services/TaxService.php b/Services/TaxService.php index e8b9a9a..ec78b71 100644 --- a/Services/TaxService.php +++ b/Services/TaxService.php @@ -1,5 +1,7 @@ subscriptions->retrieve( @@ -417,7 +420,7 @@ class UsageBillingService return null; } - $stripe = new \Stripe\StripeClient($secret); + $stripe = new StripeClient($secret); // Create or update product in Stripe $product = $stripe->products->create([ diff --git a/Services/WebhookLogger.php b/Services/WebhookLogger.php index 93f99b8..916a67c 100644 --- a/Services/WebhookLogger.php +++ b/Services/WebhookLogger.php @@ -7,6 +7,7 @@ namespace Core\Mod\Commerce\Services; use Core\Mod\Commerce\Models\Order; use Core\Mod\Commerce\Models\Subscription; use Core\Mod\Commerce\Models\WebhookEvent; +use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\QueryException; use Illuminate\Http\Request; use Illuminate\Http\Response; @@ -311,7 +312,7 @@ class WebhookLogger /** * Get recent failed events for debugging. */ - public function getRecentFailures(string $gateway, int $limit = 10): \Illuminate\Database\Eloquent\Collection + public function getRecentFailures(string $gateway, int $limit = 10): Collection { return WebhookEvent::forGateway($gateway) ->failed() diff --git a/View/Modal/Admin/CouponManager.php b/View/Modal/Admin/CouponManager.php index bae5c74..ad9122a 100644 --- a/View/Modal/Admin/CouponManager.php +++ b/View/Modal/Admin/CouponManager.php @@ -4,9 +4,11 @@ declare(strict_types=1); namespace Core\Mod\Commerce\View\Modal\Admin; +use Carbon\Carbon; use Core\Mod\Commerce\Models\Coupon; use Core\Mod\Commerce\Services\CouponService; use Core\Tenant\Models\Package; +use Illuminate\Support\Str; use Livewire\Attributes\Computed; use Livewire\Attributes\Layout; use Livewire\Attributes\Title; @@ -334,8 +336,8 @@ class CouponManager extends Component 'max_uses_per_workspace' => $this->bulk_max_uses_per_workspace, 'duration' => $this->bulk_duration, 'duration_months' => $this->bulk_duration === 'repeating' ? $this->bulk_duration_months : null, - 'valid_from' => $this->bulk_valid_from ? \Carbon\Carbon::parse($this->bulk_valid_from) : null, - 'valid_until' => $this->bulk_valid_until ? \Carbon\Carbon::parse($this->bulk_valid_until) : null, + 'valid_from' => $this->bulk_valid_from ? Carbon::parse($this->bulk_valid_from) : null, + 'valid_until' => $this->bulk_valid_until ? Carbon::parse($this->bulk_valid_until) : null, 'is_active' => $this->bulk_is_active, ]; @@ -399,8 +401,8 @@ class CouponManager extends Component 'max_uses_per_workspace' => $this->max_uses_per_workspace, 'duration' => $this->duration, 'duration_months' => $this->duration === 'repeating' ? $this->duration_months : null, - 'valid_from' => $this->valid_from ? \Carbon\Carbon::parse($this->valid_from) : null, - 'valid_until' => $this->valid_until ? \Carbon\Carbon::parse($this->valid_until) : null, + 'valid_from' => $this->valid_from ? Carbon::parse($this->valid_from) : null, + 'valid_until' => $this->valid_until ? Carbon::parse($this->valid_until) : null, 'is_active' => $this->is_active, ]; @@ -587,7 +589,7 @@ class CouponManager extends Component [ 'lines' => array_filter([ ['bold' => $c->name], - $c->description ? ['muted' => \Illuminate\Support\Str::limit($c->description, 30)] : null, + $c->description ? ['muted' => Str::limit($c->description, 30)] : null, ]), ], ['lines' => $discountLines], diff --git a/View/Modal/Admin/Dashboard.php b/View/Modal/Admin/Dashboard.php index 662598d..1432ad6 100644 --- a/View/Modal/Admin/Dashboard.php +++ b/View/Modal/Admin/Dashboard.php @@ -8,6 +8,7 @@ use Core\Mod\Commerce\Models\Coupon; use Core\Mod\Commerce\Models\Order; use Core\Mod\Commerce\Models\Subscription; use Illuminate\Contracts\View\View; +use Illuminate\Database\Eloquent\Collection; use Illuminate\Support\Facades\DB; use Livewire\Attributes\Computed; use Livewire\Attributes\Title; @@ -42,7 +43,7 @@ class Dashboard extends Component } #[Computed] - public function recentOrders(): \Illuminate\Database\Eloquent\Collection + public function recentOrders(): Collection { return Order::with('workspace') ->latest() diff --git a/View/Modal/Admin/ReferralManager.php b/View/Modal/Admin/ReferralManager.php index efd90b5..5a19f8b 100644 --- a/View/Modal/Admin/ReferralManager.php +++ b/View/Modal/Admin/ReferralManager.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Core\Mod\Commerce\View\Modal\Admin; +use Carbon\Carbon; use Core\Mod\Commerce\Models\Referral; use Core\Mod\Commerce\Models\ReferralCode; use Core\Mod\Commerce\Models\ReferralCommission; @@ -309,8 +310,8 @@ class ReferralManager extends Component 'commission_rate' => $this->codeCommissionRate, 'cookie_days' => $this->codeCookieDays, 'max_uses' => $this->codeMaxUses, - 'valid_from' => $this->codeValidFrom ? \Carbon\Carbon::parse($this->codeValidFrom) : null, - 'valid_until' => $this->codeValidUntil ? \Carbon\Carbon::parse($this->codeValidUntil) : null, + 'valid_from' => $this->codeValidFrom ? Carbon::parse($this->codeValidFrom) : null, + 'valid_until' => $this->codeValidUntil ? Carbon::parse($this->codeValidUntil) : null, 'is_active' => $this->codeIsActive, 'campaign_name' => $this->codeCampaignName, ]; diff --git a/View/Modal/Admin/SubscriptionManager.php b/View/Modal/Admin/SubscriptionManager.php index 1811a0e..9247d7a 100644 --- a/View/Modal/Admin/SubscriptionManager.php +++ b/View/Modal/Admin/SubscriptionManager.php @@ -7,6 +7,7 @@ namespace Core\Mod\Commerce\View\Modal\Admin; use Core\Mod\Commerce\Models\Subscription; use Core\Mod\Commerce\Services\SubscriptionService; use Core\Tenant\Models\Workspace; +use Illuminate\Support\Facades\DB; use Livewire\Attributes\Computed; use Livewire\Attributes\Title; use Livewire\Component; @@ -150,7 +151,7 @@ class SubscriptionManager extends Component $count = Subscription::whereIn('id', $this->selected) ->whereNotNull('current_period_end') ->update([ - 'current_period_end' => \Illuminate\Support\Facades\DB::raw('DATE_ADD(current_period_end, INTERVAL 30 DAY)'), + 'current_period_end' => DB::raw('DATE_ADD(current_period_end, INTERVAL 30 DAY)'), ]); session()->flash('message', __('commerce::commerce.bulk.period_extended', ['count' => $count, 'days' => 30])); diff --git a/View/Modal/Web/ChangePlan.php b/View/Modal/Web/ChangePlan.php index 5e9ed63..e45278c 100644 --- a/View/Modal/Web/ChangePlan.php +++ b/View/Modal/Web/ChangePlan.php @@ -1,5 +1,7 @@ displayCurrency = $currency; @@ -181,7 +185,7 @@ class CheckoutPage extends Component } #[Computed] - public function packages(): \Illuminate\Database\Eloquent\Collection + public function packages(): Collection { return Package::active() ->public() diff --git a/View/Modal/Web/CheckoutSuccess.php b/View/Modal/Web/CheckoutSuccess.php index 0b925ce..615a7d0 100644 --- a/View/Modal/Web/CheckoutSuccess.php +++ b/View/Modal/Web/CheckoutSuccess.php @@ -1,5 +1,7 @@ notify(new SubscriptionCancelled($this->activeSubscription)); } diff --git a/View/Modal/Web/UsageDashboard.php b/View/Modal/Web/UsageDashboard.php index d140887..1cc9217 100644 --- a/View/Modal/Web/UsageDashboard.php +++ b/View/Modal/Web/UsageDashboard.php @@ -1,5 +1,7 @@ name('hub.billing.')->group(function () { - Route::get('/', \Core\Mod\Commerce\View\Modal\Web\Dashboard::class)->name('index'); - Route::get('/invoices', \Core\Mod\Commerce\View\Modal\Web\Invoices::class)->name('invoices'); - Route::get('/invoices/{invoice}/pdf', [\Core\Mod\Commerce\Controllers\InvoiceController::class, 'pdf'])->name('invoices.pdf'); - Route::get('/invoices/{invoice}/view', [\Core\Mod\Commerce\Controllers\InvoiceController::class, 'view'])->name('invoices.view'); - Route::get('/payment-methods', \Core\Mod\Commerce\View\Modal\Web\PaymentMethods::class)->name('payment-methods'); - Route::get('/subscription', \Core\Mod\Commerce\View\Modal\Web\Subscription::class)->name('subscription'); - Route::get('/change-plan', \Core\Mod\Commerce\View\Modal\Web\ChangePlan::class)->name('change-plan'); - Route::get('/affiliates', \Core\Mod\Commerce\View\Modal\Web\ReferralDashboard::class)->name('affiliates'); + Route::get('/', Dashboard::class)->name('index'); + Route::get('/invoices', Invoices::class)->name('invoices'); + Route::get('/invoices/{invoice}/pdf', [InvoiceController::class, 'pdf'])->name('invoices.pdf'); + Route::get('/invoices/{invoice}/view', [InvoiceController::class, 'view'])->name('invoices.view'); + Route::get('/payment-methods', PaymentMethods::class)->name('payment-methods'); + Route::get('/subscription', Subscription::class)->name('subscription'); + Route::get('/change-plan', ChangePlan::class)->name('change-plan'); + Route::get('/affiliates', ReferralDashboard::class)->name('affiliates'); }); // Commerce management (admin only - Hades tier) Route::prefix('hub/commerce')->name('hub.commerce.')->group(function () { - Route::get('/', \Core\Mod\Commerce\View\Modal\Admin\Dashboard::class)->name('dashboard'); - Route::get('/orders', \Core\Mod\Commerce\View\Modal\Admin\OrderManager::class)->name('orders'); - Route::get('/subscriptions', \Core\Mod\Commerce\View\Modal\Admin\SubscriptionManager::class)->name('subscriptions'); - Route::get('/coupons', \Core\Mod\Commerce\View\Modal\Admin\CouponManager::class)->name('coupons'); - Route::get('/entities', \Core\Mod\Commerce\View\Modal\Admin\EntityManager::class)->name('entities'); - Route::get('/permissions', \Core\Mod\Commerce\View\Modal\Admin\PermissionMatrixManager::class)->name('permissions'); - Route::get('/products', \Core\Mod\Commerce\View\Modal\Admin\ProductManager::class)->name('products'); - Route::get('/credit-notes', \Core\Mod\Commerce\View\Modal\Admin\CreditNoteManager::class)->name('credit-notes'); - Route::get('/referrals', \Core\Mod\Commerce\View\Modal\Admin\ReferralManager::class)->name('referrals'); + Route::get('/', Core\Mod\Commerce\View\Modal\Admin\Dashboard::class)->name('dashboard'); + Route::get('/orders', OrderManager::class)->name('orders'); + Route::get('/subscriptions', SubscriptionManager::class)->name('subscriptions'); + Route::get('/coupons', CouponManager::class)->name('coupons'); + Route::get('/entities', EntityManager::class)->name('entities'); + Route::get('/permissions', PermissionMatrixManager::class)->name('permissions'); + Route::get('/products', ProductManager::class)->name('products'); + Route::get('/credit-notes', CreditNoteManager::class)->name('credit-notes'); + Route::get('/referrals', ReferralManager::class)->name('referrals'); }); diff --git a/routes/console.php b/routes/console.php index d6f3c8b..ca1bbfa 100644 --- a/routes/console.php +++ b/routes/console.php @@ -1,3 +1,5 @@ user = User::factory()->create(); diff --git a/tests/Feature/DunningServiceTest.php b/tests/Feature/DunningServiceTest.php index c77f700..b460192 100644 --- a/tests/Feature/DunningServiceTest.php +++ b/tests/Feature/DunningServiceTest.php @@ -1,5 +1,7 @@ shouldReceive('refund')->andReturn([ 'success' => true, 'refund_id' => 're_test_123', @@ -92,15 +96,15 @@ describe('RefundService', function () { it('throws exception for refund exceeding available amount', function () { expect(fn () => $this->service->refund($this->payment, 150.00)) - ->toThrow(\InvalidArgumentException::class, 'exceeds maximum refundable'); + ->toThrow(InvalidArgumentException::class, 'exceeds maximum refundable'); }); it('throws exception for zero or negative amount', function () { expect(fn () => $this->service->refund($this->payment, 0)) - ->toThrow(\InvalidArgumentException::class, 'greater than zero'); + ->toThrow(InvalidArgumentException::class, 'greater than zero'); expect(fn () => $this->service->refund($this->payment, -50.00)) - ->toThrow(\InvalidArgumentException::class, 'greater than zero'); + ->toThrow(InvalidArgumentException::class, 'greater than zero'); }); it('throws exception for non-succeeded payments', function () { @@ -114,7 +118,7 @@ describe('RefundService', function () { ]); expect(fn () => $this->service->refund($pendingPayment, 50.00)) - ->toThrow(\InvalidArgumentException::class, 'only refund successful payments'); + ->toThrow(InvalidArgumentException::class, 'only refund successful payments'); }); it('allows multiple partial refunds up to full amount', function () { diff --git a/tests/Feature/SubscriptionServiceTest.php b/tests/Feature/SubscriptionServiceTest.php index 03133b9..aa228f6 100644 --- a/tests/Feature/SubscriptionServiceTest.php +++ b/tests/Feature/SubscriptionServiceTest.php @@ -1,5 +1,7 @@ subscription->workspacePackage->setRelation('package', null); expect(fn () => $this->service->previewPlanChange($this->subscription, $this->agencyPackage)) - ->toThrow(\InvalidArgumentException::class, 'no current package'); + ->toThrow(InvalidArgumentException::class, 'no current package'); }); }); diff --git a/tests/Feature/TaxServiceTest.php b/tests/Feature/TaxServiceTest.php index d3af65c..c99fd9b 100644 --- a/tests/Feature/TaxServiceTest.php +++ b/tests/Feature/TaxServiceTest.php @@ -1,10 +1,13 @@ workspace = Workspace::factory()->create([ diff --git a/tests/Feature/WebhookRateLimitTest.php b/tests/Feature/WebhookRateLimitTest.php index d65ffb1..59febef 100644 --- a/tests/Feature/WebhookRateLimitTest.php +++ b/tests/Feature/WebhookRateLimitTest.php @@ -4,9 +4,10 @@ declare(strict_types=1); use Core\Mod\Commerce\Services\WebhookRateLimiter; use Illuminate\Cache\RateLimiter; +use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Http\Request; -uses(\Illuminate\Foundation\Testing\RefreshDatabase::class); +uses(RefreshDatabase::class); // ============================================================================ // WebhookRateLimiter Unit Tests diff --git a/tests/Feature/WebhookTest.php b/tests/Feature/WebhookTest.php index 6bf8ba2..07fce79 100644 --- a/tests/Feature/WebhookTest.php +++ b/tests/Feature/WebhookTest.php @@ -1,5 +1,7 @@ headers->set('Stripe-Signature', 't=123,v1=abc'); $response = $controller->handle($request); @@ -177,7 +181,7 @@ describe('StripeWebhookController', function () { $webhookLogger ); - $request = new \Illuminate\Http\Request; + $request = new Request; $response = $controller->handle($request); expect($response->getStatusCode())->toBe(200) @@ -213,7 +217,7 @@ describe('StripeWebhookController', function () { $webhookLogger ); - $request = new \Illuminate\Http\Request; + $request = new Request; $response = $controller->handle($request); expect($response->getStatusCode())->toBe(200) @@ -270,7 +274,7 @@ describe('StripeWebhookController', function () { $webhookLogger ); - $request = new \Illuminate\Http\Request; + $request = new Request; $response = $controller->handle($request); expect($response->getStatusCode())->toBe(200); @@ -332,7 +336,7 @@ describe('StripeWebhookController', function () { $webhookLogger ); - $request = new \Illuminate\Http\Request; + $request = new Request; $response = $controller->handle($request); expect($response->getStatusCode())->toBe(200); @@ -368,7 +372,7 @@ describe('StripeWebhookController', function () { $webhookLogger ); - $request = new \Illuminate\Http\Request; + $request = new Request; $response = $controller->handle($request); expect($response->getStatusCode())->toBe(200) @@ -460,7 +464,7 @@ describe('BTCPayWebhookController', function () { $controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger); - $request = new \Illuminate\Http\Request; + $request = new Request; $request->headers->set('BTCPay-Sig', 'valid_signature'); $response = $controller->handle($request); @@ -500,7 +504,7 @@ describe('BTCPayWebhookController', function () { $controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger); - $request = new \Illuminate\Http\Request; + $request = new Request; $response = $controller->handle($request); expect($response->getStatusCode())->toBe(200) @@ -523,7 +527,7 @@ describe('BTCPayWebhookController', function () { $controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger); - $request = new \Illuminate\Http\Request; + $request = new Request; $response = $controller->handle($request); expect($response->getStatusCode())->toBe(200) @@ -548,7 +552,7 @@ describe('BTCPayWebhookController', function () { $controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger); - $request = new \Illuminate\Http\Request; + $request = new Request; $response = $controller->handle($request); expect($response->getStatusCode())->toBe(200); @@ -575,7 +579,7 @@ describe('BTCPayWebhookController', function () { $controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger); - $request = new \Illuminate\Http\Request; + $request = new Request; $response = $controller->handle($request); expect($response->getStatusCode())->toBe(200); @@ -602,7 +606,7 @@ describe('BTCPayWebhookController', function () { $controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger); - $request = new \Illuminate\Http\Request; + $request = new Request; $response = $controller->handle($request); expect($response->getStatusCode())->toBe(200); @@ -629,7 +633,7 @@ describe('BTCPayWebhookController', function () { $controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger); - $request = new \Illuminate\Http\Request; + $request = new Request; $response = $controller->handle($request); expect($response->getStatusCode())->toBe(200); @@ -656,7 +660,7 @@ describe('BTCPayWebhookController', function () { $controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger); - $request = new \Illuminate\Http\Request; + $request = new Request; $response = $controller->handle($request); expect($response->getStatusCode())->toBe(200); @@ -683,7 +687,7 @@ describe('BTCPayWebhookController', function () { $controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger); - $request = new \Illuminate\Http\Request; + $request = new Request; $response = $controller->handle($request); expect($response->getStatusCode())->toBe(200) @@ -840,7 +844,7 @@ describe('WebhookLogger service', function () { it('extracts relevant headers', function () { $logger = new WebhookLogger; - $request = new \Illuminate\Http\Request; + $request = new Request; $request->headers->set('Stripe-Signature', 't=123,v1=secret_signature_here'); $request->headers->set('Content-Type', 'application/json'); $request->headers->set('User-Agent', 'Stripe/1.0'); @@ -1235,7 +1239,7 @@ describe('BTCPayWebhookController payload validation integration', function () { $webhookLogger = new WebhookLogger; $controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger); - $request = new \Illuminate\Http\Request; + $request = new Request; $request->headers->set('BTCPay-Sig', 'valid_signature'); $response = $controller->handle($request); @@ -1262,7 +1266,7 @@ describe('BTCPayWebhookController payload validation integration', function () { $controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger); - $request = new \Illuminate\Http\Request; + $request = new Request; $response = $controller->handle($request); expect($response->getStatusCode())->toBe(400) @@ -1282,7 +1286,7 @@ describe('BTCPayWebhookController payload validation integration', function () { $controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger); - $request = new \Illuminate\Http\Request; + $request = new Request; $response = $controller->handle($request); expect($response->getStatusCode())->toBe(400) @@ -1313,7 +1317,7 @@ describe('BTCPayWebhookController payload validation integration', function () { $webhookLogger = new WebhookLogger; $controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger); - $request = new \Illuminate\Http\Request; + $request = new Request; $response = $controller->handle($request); expect($response->getStatusCode())->toBe(200); @@ -1388,7 +1392,7 @@ describe('Webhook Idempotency (Replay Attack Protection)', function () { $webhookLogger = new WebhookLogger; $controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger); - $request = new \Illuminate\Http\Request; + $request = new Request; $response = $controller->handle($request); expect($response->getStatusCode())->toBe(200) @@ -1423,7 +1427,7 @@ describe('Webhook Idempotency (Replay Attack Protection)', function () { $controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger); // First request - should process - $request1 = new \Illuminate\Http\Request; + $request1 = new Request; $response1 = $controller->handle($request1); expect($response1->getStatusCode())->toBe(200); @@ -1437,7 +1441,7 @@ describe('Webhook Idempotency (Replay Attack Protection)', function () { // Second request with same event ID - should be rejected as duplicate $webhookLogger2 = new WebhookLogger; $controller2 = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger2); - $request2 = new \Illuminate\Http\Request; + $request2 = new Request; $response2 = $controller2->handle($request2); expect($response2->getStatusCode())->toBe(200) @@ -1517,7 +1521,7 @@ describe('Webhook Idempotency (Replay Attack Protection)', function () { $webhookLogger ); - $request = new \Illuminate\Http\Request; + $request = new Request; $response = $controller->handle($request); expect($response->getStatusCode())->toBe(200) @@ -1574,7 +1578,7 @@ describe('BTCPay Payment Amount Verification', function () { $webhookLogger = new WebhookLogger; $controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger); - $request = new \Illuminate\Http\Request; + $request = new Request; $response = $controller->handle($request); expect($response->getStatusCode())->toBe(200); @@ -1610,7 +1614,7 @@ describe('BTCPay Payment Amount Verification', function () { $webhookLogger = new WebhookLogger; $controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger); - $request = new \Illuminate\Http\Request; + $request = new Request; $response = $controller->handle($request); expect($response->getStatusCode())->toBe(200) @@ -1653,7 +1657,7 @@ describe('BTCPay Payment Amount Verification', function () { $webhookLogger = new WebhookLogger; $controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger); - $request = new \Illuminate\Http\Request; + $request = new Request; $response = $controller->handle($request); expect($response->getStatusCode())->toBe(200); @@ -1690,7 +1694,7 @@ describe('BTCPay Payment Amount Verification', function () { $webhookLogger = new WebhookLogger; $controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger); - $request = new \Illuminate\Http\Request; + $request = new Request; $response = $controller->handle($request); expect($response->getStatusCode())->toBe(200) @@ -1727,7 +1731,7 @@ describe('BTCPay Payment Amount Verification', function () { $webhookLogger = new WebhookLogger; $controller = new BTCPayWebhookController($mockGateway, $mockCommerce, $webhookLogger); - $request = new \Illuminate\Http\Request; + $request = new Request; $response = $controller->handle($request); expect($response->getStatusCode())->toBe(200); diff --git a/tests/TestCase.php b/tests/TestCase.php index 5ea3e2f..37fe149 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Tests; +use Core\Mod\Commerce\Boot; use Orchestra\Testbench\TestCase as BaseTestCase; abstract class TestCase extends BaseTestCase @@ -11,7 +12,7 @@ abstract class TestCase extends BaseTestCase protected function getPackageProviders($app): array { return [ - \Core\Mod\Commerce\Boot::class, + Boot::class, ]; } } diff --git a/tests/UseCase/AdminCrudBasic.php b/tests/UseCase/AdminCrudBasic.php index a6dad0a..2eee953 100644 --- a/tests/UseCase/AdminCrudBasic.php +++ b/tests/UseCase/AdminCrudBasic.php @@ -1,5 +1,7 @@