set order status as paid after wallet payment

This commit is contained in:
2025-12-18 19:14:09 +03:30
parent 0362540875
commit add2127998
5 changed files with 28 additions and 41 deletions
@@ -37,8 +37,7 @@ export class OrdersService {
private readonly logger = new Logger(OrdersService.name);
private static readonly STATUS_TRANSITIONS: Record<OrderStatus, readonly OrderStatus[]> = {
[OrderStatus.NEW]: [OrderStatus.PENDING_PAYMENT, OrderStatus.CONFIRMED, OrderStatus.CANCELED],
[OrderStatus.PENDING_PAYMENT]: [OrderStatus.PAID, OrderStatus.FAILED, OrderStatus.CANCELED],
[OrderStatus.PENDING_PAYMENT]: [OrderStatus.PAID, OrderStatus.FAILED, OrderStatus.CANCELED, OrderStatus.CONFIRMED],
[OrderStatus.PAID]: [OrderStatus.CONFIRMED, OrderStatus.REFUNDED],
[OrderStatus.CONFIRMED]: [OrderStatus.PREPARING, OrderStatus.CANCELED],
[OrderStatus.PREPARING]: [OrderStatus.READY, OrderStatus.SHIPPED, OrderStatus.CANCELED],
@@ -56,7 +55,7 @@ export class OrdersService {
private readonly orderRepository: OrderRepository,
private readonly paymentsService: PaymentsService,
private readonly inventoryService: InventoryService,
) { }
) {}
async checkout(userId: string, restaurantId: string) {
const cart = await this.cartService.findOneOrFail(userId, restaurantId);
@@ -80,8 +79,7 @@ export class OrdersService {
totalItems: cart.totalItems || 0,
description: cart.description,
tableNumber: cart.tableNumber,
status: OrderStatus.NEW,
paymentStatus: PaymentStatusEnum.Pending,
status: OrderStatus.PENDING_PAYMENT,
});
em.persist(order);
@@ -35,7 +35,6 @@ export class OrderRepository extends EntityRepository<Order> {
page = 1,
limit = 10,
status,
paymentStatus,
search,
startDate,
endDate,
@@ -57,11 +56,6 @@ export class OrderRepository extends EntityRepository<Order> {
where.user = { id: userId };
}
// Filter by payment status
if (paymentStatus) {
where.paymentStatus = paymentStatus;
}
// Filter by date range
if (startDate || endDate) {
where.createdAt = {};
@@ -52,7 +52,11 @@ export class ZarinpalGateway implements IPaymentGateway {
};
try {
const res = await axios.post<IZarinpalPaymentResponse>(this.zarinpalRequestUrl, zarinpalRequest, this.axiosConfig);
const res = await axios.post<IZarinpalPaymentResponse>(
this.zarinpalRequestUrl,
zarinpalRequest,
this.axiosConfig,
);
const { data, errors } = res.data ?? {};
const code = data?.code;
const message = data?.message;
@@ -112,7 +116,11 @@ export class ZarinpalGateway implements IPaymentGateway {
authority: transactionId,
};
const res = await axios.post<IZarinpalVerifyResponse>(this.zarinpalVerifyUrl, zarinpalVerifyRequest, this.axiosConfig);
const res = await axios.post<IZarinpalVerifyResponse>(
this.zarinpalVerifyUrl,
zarinpalVerifyRequest,
this.axiosConfig,
);
// Check if response data exists
if (!res.data || !res.data.data) {
@@ -128,7 +136,7 @@ export class ZarinpalGateway implements IPaymentGateway {
return {
success: code === 100,
referenceId: ref_id ? ref_id.toString() : undefined,
referenceId: ref_id ? ref_id.toString() : '',
cardPan: card_pan,
raw: res.data,
};
@@ -145,5 +153,4 @@ export class ZarinpalGateway implements IPaymentGateway {
getPaymentUrl(authority: string): string {
return `${this.zarinpalPaymentBaseUrl}/pg/StartPay/${authority}`;
}
}
+1 -1
View File
@@ -23,7 +23,7 @@ export interface IPaymentVerifyParams {
export interface IPaymentVerifyData {
success: boolean;
referenceId?: string;
referenceId: string;
cardPan?: string;
raw: Record<string, any>;
}
@@ -18,15 +18,13 @@ export class PaymentsService {
private readonly em: EntityManager,
private readonly gatewayManager: GatewayManager,
private readonly inventoryService: InventoryService,
) { }
) {}
async payOrder(
orderId: string,
): Promise<{ paymentUrl: string | null }> {
async payOrder(orderId: string): Promise<{ paymentUrl: string | null }> {
const ctx = await this.loadAndValidateOrder(orderId);
// Idempotency: avoid creating/charging again for already-paid orders
if (ctx.order.paymentStatus === PaymentStatusEnum.Paid) {
if (ctx.order.status === OrderStatus.PAID) {
return { paymentUrl: null };
}
@@ -47,9 +45,7 @@ export class PaymentsService {
}
}
private async loadAndValidateOrder(
orderId: string,
): Promise<OrderPaymentContext> {
private async loadAndValidateOrder(orderId: string): Promise<OrderPaymentContext> {
const order = await this.em.findOne(
Order,
{ id: orderId },
@@ -98,7 +94,7 @@ export class PaymentsService {
const order = await em.findOne(Order, { id: ctx.order.id }, { populate: ['user', 'restaurant'] });
if (!order) throw new NotFoundException('Order not found');
if (order.paymentStatus === PaymentStatusEnum.Paid) {
if (order.status === OrderStatus.PAID) {
return;
}
@@ -126,17 +122,14 @@ export class PaymentsService {
payment.status = PaymentStatusEnum.Paid;
payment.paidAt = new Date();
order.paymentStatus = PaymentStatusEnum.Paid;
order.status = OrderStatus.PAID;
em.persist([wallet, payment, order]);
await em.flush();
});
}
private async handleOnlinePayment(
ctx: OrderPaymentContext,
): Promise<{ paymentUrl: string }> {
private async handleOnlinePayment(ctx: OrderPaymentContext): Promise<{ paymentUrl: string }> {
const gateway = this.gatewayManager.get(ctx.gateway!);
const payment = await this.getOrCreateLatestPendingPayment(ctx.order.id, {
@@ -168,11 +161,7 @@ export class PaymentsService {
};
}
async verifyPayment(
transactionId: string,
orderId: string,
): Promise<Payment> {
async verifyPayment(transactionId: string, orderId: string): Promise<Payment> {
return this.em.transactional(async em => {
const payment = await em.findOne(
Payment,
@@ -207,9 +196,9 @@ export class PaymentsService {
this.failPayment(payment);
return payment;
}
this.markPaid(payment);
this.markPaid(payment, result.referenceId);
this.confirmOrder(payment.order);
await em.flush();
return payment;
});
@@ -223,17 +212,16 @@ export class PaymentsService {
);
}
private markPaid(payment: Payment) {
private markPaid(payment: Payment, referenceId: string) {
payment.status = PaymentStatusEnum.Paid;
payment.paidAt = new Date();
payment.referenceId = payment.referenceId;
payment.order.paymentStatus = PaymentStatusEnum.Paid;
payment.referenceId = referenceId;
}
private failPayment(payment: Payment) {
payment.status = PaymentStatusEnum.Failed;
payment.failedAt = new Date();
payment.order.paymentStatus = PaymentStatusEnum.Failed;
payment.order.status = OrderStatus.FAILED;
}
private confirmOrder(order: Order) {