diff --git a/Dockerfile b/Dockerfile index bdce6d6..e1f6f57 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM node:22-alpine AS base RUN npm install -g corepack@latest -RUN corepack enable && corepack prepare pnpm@latest --activate +RUN corepack enable && corepack prepare pnpm@9 --activate # Install tzdata to support timezone settings RUN apk add --no-cache tzdata diff --git a/src/modules/payments/payments.controller.ts b/src/modules/payments/payments.controller.ts index e390647..e261c1b 100644 --- a/src/modules/payments/payments.controller.ts +++ b/src/modules/payments/payments.controller.ts @@ -1,5 +1,6 @@ -import { Body, Controller, Get, Param, Patch, Post, Query } from "@nestjs/common"; +import { Body, Controller, Get, Param, Patch, Post, Query, Res } from "@nestjs/common"; import { ApiOperation, ApiTags } from "@nestjs/swagger"; +import { FastifyReply } from "fastify"; import { CreateBankAccountDto } from "./DTO/create-bankaccount.dto"; import { GatewayDepositDto, TransferDepositDto } from "./DTO/deposit-wallet.dto"; @@ -87,8 +88,8 @@ export class PaymentsController { } @Get("verify/:gateway") - verifyPayment(@Param() paramDto: VerifyParamDto, @Query() queryDto: VerifyQueryDto) { - return this.paymentsService.verifyPayment(paramDto.gateway, queryDto); + verifyPayment(@Param() paramDto: VerifyParamDto, @Query() queryDto: VerifyQueryDto, @Res({ passthrough: true }) rep: FastifyReply) { + return this.paymentsService.verifyPayment(paramDto.gateway, queryDto, rep); } ///------------------- bank account ----------------------------- diff --git a/src/modules/payments/providers/payments.service.ts b/src/modules/payments/providers/payments.service.ts index 8f41a6c..8ca2adb 100644 --- a/src/modules/payments/providers/payments.service.ts +++ b/src/modules/payments/providers/payments.service.ts @@ -1,8 +1,10 @@ import { InjectQueue } from "@nestjs/bullmq"; -import { BadRequestException, HttpException, Injectable, InternalServerErrorException } from "@nestjs/common"; +import { BadRequestException, HttpException, HttpStatus, Injectable, InternalServerErrorException } from "@nestjs/common"; +import { ConfigService } from "@nestjs/config"; import { Queue } from "bullmq"; // eslint-disable-next-line import/no-named-as-default import Decimal from "decimal.js"; +import { FastifyReply } from "fastify"; import { DataSource, Not, QueryRunner } from "typeorm"; import { PaginationDto } from "../../../common/DTO/pagination.dto"; @@ -36,6 +38,7 @@ import { GatewayType } from "../types/gateway.type"; export class PaymentsService { constructor( @InjectQueue(PAYMENT.PAYMENT_QUEUE_NAME) private readonly paymentQueue: Queue, + private readonly configService: ConfigService, private readonly gatewayFactory: PaymentGatewayFactory, private readonly paymentGatewaysRepository: PaymentGatewaysRepository, private readonly paymentsRepository: PaymentsRepository, @@ -125,7 +128,10 @@ export class PaymentsService { //*********************************** */ //*********************************** */ - async verifyPayment(gateway: GatewayType, queryDto: VerifyQueryDto) { + async verifyPayment(gateway: GatewayType, queryDto: VerifyQueryDto, rep: FastifyReply) { + const frontUrl = new URL(this.configService.getOrThrow("SITE_URL")); + frontUrl.pathname = "/transactions"; + const queryRunner = this.dataSource.createQueryRunner(); await queryRunner.connect(); await queryRunner.startTransaction(); @@ -135,7 +141,6 @@ export class PaymentsService { 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); @@ -144,37 +149,40 @@ export class PaymentsService { if (queryDto.Status !== "OK") { await this.handleFailedPayment(payment.id, queryRunner); await queryRunner.commitTransaction(); - return { message: "nok" }; + frontUrl.searchParams.append("status", PaymentStatus.FAILED); + frontUrl.searchParams.append("id", payment.id); + frontUrl.searchParams.append("date", payment.createdAt.toISOString()); + frontUrl.searchParams.append("amount", payment.amount.toString()); + + return rep.status(HttpStatus.FOUND).redirect(frontUrl.toString()); } + 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 this.handleSuccessfulPayment(payment.id, payment.user.id, payment.amount, `${verifyData.ref_id}`, queryRunner); await queryRunner.commitTransaction(); - return { - message: "success", - transaction, - }; + frontUrl.searchParams.append("status", PaymentStatus.COMPLETED); + frontUrl.searchParams.append("id", payment.id); + frontUrl.searchParams.append("date", payment.createdAt.toISOString()); + frontUrl.searchParams.append("amount", payment.amount.toString()); + } else if (verifyData.code === 101) { + await queryRunner.commitTransaction(); + frontUrl.searchParams.append("status", PaymentStatus.PENDING); + frontUrl.searchParams.append("id", payment.id); + frontUrl.searchParams.append("date", payment.createdAt.toISOString()); + frontUrl.searchParams.append("amount", payment.amount.toString()); + } else { + await this.handleFailedPayment(payment.id, queryRunner); + await queryRunner.commitTransaction(); + frontUrl.searchParams.append("status", PaymentStatus.FAILED); + frontUrl.searchParams.append("id", payment.id); + frontUrl.searchParams.append("date", payment.createdAt.toISOString()); + frontUrl.searchParams.append("amount", payment.amount.toString()); } - if (verifyData.code === 101) { - await queryRunner.commitTransaction(); - - return { - message: "not valid payment", - }; - } - - await this.handleFailedPayment(payment.id, queryRunner); - await queryRunner.commitTransaction(); - - return { message: "nok" }; + console.log(frontUrl.toString()); + return rep.status(HttpStatus.FOUND).redirect(frontUrl.toString()); } catch (error) { await queryRunner.rollbackTransaction(); throw error; diff --git a/src/modules/users/providers/users.service.ts b/src/modules/users/providers/users.service.ts index 1b7daff..decec51 100644 --- a/src/modules/users/providers/users.service.ts +++ b/src/modules/users/providers/users.service.ts @@ -1,6 +1,6 @@ import { createHmac } from "node:crypto"; -import { BadRequestException, Injectable, Logger } from "@nestjs/common"; +import { BadRequestException, HttpStatus, Injectable, Logger } from "@nestjs/common"; import { ConfigService } from "@nestjs/config"; import { FastifyReply } from "fastify"; import slugify from "slugify"; @@ -159,6 +159,7 @@ export class UsersService { /************************************************************ */ //TODO:fix this later async verifyEmail(queryDto: EmailVerifyQueryDto, rep: FastifyReply) { + const frontUrl = this.configService.getOrThrow("FRONT_URL"); const { token, userId, ts } = queryDto; const user = await this.userRepository.findOneBy({ id: userId }); @@ -181,7 +182,7 @@ export class UsersService { await this.userRepository.save(user); // return { message: UserMessage.EMAIL_VERIFIED }; - return rep.redirect("https://google.com"); + return rep.status(HttpStatus.FOUND).redirect(frontUrl); } /************************************************************ */ diff --git a/src/modules/users/users.controller.ts b/src/modules/users/users.controller.ts index 96e18c8..892c6f1 100644 --- a/src/modules/users/users.controller.ts +++ b/src/modules/users/users.controller.ts @@ -68,7 +68,6 @@ export class UsersController { /************************************************************ */ @ApiOperation({ summary: "Verify email" }) - @HttpCode(HttpStatus.PERMANENT_REDIRECT) @Get("verify-email") verifyEmail(@Query() queryDto: EmailVerifyQueryDto, @Res({ passthrough: true }) rep: FastifyReply) { return this.usersService.verifyEmail(queryDto, rep);