payment
This commit is contained in:
@@ -64,7 +64,7 @@ export class PaymentGatewayService {
|
|||||||
orderId,
|
orderId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
this.logger.log('gatewayResponse', gatewayResponse);
|
||||||
// Check gateway response code (typically 100 means success for Iranian gateways)
|
// Check gateway response code (typically 100 means success for Iranian gateways)
|
||||||
if (gatewayResponse.code !== 100 && gatewayResponse.code !== 0) {
|
if (gatewayResponse.code !== 100 && gatewayResponse.code !== 0) {
|
||||||
throw new BadRequestException(`Payment gateway error: ${gatewayResponse.message || 'Unknown error'}`);
|
throw new BadRequestException(`Payment gateway error: ${gatewayResponse.message || 'Unknown error'}`);
|
||||||
@@ -76,9 +76,12 @@ export class PaymentGatewayService {
|
|||||||
|
|
||||||
return { authority: gatewayResponse.authority };
|
return { authority: gatewayResponse.authority };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
this.logger.error('Error in request to gateway', error);
|
||||||
|
|
||||||
if (error instanceof BadRequestException) {
|
if (error instanceof BadRequestException) {
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
||||||
throw new BadRequestException(`Failed to connect to payment gateway: ${errorMessage}`);
|
throw new BadRequestException(`Failed to connect to payment gateway: ${errorMessage}`);
|
||||||
}
|
}
|
||||||
@@ -89,8 +92,52 @@ export class PaymentGatewayService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async requestToZarinPalGateway(requestPayment: IPaymentRequest): Promise<IPaymentResponse> {
|
private async requestToZarinPalGateway(requestPayment: IPaymentRequest): Promise<IPaymentResponse> {
|
||||||
const response = await axios.post<IPaymentResponse>(this.zarinpalRequestUrl, requestPayment);
|
// Transform camelCase to snake_case for Zarinpal API v4
|
||||||
return response.data;
|
const zarinpalRequest = {
|
||||||
|
amount: requestPayment.amount,
|
||||||
|
merchant_id: requestPayment.merchantId,
|
||||||
|
description: requestPayment.description,
|
||||||
|
callback_url: requestPayment.callbackUrl,
|
||||||
|
metadata: {
|
||||||
|
order_id: requestPayment.metadata.orderId,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Zarinpal API v4 returns response wrapped in { data: {...}, errors: [] }
|
||||||
|
interface ZarinpalError {
|
||||||
|
message?: string;
|
||||||
|
code?: number;
|
||||||
|
}
|
||||||
|
interface ZarinpalResponse {
|
||||||
|
data: IPaymentResponse;
|
||||||
|
errors: ZarinpalError[];
|
||||||
|
}
|
||||||
|
const response = await axios.post<ZarinpalResponse>(this.zarinpalRequestUrl, zarinpalRequest);
|
||||||
|
|
||||||
|
// Check if there are errors in the response
|
||||||
|
if (response.data.errors && response.data.errors.length > 0) {
|
||||||
|
const errorMessage = response.data.errors.map(err => err.message || JSON.stringify(err)).join(', ');
|
||||||
|
throw new BadRequestException(`Payment gateway error: ${errorMessage}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the nested data object
|
||||||
|
if (!response.data.data) {
|
||||||
|
throw new BadRequestException('Payment gateway returned invalid response structure');
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.data.data;
|
||||||
|
} catch (error) {
|
||||||
|
// Log the actual API error response for debugging
|
||||||
|
if (axios.isAxiosError(error) && error.response) {
|
||||||
|
this.logger.error('Zarinpal API error response', {
|
||||||
|
status: error.response.status,
|
||||||
|
data: JSON.stringify(error.response.data),
|
||||||
|
request: zarinpalRequest,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
zarinpalPaymentUrl(gateway: PaymentGatewayEnum | null, authority: string | null) {
|
zarinpalPaymentUrl(gateway: PaymentGatewayEnum | null, authority: string | null) {
|
||||||
@@ -102,12 +149,40 @@ export class PaymentGatewayService {
|
|||||||
|
|
||||||
async verifyZarinPalPayment(verifyRequest: IPaymentVerifyRequest): Promise<IPaymentVerifyResponse> {
|
async verifyZarinPalPayment(verifyRequest: IPaymentVerifyRequest): Promise<IPaymentVerifyResponse> {
|
||||||
try {
|
try {
|
||||||
const response = await axios.post<IPaymentVerifyResponse>(this.zarinpalVerifyUrl, verifyRequest);
|
// Transform camelCase to snake_case for Zarinpal API v4
|
||||||
if (!response.data) {
|
const zarinpalVerifyRequest = {
|
||||||
throw new BadRequestException('Empty response from payment gateway');
|
merchant_id: verifyRequest.merchantId,
|
||||||
|
amount: verifyRequest.amount,
|
||||||
|
authority: verifyRequest.authority,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Zarinpal API v4 returns response wrapped in { data: {...}, errors: [] }
|
||||||
|
interface ZarinpalError {
|
||||||
|
message?: string;
|
||||||
|
code?: number;
|
||||||
}
|
}
|
||||||
return response.data;
|
interface ZarinpalVerifyResponse {
|
||||||
|
data: IPaymentVerifyResponse;
|
||||||
|
errors: ZarinpalError[];
|
||||||
|
}
|
||||||
|
const response = await axios.post<ZarinpalVerifyResponse>(this.zarinpalVerifyUrl, zarinpalVerifyRequest);
|
||||||
|
|
||||||
|
// Check if there are errors in the response
|
||||||
|
if (response.data.errors && response.data.errors.length > 0) {
|
||||||
|
const errorMessage = response.data.errors.map(err => err.message || JSON.stringify(err)).join(', ');
|
||||||
|
throw new BadRequestException(`Payment gateway error: ${errorMessage}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the nested data object
|
||||||
|
if (!response.data.data) {
|
||||||
|
throw new BadRequestException('Payment gateway returned invalid response structure');
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.data.data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
if (error instanceof BadRequestException) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
||||||
throw new BadRequestException(`Failed to verify payment with gateway: ${errorMessage}`);
|
throw new BadRequestException(`Failed to verify payment with gateway: ${errorMessage}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export const restaurantsData: RestaurantData[] = [
|
|||||||
{
|
{
|
||||||
name: 'ژیوان',
|
name: 'ژیوان',
|
||||||
slug: 'zhivan',
|
slug: 'zhivan',
|
||||||
domain: 'zhivan.example.com',
|
domain: 'https://www.zhivan.ir',
|
||||||
isActive: true,
|
isActive: true,
|
||||||
phone: '09123456789',
|
phone: '09123456789',
|
||||||
serviceArea: {
|
serviceArea: {
|
||||||
@@ -33,7 +33,7 @@ export const restaurantsData: RestaurantData[] = [
|
|||||||
{
|
{
|
||||||
name: 'بوته',
|
name: 'بوته',
|
||||||
slug: 'boote',
|
slug: 'boote',
|
||||||
domain: 'boote.example.com',
|
domain: 'https://www.boote.ir',
|
||||||
isActive: true,
|
isActive: true,
|
||||||
phone: '09123456790',
|
phone: '09123456790',
|
||||||
serviceArea: {
|
serviceArea: {
|
||||||
@@ -50,4 +50,3 @@ export const restaurantsData: RestaurantData[] = [
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user