Files
api/services/nginx/app/tests/Api/StripeApiTest.php
T
Jeppe B 30d860fdef Retire payment links and capture card payments (#327)
## Summary

- retire Stripe hosted payment-link creation routes used by POS and
order management
- automatically capture authorized payment intents rather than requiring
a separate manual capture action
- preserve ordinary terminal payment and payment-intent lifecycle
behavior
- add API and wiring regressions for payment-link retirement and
automatic capture

Paired frontend change:
https://github.com/copenhagentruckwash/pleno-vue/pull/233

## Verification

- focused backend unit suite: 2 tests, 36 assertions passed
- PHP syntax checks passed
- paired frontend unit and Playwright suites passed locally
- full required GitHub runner suites are required before this task may
enter Review or merge

## Security and operational notes

- no credentials, terminal secrets, or payment data are added
- no live Stripe account or physical terminal was exercised locally
- automatic merge remains gated on both paired PRs having passing
required checks and current branches
2026-07-27 19:09:37 +02:00

119 lines
4.1 KiB
PHP

<?php
declare(strict_types=1);
use classes\stripe_fake_http_client;
putenv('STRIPE_FAKE_MODE=1');
putenv('STRIPE_FAKE_STORE_PATH=' . sys_get_temp_dir() . '/truckwash-stripe-api-tests.json');
usesApiSuite();
beforeEach(function (): void {
stripe_fake_http_client::resetStore();
if (api_tests_enabled()) {
api_test_runtime()->db()->query("DELETE FROM stripe_module_orders WHERE invoice_id LIKE 'in_fake_%'");
api_test_runtime()->db()->query("DELETE FROM stripe_module_customers WHERE customer_id LIKE 'cus_fake_%' OR email LIKE 'stripe-%@example.com'");
}
});
it('returns a setup required error when department terminal readers are requested without terminal setup', function (): void {
$department = api_fixtures()->createDepartment([
'name' => 'Stripe Setup Pending Department',
]);
$session = api_fixtures()->createUserSession([
'modules_stripe_department_terminal_readers_list',
'department_access_' . $department['id'],
]);
$response = api_client()->get(
'/modules/stripe/department/terminal/readers?id=' . $department['id'],
$session['headers']
);
$response
->assertStatus(409)
->assertEnvelope()
->assertSuccess(false)
->assertMessage('Card payments are not ready for this department. Open Stripe setup and choose a terminal location.');
expect($response->data())
->toBeArray()
->toHaveKey('code', 'stripe_terminal_setup_required');
});
it('rejects creating a Stripe hosted invoice by email because direct payment links are retired', function (): void {
$department = api_fixtures()->createDepartment([
'name' => 'Stripe Email Payments Department',
]);
$customer = api_fixtures()->createUser([
'display_name' => 'Stripe Hosted Invoice Customer',
]);
$order = api_fixtures()->createOrder([
'customer_id' => $customer['customer_number'],
'department_id' => $department['id'],
'reference' => 'STRIPE-EMAIL-SEND',
'reg_1' => 'EMAIL01',
]);
$session = api_fixtures()->createUserSession([
'modules_stripe_invoice_send',
]);
$emailAddress = sprintf('stripe-email-%d@example.com', (int)$order['id']);
$response = api_client()->post('/modules/stripe/invoice', [
'email' => $emailAddress,
'order_id' => $order['id'],
], $session['headers']);
$response
->assertStatus(410)
->assertEnvelope()
->assertSuccess(false)
->assertMessage('Direct Stripe payment links by email are no longer available. Use card payment instead.');
$stored = api_test_runtime()->queryOne(
'SELECT invoice_id, customer_id, url FROM stripe_module_orders WHERE id = ' . (int)$order['id']
);
expect($response->data())
->toBeArray()
->toHaveKey('code', 'stripe_email_payment_disabled')
->and($stored)->toBeNull();
});
it('returns a setup required error when creating a payment intent for a department without terminal setup', function (): void {
$department = api_fixtures()->createDepartment([
'name' => 'Stripe Payment Intent Pending Department',
]);
$customer = api_fixtures()->createUser([
'display_name' => 'Stripe Payment Intent Customer',
]);
$order = api_fixtures()->createOrder([
'customer_id' => $customer['customer_number'],
'department_id' => $department['id'],
'reference' => 'STRIPE-SETUP-REQUIRED',
'reg_1' => 'STRIPE01',
]);
$session = api_fixtures()->createUserSession([
'charge_order',
'department_access_' . (int)$department['id'],
]);
$response = api_client()->post('/orders/module/stripe/payment_intent', [
'id' => $order['id'],
'reader' => 'reader_pending_setup',
'tax_percentage' => 25,
], $session['headers']);
$response
->assertStatus(409)
->assertEnvelope()
->assertSuccess(false)
->assertMessage('Card payments are not ready for this department. Open Stripe setup and choose a terminal location.');
expect($response->data())
->toBeArray()
->toHaveKey('code', 'stripe_terminal_setup_required');
});