105 lines
4.4 KiB
PHP
105 lines
4.4 KiB
PHP
<?php
|
|
|
|
use App\Livewire\Admin\Integrations;
|
|
use App\Models\Operator;
|
|
use App\Services\Secrets\SecretVault;
|
|
use App\Support\OperatingMode;
|
|
use App\Support\Readiness\BillingChecks;
|
|
use App\Support\StripeWebhookSecret;
|
|
use Livewire\Livewire;
|
|
|
|
/**
|
|
* Ein Stripe-Wert in der Konsole und zwei in der Serverdatei ist keine
|
|
* Entscheidung, sondern ein Zustand. Die alte Begründung — „wird bei jedem
|
|
* eingehenden Zahlungsereignis gelesen, ein Datenbankproblem ließe die
|
|
* Signaturprüfung still fehlschlagen" — hält nicht: der Secret Key, mit dem
|
|
* das Geld eingezogen wird, liegt längst im Tresor und wird bei jeder Buchung
|
|
* gelesen. Und die AUSWAHL zwischen Test- und Live-Signaturschlüssel fragte
|
|
* ohnehin schon die Datenbank (OperatingMode::current()).
|
|
*
|
|
* Beide Werte sind jetzt ein Tresoreintrag mit den zwei Plätzen, die der
|
|
* Tresor für Test und Live sowieso führt.
|
|
*/
|
|
beforeEach(function () {
|
|
config()->set('admin_access.secrets_key', 'base64:'.base64_encode(random_bytes(32)));
|
|
});
|
|
|
|
it('prefers the stored signing secret over the server file', function () {
|
|
config()->set('services.stripe.webhook_secret_test', 'whsec_from_env');
|
|
OperatingMode::set(OperatingMode::Test);
|
|
|
|
app(SecretVault::class)->put('stripe.webhook_secret', 'whsec_from_console', Operator::factory()->create());
|
|
|
|
expect(StripeWebhookSecret::current())->toBe('whsec_from_console');
|
|
});
|
|
|
|
it('keeps the two modes apart, stored just as in the server file', function () {
|
|
// Der Grund, warum es überhaupt zwei Werte gibt: Stripe stellt je
|
|
// Betriebsmodus ein eigenes Signaturgeheimnis aus. Ein Platz, der auf den
|
|
// anderen zurückfällt, würde ein Testereignis mit dem Live-Schlüssel
|
|
// prüfen — es scheitert, aber die Konsole sagt „gesetzt".
|
|
$by = Operator::factory()->create();
|
|
$vault = app(SecretVault::class);
|
|
|
|
$vault->put('stripe.webhook_secret', 'whsec_test_slot', $by, OperatingMode::Test);
|
|
$vault->put('stripe.webhook_secret', 'whsec_live_slot', $by, OperatingMode::Live);
|
|
|
|
OperatingMode::set(OperatingMode::Test);
|
|
expect(StripeWebhookSecret::current())->toBe('whsec_test_slot');
|
|
|
|
OperatingMode::set(OperatingMode::Live);
|
|
expect(StripeWebhookSecret::current())->toBe('whsec_live_slot');
|
|
});
|
|
|
|
it('still reads the server file when nothing is stored, per mode', function () {
|
|
// Eine bestehende Installation hat beide Zeilen in der .env und darf sich
|
|
// durch diesen Umzug nicht ändern — sonst weist sie ab morgen jedes
|
|
// eingehende Zahlungsereignis ab.
|
|
config()->set('services.stripe.webhook_secret', 'whsec_live_env');
|
|
config()->set('services.stripe.webhook_secret_test', 'whsec_test_env');
|
|
|
|
OperatingMode::set(OperatingMode::Test);
|
|
expect(StripeWebhookSecret::current())->toBe('whsec_test_env');
|
|
|
|
OperatingMode::set(OperatingMode::Live);
|
|
expect(StripeWebhookSecret::current())->toBe('whsec_live_env');
|
|
});
|
|
|
|
it('does not call an unset slot "from the server file" when the server file is empty for that mode', function () {
|
|
// Die Herkunftsplakette auf der Karte muss zum Wert gehören, der WIRKLICH
|
|
// gilt — genau der Fehler, den source() für dns.token schon einmal hatte.
|
|
config()->set('services.stripe.webhook_secret', 'whsec_live_env');
|
|
config()->set('services.stripe.webhook_secret_test', '');
|
|
OperatingMode::set(OperatingMode::Test);
|
|
|
|
expect(app(SecretVault::class)->source('stripe.webhook_secret'))->toBe('none')
|
|
->and(StripeWebhookSecret::current())->toBe('');
|
|
});
|
|
|
|
it('reports the source as the server file when that mode does have a line', function () {
|
|
config()->set('services.stripe.webhook_secret_test', 'whsec_test_env');
|
|
OperatingMode::set(OperatingMode::Test);
|
|
|
|
expect(app(SecretVault::class)->source('stripe.webhook_secret'))->toBe('environment');
|
|
});
|
|
|
|
it('offers the signing secret as a field on the payments card', function () {
|
|
Livewire::actingAs(operator('Owner'), 'operator')
|
|
->test(Integrations::class)
|
|
->set('confirmablePassword', 'password')
|
|
->call('confirmPassword')
|
|
->assertSee('STRIPE_WEBHOOK_SECRET');
|
|
});
|
|
|
|
it('sends the readiness check to that card instead of the raw .env editor', function () {
|
|
foreach (BillingChecks::all() as $check) {
|
|
if ($check->key === 'billing.stripe_webhook_secret') {
|
|
expect($check->tab)->toBe('services');
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
throw new RuntimeException('billing.stripe_webhook_secret check is gone');
|
|
});
|