chore: add payment module
This commit is contained in:
+16
@@ -0,0 +1,16 @@
|
||||
import { ApiProperty } from "@nestjs/swagger";
|
||||
import { IsNotEmpty, IsUUID } from "class-validator";
|
||||
|
||||
import { PaymentMessage } from "../../../common/enums/message.enum";
|
||||
|
||||
export class CheckoutPaymentDto {
|
||||
@IsNotEmpty({ message: PaymentMessage.GATEWAY_REQUIRED })
|
||||
@IsUUID("4", { message: PaymentMessage.GATEWAY_ID_SHOULD_BE_UUID })
|
||||
@ApiProperty({ description: "Gateway id to pay", example: "e6fdce2a-9f91-47c4-8561-48368fc275b5" })
|
||||
gatewayId: string;
|
||||
|
||||
@IsNotEmpty({ message: PaymentMessage.INVOICE_ID_REQUIRED })
|
||||
@IsUUID("4", { message: PaymentMessage.INVOICE_ID_SHOULD_BE_UUID })
|
||||
@ApiProperty({ description: "Invoice id to pay", example: "e6fdce2a-9f91-47c4-8561-48368fc275b5" })
|
||||
invoiceId: string;
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
import { ApiProperty } from "@nestjs/swagger";
|
||||
import { IsEnum, IsInt, IsNotEmpty, IsUUID, IsUrl, Min } from "class-validator";
|
||||
|
||||
import { WalletMessage } from "../../../common/enums/message.enum";
|
||||
import { TransferType } from "../enums/payment-type.enum";
|
||||
|
||||
export class DepositDto {
|
||||
@IsNotEmpty({ message: WalletMessage.AMOUNT_REQUIRED })
|
||||
@IsInt({ message: WalletMessage.AMOUNT_MUST_BE_INTEGER })
|
||||
@Min(100_000, { message: WalletMessage.AMOUNT_MINIMUM })
|
||||
@ApiProperty({ description: "Amount to charge", example: 100_000 })
|
||||
amount: number;
|
||||
}
|
||||
|
||||
export class GatewayDepositDto extends DepositDto {
|
||||
// @IsNotEmpty({ message: WalletMessage.GATEWAY_REQUIRED })
|
||||
// @IsEnum(GatewayEnum)
|
||||
// @ApiProperty({ description: "Gateway to use", example: "zarinpal" })
|
||||
// gateway: GatewayEnum;
|
||||
|
||||
@IsNotEmpty({ message: WalletMessage.GATEWAY_REQUIRED })
|
||||
@IsUUID("4", { message: WalletMessage.GATEWAY_ID_SHOULD_BE_UUID })
|
||||
@ApiProperty({ description: "Gateway id to pay", example: "e6fdce2a-9f91-47c4-8561-48368fc275b5" })
|
||||
gatewayId: string;
|
||||
}
|
||||
|
||||
export class TransferDepositDto extends DepositDto {
|
||||
@IsNotEmpty({ message: WalletMessage.RECEIPT_URL_REQUIRED })
|
||||
@IsUrl({ protocols: ["http", "https"], require_protocol: true }, { message: WalletMessage.RECEIPT_URL_SHOULD_BE_URL })
|
||||
@ApiProperty({ description: "the transferReceipt url", example: "https://example.com/image.png" })
|
||||
transferReceiptUrl: string;
|
||||
|
||||
@IsNotEmpty({ message: WalletMessage.BANK_ACCOUNT_ID_REQUIRED })
|
||||
@IsUUID("4", { message: WalletMessage.BANK_ACCOUNT_ID_SHOULD_BE_UUID })
|
||||
@ApiProperty({ description: "bank account id", example: "e6fdce2a-9f91-47c4-8561-48368fc275b5" })
|
||||
bankAccountId: string;
|
||||
|
||||
@IsNotEmpty({ message: WalletMessage.TRANSFER_METHOD_REQUIRED })
|
||||
@IsEnum(TransferType)
|
||||
@ApiProperty({ description: "transfer method", example: TransferType.CARD_TO_CARD, enum: TransferType })
|
||||
method: TransferType;
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
import { ApiProperty } from "@nestjs/swagger";
|
||||
import { IsEnum, IsNotEmpty } from "class-validator";
|
||||
|
||||
import { PaginationDto } from "../../../common/DTO/pagination.dto";
|
||||
import { CommonMessage } from "../../../common/enums/message.enum";
|
||||
import { TransferType } from "../enums/payment-type.enum";
|
||||
|
||||
export class PaymentTransactionQueryDto extends PaginationDto {
|
||||
@IsNotEmpty({ message: CommonMessage.PaymentTypeQueryNotEmpty })
|
||||
@IsEnum(TransferType)
|
||||
@ApiProperty({
|
||||
description: `payment type ${TransferType.CARD_TO_CARD} ${TransferType.SHEBA} `,
|
||||
enum: TransferType,
|
||||
example: TransferType.CARD_TO_CARD,
|
||||
})
|
||||
type: TransferType;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IsEnum, IsNotEmpty, IsOptional } from "class-validator";
|
||||
import { IsEnum, IsNotEmpty } from "class-validator";
|
||||
|
||||
import { GatewayEnum } from "../enums/gateway.enum";
|
||||
import { GatewayType } from "../types/gateway.type";
|
||||
@@ -8,10 +8,6 @@ export class VerifyParamDto {
|
||||
@IsNotEmpty()
|
||||
@IsEnum(GatewayEnum)
|
||||
gateway: GatewayType;
|
||||
|
||||
@IsOptional()
|
||||
@IsNotEmpty()
|
||||
invoiceId?: string;
|
||||
}
|
||||
|
||||
export class VerifyQueryDto {
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
export enum TransferType {
|
||||
CARD_TO_CARD = "CARD_TO_CARD",
|
||||
SHEBA = "SHEBA",
|
||||
// GATEWAY = "GATEWAY",
|
||||
}
|
||||
@@ -32,9 +32,9 @@ export class ZarinpalGateway implements IPaymentGateway {
|
||||
async processPayment(processParams: IProcessPaymentParams) {
|
||||
try {
|
||||
const purchaseData: ZarinPalPGNewArgs = {
|
||||
merchant_id: this.config.merchantId,
|
||||
merchant_id: processParams.merchantId,
|
||||
amount: processParams.amount,
|
||||
callback_url: `${this.config.callBackUrl}/${GatewayEnum.ZARINPAL}${processParams.invoiceId ? "/" + processParams.invoiceId : ""}`,
|
||||
callback_url: `${this.config.callBackUrl}/${GatewayEnum.ZARINPAL}`,
|
||||
description: processParams.description,
|
||||
currency: "IRT",
|
||||
metadata: { email: processParams.email, mobile: processParams.mobile },
|
||||
@@ -68,17 +68,15 @@ export class ZarinpalGateway implements IPaymentGateway {
|
||||
const verifyData = {
|
||||
authority: verifyParams.reference,
|
||||
amount: verifyParams.amount,
|
||||
merchant_id: this.config.merchantId,
|
||||
merchant_id: verifyParams.merchantId,
|
||||
};
|
||||
const { data } = await firstValueFrom(
|
||||
this.httpService
|
||||
.post<ZarinPalPGVerifyData>(`${this.gatewayApiUrl}/v4/payment/verify.json`, verifyData, { headers: this.requestHeader })
|
||||
.pipe(
|
||||
catchError((err: AxiosError) => {
|
||||
this.logger.error(err);
|
||||
throw new InternalServerErrorException(PaymentMessage.ERROR_IN_VERIFY_PAYMENT);
|
||||
}),
|
||||
),
|
||||
this.httpService.post<ZarinPalPGVerifyData>(`${this.gatewayApiUrl}/v4/payment/verify.json`, verifyData, { headers: this.requestHeader }).pipe(
|
||||
catchError((err: AxiosError) => {
|
||||
this.logger.error(err);
|
||||
throw new InternalServerErrorException(PaymentMessage.ERROR_IN_VERIFY_PAYMENT);
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
@@ -10,10 +10,10 @@ import { GatewayType } from "../types/gateway.type";
|
||||
export interface IProcessPaymentParams {
|
||||
amount: number;
|
||||
description: string;
|
||||
// callBackPath: string;
|
||||
callBackPath: string;
|
||||
merchantId: string;
|
||||
email?: string;
|
||||
mobile?: string;
|
||||
invoiceId?: string;
|
||||
}
|
||||
|
||||
export interface IProcessPaymentData {
|
||||
@@ -32,6 +32,7 @@ export interface IVerifyPayment {
|
||||
export interface IPaymentVerifyParams {
|
||||
amount: Decimal;
|
||||
reference: string;
|
||||
merchantId: string;
|
||||
// status: GatewayPaymentStatus;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,42 @@
|
||||
import { Controller } from "@nestjs/common";
|
||||
import { Body, Controller, Get, Param, Post, Query, Res } from "@nestjs/common";
|
||||
import { ApiOperation, ApiTags } from "@nestjs/swagger";
|
||||
import { FastifyReply } from "fastify";
|
||||
|
||||
import { CheckoutPaymentDto } from "./DTO/checkout-payment.dto";
|
||||
import { VerifyParamDto, VerifyQueryDto } from "./DTO/verify-payment.dto";
|
||||
import { PaymentsService } from "./services/payments.service";
|
||||
import { AuthGuards } from "../../common/decorators/auth-guard.decorator";
|
||||
import { UserDec } from "../../common/decorators/user.decorator";
|
||||
import { PaginationDto } from "../../common/DTO/pagination.dto";
|
||||
|
||||
@Controller("payments")
|
||||
export class PaymentsController {}
|
||||
@ApiTags("Payments")
|
||||
export class PaymentsController {
|
||||
constructor(private readonly paymentsService: PaymentsService) {}
|
||||
|
||||
@AuthGuards()
|
||||
@ApiOperation({ summary: "get all available gateways" })
|
||||
@Get("gateways")
|
||||
getAvailableGateways() {
|
||||
return this.paymentsService.getAvailableGateways();
|
||||
}
|
||||
|
||||
@ApiOperation({ summary: "Charge wallet ==> user route" })
|
||||
@AuthGuards()
|
||||
@Post("checkout")
|
||||
checkoutPayment(@Body() checkoutDto: CheckoutPaymentDto, @UserDec("id") userId: string) {
|
||||
return this.paymentsService.checkoutPayment(checkoutDto, userId);
|
||||
}
|
||||
|
||||
@ApiOperation({ summary: "get deposit gateway payment ==> admin route" })
|
||||
@AuthGuards()
|
||||
@Get("checkout/gateway")
|
||||
getDepositGatewayPayment(@Query() queryDto: PaginationDto) {
|
||||
return this.paymentsService.getDepositGatewayPayment(queryDto);
|
||||
}
|
||||
|
||||
@Get("verify/:gateway")
|
||||
verifyPayments(@Param() paramDto: VerifyParamDto, @Query() queryDto: VerifyQueryDto, @Res({ passthrough: true }) rep: FastifyReply) {
|
||||
return this.paymentsService.verifyPayment(paramDto, queryDto, rep);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,8 @@ import { PaymentsController } from "./payments.controller";
|
||||
import { PaymentProcessor } from "./queue/payment.processor";
|
||||
import { PaymentsService } from "./services/payments.service";
|
||||
import { zarinpalConfig } from "../../configs/zarinpal.config";
|
||||
import { InvoicesModule } from "../invoices/invoices.module";
|
||||
import { NotificationModule } from "../notifications/notifications.module";
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
MikroOrmModule.forFeature([Payment, PaymentGateway]),
|
||||
@@ -24,6 +24,7 @@ import { NotificationModule } from "../notifications/notifications.module";
|
||||
},
|
||||
}),
|
||||
NotificationModule,
|
||||
InvoicesModule,
|
||||
],
|
||||
controllers: [PaymentsController],
|
||||
providers: [
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { EntityManager } from "@mikro-orm/postgresql";
|
||||
import { InjectQueue, Processor } from "@nestjs/bullmq";
|
||||
import { Logger } from "@nestjs/common";
|
||||
import { ConfigService } from "@nestjs/config";
|
||||
import { Job, Queue } from "bullmq";
|
||||
import Decimal from "decimal.js";
|
||||
|
||||
@@ -16,15 +17,18 @@ import { PaymentJobData } from "../types/payment-job.type";
|
||||
@Processor(PAYMENT.QUEUE_NAME)
|
||||
export class PaymentProcessor extends WorkerProcessor {
|
||||
protected readonly logger = new Logger(PaymentProcessor.name);
|
||||
private readonly zarinpalMerchantId;
|
||||
|
||||
constructor(
|
||||
@InjectQueue(PAYMENT.QUEUE_NAME) private readonly paymentQueue: Queue,
|
||||
private readonly configService: ConfigService,
|
||||
private readonly gatewayFactory: PaymentGatewayFactory,
|
||||
private readonly em: EntityManager,
|
||||
private readonly notificationQueue: NotificationQueue,
|
||||
private readonly paymentsService: PaymentsService,
|
||||
) {
|
||||
super();
|
||||
this.zarinpalMerchantId = this.configService.getOrThrow<string>("ZARINPAL_MERCHANT_ID");
|
||||
}
|
||||
//===============================================
|
||||
async process(job: Job<PaymentJobData>) {
|
||||
@@ -177,7 +181,7 @@ export class PaymentProcessor extends WorkerProcessor {
|
||||
id: paymentId,
|
||||
},
|
||||
{
|
||||
populate: ["user", "paymentGateway"],
|
||||
populate: ["user", "paymentGateway", "business", "invoice"],
|
||||
},
|
||||
);
|
||||
|
||||
@@ -198,7 +202,11 @@ export class PaymentProcessor extends WorkerProcessor {
|
||||
|
||||
try {
|
||||
const gateway = this.gatewayFactory.getPaymentGateway(payment.paymentGateway.name);
|
||||
const verifyData = await gateway.verifyPayment({ reference: payment.reference, amount: payment.amount });
|
||||
const verifyData = await gateway.verifyPayment({
|
||||
reference: payment.reference,
|
||||
amount: payment.amount,
|
||||
merchantId: payment.business.zarinpalMerchantId || this.zarinpalMerchantId,
|
||||
});
|
||||
|
||||
const result = await this.paymentsService.processVerificationResult(verifyData, payment, em);
|
||||
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
import { LockMode } from "@mikro-orm/core";
|
||||
import { EntityManager } from "@mikro-orm/postgresql";
|
||||
import { EntityManager, LockMode } from "@mikro-orm/postgresql";
|
||||
import { InjectQueue } from "@nestjs/bullmq";
|
||||
import { BadRequestException, HttpStatus, Injectable, Logger } from "@nestjs/common";
|
||||
import { BadRequestException, HttpException, HttpStatus, Injectable, InternalServerErrorException, Logger } from "@nestjs/common";
|
||||
import { ConfigService } from "@nestjs/config";
|
||||
import { Queue } from "bullmq";
|
||||
import { Decimal } from "decimal.js";
|
||||
import Decimal from "decimal.js";
|
||||
import { FastifyReply as FRply } from "fastify";
|
||||
|
||||
import { PaymentMessage } from "../../../common/enums/message.enum";
|
||||
import { PaginationDto } from "../../../common/DTO/pagination.dto";
|
||||
import { InvoiceMessage, PaymentMessage, UserMessage } from "../../../common/enums/message.enum";
|
||||
import { Business } from "../../businesses/entities/business.entity";
|
||||
import { Invoice } from "../../invoices/entities/invoice.entity";
|
||||
import { InvoicesService } from "../../invoices/providers/invoices.service";
|
||||
import { User } from "../../users/entities/user.entity";
|
||||
import { PaginationUtils } from "../../utils/providers/pagination.utils";
|
||||
import { PAYMENT } from "../constants";
|
||||
import { CheckoutPaymentDto } from "../DTO/checkout-payment.dto";
|
||||
import { VerifyParamDto, VerifyQueryDto } from "../DTO/verify-payment.dto";
|
||||
import { PaymentGateway } from "../entities/payment-gateway.entity";
|
||||
import { Payment } from "../entities/payment.entity";
|
||||
@@ -25,15 +28,65 @@ import { GatewayType } from "../types/gateway.type";
|
||||
@Injectable()
|
||||
export class PaymentsService {
|
||||
private readonly logger = new Logger(PaymentsService.name);
|
||||
|
||||
private readonly zarinpalMerchantId;
|
||||
constructor(
|
||||
@InjectQueue(PAYMENT.QUEUE_NAME) private readonly paymentQueue: Queue,
|
||||
private readonly configService: ConfigService,
|
||||
private readonly gatewayFactory: PaymentGatewayFactory,
|
||||
private readonly paymentGatewaysRepository: PaymentGatewaysRepository,
|
||||
private readonly paymentsRepository: PaymentRepository,
|
||||
private readonly invoiceService: InvoicesService,
|
||||
private readonly em: EntityManager,
|
||||
) {}
|
||||
) {
|
||||
this.zarinpalMerchantId = this.configService.getOrThrow<string>("ZARINPAL_MERCHANT_ID");
|
||||
}
|
||||
|
||||
//===============================================
|
||||
async checkoutPayment(chargeDto: CheckoutPaymentDto, userId: string) {
|
||||
const em = this.em.fork();
|
||||
try {
|
||||
em.begin();
|
||||
|
||||
const { gatewayId, invoiceId } = chargeDto;
|
||||
|
||||
const user = await this.getUserById(userId, em);
|
||||
const paymentGateway = await this.getPaymentGatewayById(gatewayId, em);
|
||||
|
||||
const invoice = await em.findOne(Invoice, { id: invoiceId }, { populate: ["company", "business", "company.user"] });
|
||||
if (!invoice) throw new BadRequestException(InvoiceMessage.NOT_FOUND_BY_ID);
|
||||
|
||||
if (invoice.company.user.id !== user.id) throw new BadRequestException(InvoiceMessage.NOT_FOUND_BY_ID_OR_NOT_BELONG_TO_USER);
|
||||
|
||||
const gatewayData = await this.processPayment(paymentGateway.name, {
|
||||
amount: invoice.totalPrice.toNumber(),
|
||||
description: PaymentMessage.CHECKOUT_INVOICE_MESSAGE.replace("[invoiceNumber]", invoice.numericId.toString()),
|
||||
email: user.email,
|
||||
mobile: user.phone,
|
||||
callBackPath: invoice.business.slug,
|
||||
merchantId: invoice.business.zarinpalMerchantId || this.zarinpalMerchantId,
|
||||
});
|
||||
|
||||
const payment = await this.createGatewayPaymentForUser(
|
||||
user,
|
||||
invoice.totalPrice.toNumber(),
|
||||
gatewayData.reference,
|
||||
paymentGateway.id,
|
||||
invoice.business.id,
|
||||
invoice.id,
|
||||
em,
|
||||
);
|
||||
|
||||
await em.commit();
|
||||
return {
|
||||
payment,
|
||||
...gatewayData,
|
||||
};
|
||||
} catch (error) {
|
||||
await em.rollback();
|
||||
if (error instanceof HttpException) throw error;
|
||||
throw new InternalServerErrorException(PaymentMessage.ERROR_IN_PAYMENT);
|
||||
}
|
||||
}
|
||||
|
||||
//===============================================
|
||||
|
||||
@@ -44,8 +97,6 @@ export class PaymentsService {
|
||||
//===============================================
|
||||
|
||||
async verifyPayment(verifyParamDto: VerifyParamDto, queryDto: VerifyQueryDto, rep: FRply) {
|
||||
const frontUrl = this.buildFrontendRedirectUrl(verifyParamDto.invoiceId);
|
||||
|
||||
const em = this.em.fork();
|
||||
|
||||
try {
|
||||
@@ -53,6 +104,7 @@ export class PaymentsService {
|
||||
|
||||
const paymentGateway = this.gatewayFactory.getPaymentGateway(verifyParamDto.gateway);
|
||||
const payment = await this.getPaymentByReference(queryDto.Authority, em);
|
||||
const frontUrl = this.buildFrontendRedirectUrl(payment.business.slug);
|
||||
|
||||
if (payment.status === PaymentStatus.COMPLETED) throw new BadRequestException(PaymentMessage.VALIDATED_BEFORE);
|
||||
|
||||
@@ -61,6 +113,7 @@ export class PaymentsService {
|
||||
const verifyData = await paymentGateway.verifyPayment({
|
||||
reference: queryDto.Authority,
|
||||
amount: payment.amount,
|
||||
merchantId: payment.business.zarinpalMerchantId || this.zarinpalMerchantId,
|
||||
});
|
||||
|
||||
return await this.handlePaymentVerificationWithResponse(verifyData, payment, rep, frontUrl, em);
|
||||
@@ -111,33 +164,26 @@ export class PaymentsService {
|
||||
//===============================================
|
||||
private async processSuccessfulVerification(payment: Payment, refId: number, em: EntityManager) {
|
||||
// Regular wallet charge
|
||||
await this.handleSuccessfulPayment(payment, refId, em);
|
||||
const { invoice } = await this.handleSuccessfulPayment(payment, refId, em);
|
||||
|
||||
const additionalParams: Record<string, string> = {};
|
||||
|
||||
return {
|
||||
status: PaymentStatus.COMPLETED,
|
||||
payment,
|
||||
invoice,
|
||||
additionalParams,
|
||||
};
|
||||
}
|
||||
//===============================================
|
||||
|
||||
async createGatewayPaymentForUser(
|
||||
usr: User,
|
||||
amt: number,
|
||||
ref_Id: string,
|
||||
gatewayId: string,
|
||||
businessId: string,
|
||||
invoiceId: string,
|
||||
em: EntityManager,
|
||||
) {
|
||||
async createGatewayPaymentForUser(usr: User, amt: number, ref_Id: string, gatewayId: string, bunsId: string, invoiceId: string, em: EntityManager) {
|
||||
const payment = em.create(Payment, {
|
||||
amount: new Decimal(amt),
|
||||
reference: ref_Id,
|
||||
user: usr,
|
||||
paymentGateway: em.getReference(PaymentGateway, gatewayId),
|
||||
business: em.getReference(Business, businessId),
|
||||
business: em.getReference(Business, bunsId),
|
||||
invoice: em.getReference(Invoice, invoiceId),
|
||||
});
|
||||
|
||||
@@ -172,19 +218,38 @@ export class PaymentsService {
|
||||
await em.nativeUpdate(Payment, { id: payment.id }, { status: PaymentStatus.COMPLETED, transactionId: transactionId.toString() });
|
||||
|
||||
await this.removePaymentReminderJobs(payment.id);
|
||||
return await this.invoiceService.payInvoice(payment.invoice.id, payment.user.id, em);
|
||||
}
|
||||
|
||||
//===============================================
|
||||
|
||||
async getDepositGatewayPayment(queryDto: PaginationDto) {
|
||||
const { limit, skip } = PaginationUtils(queryDto);
|
||||
|
||||
const [payments, count] = await this.paymentsRepository.findAndCount(
|
||||
{ deletedAt: null },
|
||||
{
|
||||
populate: ["user", "paymentGateway"],
|
||||
orderBy: { createdAt: "DESC" },
|
||||
offset: skip,
|
||||
limit,
|
||||
},
|
||||
);
|
||||
|
||||
return {
|
||||
payments,
|
||||
count,
|
||||
paginate: true,
|
||||
};
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
//-private methods
|
||||
//----------------------------------------
|
||||
|
||||
private buildFrontendRedirectUrl(invoiceId?: string): URL {
|
||||
private buildFrontendRedirectUrl(businessSlug: string): URL {
|
||||
const frontUrl = new URL(this.configService.getOrThrow<string>("SITE_URL"));
|
||||
if (invoiceId) {
|
||||
frontUrl.pathname = "/receipts/" + invoiceId;
|
||||
} else {
|
||||
frontUrl.pathname = "/payment";
|
||||
}
|
||||
frontUrl.pathname = `/${businessSlug}/payment`;
|
||||
return frontUrl;
|
||||
}
|
||||
|
||||
@@ -206,11 +271,25 @@ export class PaymentsService {
|
||||
url.searchParams.append("date", payment.createdAt.toISOString());
|
||||
url.searchParams.append("amount", payment.amount.toString());
|
||||
}
|
||||
//===============================================
|
||||
|
||||
private async getUserById(userId: string, em: EntityManager): Promise<User> {
|
||||
const user = await em.findOne(User, { id: userId }, { populate: ["company"] });
|
||||
if (!user) throw new BadRequestException(UserMessage.USER_NOT_FOUND);
|
||||
return user;
|
||||
}
|
||||
//===============================================
|
||||
|
||||
private async getPaymentGatewayById(gatewayId: string, em: EntityManager): Promise<PaymentGateway> {
|
||||
const paymentGateway = await em.findOne(PaymentGateway, { id: gatewayId });
|
||||
if (!paymentGateway) throw new BadRequestException(PaymentMessage.PAYMENT_GATEWAY_NOT_FOUND);
|
||||
return paymentGateway;
|
||||
}
|
||||
|
||||
//===============================================
|
||||
|
||||
private async getPaymentByReference(reference: string, em: EntityManager): Promise<Payment> {
|
||||
const payment = await em.findOne(Payment, { reference }, { populate: ["user"], lockMode: LockMode.PESSIMISTIC_WRITE });
|
||||
const payment = await em.findOne(Payment, { reference }, { populate: ["user", "invoice", "business"], lockMode: LockMode.PESSIMISTIC_WRITE });
|
||||
if (!payment) throw new BadRequestException(PaymentMessage.PAYMENT_NOT_FOUND_WITH_REF);
|
||||
return payment;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user