presseportale/tests/Feature/Billing/StripeCustomerHooksTest.php
Kevin Adametz f6882b621a Depublikation: Kauf als eingelöst markieren, Rechnung & Bestätigungs-Mail
Drei Lücken im bezahlten Depublikations-Flow (T12) geschlossen:

- Webhook setzt den Kauf jetzt auf status=consumed (vorher nur
  consumed_at) — erst damit erscheint er unter „Eingelöste Käufe".
- Einmalkäufe (Depublikation, Einzel-PM, Credit-Topup) aktivieren
  invoice_creation im Stripe-Checkout: Ohne das Flag erzeugt Stripe im
  Payment-Mode keine Rechnung und die STR-Spiegelung lief ins Leere.
  Abo-Checkouts bleiben unverändert (Parameter dort unzulässig).
- Neue Bestätigungs-Mail PressReleaseDepublished an den Käufer
  (nicht zwingend der PM-Autor) nach vollzogener Depublikation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 11:25:12 +00:00

99 lines
3.6 KiB
PHP

<?php
use App\Models\BillingAddress;
use App\Models\User;
use App\Services\Billing\StripeCheckoutService;
test('the stripe recipient name prefers the billing company over names', function () {
$user = User::factory()->create(['name' => 'Login Anzeigename']);
BillingAddress::factory()->create([
'user_id' => $user->id,
'company' => 'Beispiel GmbH',
'name' => 'Max Mustermann',
]);
expect($user->fresh()->stripeName())->toBe('Beispiel GmbH');
});
test('the stripe recipient name falls back to the billing name, then the display name', function () {
$user = User::factory()->create(['name' => 'Login Anzeigename']);
BillingAddress::factory()->create([
'user_id' => $user->id,
'company' => null,
'name' => 'Max Mustermann',
]);
expect($user->fresh()->stripeName())->toBe('Max Mustermann');
$withoutAddress = User::factory()->create(['name' => 'Nur Anzeigename']);
expect($withoutAddress->stripeName())->toBe('Nur Anzeigename');
});
test('the stripe address mirrors the billing address', function () {
$user = User::factory()->create();
BillingAddress::factory()->create([
'user_id' => $user->id,
'address1' => 'Rechnungsweg 12',
'address2' => 'Hinterhaus',
'postal_code' => '33739',
'city' => 'Bielefeld',
'country_code' => 'DE',
]);
expect($user->fresh()->stripeAddress())->toBe([
'line1' => 'Rechnungsweg 12',
'line2' => 'Hinterhaus',
'postal_code' => '33739',
'city' => 'Bielefeld',
'country' => 'DE',
]);
expect(User::factory()->create()->stripeAddress())->toBeNull();
});
test('checkout session options leave the stripe customer untouched when a billing address exists', function () {
$user = User::factory()->create();
BillingAddress::factory()->create(['user_id' => $user->id]);
$options = invokeSessionOptions($user->fresh());
expect($options['billing_address_collection'])->toBe('auto')
->and($options['automatic_tax'])->toBe(['enabled' => true])
->and($options)->not->toHaveKeys(['customer_update', 'tax_id_collection']);
});
test('checkout session options collect the address in stripe when no billing address exists', function () {
$options = invokeSessionOptions(User::factory()->create());
expect($options['billing_address_collection'])->toBe('required')
->and($options['tax_id_collection'])->toBe(['enabled' => true])
->and($options['customer_update'])->toBe(['address' => 'auto', 'name' => 'auto']);
});
test('one-time checkouts enable stripe invoice creation, subscription checkouts do not', function () {
$user = User::factory()->create();
BillingAddress::factory()->create(['user_id' => $user->id]);
$user = $user->fresh();
// Payment-Mode: ohne invoice_creation erzeugt Stripe keine Rechnung —
// und damit gäbe es kein invoice.payment_succeeded für die STR-Spiegelung.
$oneTime = invokeSessionOptions($user, 'oneTimeSessionOptions');
expect($oneTime['invoice_creation'])->toBe(['enabled' => true])
->and($oneTime['automatic_tax'])->toBe(['enabled' => true]);
// Subscription-Mode lehnt invoice_creation ab — dort erzeugt Stripe
// die Rechnungen ohnehin selbst.
expect(invokeSessionOptions($user))->not->toHaveKey('invoice_creation');
});
/**
* @return array<string, mixed>
*/
function invokeSessionOptions(User $user, string $method = 'sessionOptions'): array
{
$service = app(StripeCheckoutService::class);
$method = new ReflectionMethod($service, $method);
return $method->invoke($service, $user);
}