Create model for payment module

master
nicekid1 2 months ago
parent 871fda173b
commit 3110dc9645
  1. 56
      migrations/20250108080238-create-payment-table.js
  2. 8
      src/invoice/invoice.controller.ts
  3. 41
      src/payment/entities/payment.entity.ts
  4. 31
      src/payment/payment.controller.ts
  5. 4
      src/payment/payment.module.ts
  6. 4
      src/payment/payment.service.ts
  7. 8
      src/wallet/wallet.controller.ts
  8. 10
      src/wallet/wallet.service.ts

@ -0,0 +1,56 @@
'use strict';
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.dropTable("Payments", { cascade: true });
await queryInterface.createTable('Payments', {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true,
allowNull: false,
},
userId: {
type: Sequelize.INTEGER,
allowNull: false,
references: {
model: 'Users',
key: 'id',
},
onDelete: 'CASCADE',
},
walletId: {
type: Sequelize.INTEGER,
allowNull: false,
references: {
model: 'Wallets',
key: 'id',
},
onDelete: 'CASCADE',
},
paymentAmount: {
type: Sequelize.INTEGER,
allowNull: false,
},
status: {
type: Sequelize.ENUM('completed', 'failed'),
allowNull: false,
defaultValue: 'failed',
},
paymentDate: {
type: Sequelize.DATE,
allowNull: false,
defaultValue: Sequelize.fn('NOW'),
},
updatedAt: {
type: Sequelize.DATE,
allowNull: false,
defaultValue: Sequelize.fn('NOW'),
},
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable('Payments');
},
};

@ -4,8 +4,8 @@ import { InvoiceService } from "./invoice.service";
@Controller("invoice")
export class InvoiceController {
constructor(private readonly invoiceService: InvoiceService) {}
// @Get(":userId")
// async getInvoices(@Param("userId") userId: number): Promise<any> {
// return this.invoiceService.getInvoicesByUser(userId);
// }
@Get(":userId")
async getInvoices(@Param("userId") userId: number): Promise<any> {
return this.invoiceService.getInvoiceByUser(userId);
}
}

@ -0,0 +1,41 @@
import { BelongsTo, Column, DataType, ForeignKey, Model, Table } from "sequelize-typescript";
import { User } from "src/users/entities/user.entity";
import { Wallet } from "src/wallet/entities/wallet.entity";
@Table
export class Payment extends Model<Payment> {
@ForeignKey(() => User)
@Column
userId: number;
@BelongsTo(() => User, { onDelete: "CASCADE" })
user: User;
@ForeignKey(() => Wallet)
@Column
walletId: number;
@BelongsTo(() => Wallet, { onDelete: "CASCADE" })
wallet: Wallet;
@Column({
type: DataType.INTEGER,
allowNull: false,
})
paymentAmount: number;
@Column({
type: DataType.ENUM( "completed", "failed",),
allowNull: false,
defaultValue: "failed",
})
status: string;
@Column({
type: DataType.DATE,
allowNull: false,
defaultValue: DataType.NOW,
})
paymentDate: Date;
}

@ -1,22 +1,24 @@
import { Controller, Post, Body, Param, Get, Query } from "@nestjs/common";
import { PaymentService } from "./payment.service";
import { CartService } from "../cart/cart.service";
import { InvoiceService } from "../invoice/invoice.service";
import { WalletService } from "src/wallet/wallet.service";
import { console } from "inspector";
import { InjectModel } from "@nestjs/sequelize";
import { Payment } from "./entities/payment.entity";
@Controller("payment")
export class PaymentController {
constructor(
private readonly wallet: WalletService,
@InjectModel(Payment) private readonly paymentModel: typeof Payment,
private readonly walletService: WalletService,
private readonly paymentService: PaymentService,
private readonly cartService: CartService,
private readonly invoiceService: InvoiceService,
) {}
@Post("request/:userId")
async requestPayment(@Param("userId") userId: number): Promise<{ url: string }> {
const invoice = await this.invoiceService.getInvoiceByUser(userId);
const totalAmount = Math.round(invoice.totalPaymentAmount);
const totalAmount = invoice.totalPaymentAmount;
const callbackUrl = `http://localhost:3000/payment/verify?userId=${userId}`;
const paymentUrl = await this.paymentService.requestPayment(totalAmount, "Purchase products", callbackUrl);
@ -34,15 +36,28 @@ export class PaymentController {
if (!userId) {
throw new Error("User ID is required.");
}
const invoice = await this.invoiceService.getInvoiceByUser(userId);
const totalAmount = invoice.totalPaymentAmount;
const wallet = this.walletService.getBalance(userId);
try {
const invoice = await this.invoiceService.getInvoiceByUser(userId);
const totalAmount = Math.round(invoice.totalPaymentAmount);
const refId = await this.paymentService.verifyPayment(Authority, totalAmount);
await this.wallet.addBalance(userId, totalAmount);
await this.walletService.addBalance(userId, totalAmount);
const wallet = this.walletService.getBalance(userId);
await this.paymentModel.create({
userId,
walletId: (await wallet).walletId,
paymentAmount: totalAmount,
status: "completed",
});
return { message: "Payment successful", refId };
} catch (error) {
console.log(error);
await this.paymentModel.create({
userId,
walletId: (await wallet).walletId,
paymentAmount: totalAmount,
status: "failed",
});
throw new Error(`Error during payment verification: ${error.message}`);
}
}

@ -5,9 +5,11 @@ import { InvoiceService } from 'src/invoice/invoice.service';
import { CartModule } from 'src/cart/cart.module';
import { WalletModule } from 'src/wallet/wallet.module';
import { InvoiceModule } from 'src/invoice/invoice.module';
import { Payment } from './entities/payment.entity';
import { SequelizeModule } from '@nestjs/sequelize';
@Module({
imports:[CartModule,WalletModule,InvoiceModule],
imports:[SequelizeModule.forFeature([Payment]),CartModule,WalletModule,InvoiceModule],
controllers: [PaymentController],
providers: [PaymentService],
})

@ -1,4 +1,6 @@
import { Injectable, InternalServerErrorException } from '@nestjs/common';
import { InjectModel } from '@nestjs/sequelize';
import { Payment } from './entities/payment.entity';
const ZarinpalCheckout = require('zarinpal-checkout');
@ -7,6 +9,7 @@ export class PaymentService {
private zarinpal;
constructor(
) {
this.zarinpal = this.initializeZarinpal();
}
@ -28,6 +31,7 @@ export class PaymentService {
if (result.status === 100) {
return result.url;
} else {
throw new Error(`Payment request failed with status: ${result.status}`);
}
} catch (error) {

@ -1,16 +1,12 @@
import { Controller, Get, Post, Body, Patch, Param, Delete } from "@nestjs/common";
import { WalletService } from "./wallet.service";
import { AddBalanceResponse } from "./add-balance-response.interface";
@Controller("wallet")
export class WalletController {
constructor(private readonly walletService: WalletService) {}
@Get(":userId")
async getBalance(@Param("userId") userId: number): Promise<number> {
async getBalance(@Param("userId") userId: number) {
return this.walletService.getBalance(userId);
}
@Post(":userId/add")
async addBalance(@Param("userId") userId: number, @Body("amount") amount: number): Promise<AddBalanceResponse> {
return this.walletService.addBalance(userId, amount);
}
}

@ -8,10 +8,16 @@ import { AddBalanceResponse } from "./add-balance-response.interface";
export class WalletService {
constructor(@InjectModel(Wallet) private walletModel: typeof Wallet) {}
async getBalance(userId: number): Promise<number> {
async getBalance(userId: number){
const wallet = await this.walletModel.findOne({ where: { userId } });
return wallet ? wallet.balance : 0;
if (!wallet) {
throw new HttpException("Wallet not found", HttpStatus.NOT_FOUND);
}
return { walletId:wallet.id, userId:wallet.userId ,balance: wallet.balance };
}
async addBalance(userId: number, amount: number): Promise<AddBalanceResponse> {
try {
const wallet = await this.walletModel.findOne({ where: { userId } });

Loading…
Cancel
Save