Lock payment process steps to gateway-only updates.

Reject admin PATCH of awaiting-payment / payment-successful so order payment status cannot be set manually.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-10-02 22:07:32 +03:30
co-authored by Cursor
parent 88ef4e82a1
commit 0a330b8749
2 changed files with 18 additions and 1 deletions
@@ -370,7 +370,17 @@ export function listPublicPaymentGateways(settings: EPaymentSettings) {
};
}
const PAYMENT_PROCESS_STEP_IDS = ['awaiting-payment', 'payment-successful'] as const;
/** System-managed payment steps — set by gateway callbacks, not admin UI. */
export const PAYMENT_PROCESS_STEP_IDS = [
'awaiting-payment',
'payment-successful',
] as const;
export type PaymentProcessStepId = (typeof PAYMENT_PROCESS_STEP_IDS)[number];
export function isSystemPaymentProcessStep(stepId: string): boolean {
return (PAYMENT_PROCESS_STEP_IDS as readonly string[]).includes(stepId);
}
/** Prepend default payment steps when an older store settings JSON omits them. */
function ensurePaymentProcessSteps(steps: OrderProcessStep[]): OrderProcessStep[] {
+7
View File
@@ -15,6 +15,7 @@ import {
} from '@prisma/client';
import { AuthUser } from '../auth/auth.types';
import { BusinessSettingsService } from '../business-settings/business-settings.service';
import { isSystemPaymentProcessStep } from '../business-settings/business-settings.util';
import { PermissionsService } from '../auth/permissions.service';
import { PrismaService } from '../prisma/prisma.service';
import {
@@ -764,6 +765,12 @@ export class OrdersService {
}
private async assertValidProcessStepId(businessId: bigint, processStepId: string) {
if (isSystemPaymentProcessStep(processStepId)) {
throw new BadRequestException(
'Payment steps are set automatically by the payment gateway and cannot be changed manually',
);
}
const steps = await this.businessSettings.getOrderProcessSteps(businessId);
const valid = steps.some((step) => step.id === processStepId);
if (!valid) {