aeremmiddleware 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,205 @@
1
+ import axios, { AxiosRequestConfig, AxiosResponse } from "axios";
2
+
3
+
4
+ export default class IdfyAPIWrapper {
5
+
6
+ private bodyTaskIdGroupId = {
7
+ task_id: '74f4c926-250c-43ca-9c53-453e87ceacd1',
8
+ group_id: '8e16424a-58fc-4ba4-ab20-5bc8e7c3c41e',
9
+ }
10
+ private defaultHeaderIdfyApi = {
11
+ "account-id": "e0d2add9d3c1/86e1d197-adb5-4f8f-af82-2728599a3615",
12
+ "api-key": "7fad350f-5519-4ec7-b977-d8c8b131b8e4"
13
+ }
14
+ private baseUrl: string = "https://eve.idfy.com/";
15
+ private gstVerificationEndPoint = 'v3/tasks/sync/verify_with_source/ind_gst_certificate'
16
+ private panIndividualVerificationEndPoint = 'v3/tasks/async/verify_with_source/ind_pan'
17
+ private cinCompanyVerificationEndPoint = 'v3/tasks/async/verify_with_source/ind_mca'
18
+ private taskUrl = 'v3/tasks?request_id='
19
+ private syncIndividualAadharScanInfoEndpoint = 'v3/tasks/sync/extract/ind_aadhaar_plus'
20
+ private syncIndividualPANScanInfoEndpoint = 'v3/tasks/sync/extract/ind_pan'
21
+ private syncIndividualLiveFaceLivenessEndpoint = 'v3/tasks/sync/check_photo_liveness/face'
22
+
23
+
24
+
25
+
26
+ constructor() { }
27
+
28
+ private async makeRequest<T>(
29
+ method: string,
30
+ endpoint: string,
31
+ data?: any
32
+ ): Promise<T> {
33
+ const requestConfig: AxiosRequestConfig = {
34
+ method,
35
+ url: this.baseUrl + endpoint,
36
+ headers: this.defaultHeaderIdfyApi,
37
+ data,
38
+ };
39
+
40
+ try {
41
+ const response: AxiosResponse<T> = await axios(requestConfig);
42
+ return response.data;
43
+ } catch (error) {
44
+ console.error("Error while making Idfy Axios API request:", error);
45
+ throw error;
46
+ }
47
+ }
48
+
49
+ private async getTask(requestId: string): Promise<any> {
50
+ try {
51
+ // const data = {}
52
+ const urlEndPoint = this.taskUrl + requestId
53
+ const response = await this.makeRequest<any>("get", urlEndPoint);
54
+ return response;
55
+ } catch (error) {
56
+ console.error("Error while fetching Idfy getTask API data:", error);
57
+ throw error;
58
+ }
59
+ }
60
+
61
+ private async pingTaskUntilSuccess(requestId: string): Promise<any> {
62
+ try {
63
+
64
+ let res: any = null
65
+ const checkTaskAfter1sec = (requestId:string) => {
66
+ return new Promise<any>((resolve, reject) => {
67
+ try{
68
+ setTimeout(async () => {
69
+ const data = await this.getTask(requestId)
70
+ if(res?.[0].status == 'failed'){
71
+ reject(res)
72
+ }
73
+ resolve(data)
74
+ }, 1000)
75
+
76
+ }catch(e){
77
+ reject(e)
78
+ }
79
+ })
80
+ }
81
+ do {
82
+ res = await checkTaskAfter1sec(requestId)
83
+
84
+ console.log( "### res ",res) ;
85
+ } while (res?.[0].status !== 'completed')
86
+
87
+ return res;
88
+
89
+ } catch (error) {
90
+ console.error("Error while fetching Idfy getTask API data:", error);
91
+ throw error;
92
+ }
93
+ }
94
+ async getCompanyGstInfo({ gstNo }: { gstNo: string }): Promise<any> {
95
+ try {
96
+ const data = {
97
+ ...(this.bodyTaskIdGroupId),
98
+ data: {
99
+ gstin: gstNo,
100
+ }
101
+ }
102
+ const response = await this.makeRequest<any>("post", this.gstVerificationEndPoint, data);
103
+ return response;
104
+ } catch (error) {
105
+ console.error("Error while fetching Idfy API data:", error);
106
+ throw error;
107
+ }
108
+ }
109
+ async getCompanyCINInfo({ cinNo }: { cinNo: string }): Promise<any> {
110
+ try {
111
+ const data = {
112
+ ...(this.bodyTaskIdGroupId),
113
+ data: {
114
+ "cin": cinNo,
115
+ }
116
+ }
117
+ const response = await this.makeRequest<any>("post", this.cinCompanyVerificationEndPoint, data);
118
+ const successData = await this.pingTaskUntilSuccess(response.request_id)
119
+
120
+ return successData?.[0]?.result?.source_output;
121
+ } catch (error) {
122
+ console.error("Error while fetching Idfy CIN API data:", error);
123
+ throw error;
124
+ }
125
+ }
126
+ async getIndividualPANInfo({ panNo }: { panNo: string }): Promise<any> {
127
+ try {
128
+ const data = {
129
+ ...(this.bodyTaskIdGroupId),
130
+ data: {
131
+ "id_number": panNo,
132
+ }
133
+ }
134
+ const response = await this.makeRequest<any>("post", this.panIndividualVerificationEndPoint, data);
135
+ const successData = await this.pingTaskUntilSuccess(response.request_id)
136
+
137
+ return successData?.[0]?.result?.source_output;
138
+ } catch (error) {
139
+ console.error("Error while fetching Idfy PAN API data:", error);
140
+ throw error;
141
+ }
142
+ }
143
+
144
+ async getSyncIndividualAadharScanInfo({ frontScanBase64,backScanBase64 }: { frontScanBase64: string,backScanBase64:string }): Promise<any> {
145
+ try {
146
+ const data = {
147
+ ...(this.bodyTaskIdGroupId),
148
+ data: {
149
+ "document1":frontScanBase64,
150
+ "document2":backScanBase64,
151
+ "consent":"yes",
152
+ "advanced_details": {
153
+ "extract_qr_info": true,
154
+ "extract_last_4_digit":false
155
+ }
156
+ }
157
+ }
158
+ const response = await this.makeRequest<any>("post", this.syncIndividualAadharScanInfoEndpoint, data);
159
+
160
+ return response?.result;
161
+ } catch (error) {
162
+ console.error("Error while fetching Idfy PAN API data:", error);
163
+ throw error;
164
+ }
165
+ }
166
+
167
+ async getSyncIndividualPANScanInfo({ frontScanBase64 }: { frontScanBase64: string }): Promise<any> {
168
+ try {
169
+ const data = {
170
+ ...(this.bodyTaskIdGroupId),
171
+ data: {
172
+ "document1":frontScanBase64,
173
+ "consent":"yes",
174
+ }
175
+ }
176
+ const response = await this.makeRequest<any>("post", this.syncIndividualPANScanInfoEndpoint, data);
177
+
178
+ return response?.result;
179
+ } catch (error) {
180
+ console.error("Error while fetching Idfy PAN API data:", error);
181
+ throw error;
182
+ }
183
+ }
184
+
185
+ async getSyncIndividualLivenessSelfyScanInfo({ faceScanBase64 }: { faceScanBase64: string }): Promise<any> {
186
+ try {
187
+ const data = {
188
+ ...(this.bodyTaskIdGroupId),
189
+ data: {
190
+ "document1":faceScanBase64,
191
+ "consent":"yes",
192
+ }
193
+ }
194
+ const response = await this.makeRequest<any>("post", this.syncIndividualLiveFaceLivenessEndpoint, data);
195
+
196
+ return response?.result;
197
+ } catch (error) {
198
+ console.error("Error while fetching Idfy PAN API data:", error);
199
+ throw error;
200
+ }
201
+ }
202
+
203
+
204
+
205
+ }
@@ -0,0 +1,5 @@
1
+ import IdfyAPIWrapper from './idfy'
2
+
3
+ export const finance = {
4
+ idFy : IdfyAPIWrapper
5
+ }
package/Maps/index.ts ADDED
File without changes
@@ -0,0 +1,95 @@
1
+ interface WhatsAppMessageData {
2
+ from: string;
3
+ to: string;
4
+ body?: string;
5
+ content?: WhatsappContentType;
6
+ }
7
+
8
+ interface Templatetype {
9
+ name: string;
10
+ language: {
11
+ policy: string;
12
+ code: string;
13
+ };
14
+ components: Array<{
15
+ type: string;
16
+ parameters: Array<{
17
+ type: string;
18
+ text: string;
19
+ }>;
20
+ }>;
21
+ }
22
+ interface WhatsappContentType {
23
+ type: string; //"text", "document", "image", "video", "template";
24
+ text?: { preview_url: string; body: string };
25
+ document?: any;
26
+ image?: any;
27
+ video?: any;
28
+ recipient_type: any;
29
+ template?: Templatetype;
30
+ }
31
+
32
+ export interface DemoBody {
33
+ whatsapp: {
34
+ messages: Array<WhatsAppMessageData>;
35
+ };
36
+ }
37
+
38
+ interface WhatsAppTemplateMessage {
39
+ from: string;
40
+ to: string;
41
+ content: {
42
+ type: string;
43
+ template: {
44
+ name: string;
45
+ language: {
46
+ policy?: string;
47
+ code: string;
48
+ };
49
+ components: Array<{
50
+ type: string;
51
+ parameters: Array<{
52
+ type: string;
53
+ text: string;
54
+ }>;
55
+ }>;
56
+ };
57
+ };
58
+ }
59
+
60
+ export interface WhatsAppTemplateDemoBody {
61
+ whatsapp: {
62
+ messages: Array<WhatsAppTemplateMessage>;
63
+ };
64
+ }
65
+
66
+ export interface EmiReminderAug2023 {
67
+ code: number;
68
+ error_data: null;
69
+ status: string;
70
+ data: {
71
+ waba_id: string;
72
+ name: string;
73
+ components: Array<HeaderComponent | BodyComponent>;
74
+ };
75
+ }
76
+
77
+ interface HeaderComponent {
78
+ type: string;
79
+ format: string;
80
+ text: string;
81
+ example: {
82
+ header_text: Array<string>;
83
+ };
84
+ }
85
+ interface BodyComponent {
86
+ type: string;
87
+ text: string;
88
+ example: {
89
+ body_text: Array<Array<string>>;
90
+ };
91
+ }
92
+ export enum Provider {
93
+ EXOTEL = "EXOTEL",
94
+ GUPSHUP = "GUPSHUP",
95
+ }
@@ -0,0 +1,5 @@
1
+ import Socials from './message'
2
+
3
+ export const socials = {
4
+ message : Socials
5
+ }
@@ -0,0 +1,188 @@
1
+ import axios from "axios";
2
+ import { DemoBody, EmiReminderAug2023, Provider, WhatsAppTemplateDemoBody } from "./Whatsapp.types";
3
+
4
+ class ExotelWhatsAppSender {
5
+ private exotelSid: string;
6
+ private exotelToken: string;
7
+ private exotelApiKey: string;
8
+ private whatsappApiUrl!: string;
9
+ private provider: string;
10
+
11
+ constructor(payload: {
12
+ exotelSid: string;
13
+ exotelToken: string;
14
+ exotelApiKey: string;
15
+ provider: string;
16
+ }) {
17
+ const { exotelSid, exotelToken, exotelApiKey, provider } = payload;
18
+ this.exotelSid = exotelSid;
19
+ this.exotelToken = exotelToken;
20
+ this.exotelApiKey = exotelApiKey;
21
+ this.provider = provider;
22
+
23
+ if (this.provider === Provider.EXOTEL) {
24
+ this.whatsappApiUrl = `https://${exotelApiKey}:${exotelToken}@api.exotel.com/v2/accounts/${exotelSid}/messages`;
25
+ } else if (this.provider === Provider.GUPSHUP) {
26
+ // Define the URL for Gupshup API
27
+ // this.gupshupApiUrl = ...;
28
+ }
29
+ }
30
+
31
+ async getTemplates() {
32
+ const request = await axios.get(
33
+ `https://${this.exotelApiKey}:${this.exotelToken}@api.exotel.com/v2/accounts/${this.exotelSid}/templates?waba_id=114033855070320`
34
+ );
35
+
36
+ return request.data.response.whatsapp.templates;
37
+ }
38
+ getUniquePlaceholderCount(str: string) {
39
+ const arr:Array<string> = [];
40
+ str.split("{{").map((s) => arr.push(...s.split("}}")));
41
+ const placeholders: Array<string> = arr.filter(
42
+ (i) => i.match(/[0-9]+/) && !isNaN(Number(i))
43
+ );
44
+ return [...new Set(placeholders)].length;
45
+ }
46
+
47
+ validateTemplatePayload(template:EmiReminderAug2023, payload:any) {
48
+ const templateComponents = template.data.components;
49
+ if (templateComponents.length != 2) {
50
+ return;
51
+ }
52
+
53
+ const [headerTemplate, bodyTemplate] = templateComponents;
54
+ //this checks if placeholder is correct or not
55
+ for (let index = 0; index < payload.whatsapp.messages.length; index++) {
56
+ const message = payload.whatsapp.messages[index];
57
+ const payloadComponents = message.content.template.components;
58
+ for (let index2 = 0; index2 < payloadComponents.length; index2++) {
59
+ const payloadComponent = payloadComponents[index2];
60
+ // validate template header
61
+ if (payloadComponent.type === headerTemplate.type.toLowerCase()) {
62
+ const headerPlaceholdersCount = this.getUniquePlaceholderCount(
63
+ headerTemplate.text
64
+ );
65
+ if (payloadComponent.parameters.length != headerPlaceholdersCount) {
66
+ console.log("invalid header");
67
+ throw new Error("header count mismatch");
68
+ } else {
69
+ // header validated
70
+ // TODO: add more validations if required
71
+ }
72
+ } else if (payloadComponent.type === bodyTemplate.type.toLowerCase()) {
73
+ const bodyPlaceholdersCount = this.getUniquePlaceholderCount(
74
+ bodyTemplate.text
75
+ );
76
+ if (payloadComponent.parameters.length != bodyPlaceholdersCount) {
77
+ console.log("invalid body");
78
+ throw new Error("body count mismatch");
79
+ } else {
80
+ // validate template body
81
+ // body validated
82
+ // TODO: add more validations if required
83
+ }
84
+ }
85
+ else
86
+ throw new Error("type mismatch or incorrect")
87
+
88
+ }
89
+ return true;
90
+ }
91
+ }
92
+ testType(obj: DemoBody) {
93
+ let returnValue = true;
94
+ obj.whatsapp.messages.every((message, index) => {
95
+ returnValue =
96
+ Boolean(message?.content?.type === "text" && message.content.text) ||
97
+ Boolean(
98
+ message?.content?.type === "document" && message.content.document
99
+ ) ||
100
+ Boolean(message?.content?.type === "image" && message.content.image) ||
101
+ Boolean(message?.content?.type === "video" && message.content.video) ||
102
+ Boolean(
103
+ message?.content?.type === "template" && message.content.template
104
+ );
105
+ return returnValue;
106
+ });
107
+ return returnValue;
108
+ }
109
+
110
+ private async sendMessage(messageData: DemoBody): Promise<boolean> {
111
+ try {
112
+ let config = {
113
+ method: "post",
114
+ maxBodyLength: Infinity,
115
+ url: this.whatsappApiUrl,
116
+ headers: {
117
+ "Content-Type": "application/json",
118
+ },
119
+
120
+ data: JSON.stringify(messageData),
121
+ };
122
+
123
+ const response = await axios.request(config);
124
+ if (response.data.metadata && response.data.metadata.success != 0) {
125
+ console.log("WhatsApp message sent successfully:", response.data);
126
+ return true;
127
+ } else {
128
+ console.error("Error sending WhatsApp message:", response.data);
129
+ return false;
130
+ }
131
+ } catch (error) {
132
+ console.error("Error sending WhatsApp message:", error);
133
+ return false;
134
+ }
135
+ }
136
+
137
+ private async sendTemplateMessage(
138
+ messageData: WhatsAppTemplateDemoBody
139
+ ): Promise<boolean> {
140
+ try {
141
+ const config = {
142
+ method: "post",
143
+ maxBodyLength: Infinity,
144
+ url: this.whatsappApiUrl,
145
+ headers: {
146
+ "Content-Type": "application/json",
147
+ },
148
+ data: JSON.stringify(messageData),
149
+ };
150
+
151
+ const response = await axios.request(config);
152
+ if (response.data.metadata && response.data.metadata.success !== 0) {
153
+ console.log(
154
+ "WhatsApp template message sent successfully:",
155
+ response.data
156
+ );
157
+ return true;
158
+ } else {
159
+ console.error(
160
+ "Error sending WhatsApp template message:",
161
+ response.data
162
+ );
163
+ return false;
164
+ }
165
+ } catch (error) {
166
+ console.error("Error sending WhatsApp template message:", error);
167
+ return false;
168
+ }
169
+ }
170
+
171
+ async sendWhatsAppMessage(obj: DemoBody): Promise<boolean> {
172
+ if (this.testType(obj)) return this.sendMessage(obj);
173
+ else return false;
174
+ }
175
+
176
+ async sendWhatsappTemplateMessage(
177
+ obj: WhatsAppTemplateDemoBody
178
+ ): Promise<boolean> {
179
+ let templatevalue=await this.getTemplates();
180
+ let tempVariable=obj.whatsapp.messages[0].content.template.name;
181
+ let template = templatevalue.find((e:any)=>e.data.name==tempVariable)
182
+ if(this.validateTemplatePayload(template,obj)){
183
+ return this.sendTemplateMessage(obj)
184
+ }
185
+ else return false;
186
+ }
187
+ }
188
+ export default ExotelWhatsAppSender;
package/index.ts ADDED
@@ -0,0 +1,8 @@
1
+ import { finance } from "./Finance";
2
+ import { socials } from "./Socials";
3
+
4
+
5
+ export const AeremMiddleware = {
6
+ finance,socials
7
+
8
+ }
package/package.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "aeremmiddleware",
3
+ "version": "1.0.1",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "build": "rm -rf build && tsc ",
8
+ "prod": "node ./build/src/index.js"
9
+ },
10
+ "keywords": [],
11
+ "author": "",
12
+ "license": "ISC",
13
+ "dependencies": {
14
+ "axios": "^1.4.0"
15
+ }
16
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "compilerOptions": {
3
+
4
+ "target": "ES2017",
5
+ "module": "commonjs",
6
+ "esModuleInterop": true,
7
+ "forceConsistentCasingInFileNames": true,
8
+ "strict": true,
9
+ "skipLibCheck": true,
10
+ "rootDir": "./",
11
+ "outDir": "build"
12
+ }
13
+ }