chore: complete the payment service

This commit is contained in:
mahyargdz
2025-02-04 16:12:33 +03:30
parent 5d91afcc6e
commit 626206c389
25 changed files with 296 additions and 82 deletions
+1
View File
@@ -1,6 +1,7 @@
# Stage 1: Build Stage
FROM node:22-alpine AS base
RUN npm install -g corepack@latest
RUN corepack enable && corepack prepare pnpm@latest --activate
# Install tzdata to support timezone settings
+1
View File
@@ -55,6 +55,7 @@
"cache-manager": "^6.3.2",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"decimal.js": "^10.5.0",
"dotenv": "^16.4.7",
"fastify": "^5.2.1",
"handlebars": "^4.7.8",
+8
View File
@@ -86,6 +86,9 @@ importers:
class-validator:
specifier: ^0.14.1
version: 0.14.1
decimal.js:
specifier: ^10.5.0
version: 10.5.0
dotenv:
specifier: ^16.4.7
version: 16.4.7
@@ -2277,6 +2280,9 @@ packages:
supports-color:
optional: true
decimal.js@10.5.0:
resolution: {integrity: sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==}
dedent@1.5.3:
resolution: {integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==}
peerDependencies:
@@ -8316,6 +8322,8 @@ snapshots:
dependencies:
ms: 2.1.3
decimal.js@10.5.0: {}
dedent@1.5.3: {}
deep-extend@0.6.0:
+3 -1
View File
@@ -1,13 +1,14 @@
import { FastifyMulterModule } from "@nest-lab/fastify-multer";
import { HttpModule } from "@nestjs/axios";
import { BullModule } from "@nestjs/bullmq";
import { CacheModule } from "@nestjs/cache-manager";
import { MiddlewareConsumer, Module, NestModule } from "@nestjs/common";
import { ConfigModule } from "@nestjs/config";
import { ThrottlerModule } from "@nestjs/throttler";
import { TypeOrmModule } from "@nestjs/typeorm";
import { bullMqConfig } from "./configs/bullmq.config";
import { cacheConfig } from "./configs/cache.config";
// import { httpConfig } from "./configs/http.config";
import { rateLimitConfig } from "./configs/rateLimit.config";
import { databaseConfigs } from "./configs/typeorm.config";
import { HTTPLogger } from "./core/middlewares/logger.middleware";
@@ -25,6 +26,7 @@ import { WalletsModule } from "./modules/wallets/wallets.module";
@Module({
imports: [
BullModule.forRootAsync(bullMqConfig()),
ThrottlerModule.forRootAsync(rateLimitConfig()),
ConfigModule.forRoot({ cache: true, isGlobal: true }),
CacheModule.registerAsync(cacheConfig()),
-4
View File
@@ -2,7 +2,3 @@
export const AUTH_THROTTLE_TTL = 5 * 60 * 1000;
export const AUTH_THROTTLE_LIMIT = 5;
export const JWT_STRATEGY_NAME = "jwt_Strategy";
export const PAYMENT = Object.freeze({
PAYMENT_QUEUE: "payment",
});
@@ -0,0 +1,5 @@
import { InjectQueue } from "@nestjs/bullmq";
import { PAYMENT } from "../../modules/payments/constants";
export const InjectPaymentQueue = () => InjectQueue(PAYMENT.PAYMENT_QUEUE_NAME);
+1
View File
@@ -202,6 +202,7 @@ export const enum PaymentMessage {
PAYMENT_GATEWAY_NOT_FOUND = "درگاه پرداخت یافت نشد",
ERROR_IN_PROCESS_PAYMENT = "خطا در پردازش پرداخت",
ERROR_IN_VERIFY_PAYMENT = "خطا در تایید پرداخت",
PAYMENT_NOT_FOUND_WITH_REF = "پرداختی با این شناسه یافت نشد",
}
export const enum SettingMessageEnum {
@@ -0,0 +1,16 @@
// eslint-disable-next-line import/no-named-as-default
import Decimal from "decimal.js";
export class DecimalTransformer {
to(value: Decimal | string | number): string {
return new Decimal(value).toString();
}
from(value: string): number {
return new Decimal(value).toNumber();
}
}
export function decimal(value: Decimal | number | string): number {
return new Decimal(value).toNumber();
}
@@ -2,7 +2,7 @@ import { ApiProperty } from "@nestjs/swagger";
import { IsEnum, IsInt, IsNotEmpty, IsUUID, IsUrl, Min } from "class-validator";
import { WalletMessage } from "../../../common/enums/message.enum";
import { GatewayEnum } from "../../payments/enums/gateway.enum";
import { GatewayEnum } from "../enums/gateway.enum";
export class DepositDto {
@IsNotEmpty({ message: WalletMessage.AMOUNT_REQUIRED })
@@ -0,0 +1,19 @@
import { IsEnum, IsNotEmpty } from "class-validator";
import { GatewayEnum } from "../enums/gateway.enum";
import { GatewayType } from "../types/gateway.type";
import { GatewayPaymentStatus } from "../types/payment-status.type";
export class VerifyParamDto {
@IsNotEmpty()
@IsEnum(GatewayEnum)
gateway: GatewayType;
}
export class VerifyQueryDto {
@IsNotEmpty()
Authority: string;
@IsNotEmpty()
Status: GatewayPaymentStatus;
}
+5
View File
@@ -1 +1,6 @@
export const ZARINPAL_CONFIG = "ZARINPAL_CONFIG";
export const PAYMENT = Object.freeze({
PAYMENT_QUEUE_NAME: "payment",
PAYMENT_START: "payment_start",
});
@@ -1,15 +1,18 @@
// eslint-disable-next-line import/no-named-as-default
import Decimal from "decimal.js";
import { Column, Entity, ManyToOne } from "typeorm";
import { PaymentMethod } from "./payment-method.entity";
import { BaseEntity } from "../../../common/entities/base.entity";
import { DecimalTransformer } from "../../../common/transformers/decimal.transformer";
import { User } from "../../users/entities/user.entity";
import { PaymentStatus } from "../enums/payment-status.enum";
import { PaymentType } from "../enums/payment-type.enum";
@Entity()
export class Payment extends BaseEntity {
@Column({ type: "decimal", precision: 10, scale: 2 })
amount: number;
@Column({ type: "decimal", precision: 16, scale: 2, nullable: false, transformer: new DecimalTransformer() })
amount: Decimal;
@Column({ type: "varchar", length: 150, nullable: false })
reference: string;
@@ -66,11 +66,14 @@ export class ZarinpalGateway implements IPaymentGateway {
//********************************** */
async verifyPayment(verifyParams: IPaymentVerifyParams) {
try {
const verifyData = { authority: verifyParams.reference, amount: verifyParams.amount, merchant_id: this.config.merchantId };
const verifyData = {
authority: verifyParams.reference,
amount: verifyParams.amount,
merchant_id: this.config.merchantId,
};
const { data } = await firstValueFrom(
this.httpService
.post<ZarinPalPGVerifyData>(`${this.config.gatewayApiUrl}/v4/payment/verify.json`, verifyData, { headers: this.requestHeader })
.post<ZarinPalPGVerifyData>(`${this.gatewayApiUrl}/v4/payment/verify.json`, verifyData, { headers: this.requestHeader })
.pipe(
catchError((err: AxiosError) => {
this.logger.error(err);
@@ -89,6 +92,7 @@ export class ZarinpalGateway implements IPaymentGateway {
fee: data.data.fee,
};
} catch (error) {
console.error({ error });
this.logger.error(error);
throw new InternalServerErrorException(PaymentMessage.ERROR_IN_VERIFY_PAYMENT);
}
+5 -1
View File
@@ -1,5 +1,8 @@
//------------------ process payment -------------------------
// eslint-disable-next-line import/no-named-as-default
import Decimal from "decimal.js";
export interface IProcessPaymentParams {
amount: number;
description: string;
@@ -22,8 +25,9 @@ export interface IPaymentVerifyData {
}
export interface IPaymentVerifyParams {
amount: number;
amount: Decimal;
reference: string;
// status: GatewayPaymentStatus;
}
//--------------------- zarinpal --------------------------------
+18 -3
View File
@@ -1,8 +1,13 @@
import { Controller, Get } from "@nestjs/common";
import { Body, Controller, Get, Param, Post, Query } from "@nestjs/common";
import { ApiOperation, ApiTags } from "@nestjs/swagger";
import { GatewayDepositDto } from "./DTO/deposit-wallet.dto";
import { VerifyParamDto, VerifyQueryDto } from "./DTO/verify-payment.dto";
import { PaymentsService } from "./providers/payments.service";
import { AuthGuards } from "../../common/decorators/auth-guard.decorator";
import { Roles } from "../../common/decorators/roles.decorator";
import { UserDec } from "../../common/decorators/user.decorator";
import { RoleEnum } from "../users/enums/role.enum";
@Controller("payments")
@ApiTags("Payments")
@@ -16,6 +21,16 @@ export class PaymentsController {
return this.paymentsService.getAvailableGateways();
}
@Get("verify")
verifyPayment() {}
@ApiOperation({ summary: "Charge wallet ==> user route" })
@AuthGuards()
@Roles(RoleEnum.USER)
@Post("deposit/gateway")
chargeWalletWithGateway(@Body() chargeDto: GatewayDepositDto, @UserDec("id") userId: string) {
return this.paymentsService.chargeWalletWithGateway(chargeDto, userId);
}
@Get("verify/:gateway")
verifyPayment(@Param() paramDto: VerifyParamDto, @Query() queryDto: VerifyQueryDto) {
return this.paymentsService.verifyPayment(paramDto.gateway, queryDto);
}
}
+10 -2
View File
@@ -1,7 +1,8 @@
import { BullModule } from "@nestjs/bullmq";
import { Module } from "@nestjs/common";
import { TypeOrmModule } from "@nestjs/typeorm";
import { ZARINPAL_CONFIG } from "./constants";
import { PAYMENT, ZARINPAL_CONFIG } from "./constants";
import { BankAccount } from "./entities/bank-account.entity";
import { PaymentMethod } from "./entities/payment-method.entity";
import { Payment } from "./entities/payment.entity";
@@ -9,12 +10,18 @@ import { PaymentGatewayFactory } from "./factories/payment.factory";
import { ZarinpalGateway } from "./gateways/zarinpal.gateway";
import { PaymentsController } from "./payments.controller";
import { PaymentsService } from "./providers/payments.service";
import { PaymentProcessor } from "./queue/payment.processor";
import { BankAccountsRepository } from "./repositories/bank-accounts.repository";
import { PaymentsRepository } from "./repositories/payments.repository";
import { zarinpalConfig } from "../../configs/zarinpal.config";
import { WalletsModule } from "../wallets/wallets.module";
@Module({
imports: [TypeOrmModule.forFeature([Payment, PaymentMethod, BankAccount])],
imports: [
TypeOrmModule.forFeature([Payment, PaymentMethod, BankAccount]),
BullModule.registerQueue({ name: PAYMENT.PAYMENT_QUEUE_NAME }),
WalletsModule,
],
controllers: [PaymentsController],
providers: [
PaymentsService,
@@ -22,6 +29,7 @@ import { zarinpalConfig } from "../../configs/zarinpal.config";
ZarinpalGateway,
PaymentsRepository,
BankAccountsRepository,
PaymentProcessor,
{
provide: ZARINPAL_CONFIG,
useFactory: zarinpalConfig().useFactory,
@@ -1,27 +1,138 @@
import { Injectable } from "@nestjs/common";
import { QueryRunner } from "typeorm";
import { InjectQueue } from "@nestjs/bullmq";
import { BadRequestException, HttpException, Injectable, InternalServerErrorException } from "@nestjs/common";
import { Queue } from "bullmq";
// eslint-disable-next-line import/no-named-as-default
import Decimal from "decimal.js";
import { DataSource, QueryRunner } from "typeorm";
import { WalletMessage } from "../../../common/enums/message.enum";
import { PaymentMessage, WalletMessage } from "../../../common/enums/message.enum";
import { User } from "../../users/entities/user.entity";
import { Wallet } from "../../wallets/entities/wallet.entity";
import { WalletsService } from "../../wallets/providers/wallets.service";
import { PAYMENT } from "../constants";
import { GatewayDepositDto } from "../DTO/deposit-wallet.dto";
import { VerifyQueryDto } from "../DTO/verify-payment.dto";
import { PaymentMethod } from "../entities/payment-method.entity";
import { Payment } from "../entities/payment.entity";
import { PaymentStatus } from "../enums/payment-status.enum";
import { PaymentType } from "../enums/payment-type.enum";
import { PaymentGatewayFactory } from "../factories/payment.factory";
// import { PaymentsRepository } from "../repositories/payments.repository";
import { PaymentsRepository } from "../repositories/payments.repository";
import { GatewayType } from "../types/gateway.type";
@Injectable()
export class PaymentsService {
constructor(
@InjectQueue(PAYMENT.PAYMENT_QUEUE_NAME) private readonly paymentQueue: Queue,
private readonly gatewayFactory: PaymentGatewayFactory,
// private readonly paymentsRepository: PaymentsRepository,
private readonly paymentsRepository: PaymentsRepository,
private readonly walletsService: WalletsService,
private dataSource: DataSource,
) {}
//*********************************** */
async chargeWalletWithGateway(chargeDto: GatewayDepositDto, userId: string) {
const queryRunner = this.dataSource.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();
try {
const { amount, gateway } = chargeDto;
const wallet = await queryRunner.manager.findOne(Wallet, { where: { user: { id: userId } }, relations: ["user"] });
if (!wallet) throw new BadRequestException(WalletMessage.WALLET_NOT_FOUND);
const gatewayData = await this.processPayment(
gateway,
amount,
WalletMessage.DEPOSIT_WALLET_IPG,
wallet.user.email,
wallet.user.phone,
);
const payment = await this.createPaymentForUser(wallet.user, amount, gatewayData.reference, gateway, queryRunner);
await queryRunner.commitTransaction();
return {
payment,
...gatewayData,
};
} catch (error) {
await queryRunner.rollbackTransaction();
if (error instanceof HttpException) throw error;
throw new InternalServerErrorException(WalletMessage.ERROR_IN_CHARGE_WALLET);
} finally {
await queryRunner.release();
}
}
//*********************************** */
//*********************************** */
async processPayment(provider: GatewayType, amount: number, description: string, email?: string, mobile?: string) {
const paymentGateway = this.gatewayFactory.getPaymentGateway(provider);
return paymentGateway.processPayment({ amount, description, email, mobile });
}
//*********************************** */
//*********************************** */
async verifyPayment(gateway: GatewayType, queryDto: VerifyQueryDto) {
const queryRunner = this.dataSource.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();
try {
const paymentGateway = this.gatewayFactory.getPaymentGateway(gateway);
const payment = await queryRunner.manager.findOne(Payment, {
where: { reference: queryDto.Authority },
relations: ["user"],
// lock: { mode: "pessimistic_write" },
});
if (!payment) throw new BadRequestException(PaymentMessage.PAYMENT_NOT_FOUND_WITH_REF);
if (payment.status === PaymentStatus.COMPLETED) {
return {
message: "completed before",
};
}
if (queryDto.Status !== "OK") {
await this.handleFailedPayment(payment.id, queryRunner);
await queryRunner.commitTransaction();
return { message: "nok" };
}
const verifyData = await paymentGateway.verifyPayment({ reference: queryDto.Authority, amount: payment.amount });
//
if (verifyData.code === 100) {
const transaction = await this.handleSuccessfulPayment(
payment.id,
payment.user.id,
payment.amount,
`${verifyData.ref_id}`,
queryRunner,
);
await queryRunner.commitTransaction();
return {
message: "success",
transaction,
};
}
if (verifyData.code === 101) {
await queryRunner.commitTransaction();
return {
message: "not valid payment",
};
}
await this.handleFailedPayment(payment.id, queryRunner);
await queryRunner.commitTransaction();
return { message: "nok" };
} catch (error) {
await queryRunner.rollbackTransaction();
throw error;
} finally {
await queryRunner.release();
}
}
//*********************************** */
//*********************************** */
async createPaymentForUser(user: User, amount: number, reference: string, gateway: GatewayType, queryRunner: QueryRunner) {
@@ -39,8 +150,9 @@ export class PaymentsService {
user,
paymentMethod,
});
await queryRunner.manager.save(Payment, payment);
this.paymentQueue.add(PAYMENT.PAYMENT_START, { payment }, { delay: 1000 });
return payment;
}
//*********************************** */
@@ -48,4 +160,25 @@ export class PaymentsService {
async getAvailableGateways() {
return this.gatewayFactory.getAvailablePaymentGateways();
}
//*********************************** */
//*********************************** */
async getPaymentWithReference(reference: string) {
const payment = await this.paymentsRepository.findOneWithReference(reference);
if (!payment) throw new BadRequestException(PaymentMessage.PAYMENT_NOT_FOUND_WITH_REF);
return { payment };
}
//*********************************** */
//*********************************** */
async handleFailedPayment(paymentId: string, queryRunner: QueryRunner) {
await queryRunner.manager.update(Payment, { id: paymentId }, { status: PaymentStatus.CANCELLED });
}
//*********************************** */
async handleSuccessfulPayment(paymentId: string, userId: string, amount: Decimal, transactionId: string, queryRunner: QueryRunner) {
await queryRunner.manager.update(Payment, { id: paymentId }, { status: PaymentStatus.COMPLETED, transactionId });
const transaction = await this.walletsService.createPaymentTransaction(userId, amount, queryRunner);
return transaction;
}
}
@@ -2,10 +2,10 @@ import { Processor } from "@nestjs/bullmq";
import { Logger } from "@nestjs/common";
import { Job } from "bullmq";
import { PAYMENT } from "../../../common/constants";
import { WorkerProcessor } from "../../../common/queues/worker.processor";
import { PAYMENT } from "../constants";
@Processor(PAYMENT.PAYMENT_QUEUE)
@Processor(PAYMENT.PAYMENT_QUEUE_NAME)
export class PaymentProcessor extends WorkerProcessor {
protected readonly logger = new Logger(PaymentProcessor.name);
@@ -9,4 +9,8 @@ export class PaymentsRepository extends Repository<Payment> {
constructor(@InjectRepository(Payment) paymentsRepository: Repository<Payment>) {
super(paymentsRepository.target, paymentsRepository.manager, paymentsRepository.queryRunner);
}
async findOneWithReference(reference: string): Promise<Payment | null> {
return this.findOneBy({ reference });
}
}
@@ -0,0 +1 @@
export type GatewayPaymentStatus = "OK" | "NOK";
@@ -1,16 +1,22 @@
// eslint-disable-next-line import/no-named-as-default
import Decimal from "decimal.js";
import { Column, Entity, ManyToOne } from "typeorm";
import { Wallet } from "./wallet.entity";
import { BaseEntity } from "../../../common/entities/base.entity";
import { DecimalTransformer } from "../../../common/transformers/decimal.transformer";
import { TransactionType } from "../enums/transaction-type.enum";
@Entity()
export class WalletTransaction extends BaseEntity {
@Column({ type: "int", generated: "identity", insert: false })
numericId: number;
@ManyToOne(() => Wallet, (wallet) => wallet.transactions, { onDelete: "CASCADE", nullable: false })
wallet: Wallet;
@Column({ type: "decimal", precision: 10, scale: 2, nullable: false })
amount: number;
@Column({ type: "decimal", precision: 16, scale: 2, nullable: false, transformer: new DecimalTransformer() })
amount: Decimal;
@Column({ type: "enum", enum: TransactionType, nullable: false })
type: TransactionType;
@@ -1,7 +1,10 @@
// eslint-disable-next-line import/no-named-as-default
import Decimal from "decimal.js";
import { Column, Entity, JoinColumn, OneToMany, OneToOne } from "typeorm";
import { WalletTransaction } from "./transaction.entity";
import { BaseEntity } from "../../../common/entities/base.entity";
import { DecimalTransformer } from "../../../common/transformers/decimal.transformer";
import { User } from "../../users/entities/user.entity";
@Entity()
@@ -10,8 +13,8 @@ export class Wallet extends BaseEntity {
@JoinColumn()
user: User;
@Column({ type: "decimal", precision: 10, scale: 2, default: 0 })
balance: number;
@Column({ type: "decimal", precision: 16, scale: 2, default: 0, transformer: new DecimalTransformer() })
balance: Decimal;
@OneToMany(() => WalletTransaction, (transaction) => transaction.wallet)
transactions: WalletTransaction[];
@@ -1,19 +1,17 @@
import { BadRequestException, HttpException, Injectable, InternalServerErrorException } from "@nestjs/common";
import { DataSource, QueryRunner } from "typeorm";
import { BadRequestException, Injectable } from "@nestjs/common";
// eslint-disable-next-line import/no-named-as-default
import Decimal from "decimal.js";
import { QueryRunner } from "typeorm";
import { WalletMessage } from "../../../common/enums/message.enum";
import { PaymentsService } from "../../payments/providers/payments.service";
import { GatewayDepositDto } from "../DTO/deposit-wallet.dto";
import { WalletTransaction } from "../entities/transaction.entity";
import { Wallet } from "../entities/wallet.entity";
import { TransactionType } from "../enums/transaction-type.enum";
import { WalletsRepository } from "../repositories/wallets.repository";
@Injectable()
export class WalletsService {
constructor(
private readonly walletsRepository: WalletsRepository,
private readonly paymentsService: PaymentsService,
private readonly dataSource: DataSource,
) {}
constructor(private readonly walletsRepository: WalletsRepository) {}
//*********************************** */
async getBalance(userId: string) {
@@ -24,41 +22,6 @@ export class WalletsService {
balance: wallet.balance,
};
}
//*********************************** */
async chargeWalletWithGateway(chargeDto: GatewayDepositDto, userId: string) {
const queryRunner = this.dataSource.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();
try {
const { amount, gateway } = chargeDto;
const wallet = await queryRunner.manager.findOne(Wallet, { where: { user: { id: userId } }, relations: ["user"] });
if (!wallet) throw new BadRequestException(WalletMessage.WALLET_NOT_FOUND);
const gatewayData = await this.paymentsService.processPayment(
gateway,
amount,
WalletMessage.DEPOSIT_WALLET_IPG,
wallet.user.email,
wallet.user.phone,
);
console.log(gatewayData);
const payment = await this.paymentsService.createPaymentForUser(wallet.user, amount, gatewayData.reference, gateway, queryRunner);
await queryRunner.commitTransaction();
return {
payment,
...gatewayData,
};
} catch (error) {
await queryRunner.rollbackTransaction();
if (error instanceof HttpException) throw error;
throw new InternalServerErrorException(WalletMessage.ERROR_IN_CHARGE_WALLET);
} finally {
await queryRunner.release();
}
}
//*********************************** */
async createUserWallet(userId: string, queryRunner: QueryRunner) {
@@ -67,4 +30,24 @@ export class WalletsService {
//
return wallet;
}
//*********************************** */
async createPaymentTransaction(userId: string, amount: Decimal, queryRunner: QueryRunner) {
const wallet = await queryRunner.manager.findOne(Wallet, { where: { user: { id: userId } }, lock: { mode: "pessimistic_write" } });
if (!wallet) throw new BadRequestException(WalletMessage.WALLET_NOT_FOUND);
const transaction = queryRunner.manager.create(WalletTransaction, {
amount,
wallet,
type: TransactionType.DEPOSIT,
description: WalletMessage.DEPOSIT_WALLET_IPG,
});
wallet.balance = new Decimal(wallet.balance).add(transaction.amount);
await queryRunner.manager.save(Wallet, wallet);
await queryRunner.manager.save(WalletTransaction, transaction);
return transaction;
}
//*********************************** */
}
+4 -7
View File
@@ -1,7 +1,6 @@
import { Body, Controller, Get, Post } from "@nestjs/common";
import { Controller, Get } from "@nestjs/common";
import { ApiOperation, ApiTags } from "@nestjs/swagger";
import { GatewayDepositDto } from "./DTO/deposit-wallet.dto";
import { WalletsService } from "./providers/wallets.service";
import { AuthGuards } from "../../common/decorators/auth-guard.decorator";
import { Roles } from "../../common/decorators/roles.decorator";
@@ -21,11 +20,9 @@ export class WalletsController {
return this.walletsService.getBalance(userId);
}
@ApiOperation({ summary: "Charge wallet ==> user route" })
@ApiOperation({ summary: "get wallet transactions" })
@AuthGuards()
@Roles(RoleEnum.USER)
@Post("deposit/gateway")
chargeWalletWithGateway(@Body() chargeDto: GatewayDepositDto, @UserDec("id") userId: string) {
return this.walletsService.chargeWalletWithGateway(chargeDto, userId);
}
@Get("transactions")
getTransactions() {}
}
+1 -2
View File
@@ -7,10 +7,9 @@ import { WalletsService } from "./providers/wallets.service";
import { WalletTransactionsRepository } from "./repositories/wallet-transactions.repository";
import { WalletsRepository } from "./repositories/wallets.repository";
import { WalletsController } from "./wallets.controller";
import { PaymentsModule } from "../payments/payments.module";
@Module({
imports: [TypeOrmModule.forFeature([Wallet, WalletTransaction]), PaymentsModule],
imports: [TypeOrmModule.forFeature([Wallet, WalletTransaction])],
providers: [WalletsService, WalletsRepository, WalletTransactionsRepository],
controllers: [WalletsController],
exports: [WalletsService],