nestjs-khalti
Version:
This is simple wrapper for Khalti Payment extended from @dallotech/nestjs-khalti. It supports ePayment Gateway(NEW) and transaction verification, but later more will be added. Just ping us or open pull request and contribute :)
120 lines (111 loc) • 4.51 kB
text/typescript
import {BadRequestException, Inject, Injectable, InternalServerErrorException} from '@nestjs/common';
import {HttpService} from '@nestjs/axios';
import {firstValueFrom} from 'rxjs';
import {
KHALTI_CONFIG_OPTIONS,
KHALTI_LOOKUP_TEST_URL,
KHALTI_LOOKUP_URL,
KHALTI_PAYMENT_TEST_URL,
KHALTI_PAYMENT_URL,
KHALTI_VERIFY_URL,
KhaltiDto, KhaltiInitResponse,
KhaltiOptions,
KhaltiRequestDto, KhaltiResponseDto,
PaymentMode
} from "./khalti.interface";
export class KhaltiService {
private readonly paymentMode = null;
private readonly secretKey = null;
private readonly initiateUrl = null;
private readonly initiateUrlForTest = null;
private readonly lookupUrl = null;
private readonly lookupUrlForTest = null;
private readonly verifyUrl = null;
constructor( private readonly options: KhaltiOptions, private readonly httpService: HttpService) {
if (!options.secretKey) {
throw new InternalServerErrorException("Secret Key for khalti payment is missing")
}
this.paymentMode = options.paymentMode || PaymentMode.TEST;
this.secretKey = options.secretKey;
this.initiateUrl = options.initiateUrl || KHALTI_PAYMENT_URL;
this.initiateUrlForTest = options.initiateUrlForTest || KHALTI_PAYMENT_TEST_URL;
this.lookupUrl = options.lookupUrl || KHALTI_LOOKUP_URL;
this.lookupUrlForTest = options.lookupUrl || KHALTI_LOOKUP_TEST_URL;
this.verifyUrl = KHALTI_VERIFY_URL;
}
async init(khaltiRequestDto: KhaltiRequestDto):Promise<KhaltiInitResponse> {
const {
returnUrl,
websiteUrl,
amount,
purchaseOrderId,
purchaseOrderName,
customerInfo,
amountBreakdown,
productDetails
} = khaltiRequestDto;
if (!returnUrl || !websiteUrl || !amount || !purchaseOrderId || !purchaseOrderName) {
throw new BadRequestException("Data missing for initiating Khalti payment");
}
const khaltiDto: KhaltiDto = {
return_url: returnUrl,
website_url: websiteUrl,
amount: amount,
purchase_order_id: purchaseOrderId,
purchase_order_name: purchaseOrderName,
customer_info: customerInfo,
amount_breakdown: amountBreakdown,
product_details: productDetails
}
const response = await firstValueFrom(this.httpService
.post(
this.paymentMode.localeCompare(PaymentMode.TEST) == 0 ? this.initiateUrlForTest : this.initiateUrl,
khaltiDto, {
headers: {
Authorization: this.secretKey,
},
}));
if(response && response?.status == 200 && response?.data){
const {pidx,payment_url,expires_in,expires_at} = response?.data;
return{
pidx: pidx,
paymentUrl: payment_url,
expiresIn: expires_in,
expiresAt: expires_at,
}
}
}
async lookUp(data: any):Promise<KhaltiResponseDto> {
try{
const {pidx} = data;
if (!pidx) {
throw new BadRequestException("pidx missing for validating khalti payment");
}
const response = await firstValueFrom(this.httpService
.post(
this.paymentMode.localeCompare(PaymentMode.TEST) == 0 ? this.lookupUrlForTest : this.lookupUrl,
{pidx},
{
headers: {
Authorization: this.secretKey,
},
},
));
if(response && response?.status == 200 && response?.data){
const {pidx,total_amount,status,transaction_id,fee,refunded} = response?.data;
return{
pidx,
totalAmount:total_amount,
status,
transactionId:transaction_id,
fee,
refunded
}
}
throw new InternalServerErrorException('Unexpected response from Khalti lookup endpoint');
}catch (error:any) {
throw new InternalServerErrorException(`Error in payment verification \n ${error?.message}`);
}
}
}