import { HttpException, HttpStatus, Injectable, Logger } from "@nestjs/common"; import { PaymentDataAccess } from "../../dataAccess/payment.dataAccess"; import mongoose, { Mongoose, startSession } from "mongoose"; import { PaymentGateway } from "../IPG/PaymentGateway"; import { UserDataAccess } from "../../dataAccess/user.dataAccess"; import { PurchaseDataAccess } from "../../dataAccess/purchase.dataAccess"; import { CourseDataAccess } from "../../dataAccess/course.dataAccess"; import { PaymentStatus } from "../../common/eNums/paymentStatus.enum"; @Injectable() export class PaymentService { private readonly logger = new Logger(PaymentService.name); constructor( private readonly paymentDataAccess: PaymentDataAccess, private readonly paymentGateway: PaymentGateway, private readonly userDataAccess: UserDataAccess, private readonly purchaseDataAccess: PurchaseDataAccess, private readonly courseDataAccess: CourseDataAccess ) { } async createPayment(userId: string, courseId: string) { const session = await startSession(); session.startTransaction(); try { const user = await this.userDataAccess.findOne(userId); const course = await this.courseDataAccess.getOneCourse(courseId); if (!course) { throw new HttpException( { status: HttpStatus.BAD_REQUEST, error: 'دوره مورد نظر یافت نشد', }, HttpStatus.BAD_REQUEST, ); } const courseExists = user.courseIds.find(id => id.equals(courseId)); if (courseExists) { throw new HttpException( { status: HttpStatus.BAD_REQUEST, error: 'شما قبلا این دوره را خریداری کرده اید', }, HttpStatus.BAD_REQUEST, ); } if (course.price === 0) { // Handle free course registration const transactionNumber = `FREE-${Date.now()}-${Math.floor(Math.random() * 10000)}`; const payment = await this.paymentDataAccess.createPayment( userId, 0, courseId, transactionNumber, 'FREE', session ); await session.commitTransaction(); await this.purchaseDataAccess.createPurchase(payment.userId.toString(), payment.courseId.toString(), payment._id.toString()); payment.paymentStatus = PaymentStatus.Completed; await this.paymentDataAccess.updatePaymentStatus(payment._id.toString(), PaymentStatus.Completed); const registerCourse = await this.userDataAccess.registerCourse(payment.userId, payment.courseId); if (!registerCourse.success) { if (!payment) { throw new HttpException( { status: HttpStatus.BAD_REQUEST, error: 'درخواست خرید دوره با مشکل مواجه شد', }, HttpStatus.BAD_REQUEST, ); } } await session.commitTransaction(); await session.endSession(); return { success: true, payment: payment } } const paymentData = await this.paymentGateway.requestPayment({ amount: course.price, userId, callbackPath: "cart" }); if (!paymentData) { throw new HttpException( { status: HttpStatus.BAD_REQUEST, error: 'درخواست خرید دوره با مشکل مواجه شد', }, HttpStatus.BAD_REQUEST, ); } const transactionNumber = `DLR-${Date.now()}-${Math.floor(Math.random() * 10000)}`; const payment = await this.paymentDataAccess.createPayment( userId, course.price, //amount courseId, transactionNumber, paymentData.authority, session ); await session.commitTransaction(); await session.endSession(); return { payment: payment, paymentData } } catch (error) { await session.abortTransaction(); await session.endSession(); this.logger.warn(error); return error; } } async verifyPayment(authority: string, status: string) { const paymentData = await this.paymentDataAccess.getPaymentByAuthority(authority); if (!paymentData) { throw new Error("payment not found"); } const verifyData = await this.paymentGateway.verifyPayment({ authority, amount: paymentData.amount }); console.log({verifyData}) if (verifyData.code === 100 || verifyData.code === 101) { await this.purchaseDataAccess.createPurchase(paymentData.userId.toString(), paymentData.courseId.toString(), paymentData._id.toString()); paymentData.paymentStatus = PaymentStatus.Completed; await paymentData.save(); const registerCourse = await this.userDataAccess.registerCourse(paymentData.userId, paymentData.courseId); if (!registerCourse.success) { if (!paymentData) { throw new HttpException( { status: HttpStatus.BAD_REQUEST, error: 'درخواست خرید دوره با مشکل مواجه شد', }, HttpStatus.BAD_REQUEST, ); } } return { success: true, payment: paymentData, verifyData } } } async getPayments() { return this.paymentDataAccess.getPayments(); } async getPaymentsByUser(userId: string) { return this.paymentDataAccess.getPaymentsByUserId(userId); } }