checkout_id direkt an das Backend, damit der Server die Session via Paddle‑API finalisiert (auch wenn der Webhook nicht greift). Dadurch sollte “Zahlung wird verarbeitet” nicht mehr hängen bleiben.
192 lines
6.0 KiB
PHP
192 lines
6.0 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature\Checkout;
|
|
|
|
use App\Models\CheckoutSession;
|
|
use App\Models\Package;
|
|
use App\Models\Tenant;
|
|
use App\Models\User;
|
|
use App\Services\Checkout\CheckoutSessionService;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Facades\Http;
|
|
use Illuminate\Support\Facades\Mail;
|
|
use Illuminate\Support\Facades\Notification;
|
|
use Tests\TestCase;
|
|
|
|
class CheckoutSessionStatusTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
public function test_user_can_fetch_checkout_session_status(): void
|
|
{
|
|
$tenant = Tenant::factory()->create();
|
|
$user = User::factory()->for($tenant)->create();
|
|
$package = Package::factory()->create();
|
|
|
|
/** @var CheckoutSessionService $sessions */
|
|
$sessions = app(CheckoutSessionService::class);
|
|
$session = $sessions->createOrResume($user, $package, [
|
|
'tenant' => $tenant,
|
|
]);
|
|
$sessions->markCompleted($session, now());
|
|
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->getJson(route('checkout.session.status', $session));
|
|
|
|
$response->assertOk()
|
|
->assertJsonPath('status', CheckoutSession::STATUS_COMPLETED);
|
|
}
|
|
|
|
public function test_user_cannot_fetch_other_users_checkout_session_status(): void
|
|
{
|
|
$tenant = Tenant::factory()->create();
|
|
$owner = User::factory()->for($tenant)->create();
|
|
$otherUser = User::factory()->create();
|
|
$package = Package::factory()->create();
|
|
|
|
/** @var CheckoutSessionService $sessions */
|
|
$sessions = app(CheckoutSessionService::class);
|
|
$session = $sessions->createOrResume($owner, $package, [
|
|
'tenant' => $tenant,
|
|
]);
|
|
|
|
$this->actingAs($otherUser);
|
|
|
|
$response = $this->getJson(route('checkout.session.status', $session));
|
|
|
|
$response->assertForbidden();
|
|
}
|
|
|
|
public function test_session_status_recovers_completed_paddle_transaction(): void
|
|
{
|
|
$tenant = Tenant::factory()->create();
|
|
$user = User::factory()->for($tenant)->create([
|
|
'pending_purchase' => true,
|
|
]);
|
|
$package = Package::factory()->create([
|
|
'type' => 'endcustomer',
|
|
'price' => 99,
|
|
]);
|
|
|
|
/** @var CheckoutSessionService $sessions */
|
|
$sessions = app(CheckoutSessionService::class);
|
|
$session = $sessions->createOrResume($user, $package, [
|
|
'tenant' => $tenant,
|
|
]);
|
|
$sessions->selectProvider($session, CheckoutSession::PROVIDER_PADDLE);
|
|
$session->forceFill([
|
|
'provider_metadata' => [
|
|
'paddle_checkout_id' => 'chk_123',
|
|
],
|
|
])->save();
|
|
|
|
config()->set([
|
|
'paddle.api_key' => 'test-key',
|
|
'paddle.base_url' => 'https://paddle.test',
|
|
'paddle.environment' => 'sandbox',
|
|
]);
|
|
|
|
Http::fake([
|
|
'https://paddle.test/*' => Http::response([
|
|
'data' => [
|
|
[
|
|
'id' => 'txn_123',
|
|
'status' => 'completed',
|
|
'details' => [
|
|
'totals' => [
|
|
'currency_code' => 'EUR',
|
|
'total' => ['amount' => 9900],
|
|
],
|
|
],
|
|
'custom_data' => [
|
|
'checkout_session_id' => $session->id,
|
|
],
|
|
],
|
|
],
|
|
], 200),
|
|
]);
|
|
|
|
Mail::fake();
|
|
Notification::fake();
|
|
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->getJson(route('checkout.session.status', $session));
|
|
|
|
$response->assertOk()
|
|
->assertJsonPath('status', CheckoutSession::STATUS_COMPLETED);
|
|
|
|
$this->assertDatabaseHas('checkout_sessions', [
|
|
'id' => $session->id,
|
|
'status' => CheckoutSession::STATUS_COMPLETED,
|
|
]);
|
|
|
|
$this->assertDatabaseHas('package_purchases', [
|
|
'tenant_id' => $tenant->id,
|
|
'package_id' => $package->id,
|
|
]);
|
|
}
|
|
|
|
public function test_session_confirm_recovers_completed_paddle_transaction(): void
|
|
{
|
|
$tenant = Tenant::factory()->create();
|
|
$user = User::factory()->for($tenant)->create([
|
|
'pending_purchase' => true,
|
|
]);
|
|
$package = Package::factory()->create([
|
|
'type' => 'endcustomer',
|
|
'price' => 79,
|
|
]);
|
|
|
|
/** @var CheckoutSessionService $sessions */
|
|
$sessions = app(CheckoutSessionService::class);
|
|
$session = $sessions->createOrResume($user, $package, [
|
|
'tenant' => $tenant,
|
|
]);
|
|
$sessions->selectProvider($session, CheckoutSession::PROVIDER_PADDLE);
|
|
|
|
config()->set([
|
|
'paddle.api_key' => 'test-key',
|
|
'paddle.base_url' => 'https://paddle.test',
|
|
'paddle.environment' => 'sandbox',
|
|
]);
|
|
|
|
Http::fake([
|
|
'https://paddle.test/transactions/txn_987' => Http::response([
|
|
'data' => [
|
|
'id' => 'txn_987',
|
|
'status' => 'completed',
|
|
'details' => [
|
|
'totals' => [
|
|
'currency_code' => 'EUR',
|
|
'total' => ['amount' => 7900],
|
|
],
|
|
],
|
|
'custom_data' => [
|
|
'checkout_session_id' => $session->id,
|
|
],
|
|
],
|
|
], 200),
|
|
]);
|
|
|
|
Mail::fake();
|
|
Notification::fake();
|
|
|
|
$this->actingAs($user);
|
|
|
|
$response = $this->postJson(route('checkout.session.confirm', $session), [
|
|
'transaction_id' => 'txn_987',
|
|
'checkout_id' => 'che_987',
|
|
]);
|
|
|
|
$response->assertOk()
|
|
->assertJsonPath('status', CheckoutSession::STATUS_COMPLETED);
|
|
|
|
$this->assertDatabaseHas('checkout_sessions', [
|
|
'id' => $session->id,
|
|
'status' => CheckoutSession::STATUS_COMPLETED,
|
|
]);
|
|
}
|
|
}
|