feat: ( payment ) implement cbe payment

This commit is contained in:
Abubeker
2026-07-31 07:50:10 +00:00
parent e4a2c61224
commit 37855b0a83
52 changed files with 2244 additions and 368 deletions

View File

@@ -1,30 +1,42 @@
import {
Body,
Controller,
forwardRef,
HttpCode,
HttpStatus,
Inject,
Logger,
Post,
UseGuards,
} from "@nestjs/common";
import { ApiOperation, ApiTags } from "@nestjs/swagger";
import { Public } from "@edr/api-common";
import { PaymentEventDto, MarkPaidResponseDto } from "./internal-payment.dto";
import {
PaymentEventDto,
MarkPaidResponseDto,
BillQueryRequestDto,
BillQueryResponseDto,
} from "./internal-payment.dto";
import { PaymentService } from "./payment.service";
import { BillingService } from "../billing/billing.service";
import { ServiceAuthGuard } from "../../common/guards/service-auth.guard";
/**
* Consumer side of the payment microservice's outbox relay.
* WARNING: currently unauthenticated — anyone who can reach the API can mark
* payments as paid. Re-add ServiceAuthGuard before exposing beyond a trusted network.
* Consumer side of the payment microservice's outbox relay. Only the payment service may
* call this (shared service token — restored per docs/cbe/CBE_IMPLEMENTATION_PLAN.md R8).
* Idempotent by design — the relay delivers at-least-once, so duplicates must be harmless.
* Becomes a queue consumer via PaymentEventsConsumer when RabbitMQ is available;
* this HTTP endpoint remains as a transport-agnostic fallback.
*/
@ApiTags("Internal Payments")
@Public()
@UseGuards(ServiceAuthGuard)
@Controller("internal/payments")
export class InternalPaymentController {
private readonly logger = new Logger(InternalPaymentController.name);
constructor(private readonly paymentService: PaymentService) { }
constructor(
private readonly paymentService: PaymentService,
@Inject(forwardRef(() => BillingService))
private readonly billingService: BillingService,
) { }
@Post("mark-paid")
@HttpCode(HttpStatus.OK)
@@ -36,4 +48,16 @@ export class InternalPaymentController {
this.logger.log(`Marking payment ${event} as PAID`);
return this.paymentService.handlePaymentEvent(event);
}
@Post("bill-query")
@HttpCode(HttpStatus.OK)
@ApiOperation({
summary:
"Live still-payable check + payer name for a CBE bill (called while CBE is on the line)",
})
async billQuery(
@Body() request: BillQueryRequestDto,
): Promise<BillQueryResponseDto> {
return this.billingService.billQuery(request.referenceId);
}
}