Skip to content

Commit

Permalink
refactor and add eligble to revert
Browse files Browse the repository at this point in the history
  • Loading branch information
bahram1249 committed May 12, 2024
1 parent 27e35e6 commit eb9476f
Show file tree
Hide file tree
Showing 13 changed files with 187 additions and 87 deletions.
7 changes: 4 additions & 3 deletions apps/e-commerce/src/inventory/inventory.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
DecreaseInventoryService,
InventoryService,
InventoryValidationService,
RevertInventoryQtyService,
inventoryStatusService,
} from './services';
import { ECInventory } from '@rahino/database/models/ecommerce-eav/ec-inventory.entity';
Expand All @@ -34,6 +33,8 @@ import {
import { ECPayment } from '@rahino/database/models/ecommerce-eav/ec-payment-entity';
import { ECOrder } from '@rahino/database/models/ecommerce-eav/ec-order.entity';
import { RevertInventoryQtyProcessor } from './processor/revert-inventory-qty.processor';
import { PaymentServiceProviderModule } from '../user/payment/provider/payment-provider.module';
import { RevertInventoryModule } from './revert-inventory.module';

@Module({
imports: [
Expand Down Expand Up @@ -73,6 +74,8 @@ import { RevertInventoryQtyProcessor } from './processor/revert-inventory-qty.pr
BullModule.registerQueue({
name: REVERT_INVENTORY_QTY_QUEUE,
}),
PaymentServiceProviderModule,
RevertInventoryModule,
],
providers: [
InventoryValidationService,
Expand All @@ -82,15 +85,13 @@ import { RevertInventoryQtyProcessor } from './processor/revert-inventory-qty.pr
ProductInventoryStatusProcessor,
DecreaseInventoryService,
DecreaseInventoryProcessor,
RevertInventoryQtyService,
RevertInventoryQtyProcessor,
],
exports: [
InventoryValidationService,
InventoryService,
inventoryStatusService,
DecreaseInventoryService,
RevertInventoryQtyService,
],
})
export class InventoryModule {}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
PaymentTypeEnum,
} from '@rahino/ecommerce/util/enum';
import { Op, Sequelize } from 'sequelize';
import { PaymentServiceManualProviderFactory } from '@rahino/ecommerce/user/payment/provider/factory/payment-service-manual-provider.factory';

@Processor(REVERT_INVENTORY_QTY_QUEUE)
export class RevertInventoryQtyProcessor extends WorkerHost {
Expand All @@ -19,6 +20,7 @@ export class RevertInventoryQtyProcessor extends WorkerHost {
@InjectModel(ECPayment)
private readonly paymentRepository: typeof ECPayment,
private readonly revertInventoryQtyService: RevertInventoryQtyService,
private readonly paymentServiceManualProviderFactory: PaymentServiceManualProviderFactory,
) {
super();
}
Expand All @@ -29,7 +31,7 @@ export class RevertInventoryQtyProcessor extends WorkerHost {
}
const paymentId = job.data.paymentId;
try {
const payment = await this.paymentRepository.findOne(
let payment = await this.paymentRepository.findOne(
new QueryOptionsBuilder()
.filter({ id: paymentId })
.filter({ paymentStatusId: PaymentStatusEnum.WaitingForPayment })
Expand All @@ -45,7 +47,22 @@ export class RevertInventoryQtyProcessor extends WorkerHost {
.build(),
);
if (payment) {
await this.revertInventoryQtyService.revertQty(paymentId);
const paymentService =
await this.paymentServiceManualProviderFactory.create(
payment.paymentGatewayId,
);
const eligbleToRevert = await paymentService.eligbleToRevert(
payment.id,
);
if (eligbleToRevert) {
await this.revertInventoryQtyService.revertQty(paymentId);
payment = (
await this.paymentRepository.update(
{ paymentStatusId: PaymentStatusEnum.FailedPayment },
{ where: { id: payment.id }, returning: true },
)
)[1][0];
}
}
} catch (error) {
return Promise.reject(paymentId);
Expand Down
16 changes: 16 additions & 0 deletions apps/e-commerce/src/inventory/revert-inventory.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Module } from '@nestjs/common';
import { RevertInventoryQtyService, inventoryStatusService } from './services';
import { SequelizeModule } from '@nestjs/sequelize';
import { ECInventory } from '@rahino/database/models/ecommerce-eav/ec-inventory.entity';
import { ECPayment } from '@rahino/database/models/ecommerce-eav/ec-payment-entity';
import { ECOrder } from '@rahino/database/models/ecommerce-eav/ec-order.entity';
import { ECProduct } from '@rahino/database/models/ecommerce-eav/ec-product.entity';

@Module({
imports: [
SequelizeModule.forFeature([ECInventory, ECPayment, ECOrder, ECProduct]),
],
providers: [RevertInventoryQtyService, inventoryStatusService],
exports: [RevertInventoryQtyService],
})
export class RevertInventoryModule {}
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import {
BadRequestException,
Injectable,
InternalServerErrorException,
} from '@nestjs/common';
import { Injectable, InternalServerErrorException } from '@nestjs/common';
import { InjectModel } from '@nestjs/sequelize';
import { ECInventory } from '@rahino/database/models/ecommerce-eav/ec-inventory.entity';
import { QueryOptionsBuilder } from '@rahino/query-filter/sequelize-query-builder';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ export interface PayInterface {
titleMessage?: string;
description?: string;
}>;

eligbleToRevert(paymentId: bigint): Promise<boolean>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ import { SequelizeModule } from '@nestjs/sequelize';
import { ECPaymentGateway } from '@rahino/database/models/ecommerce-eav/ec-payment-gateway.entity';
import { ECPayment } from '@rahino/database/models/ecommerce-eav/ec-payment-entity';
import { ECOrder } from '@rahino/database/models/ecommerce-eav/ec-order.entity';
import { InventoryModule } from '@rahino/ecommerce/inventory/inventory.module';
import { PaymentServiceManualProviderFactory } from './factory/payment-service-manual-provider.factory';
import { RevertInventoryModule } from '@rahino/ecommerce/inventory/revert-inventory.module';

@Module({
imports: [
InventoryModule,
RevertInventoryModule,
SequelizeModule.forFeature([ECPaymentGateway, ECPayment, ECOrder]),
],
providers: [
Expand Down
123 changes: 123 additions & 0 deletions apps/e-commerce/src/user/payment/provider/services/snap-pay.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -293,11 +293,29 @@ export class SnapPayService implements PayInterface {
},
);
if (result.data.successful != true) {
payment = (
await this.paymentRepository.update(
{ paymentStatusId: PaymentStatusEnum.FailedPayment },
{ where: { id: payment.id }, returning: true },
)
)[1][0];
// revert qty
await this.revertInventoryQtyService.revertQty(payment.id);

throw new BadRequestException('invalid payment');
}
if (
result.data.response.transactionId != payment.transactionId.toString()
) {
payment = (
await this.paymentRepository.update(
{ paymentStatusId: PaymentStatusEnum.FailedPayment },
{ where: { id: payment.id }, returning: true },
)
)[1][0];
// revert qty
await this.revertInventoryQtyService.revertQty(payment.id);

throw new BadRequestException('invalid payment');
}
const finalRequest = await axios.post(
Expand Down Expand Up @@ -346,6 +364,111 @@ export class SnapPayService implements PayInterface {
);
}

async eligbleToRevert(paymentId: bigint): Promise<boolean> {
const paymentGateway = await this.paymentGateway.findOne(
new QueryOptionsBuilder()
.filter({ serviceName: 'SnapPayService' })
.filter(
Sequelize.where(
Sequelize.fn('isnull', Sequelize.col('isDeleted'), 0),
{
[Op.eq]: 0,
},
),
)
.build(),
);
if (!paymentGateway) {
throw new BadRequestException('invalid payment');
}

let payment = await this.paymentRepository.findOne(
new QueryOptionsBuilder()
.filter({ paymentGatewayId: paymentGateway.id })
.filter({ id: paymentId })
.filter({ paymentStatusId: PaymentStatusEnum.WaitingForPayment })
.build(),
);
if (!payment) {
throw new BadRequestException('invalid payment');
}
const token = await this.generateToken(paymentGateway);

const statusRequest = await axios.get(
this.baseUrl +
`/api/online/payment/v1/status?paymentToken=${payment.paymentToken}`,
{
headers: {
Authorization: 'Bearer ' + token,
},
timeout: 60000,
},
);
if (statusRequest.data.successful == false) {
return true;
}

const result = await axios.post(
this.baseUrl + '/api/online/payment/v1/verify',
{
paymentToken: payment.paymentToken,
},
{
headers: {
Authorization: 'Bearer ' + token,
},
timeout: 60000,
},
);
if (result.data.successful != true) {
return true;
}
if (
result.data.response.transactionId != payment.transactionId.toString()
) {
return true;
}
const finalRequest = await axios.post(
this.baseUrl + '/api/online/payment/v1/settle',
{
paymentToken: payment.paymentToken,
},
{
headers: {
Authorization: 'Bearer ' + token,
},
timeout: 60000,
},
);
if (finalRequest.data.successful == true) {
payment = (
await this.paymentRepository.update(
{ paymentStatusId: PaymentStatusEnum.SuccessPayment },
{
where: {
id: payment.id,
},
returning: true,
},
)
)[1][0];
await this.orderRepository.update(
{
orderStatusId: OrderStatusEnum.Paid,
transactionId: payment.transactionId,
paymentId: payment.id,
},
{
where: {
id: payment.orderId,
},
},
);
return false;
}
return true;
}

async update(
totalPrice: number,
discountAmount: number,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import { ECOrderDetail } from '@rahino/database/models/ecommerce-eav/ec-order-de

export class WalletService implements PayInterface {
constructor() {}
async eligbleToRevert(paymentId: bigint): Promise<boolean> {
return true;
}
async requestPayment(
totalPrice: number,
discountAmount: number,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { ECOrderDetail } from '@rahino/database/models/ecommerce-eav/ec-order-de
import {
BadRequestException,
InternalServerErrorException,
NotImplementedException,
} from '@nestjs/common';
import { ECPaymentGateway } from '@rahino/database/models/ecommerce-eav/ec-payment-gateway.entity';
import { InjectModel } from '@nestjs/sequelize';
Expand All @@ -37,6 +36,9 @@ export class ZarinPalService implements PayInterface {
this.baseUrl = 'https://api.zarinpal.com';
//this.baseUrl = 'https://sandbox.zarinpal.com';
}
async eligbleToRevert(paymentId: bigint): Promise<boolean> {
return true;
}
async requestPayment(
totalPrice: number,
discountAmount: number,
Expand Down Expand Up @@ -211,6 +213,15 @@ export class ZarinPalService implements PayInterface {
},
},
);
} else {
payment = (
await this.paymentRepository.update(
{ paymentStatusId: PaymentStatusEnum.FailedPayment },
{ where: { id: payment.id }, returning: true },
)
)[1][0];
// revert qty
await this.revertInventoryQtyService.revertQty(payment.id);
}
}
const frontUrl = this.config.get('BASE_FRONT_URL');
Expand Down
4 changes: 2 additions & 2 deletions apps/e-commerce/src/user/payment/provider/snappay.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import { SequelizeModule } from '@nestjs/sequelize';
import { ECPaymentGateway } from '@rahino/database/models/ecommerce-eav/ec-payment-gateway.entity';
import { ECPayment } from '@rahino/database/models/ecommerce-eav/ec-payment-entity';
import { ECOrder } from '@rahino/database/models/ecommerce-eav/ec-order.entity';
import { InventoryModule } from '@rahino/ecommerce/inventory/inventory.module';
import { RevertInventoryModule } from '@rahino/ecommerce/inventory/revert-inventory.module';

@Module({
imports: [
SequelizeModule.forFeature([ECPaymentGateway, ECPayment, ECOrder]),
InventoryModule,
RevertInventoryModule,
],
providers: [SnapPayService],
exports: [SnapPayService],
Expand Down
4 changes: 2 additions & 2 deletions apps/e-commerce/src/user/payment/provider/zarinpal.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import { SequelizeModule } from '@nestjs/sequelize';
import { ECPaymentGateway } from '@rahino/database/models/ecommerce-eav/ec-payment-gateway.entity';
import { ECPayment } from '@rahino/database/models/ecommerce-eav/ec-payment-entity';
import { ECOrder } from '@rahino/database/models/ecommerce-eav/ec-order.entity';
import { InventoryModule } from '@rahino/ecommerce/inventory/inventory.module';
import { RevertInventoryModule } from '@rahino/ecommerce/inventory/revert-inventory.module';

@Module({
imports: [
SequelizeModule.forFeature([ECPaymentGateway, ECPayment, ECOrder]),
InventoryModule,
RevertInventoryModule,
],
providers: [ZarinPalService],
exports: [ZarinPalService],
Expand Down
Loading

0 comments on commit eb9476f

Please sign in to comment.