diff --git a/src/common/constants.ts b/src/common/constants.ts index 4f83faf..a9e50fc 100644 --- a/src/common/constants.ts +++ b/src/common/constants.ts @@ -17,7 +17,7 @@ export const AADHAAR_GREETING_MESSAGE = ( ) => `Beneficiary Name - ${BeneficiaryName} Beneficiary Location - ${StateName}, ${DistrictName}, ${SubDistrictName}, ${VillageName} Registration Number - ${Reg_No} -Registration Date - ${moment(DateOfRegistration).format('DD-MM-YYYY')} +Registration Date - ${moment(DateOfRegistration).format('M/D/YYYY h:mm:ss A')} Last Installment Status - ${LatestInstallmentPaid==0?"No":addOrdinalSuffix(LatestInstallmentPaid)} Installment payment done eKYC - ${eKYC_Status=='Y'?'Done':'Not Done'} ` diff --git a/src/common/utils.ts b/src/common/utils.ts index d392703..d10fa0e 100644 --- a/src/common/utils.ts +++ b/src/common/utils.ts @@ -1,4 +1,8 @@ -const fetch = require("./fetch"); +import { ConstraintMetadata } from "class-validator/types/metadata/ConstraintMetadata"; +import { randomBytes, createCipheriv, createDecipheriv } from 'crypto'; +const crypto = require('crypto'); + +const fetch = require("node-fetch"); const { Headers } = fetch; const { Logger } = require('@nestjs/common'); const { HttpService } = require('@nestjs/axios'); @@ -151,29 +155,108 @@ export const wordToNumber = (input, type = "benId") => { } }; +export const getUniqueKey = (maxSize = 15): string => { + const chars = "abcdefghijklmnopqrstuvwxyz"; + const data = new Uint8Array(maxSize); + crypto.getRandomValues(data); + + const result = Array.from(data) + .map(byte => chars[byte % chars.length]) + .join('') + .toUpperCase(); + console.log(result) + return result; +} + + +//Encryption Method +export function encrypt(textToEncrypt: string, key: string): string { + try { + // Ensure the key is 16 bytes (AES-128) + const keyBytes = Buffer.alloc(16, 0); // Create a 16-byte buffer filled with zeros + const pwdBytes = Buffer.from(key, 'utf8'); + pwdBytes.copy(keyBytes, 0, 0, Math.min(pwdBytes.length, keyBytes.length)); + + const iv = keyBytes; // Use the same value for IV and key + const cipher = crypto.createCipheriv('aes-128-cbc', keyBytes, iv); + + // Encrypt the plaintext + const encrypted = Buffer.concat([ + cipher.update(Buffer.from(textToEncrypt, 'utf8')), + cipher.final(), + ]); + + // Return the encrypted text as Base64 + return encrypted.toString('base64'); + } catch (error) { + console.error("Error while encrypting the message:", error); + return "Error while encrypting the message." + } +} + + + + +//Decryption Method +function decrypt(textToDecrypt: string, key: string): string { + try { + const keyBytes = Buffer.alloc(16); // Create a buffer of 16 bytes for the key + const pwdBytes = Buffer.from(key, 'utf-8'); // Convert the key to bytes + const len = Math.min(pwdBytes.length, keyBytes.length); + pwdBytes.copy(keyBytes, 0, 0, len); // Copy the key into the buffer + + const encryptedData = Buffer.from(textToDecrypt, 'base64'); // Convert the encrypted text from Base64 to bytes + + // Initialize the cipher configuration + const decipher = createDecipheriv('aes-128-cbc', keyBytes, keyBytes); + decipher.setAutoPadding(false); // Set auto padding to false + + // Decrypt the data + let decrypted = decipher.update(encryptedData); + decrypted = Buffer.concat([decrypted, decipher.final()]); + + // Convert the decrypted data to a UTF-8 string + let decryptedText = decrypted.toString('utf-8'); + + // Trim the decrypted text to remove padding and get the JSON object + const lastIndex = decryptedText.lastIndexOf('}'); + const trimmedText = lastIndex !== -1 ? decryptedText.substring(0, lastIndex + 1) : decryptedText; + + return trimmedText; + } catch (error) { + console.error("Error while decrypting the message:", error); + return "Error while decrypting the message." + } +} + export const encryptRequest = async (text: string) => { try { - var myHeaders = new Headers(); - myHeaders.append("Content-Type", "application/json"); - logger.log("text: ", text); - var raw = JSON.stringify({ - EncryptedRequest: text, - }); + console.log("text to encrypt is : ", text); + // var myHeaders = new Headers(); + // myHeaders.append("Content-Type", "application/json"); + // console.log("text: ", text); + // var raw = JSON.stringify({ + // EncryptedRequest: text, + // }); - var requestOptions: any = { - method: "POST", - headers: myHeaders, - body: raw, - redirect: "follow", - }; + // var requestOptions: any = { + // method: "POST", + // headers: myHeaders, + // body: raw, + // redirect: "follow", + // }; - let response: any = await fetch( - `${process.env.PM_KISAN_ENC_DEC_API}/EncryptedRequest`, - requestOptions - ); - response = await response.json(); - return response; + // let response: any = await fetch( + // `${process.env.PM_KISAN_ENC_DEC_API}/EncryptedRequest`, + // requestOptions + // ); + + // Extract Token from the parsed text + + // response = await response.json(); + } catch (error) { + console.error("Error while encrypting the message:", error); return { error: "Error while encrypting the message.", }; @@ -182,25 +265,26 @@ export const encryptRequest = async (text: string) => { export const decryptRequest = async (text: string, token: string) => { try { - var myHeaders = new Headers(); - myHeaders.append("Content-Type", "application/json"); - + console.log("the text for decryption is : ", text); + console.log("the token for decryption is : ", token); var raw = JSON.stringify({ DecryptedRequest: `${text}@${token}`, }); + // text = "jhp8OW+FdOFZJck8eIm6mx1DSWwPghgYKFRwu7e+Ppj72A++R10Vaa7p7+KtLTQtnaK2mZv3I8TwiJo+pr1jjnrh/2cRjlK23REX2mJf10osnDpD2AFI8ihoFb/ShNAReW4Jj5fqVGdPYVX8peWn51Cu2iD0WouyOHrl9OwZ4b8=" + // var requestOptions: any = { + // method: "POST", + // headers: myHeaders, + // body: raw, + // redirect: "follow", + // }; - var requestOptions: any = { - method: "POST", - headers: myHeaders, - body: raw, - redirect: "follow", - }; - - let response = await fetch( - `${process.env.PM_KISAN_ENC_DEC_API}/DecryptedRequest`, - requestOptions - ); - response = await response.json(); + // let response = await fetch( + // `${process.env.PM_KISAN_ENC_DEC_API}/DecryptedRequest`, + // requestOptions + // ); + let response = await decrypt(text, token); + // response = await response.json(); + console.log("the response from decrypt request: ", response); return response; } catch (error) { return { diff --git a/src/modules/user/user.service.ts b/src/modules/user/user.service.ts index f7cda37..d0f6485 100644 --- a/src/modules/user/user.service.ts +++ b/src/modules/user/user.service.ts @@ -2,9 +2,10 @@ import { Injectable, Logger } from "@nestjs/common"; import { PrismaService } from "../../global-services/prisma.service"; import { ConfigService } from "@nestjs/config"; import axios from "axios"; -import { decryptRequest, encryptRequest } from "../../common/utils"; +import { decryptRequest, encrypt, encryptRequest } from "../../common/utils"; import { Message } from "@prisma/client"; import { MonitoringService } from "../monitoring/monitoring.service"; +import { getUniqueKey } from "../../common/utils"; @Injectable() export class UserService { @@ -19,15 +20,25 @@ export class UserService { async sendOTP(mobileNumber: string, type: string = "Mobile"): Promise { try { - let encryptedData = await encryptRequest( - `{\"Types\":\"${type}\",\"Values\":\"${mobileNumber}\",\"Token\":\"${this.configService.get( - "PM_KISSAN_TOKEN" - )}\"}` - ); - this.logger.log("encrypted data: ", encryptedData); - let data = JSON.stringify({ - EncryptedRequest: `${encryptedData.d.encryptedvalu}@${encryptedData.d.token}`, - }); + // let encryptedData = await encryptRequest( + // `{\"Types\":\"${type}\",\"Values\":\"${mobileNumber}\",\"Token\":\"${this.configService.get( + // "PM_KISSAN_TOKEN" + // )}\"}` + // ); + let key = getUniqueKey(); + let requestData = `{\"Types\":\"${type}\",\"Values\":\"${mobileNumber}\",\"Token\":\"${this.configService.get("PM_KISSAN_TOKEN")}\"}`; + console.log("Request data: ", requestData); + let encrypted_text = await encrypt(requestData, key); //without @ + + console.log("encrypted text without @: ", encrypted_text); + // let data = JSON.stringify({ + // EncryptedRequest: `${encryptedData.d.encryptedvalu}@${encryptedData.d.token}`, + // }); + let data = { + "EncryptedRequest":`${encrypted_text}@${key}` + }; + + console.log("(in sendOTP)the data in the data var is as: ", data); let config = { method: "post", @@ -38,16 +49,18 @@ export class UserService { }, data: data, }; - let response: any = await axios.request(config); this.logger.log("sendOTP", response.status); if (response.status >= 200 && response.status < 300) { response = await response.data; let decryptedData: any = await decryptRequest( response.d.output, - encryptedData.d.token + key ); - response.d.output = JSON.parse(decryptedData.d.decryptedvalue); + const parsedData = JSON.parse(decryptedData); // Convert JSON string to an object + // const values = parsedData.Values; // Access the Values property + // console.log("Values:", values); + response.d.output = parsedData; response["status"] = response.d.output.Rsponce != "False" ? "OK" : "NOT_OK"; return response; @@ -62,7 +75,7 @@ export class UserService { }; } } catch (error) { - this.logger.error(error); + console.error("Error in sendOTP:", error.message, error.response?.data || error); return { d: { output: { @@ -80,15 +93,33 @@ export class UserService { type: string = "Mobile" ): Promise { try { - let encryptedData = await encryptRequest( - `{\"Types\":\"${type}\",\"Values\":\"${mobileNumber}\",\"OTP\":\"${otp}\",\"Token\":\"${this.configService.get( - "PM_KISSAN_TOKEN" - )}\"}` - ); - let data = JSON.stringify({ - EncryptedRequest: `${encryptedData.d.encryptedvalu}@${encryptedData.d.token}`, - }); + // let encryptedData = await encryptRequest( + // `{\"Types\":\"${type}\",\"Values\":\"${mobileNumber}\",\"OTP\":\"${otp}\",\"Token\":\"${this.configService.get( + // "PM_KISSAN_TOKEN" + // )}\"}` + // ); + // const requestData = `{\"Types\":\"${type}\",\"Values\":\"${mobileNumber}\",\"Token\":\"${this.configService.get("PM_KISSAN_TOKEN")}\"}`; + let requestData = `{\"Types\":\"${type}\",\"Values\":\"${mobileNumber}\",\"OTP\":\"${otp}\",\"${this.configService.get("PM_KISSAN_TOKEN")}\"}`; + console.log("Request data: ", requestData); + let key = getUniqueKey(); + // const requestData = JSON.stringify({ + // Types: type, + // Values: mobileNumber, + // Token: "" + // }); + let encrypted_text = await encrypt(requestData, key); //without @ + + console.log("encrypted text without @: ", encrypted_text); + + // let data = JSON.stringify({ + // EncryptedRequest: `${encryptedData.d.encryptedvalu}@${encryptedData.d.token}`, + // }); + let data = { + // EncryptedRequest: `${encryptedData}` + "EncryptedRequest": `${encrypted_text}@${key}`, + }; + console.log("(inside verifyOTP)the data in the data var is : ", data); let config = { method: "post", maxBodyLength: Infinity, @@ -107,10 +138,11 @@ export class UserService { response = await response.data; let decryptedData: any = await decryptRequest( response.d.output, - encryptedData.d.token + key ); - this.logger.log(decryptedData); - response.d.output = JSON.parse(decryptedData.d.decryptedvalue); + console.log("Response of VerifyOTP",response); + console.log("Response from decryptedData(verifyOTP)",decryptedData); + // response.d.output = JSON.parse(decryptedData); response["status"] = response.d.output.Rsponce != "False" ? "OK" : "NOT_OK"; return response; @@ -143,14 +175,27 @@ export class UserService { ): Promise { let res: any; try { - let encryptedData = await encryptRequest( - `{\"Types\":\"${type}\",\"Values\":\"${mobileNumber}\",\"Token\":\"${this.configService.get( - "PM_KISSAN_TOKEN" - )}\"}` - ); - let data = JSON.stringify({ - EncryptedRequest: `${encryptedData.d.encryptedvalu}@${encryptedData.d.token}`, - }); + // let encryptedData = await encryptRequest( + // `{\"Types\":\"${type}\",\"Values\":\"${mobileNumber}\",\"Token\":\"${this.configService.get( + // "PM_KISSAN_TOKEN" + // )}\"}` + // ); + const requestData = `{\"Types\":\"${type}\",\"Values\":\"${mobileNumber}\",\"Token\":\"${this.configService.get("PM_KISSAN_TOKEN")}\"}`; + console.log("Request data: ", requestData); + let key = getUniqueKey(); + // const requestData = JSON.stringify({ + // Types: type, + // Values: mobileNumber, + // Token: "" + // }); + let encrypted_text = await encrypt(requestData, key); //without @ + console.log("encrypted text without @: ", encrypted_text); + // let data = JSON.stringify({ + // EncryptedRequest: `${encryptedData.d.encryptedvalu}@${encryptedData.d.token}`, + // }); + let data = { + "EncryptedRequest": `${encrypted_text}@${key}`, + }; let config = { method: "post", @@ -169,9 +214,11 @@ export class UserService { res = await res.data; let decryptedData: any = await decryptRequest( res.d.output, - encryptedData.d.token + key ); - res.d.output = JSON.parse(decryptedData.d.decryptedvalue); + console.log("Response of getUserData",res); + console.log("decrypted data(from getUserData): ", decryptedData); + res.d.output = JSON.parse(decryptedData); res["status"] = res.d.output.Rsponce != "False" ? "OK" : "NOT_OK"; } else { this.monitoringService.incrementUnableToGetUserDetailsCount(); diff --git a/src/xstate/prompt/prompt.service.ts b/src/xstate/prompt/prompt.service.ts index cdd928b..382691b 100644 --- a/src/xstate/prompt/prompt.service.ts +++ b/src/xstate/prompt/prompt.service.ts @@ -3,7 +3,7 @@ import { AiToolsService } from "../../modules/aiTools/ai-tools.service"; import { AADHAAR_GREETING_MESSAGE } from "../../common/constants"; import { UserService } from "../../modules/user/user.service"; import axios from "axios"; -import { decryptRequest, encryptRequest, titleCase } from "../../common/utils"; +import { decryptRequest, encryptRequest, getUniqueKey, titleCase, encrypt } from "../../common/utils"; import { PrismaService } from "src/global-services/prisma.service"; import { Injectable, Logger } from "@nestjs/common"; import { @@ -20,6 +20,7 @@ const filePath = path.resolve(__dirname, "../../common/kisanPortalErrors.json"); const PMKissanProtalErrors = require(filePath); import * as moment from "moment"; + @Injectable() export class PromptServices { private userService: UserService; @@ -181,7 +182,7 @@ export class PromptServices { if (res.d.output.Message == "Unable to get user details") { return Promise.reject(new Error(res.d.output.Message)); } - let userDetails = AADHAAR_GREETING_MESSAGE( + let userDetails = AADHAAR_GREETING_MESSAGE( titleCase(res.d.output["BeneficiaryName"]), titleCase(res.d.output["FatherName"]), res.d.output["DOB"], @@ -200,15 +201,27 @@ export class PromptServices { this.logger.log("using...", userIdentifier, type); let userErrors = []; try { - let encryptedData = await encryptRequest( - `{\"Types\":\"${type}",\"Values\":\"${userIdentifier}\",\"Token\":\"${this.configService.get( - "PM_KISSAN_TOKEN" - )}\"}` - ); - let data = JSON.stringify({ - EncryptedRequest: `${encryptedData.d.encryptedvalu}@${encryptedData.d.token}`, - }); - this.logger.log("body", data); + // let encryptedData = await encryptRequest( + // `{\"Types\":\"${type}",\"Values\":\"${userIdentifier}\",\"Token\":\"${this.configService.get( + // "PM_KISSAN_TOKEN" + // )}\"}` + // ); + var token = getUniqueKey(); + // const requestData = JSON.stringify({ + // Types: type, + // Values: userIdentifier, + // Token: token + // }); + let requestData = `{\"Types\":\"${type}\",\"Values\":\"${userIdentifier}\",\"Token\":\"${this.configService.get("PM_KISSAN_TOKEN")}\"}`; + + let encrypted_text = await encrypt(requestData, token); //without @ + // let data = JSON.stringify({ + // EncryptedRequest: `${encryptedData.d.encryptedvalu}@${encryptedData.d.token}`, + // }); + // console.log("body", data); + let data = { + "EncryptedRequest":`${encrypted_text}@${token}` + }; let config = { method: "post", @@ -227,9 +240,9 @@ export class PromptServices { this.logger.log("related issues", errors); let decryptedData: any = await decryptRequest( errors.d.output, - encryptedData.d.token + token ); - errors = JSON.parse(decryptedData.d.decryptedvalue); + errors = JSON.parse(decryptedData); if (errors.Rsponce == "True") { Object.entries(errors).forEach(([key, value]) => { if (key != "Rsponce" && key != "Message") {