## 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
119 lines
4.1 KiB
PHP
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');
|
|
});
|