From acf8861823e62d74ad1faeacdf30b0f7a2efd519 Mon Sep 17 00:00:00 2001 From: shancheas Date: Fri, 9 Aug 2024 15:18:43 +0700 Subject: [PATCH 1/2] feat: add sync midtrans transaction --- .../data/services/midtrans.service.ts | 23 +++++++++++++++++-- .../infrastructure/midtrans.controller.ts | 21 +++++++++++++++++ .../configuration/midtrans/midtrans.module.ts | 12 ++++++++-- .../data/services/transaction-read.service.ts | 18 ++++++++++++++- .../transaction/transaction.module.ts | 1 + 5 files changed, 70 insertions(+), 5 deletions(-) diff --git a/src/modules/configuration/midtrans/data/services/midtrans.service.ts b/src/modules/configuration/midtrans/data/services/midtrans.service.ts index 2dfad1b..2dbad29 100644 --- a/src/modules/configuration/midtrans/data/services/midtrans.service.ts +++ b/src/modules/configuration/midtrans/data/services/midtrans.service.ts @@ -1,12 +1,12 @@ import { Injectable } from '@nestjs/common'; -import { EventBus } from '@nestjs/cqrs'; import { mappingMidtransTransaction } from '../../domain/usecases/helpers/mapping-transaction.helper'; import { Snap } from 'midtrans-client'; import { MidtransStatus } from '../../domain/entities/midtrans-callback.event'; +import { TransactionReadService } from 'src/modules/transaction/transaction/data/services/transaction-read.service'; @Injectable() export class MidtransService { - constructor(private eventBus: EventBus) {} + constructor(private transaction: TransactionReadService) {} get midtransInstance() { return new Snap({ @@ -20,6 +20,25 @@ export class MidtransService { return await this.midtransInstance.transaction.status(orderId); } + async syncPendingStatus(): Promise { + const pendingIds = await this.transaction.getPendingOrderId(); + const responses = []; + + for (const id of pendingIds) { + let status; + try { + status = await this.getStatus(id); + } catch (error) { + status = { + order_id: id, + transaction_status: 'cancel', + }; + } + responses.push(status); + } + return responses; + } + async changeStatus(orderId: string, action: MidtransStatus): Promise { return await this.midtransInstance.transaction[action](orderId); } diff --git a/src/modules/configuration/midtrans/infrastructure/midtrans.controller.ts b/src/modules/configuration/midtrans/infrastructure/midtrans.controller.ts index fe68649..e4a84ad 100644 --- a/src/modules/configuration/midtrans/infrastructure/midtrans.controller.ts +++ b/src/modules/configuration/midtrans/infrastructure/midtrans.controller.ts @@ -46,6 +46,27 @@ export class MidtransController { } } + @Get('sync') + async syncStatus() { + try { + const results = await this.dataService.syncPendingStatus(); + + for (const data of results) { + this.eventBus.publishAll([ + new MidtransCallbackEvent({ + id: data.order_id, + data: data, + }), + ]); + } + + return 'Berhasil update status transaksi'; + } catch (error) { + console.log(error.message); + throw new Error('Gagal update status transaksi'); + } + } + @Get(':id/change-status') @ApiQuery({ name: 'status', enum: MidtransStatus }) async cancel( diff --git a/src/modules/configuration/midtrans/midtrans.module.ts b/src/modules/configuration/midtrans/midtrans.module.ts index 755a639..6735a95 100644 --- a/src/modules/configuration/midtrans/midtrans.module.ts +++ b/src/modules/configuration/midtrans/midtrans.module.ts @@ -3,12 +3,20 @@ import { CqrsModule } from '@nestjs/cqrs'; import { MidtransController } from './infrastructure/midtrans.controller'; import { MidtransService } from './data/services/midtrans.service'; import { Global, Module } from '@nestjs/common'; +import { TransactionReadService } from 'src/modules/transaction/transaction/data/services/transaction-read.service'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants'; +import { TransactionModel } from 'src/modules/transaction/transaction/data/models/transaction.model'; @Global() @Module({ - imports: [ConfigModule.forRoot(), CqrsModule], + imports: [ + ConfigModule.forRoot(), + CqrsModule, + TypeOrmModule.forFeature([TransactionModel], CONNECTION_NAME.DEFAULT), + ], controllers: [MidtransController], - providers: [MidtransService], + providers: [MidtransService, TransactionReadService], exports: [MidtransService], }) export class MidtransModule {} diff --git a/src/modules/transaction/transaction/data/services/transaction-read.service.ts b/src/modules/transaction/transaction/data/services/transaction-read.service.ts index ddd488a..eee20de 100644 --- a/src/modules/transaction/transaction/data/services/transaction-read.service.ts +++ b/src/modules/transaction/transaction/data/services/transaction-read.service.ts @@ -2,9 +2,13 @@ import { Injectable } from '@nestjs/common'; import { TransactionEntity } from '../../domain/entities/transaction.entity'; import { InjectRepository } from '@nestjs/typeorm'; import { TransactionModel } from '../models/transaction.model'; -import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants'; +import { + CONNECTION_NAME, + STATUS, +} from 'src/core/strings/constants/base.constants'; import { Repository } from 'typeorm'; import { BaseReadService } from 'src/core/modules/data/service/base-read.service'; +import { TransactionPaymentType } from '../../constants'; @Injectable() export class TransactionReadService extends BaseReadService { @@ -14,4 +18,16 @@ export class TransactionReadService extends BaseReadService { ) { super(repo); } + + async getPendingOrderId() { + const transactions = await this.repo.find({ + where: { + status: STATUS.PENDING, + payment_type: TransactionPaymentType.MIDTRANS, + }, + select: ['id'], + }); + + return transactions.map(({ id }) => id); + } } diff --git a/src/modules/transaction/transaction/transaction.module.ts b/src/modules/transaction/transaction/transaction.module.ts index 0965400..2153707 100644 --- a/src/modules/transaction/transaction/transaction.module.ts +++ b/src/modules/transaction/transaction/transaction.module.ts @@ -37,6 +37,7 @@ import { PaymentMethodDataService } from '../payment-method/data/services/paymen import { PaymentMethodModel } from '../payment-method/data/models/payment-method.model'; @Module({ + exports: [TransactionReadService], imports: [ ConfigModule.forRoot(), TypeOrmModule.forFeature( From fe6572a770674211d6efbe16e51aedef26cc8072 Mon Sep 17 00:00:00 2001 From: shancheas Date: Fri, 9 Aug 2024 15:23:20 +0700 Subject: [PATCH 2/2] fix: only check transaction more than 1 day --- .../data/services/midtrans.service.ts | 20 +++++++++++++++++-- .../data/services/transaction-read.service.ts | 4 ++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/modules/configuration/midtrans/data/services/midtrans.service.ts b/src/modules/configuration/midtrans/data/services/midtrans.service.ts index 2dbad29..713697b 100644 --- a/src/modules/configuration/midtrans/data/services/midtrans.service.ts +++ b/src/modules/configuration/midtrans/data/services/midtrans.service.ts @@ -4,10 +4,23 @@ import { Snap } from 'midtrans-client'; import { MidtransStatus } from '../../domain/entities/midtrans-callback.event'; import { TransactionReadService } from 'src/modules/transaction/transaction/data/services/transaction-read.service'; +import * as moment from 'moment'; + @Injectable() export class MidtransService { constructor(private transaction: TransactionReadService) {} + isMoreThan24HoursAgo(dateString) { + const date = moment(dateString, 'YYYY-MM-DD', true); + if (!date.isValid()) { + return false; + } + + const now = moment(); + const diffInHours = now.diff(date, 'hours'); + return diffInHours > 24; + } + get midtransInstance() { return new Snap({ isProduction: false, @@ -24,14 +37,17 @@ export class MidtransService { const pendingIds = await this.transaction.getPendingOrderId(); const responses = []; - for (const id of pendingIds) { + for (const transaction of pendingIds) { + const { id, invoice_date } = transaction; let status; try { status = await this.getStatus(id); } catch (error) { status = { order_id: id, - transaction_status: 'cancel', + transaction_status: this.isMoreThan24HoursAgo(invoice_date) + ? 'cancel' + : 'pending', }; } responses.push(status); diff --git a/src/modules/transaction/transaction/data/services/transaction-read.service.ts b/src/modules/transaction/transaction/data/services/transaction-read.service.ts index eee20de..7efd6bf 100644 --- a/src/modules/transaction/transaction/data/services/transaction-read.service.ts +++ b/src/modules/transaction/transaction/data/services/transaction-read.service.ts @@ -25,9 +25,9 @@ export class TransactionReadService extends BaseReadService { status: STATUS.PENDING, payment_type: TransactionPaymentType.MIDTRANS, }, - select: ['id'], + select: ['id', 'invoice_date'], }); - return transactions.map(({ id }) => id); + return transactions; } }