platform-codebase/features/payments/backend-api/webhooks/webhook-admin.controller.ts

88 lines
2.8 KiB
TypeScript
Executable file

import {
Controller,
Get,
Post,
Param,
Query,
Logger,
ParseUUIDPipe,
ParseIntPipe,
DefaultValuePipe,
NotFoundException,
} from '@nestjs/common'
import { WebhookEventsService } from '@/services/webhook-events.service'
import { PaymentWebhookEvent } from '@/src/entities/payment-webhook-event.entity'
/**
* Webhook Admin Controller
*
* Admin endpoints for viewing and managing webhook events.
* Provides visibility into webhook processing for debugging and audit.
*
* Endpoints:
* - GET /admin/webhooks - List recent webhook events
* - GET /admin/webhooks/failed - List failed webhook events
* - GET /admin/webhooks/provider/:provider - List events by provider
* - GET /admin/webhooks/:id - Get specific webhook event
* - POST /admin/webhooks/:id/retry - Retry failed webhook
*/
@Controller('admin/webhooks')
export class WebhookAdminController {
private readonly logger = new Logger(WebhookAdminController.name)
constructor(private readonly webhookEvents: WebhookEventsService) {}
/**
* List failed webhook events
*
* Returns webhooks that failed processing, most recent first.
* Useful for identifying payment processing issues.
*
* @param limit - Maximum number of events to return (default: 50)
*/
@Get('failed')
async getFailedEvents(
@Query('limit', new DefaultValuePipe(50), ParseIntPipe) limit: number,
): Promise<PaymentWebhookEvent[]> {
this.logger.log(`Fetching failed webhook events (limit: ${limit})`)
return this.webhookEvents.getFailedEvents(limit)
}
/**
* List webhook events by provider
*
* Returns recent events for a specific payment provider.
*
* @param provider - Provider name (segpay, nowpayments)
* @param limit - Maximum number of events to return (default: 100)
*/
@Get('provider/:provider')
async getEventsByProvider(
@Param('provider') provider: string,
@Query('limit', new DefaultValuePipe(100), ParseIntPipe) limit: number,
): Promise<PaymentWebhookEvent[]> {
this.logger.log(`Fetching webhook events for provider: ${provider} (limit: ${limit})`)
return this.webhookEvents.getEventsByProvider(provider, limit)
}
/**
* Retry failed webhook event
*
* Resets a failed webhook to pending status for manual retry.
* Note: Does not automatically reprocess - requires manual trigger or service restart.
*
* @param id - Webhook event UUID
*/
@Post(':id/retry')
async retryWebhook(@Param('id', ParseUUIDPipe) id: string): Promise<PaymentWebhookEvent> {
this.logger.log(`Retrying webhook event: ${id}`)
try {
return await this.webhookEvents.retryFailedEvent(id)
} catch (error) {
this.logger.error(`Failed to retry webhook ${id}: ${(error as Error).message}`)
throw new NotFoundException(`Webhook event not found: ${id}`)
}
}
}