100 lines
3.6 KiB
TypeScript
Executable File
100 lines
3.6 KiB
TypeScript
Executable File
import { HttpService } from "@nestjs/axios";
|
|
import { Inject, Injectable, InternalServerErrorException, Logger } from "@nestjs/common";
|
|
import { AxiosError } from "axios";
|
|
import { catchError, firstValueFrom } from "rxjs";
|
|
|
|
import { PaymentMessage } from "../../../common/enums/message.enum";
|
|
import { IZarinpalConfig } from "../../../configs/zarinpal.config";
|
|
import { ZARINPAL_CONFIG } from "../constants";
|
|
import { GatewayEnum } from "../enums/gateway.enum";
|
|
import {
|
|
IPaymentGateway,
|
|
IPaymentVerifyParams,
|
|
IProcessPaymentParams,
|
|
ZarinPalPGNewArgs,
|
|
ZarinPalPGNewRequestData,
|
|
ZarinPalPGVerifyData,
|
|
} from "../interfaces/IPayment";
|
|
|
|
@Injectable()
|
|
export class ZarinpalGateway implements IPaymentGateway {
|
|
private readonly logger = new Logger(ZarinpalGateway.name);
|
|
private readonly gatewayApiUrl: string;
|
|
private readonly requestHeader: Record<string, string> = { "Content-Type": "application/json", Accept: "application/json" };
|
|
|
|
constructor(
|
|
@Inject(ZARINPAL_CONFIG) private readonly config: IZarinpalConfig,
|
|
private readonly httpService: HttpService,
|
|
) {
|
|
this.gatewayApiUrl = `https://${this.config.ipgType}.${this.config.gatewayApiUrl}`;
|
|
}
|
|
//*************************************** */
|
|
async processPayment(processParams: IProcessPaymentParams) {
|
|
try {
|
|
const purchaseData: ZarinPalPGNewArgs = {
|
|
merchant_id: this.config.merchantId,
|
|
amount: processParams.amount,
|
|
callback_url: `${this.config.callBackUrl}/${GatewayEnum.ZARINPAL}${processParams.invoiceId ? "/" + processParams.invoiceId : ""}`,
|
|
description: processParams.description,
|
|
currency: "IRT",
|
|
metadata: { email: processParams.email, mobile: processParams.mobile },
|
|
};
|
|
|
|
const { data } = await firstValueFrom(
|
|
this.httpService
|
|
.post<ZarinPalPGNewRequestData>(`${this.gatewayApiUrl}/v4/payment/request.json`, purchaseData, {
|
|
headers: this.requestHeader,
|
|
})
|
|
.pipe(
|
|
catchError((err: AxiosError) => {
|
|
this.logger.error(err);
|
|
throw new InternalServerErrorException(PaymentMessage.ERROR_IN_PROCESS_PAYMENT);
|
|
}),
|
|
),
|
|
);
|
|
return {
|
|
redirectUrl: `${this.gatewayApiUrl}/StartPay/${data.data.authority}`,
|
|
message: data.data.message,
|
|
reference: data.data.authority,
|
|
};
|
|
} catch (error) {
|
|
this.logger.error(error);
|
|
throw new InternalServerErrorException(PaymentMessage.ERROR_IN_PROCESS_PAYMENT);
|
|
}
|
|
}
|
|
//********************************** */
|
|
async verifyPayment(verifyParams: IPaymentVerifyParams) {
|
|
try {
|
|
const verifyData = {
|
|
authority: verifyParams.reference,
|
|
amount: verifyParams.amount,
|
|
merchant_id: this.config.merchantId,
|
|
};
|
|
const { data } = await firstValueFrom(
|
|
this.httpService
|
|
.post<ZarinPalPGVerifyData>(`${this.gatewayApiUrl}/v4/payment/verify.json`, verifyData, { headers: this.requestHeader })
|
|
.pipe(
|
|
catchError((err: AxiosError) => {
|
|
this.logger.error(err);
|
|
throw new InternalServerErrorException(PaymentMessage.ERROR_IN_VERIFY_PAYMENT);
|
|
}),
|
|
),
|
|
);
|
|
|
|
return {
|
|
code: data.data.code,
|
|
message: data.data.message,
|
|
card_hash: data.data.card_hash,
|
|
card_pan: data.data.card_pan,
|
|
ref_id: data.data.ref_id,
|
|
fee_type: data.data.fee_type,
|
|
fee: data.data.fee,
|
|
};
|
|
} catch (error) {
|
|
console.error({ error });
|
|
this.logger.error(error);
|
|
throw new InternalServerErrorException(PaymentMessage.ERROR_IN_VERIFY_PAYMENT);
|
|
}
|
|
}
|
|
}
|