import { Controller, Post, Headers, Req, HttpCode, HttpStatus, BadRequestException, } from '@nestjs/common'; import { ApiTags, ApiOperation, ApiExcludeEndpoint } from '@nestjs/swagger'; import { Request } from 'express'; import { PaymentsService } from './payments.service'; import { StripeService } from './stripe.service'; @ApiTags('webhooks') @Controller('webhooks') export class WebhooksController { constructor( private paymentsService: PaymentsService, private stripeService: StripeService ) {} @Post('stripe') @HttpCode(HttpStatus.OK) @ApiExcludeEndpoint() @ApiOperation({ summary: 'Handle Stripe webhooks' }) async handleStripeWebhook( @Req() req: Request, @Headers('stripe-signature') signature: string ) { if (!signature) { throw new BadRequestException('Missing stripe-signature header'); } let event; try { // req.body should be raw buffer for webhook verification const rawBody = (req as Request & { rawBody?: Buffer }).rawBody; if (!rawBody) { throw new BadRequestException('Missing raw body'); } event = this.stripeService.constructWebhookEvent(rawBody, signature); } catch (err) { throw new BadRequestException(`Webhook signature verification failed: ${err}`); } await this.paymentsService.handleWebhookEvent(event); return { received: true }; } }