59 lines
2.0 KiB
TypeScript
59 lines
2.0 KiB
TypeScript
import {
|
|
Controller, Post, Req, Headers, HttpCode, HttpStatus, Logger, BadRequestException,
|
|
} from '@nestjs/common';
|
|
import { Request } from 'express';
|
|
import { HandlePaymentWebhookUseCase } from '../../../application/use-cases/handle-payment-webhook.use-case';
|
|
import { PaymentProviderType } from '../../../domain/ports/payment-provider.port';
|
|
|
|
@Controller('api/v1/billing/webhooks')
|
|
export class WebhookController {
|
|
private readonly logger = new Logger(WebhookController.name);
|
|
|
|
constructor(private readonly handleWebhook: HandlePaymentWebhookUseCase) {}
|
|
|
|
@Post('stripe')
|
|
@HttpCode(HttpStatus.OK)
|
|
async stripeWebhook(@Req() req: Request, @Headers() headers: Record<string, string>) {
|
|
return this.processWebhook(PaymentProviderType.STRIPE, req, headers);
|
|
}
|
|
|
|
@Post('alipay')
|
|
@HttpCode(HttpStatus.OK)
|
|
async alipayWebhook(@Req() req: Request, @Headers() headers: Record<string, string>) {
|
|
await this.processWebhook(PaymentProviderType.ALIPAY, req, headers);
|
|
// Alipay expects plain text "success" response
|
|
return 'success';
|
|
}
|
|
|
|
@Post('wechat')
|
|
@HttpCode(HttpStatus.OK)
|
|
async wechatWebhook(@Req() req: Request, @Headers() headers: Record<string, string>) {
|
|
await this.processWebhook(PaymentProviderType.WECHAT_PAY, req, headers);
|
|
return { code: 'SUCCESS', message: '成功' };
|
|
}
|
|
|
|
@Post('crypto')
|
|
@HttpCode(HttpStatus.OK)
|
|
async cryptoWebhook(@Req() req: Request, @Headers() headers: Record<string, string>) {
|
|
return this.processWebhook(PaymentProviderType.CRYPTO, req, headers);
|
|
}
|
|
|
|
private async processWebhook(
|
|
provider: PaymentProviderType,
|
|
req: Request,
|
|
headers: Record<string, string>,
|
|
) {
|
|
const rawBody = (req as any).rawBody as Buffer;
|
|
if (!rawBody) {
|
|
throw new BadRequestException('Raw body not available — ensure rawBody middleware is enabled');
|
|
}
|
|
|
|
try {
|
|
await this.handleWebhook.execute(provider, rawBody, headers);
|
|
} catch (err) {
|
|
this.logger.error(`Webhook error for ${provider}: ${err.message}`);
|
|
throw err;
|
|
}
|
|
}
|
|
}
|