154 lines
5.3 KiB
TypeScript
154 lines
5.3 KiB
TypeScript
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);
|
|
}
|
|
}
|