diff --git a/src/modules/payments/services/payment-gateway.service.ts b/src/modules/payments/services/payment-gateway.service.ts index a09cfff..1ed717c 100644 --- a/src/modules/payments/services/payment-gateway.service.ts +++ b/src/modules/payments/services/payment-gateway.service.ts @@ -64,7 +64,7 @@ export class PaymentGatewayService { orderId, }, }); - + this.logger.log('gatewayResponse', gatewayResponse); // Check gateway response code (typically 100 means success for Iranian gateways) if (gatewayResponse.code !== 100 && gatewayResponse.code !== 0) { throw new BadRequestException(`Payment gateway error: ${gatewayResponse.message || 'Unknown error'}`); @@ -76,9 +76,12 @@ export class PaymentGatewayService { return { authority: gatewayResponse.authority }; } catch (error) { + this.logger.error('Error in request to gateway', error); + if (error instanceof BadRequestException) { throw error; } + const errorMessage = error instanceof Error ? error.message : 'Unknown error'; throw new BadRequestException(`Failed to connect to payment gateway: ${errorMessage}`); } @@ -89,8 +92,52 @@ export class PaymentGatewayService { } private async requestToZarinPalGateway(requestPayment: IPaymentRequest): Promise { - const response = await axios.post(this.zarinpalRequestUrl, requestPayment); - return response.data; + // Transform camelCase to snake_case for Zarinpal API v4 + 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(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) { @@ -102,12 +149,40 @@ export class PaymentGatewayService { async verifyZarinPalPayment(verifyRequest: IPaymentVerifyRequest): Promise { try { - const response = await axios.post(this.zarinpalVerifyUrl, verifyRequest); - if (!response.data) { - throw new BadRequestException('Empty response from payment gateway'); + // Transform camelCase to snake_case for Zarinpal API v4 + const zarinpalVerifyRequest = { + 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(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) { + if (error instanceof BadRequestException) { + throw error; + } const errorMessage = error instanceof Error ? error.message : 'Unknown error'; throw new BadRequestException(`Failed to verify payment with gateway: ${errorMessage}`); } diff --git a/src/seeders/data/restaurants.data.ts b/src/seeders/data/restaurants.data.ts index fe88fd5..94026b5 100644 --- a/src/seeders/data/restaurants.data.ts +++ b/src/seeders/data/restaurants.data.ts @@ -14,7 +14,7 @@ export const restaurantsData: RestaurantData[] = [ { name: 'ژیوان', slug: 'zhivan', - domain: 'zhivan.example.com', + domain: 'https://www.zhivan.ir', isActive: true, phone: '09123456789', serviceArea: { @@ -33,7 +33,7 @@ export const restaurantsData: RestaurantData[] = [ { name: 'بوته', slug: 'boote', - domain: 'boote.example.com', + domain: 'https://www.boote.ir', isActive: true, phone: '09123456790', serviceArea: { @@ -50,4 +50,3 @@ export const restaurantsData: RestaurantData[] = [ }, }, ]; -