import { Controller, Get, Post, Body, Query, UseGuards, Req, Logger, BadRequestException } from '@nestjs/common'; import { BillingService } from './billing.service'; import { PayMobProvider } from './providers/paymob.provider'; import { BinanceProvider } from './providers/binance.provider'; import { FirebaseAuthGuard } from '../auth/guards/firebase-auth.guard'; import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger'; import { PaymentProvider, PaymentStatus } from './entities/transaction.entity'; @ApiTags('billing') @Controller('billing') export class BillingController { private readonly logger = new Logger(BillingController.name); constructor( private billingService: BillingService, private paymobProvider: PayMobProvider, private binanceProvider: BinanceProvider, ) {} @ApiBearerAuth() @UseGuards(FirebaseAuthGuard) @Get('subscription') @ApiOperation({ summary: 'Get current subscription details' }) async getSubscription(@Req() req: any) { return this.billingService.getSubscription(req.tenant.id); } @ApiBearerAuth() @UseGuards(FirebaseAuthGuard) @Post('checkout') @ApiOperation({ summary: 'Initialize a checkout session' }) async checkout(@Req() req: any, @Body() body: { plan: string; provider: PaymentProvider }) { const tenantId = req.tenant.id; const plan = body.plan; const amount = plan === 'PRO' ? 40 : 0; // Price logic if (body.provider === PaymentProvider.PAYMOB) { const { paymentKey, orderId } = await this.paymobProvider.createPaymentKey(tenantId, amount, plan); // Iframe URL (Using the new provided Iframe ID) const iframeId = this.billingService.getIframeId(); const checkoutUrl = `https://accept.paymob.com/api/acceptance/iframes/${iframeId}?payment_token=${paymentKey}`; return { checkoutUrl, orderId }; } if (body.provider === PaymentProvider.BINANCE) { return this.binanceProvider.createOrder(tenantId, amount, plan); } throw new BadRequestException('Invalid payment provider'); } /** * PayMob Redirection Callback (Success/Fail) * This handles the GET request when PayMob redirects the user back to our site */ @Get('callback/paymob') @ApiOperation({ summary: 'PayMob Redirection Handler' }) async handlePaymobCallback(@Query() query: any, @Req() req: any) { this.logger.log(`🔄 PayMob Redirect Callback: ID ${query.id}, Success: ${query.success}`); // Fallback: If success=true, proactively fetch transaction details and upgrade if (query.success === 'true' && query.id) { try { const txDetails = await this.paymobProvider.getTransactionDetails(query.id); if (txDetails && txDetails.success === true) { const extraDesc = txDetails.order?.shipping_data?.extra_description || ""; const [tenantId, plan] = extraDesc.split('|'); if (tenantId) { await this.billingService.processSuccessfulPayment( query.id.toString(), PaymentProvider.PAYMOB, txDetails.amount_cents / 100, { tenantId, plan: plan || 'PRO' } ); this.logger.log(`🚀 Immediate Activation triggered via Callback for Tenant ${tenantId}`); } } } catch (e) { this.logger.error(`Failed during immediate activation fallback: ${e.message}`); } } // Redirect back to dashboard with status const targetUrl = `https://map-dashbord.intaleqapp.com/dashboard.html#billing?payment_status=${query.success === 'true' ? 'success' : 'failed'}&id=${query.id}`; return `
تم تفعيل خطة PRO بنجاح. يتم الآن توجيهك إلى لوحة التحكم...