providers

This commit is contained in:
Eyosiyas
2026-06-06 11:32:14 +03:00
parent 06276764e0
commit b5f64bc9ad
8 changed files with 107 additions and 79 deletions

View File

@@ -1,36 +1,42 @@
import { Controller, Get, NotFoundException, Param, ParseUUIDPipe, Post, Res } from "@nestjs/common";
import { PaymentService } from "./payment.service";
import { Public } from "@edr/api-common";
import { randomUUID } from "crypto";
// import { randomUUID } from "crypto";
import { Response } from "express"
@Public()
@Controller("payments")
export class PaymentController {
constructor(private readonly paymentService: PaymentService) { }
constructor(private readonly paymentService: PaymentService,) { }
@Get("/receipts/:orderId/html")
async genReceipt(@Param("orderId") orderId: string, @Res() res: Response) {
const filled = await this.paymentService.genReceiptHtml(orderId);
return res.send(filled)
}
// @Get("/receipts/:orderId/html")
// async genReceipt(@Param("orderId") orderId: string, @Res() res: Response) {
// const filled = await this.paymentService.genReceiptHtml(orderId);
// return res.send(filled)
// }
@Post("/initiate/booking")
async initiatePayment() {
// @Post("/initiate/booking")
// async initiatePayment() {
//Only for testing..
const description = "booking"
const data = await this.paymentService.pay(20, "ETB", "telebirr", description, "booking", (_) => {
return new Promise((resp, _) => {
resp({
id: randomUUID(),
type: "booking"
})
});
})
// //Only for testing..
// const description = "Booking for contact"
// const price = 2000
// const data = await this.paymentService.pay(price, "ETB", "telebirr", description, "booking", (_) => {
// return new Promise((resp, _) => {
// resp({
// id: randomUUID(),
// type: "booking"
// })
// });
// })
return data
// return data
// }
@Post("/bookings/check-payment/:orderId")
checkPayment(@Param("orderId", ParseUUIDPipe) orderId: string) {
return this.paymentService.checkStatusAndUpdate(orderId)
}

View File

@@ -7,11 +7,11 @@ import { ConfigModule } from "@nestjs/config";
import { PaymentRepository } from "./payment.repository";
import { WebhookController } from "./webhooks/webhook.controller";
import { TelebirrWebhookService } from "./webhooks/providers/telebirr.service";
import { BookingsModule } from "../bookings/bookings.module";
@Module({
imports: [HttpModule, ConfigModule, BookingsModule],
imports: [HttpModule, ConfigModule],
providers: [PaymentRepository, PaymentTelebirrStrategy, PaymentService, TelebirrWebhookService],
controllers: [PaymentController, WebhookController]
controllers: [PaymentController, WebhookController],
exports: [PaymentService]
})
export class PaymentModule { }

View File

@@ -10,6 +10,8 @@ import * as crypto from 'crypto';
import * as fs from 'fs';
import * as path from 'path';
import * as Handlebars from 'handlebars';
import { ConfigService } from "@nestjs/config";
import { Booking } from "../bookings/entities/booking.entity";
type PaymentMethod = PaymentEntity["method"]
@@ -20,6 +22,7 @@ export class PaymentService {
private strategies: Map<PaymentMethod, PaymentStrategy>;
constructor(
private readonly configService: ConfigService,
private readonly datasource: DataSource,
private readonly paymentRepo: PaymentRepository,
private readonly telebirrPaymentStategy: PaymentTelebirrStrategy) {
@@ -47,7 +50,8 @@ export class PaymentService {
let redirectUrl: string;
switch (type) {
case "booking":
redirectUrl = `http://localhost:3001/api/payments/receipts/${orderId}/html`
const url = this.configService.get<string>("TELEBIRR_SUCCESS_REDIRECT_BASE_URL")
redirectUrl = `${url}/check-status/${orderId}`
break;
}
@@ -132,17 +136,27 @@ export class PaymentService {
return html;
}
// const templatePath = path.join(
// process.cwd(),
// 'src/modules/payment/templates/receipt.hbs',
// );
async checkStatusAndUpdate(orderId: string) {
const resp = await this.paymentRepo.findOneBy({ merchantOrderId: orderId })
if (!resp) {
throw new NotFoundException("order id not found")
}
const result = await this.telebirrPaymentStategy.queryStatus(resp.merchantOrderId)
const bizContent = result.rawResponse.biz_content as {
order_status: string;
};
// console.log(templatePath)
// const source = fs.readFileSync(templatePath, 'utf8');
// const template = Handlebars.compile(source);
// return this.getReceiptTemplate();
const ordersStatus = bizContent.order_status
if (ordersStatus == "PAY_SUCCESS") {
await this.datasource.transaction(async (mg) => {
await mg.update(Booking, { id: resp.refId }, { status: "PAID" })
await mg.update(PaymentEntity, { id: resp.id }, { status: "success" })
})
}
return {
status: result.status
}
}
}

View File

@@ -301,5 +301,4 @@ export class PaymentTelebirrStrategy implements PaymentStrategy {
return this.config.get<string>('telebirr.publicKey') ?? '';
}
}

View File

@@ -2,15 +2,16 @@ import { Injectable, } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import * as crypto from "crypto"
import { TelebirrDto } from '../dto/telebirr.dto';
import { BookingsRepository } from 'src/modules/bookings/bookings.repository';
import { PaymentRepository } from '../../payment.repository';
import { DataSource } from 'typeorm';
import { Booking } from 'src/modules/bookings/entities/booking.entity';
@Injectable()
export class TelebirrWebhookService {
// private readonly logger = new Logger(TelebirrWebhookService.name);
constructor(
private readonly datasource: DataSource,
private readonly config: ConfigService,
private readonly bookingRepo: BookingsRepository,
private readonly paymentRepo: PaymentRepository,
) { }
@@ -57,7 +58,8 @@ export class TelebirrWebhookService {
await this.paymentRepo.update({ id: payment.id }, { status: "success", paidAt: new Date() })
switch (payment.type) {
case "booking":
await this.bookingRepo.update(payment.refId, { paymentStatus: "PAID", })
await this.datasource.manager.update(Booking, { id: payment.refId }, { paymentStatus: "PAID", })
// await this.bookingRepo.update(payment.refId, { paymentStatus: "PAID", })
break;
}
break;