payment redirect
This commit is contained in:
@@ -0,0 +1,161 @@
|
||||
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<PaymentGatewayRedirect> {
|
||||
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<string>('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<string>('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<string>('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<string>('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()}`;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user