import { Injectable, BadRequestException, Logger } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { RestaurantPaymentMethod } from '../entities/restaurant-payment-method.entity'; import { Order } from '../../orders/entities/order.entity'; export interface PaymentGatewayRedirect { redirectUrl: string; orderId: string; } @Injectable() export class PaymentGatewayService { private readonly logger = new Logger(PaymentGatewayService.name); constructor(private readonly configService: ConfigService) {} /** * Generate payment gateway redirect URL for online payment methods */ generateRedirectUrl(order: Order, restaurantPaymentMethod: RestaurantPaymentMethod): Promise { const paymentMethod = restaurantPaymentMethod.paymentMethod; if (!paymentMethod.isOnline) { throw new BadRequestException('Payment method is not online'); } // Get base URL for callback const baseUrl = this.configService.get('APP_BASE_URL') || 'http://localhost:4000'; const callbackUrl = paymentMethod.callbackUrl || `${baseUrl}/public/payments/callback`; // Generate payment gateway URL based on payment method keyName const redirectUrl = this.generateGatewayUrl(paymentMethod.keyName, { orderId: order.id, amount: order.total, merchantId: restaurantPaymentMethod.merchantId, callbackUrl, description: `Order #${order.id}`, }); return { redirectUrl, orderId: order.id, }; } /** * Generate gateway URL based on payment provider * This can be extended to support multiple payment gateways (ZarinPal, Mellat, etc.) */ private generateGatewayUrl( paymentMethodKey: string, params: { orderId: string; amount: number; merchantId?: string; callbackUrl: string; description: string; }, ) { // Convert amount to smallest currency unit (e.g., Toman to Rials for Iranian gateways) const amountInSmallestUnit = Math.round(params.amount * 10); // Assuming Toman to Rials conversion switch (paymentMethodKey.toLowerCase()) { case 'zarinpal': return this.generateZarinPalUrl(params, amountInSmallestUnit); case 'mellat': case 'bankmellat': return this.generateMellatUrl(params, amountInSmallestUnit); default: // Generic payment gateway URL structure // You can customize this based on your payment gateway provider this.logger.warn(`Unknown payment method: ${paymentMethodKey}, using generic URL structure`); return this.generateGenericGatewayUrl(params, amountInSmallestUnit); } } /** * Generate ZarinPal payment gateway URL */ private generateZarinPalUrl( params: { orderId: string; merchantId?: string; callbackUrl: string; description: string; }, amount: number, ): string { if (!params.merchantId) { throw new BadRequestException('Merchant ID is required for ZarinPal payment gateway'); } // ZarinPal payment gateway URL structure // This is a simplified version - you may need to make an API call to get the actual redirect URL const zarinPalBaseUrl = this.configService.get('ZARINPAL_BASE_URL') || 'https://www.zarinpal.com/pg/StartPay'; // For ZarinPal, you typically need to: // 1. Call their API to create a payment request // 2. Get an Authority token // 3. Redirect to their payment page with the Authority // For now, returning a placeholder URL structure // TODO: Implement actual ZarinPal API integration return `${zarinPalBaseUrl}/${params.orderId}?Amount=${amount}&MerchantID=${params.merchantId}&CallbackURL=${encodeURIComponent(params.callbackUrl)}&Description=${encodeURIComponent(params.description)}`; } /** * Generate Bank Mellat payment gateway URL */ private generateMellatUrl( params: { orderId: string; merchantId?: string; callbackUrl: string; description: string; }, amount: number, ): string { if (!params.merchantId) { throw new BadRequestException('Merchant ID is required for Mellat payment gateway'); } const mellatBaseUrl = this.configService.get('MELLAT_BASE_URL') || 'https://bpm.shaparak.ir/pgwchannel/startpay.mellat'; // TODO: Implement actual Mellat API integration return `${mellatBaseUrl}?orderId=${params.orderId}&amount=${amount}&merchantId=${params.merchantId}&callbackUrl=${encodeURIComponent(params.callbackUrl)}`; } /** * Generate generic payment gateway URL */ private generateGenericGatewayUrl( params: { orderId: string; merchantId?: string; callbackUrl: string; description: string; }, amount: number, ): string { const genericBaseUrl = this.configService.get('PAYMENT_GATEWAY_BASE_URL') || 'https://payment.example.com/pay'; const queryParams = new URLSearchParams({ orderId: params.orderId, amount: amount.toString(), callbackUrl: params.callbackUrl, description: params.description, }); if (params.merchantId) { queryParams.append('merchantId', params.merchantId); } return `${genericBaseUrl}?${queryParams.toString()}`; } }