Skip to content

Commit 8276046

Browse files
Merge pull request #1918 from ricaelchiquetti/main
feat: implement standardized error handling for WhatsApp API responses
2 parents 5a39f1a + 4378c33 commit 8276046

File tree

4 files changed

+137
-34
lines changed

4 files changed

+137
-34
lines changed

src/api/routes/business.router.ts

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { RouterBroker } from '@api/abstract/abstract.router';
22
import { NumberDto } from '@api/dto/chat.dto';
33
import { businessController } from '@api/server.module';
4+
import { createMetaErrorResponse } from '@utils/errorResponse';
45
import { catalogSchema, collectionsSchema } from '@validate/validate.schema';
56
import { RequestHandler, Router } from 'express';
67

@@ -11,25 +12,43 @@ export class BusinessRouter extends RouterBroker {
1112
super();
1213
this.router
1314
.post(this.routerPath('getCatalog'), ...guards, async (req, res) => {
14-
const response = await this.dataValidate<NumberDto>({
15-
request: req,
16-
schema: catalogSchema,
17-
ClassRef: NumberDto,
18-
execute: (instance, data) => businessController.fetchCatalog(instance, data),
19-
});
20-
21-
return res.status(HttpStatus.OK).json(response);
15+
try {
16+
const response = await this.dataValidate<NumberDto>({
17+
request: req,
18+
schema: catalogSchema,
19+
ClassRef: NumberDto,
20+
execute: (instance, data) => businessController.fetchCatalog(instance, data),
21+
});
22+
23+
return res.status(HttpStatus.OK).json(response);
24+
} catch (error) {
25+
// Log error for debugging
26+
console.error('Business catalog error:', error);
27+
28+
// Use utility function to create standardized error response
29+
const errorResponse = createMetaErrorResponse(error, 'business_catalog');
30+
return res.status(errorResponse.status).json(errorResponse);
31+
}
2232
})
2333

2434
.post(this.routerPath('getCollections'), ...guards, async (req, res) => {
25-
const response = await this.dataValidate<NumberDto>({
26-
request: req,
27-
schema: collectionsSchema,
28-
ClassRef: NumberDto,
29-
execute: (instance, data) => businessController.fetchCollections(instance, data),
30-
});
31-
32-
return res.status(HttpStatus.OK).json(response);
35+
try {
36+
const response = await this.dataValidate<NumberDto>({
37+
request: req,
38+
schema: collectionsSchema,
39+
ClassRef: NumberDto,
40+
execute: (instance, data) => businessController.fetchCollections(instance, data),
41+
});
42+
43+
return res.status(HttpStatus.OK).json(response);
44+
} catch (error) {
45+
// Log error for debugging
46+
console.error('Business collections error:', error);
47+
48+
// Use utility function to create standardized error response
49+
const errorResponse = createMetaErrorResponse(error, 'business_collections');
50+
return res.status(errorResponse.status).json(errorResponse);
51+
}
3352
});
3453
}
3554

src/api/routes/template.router.ts

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { InstanceDto } from '@api/dto/instance.dto';
33
import { TemplateDto } from '@api/dto/template.dto';
44
import { templateController } from '@api/server.module';
55
import { ConfigService } from '@config/env.config';
6+
import { createMetaErrorResponse } from '@utils/errorResponse';
67
import { instanceSchema, templateSchema } from '@validate/validate.schema';
78
import { RequestHandler, Router } from 'express';
89

@@ -16,24 +17,42 @@ export class TemplateRouter extends RouterBroker {
1617
super();
1718
this.router
1819
.post(this.routerPath('create'), ...guards, async (req, res) => {
19-
const response = await this.dataValidate<TemplateDto>({
20-
request: req,
21-
schema: templateSchema,
22-
ClassRef: TemplateDto,
23-
execute: (instance, data) => templateController.createTemplate(instance, data),
24-
});
20+
try {
21+
const response = await this.dataValidate<TemplateDto>({
22+
request: req,
23+
schema: templateSchema,
24+
ClassRef: TemplateDto,
25+
execute: (instance, data) => templateController.createTemplate(instance, data),
26+
});
2527

26-
res.status(HttpStatus.CREATED).json(response);
28+
res.status(HttpStatus.CREATED).json(response);
29+
} catch (error) {
30+
// Log error for debugging
31+
console.error('Template creation error:', error);
32+
33+
// Use utility function to create standardized error response
34+
const errorResponse = createMetaErrorResponse(error, 'template_creation');
35+
res.status(errorResponse.status).json(errorResponse);
36+
}
2737
})
2838
.get(this.routerPath('find'), ...guards, async (req, res) => {
29-
const response = await this.dataValidate<InstanceDto>({
30-
request: req,
31-
schema: instanceSchema,
32-
ClassRef: InstanceDto,
33-
execute: (instance) => templateController.findTemplate(instance),
34-
});
39+
try {
40+
const response = await this.dataValidate<InstanceDto>({
41+
request: req,
42+
schema: instanceSchema,
43+
ClassRef: InstanceDto,
44+
execute: (instance) => templateController.findTemplate(instance),
45+
});
46+
47+
res.status(HttpStatus.OK).json(response);
48+
} catch (error) {
49+
// Log error for debugging
50+
console.error('Template find error:', error);
3551

36-
res.status(HttpStatus.OK).json(response);
52+
// Use utility function to create standardized error response
53+
const errorResponse = createMetaErrorResponse(error, 'template_find');
54+
res.status(errorResponse.status).json(errorResponse);
55+
}
3756
});
3857
}
3958

src/api/services/template.service.ts

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@ export class TemplateService {
6060
const response = await this.requestTemplate(postData, 'POST');
6161

6262
if (!response || response.error) {
63+
// If there's an error from WhatsApp API, throw it with the real error data
64+
if (response && response.error) {
65+
// Create an error object that includes the template field for Meta errors
66+
const metaError = new Error(response.error.message || 'WhatsApp API Error');
67+
(metaError as any).template = response.error;
68+
throw metaError;
69+
}
6370
throw new Error('Error to create template');
6471
}
6572

@@ -75,8 +82,9 @@ export class TemplateService {
7582

7683
return template;
7784
} catch (error) {
78-
this.logger.error(error);
79-
throw new Error('Error to create template');
85+
this.logger.error('Error in create template: ' + error);
86+
// Propagate the real error instead of "engolindo" it
87+
throw error;
8088
}
8189
}
8290

@@ -86,6 +94,7 @@ export class TemplateService {
8694
const version = this.configService.get<WaBusiness>('WA_BUSINESS').VERSION;
8795
urlServer = `${urlServer}/${version}/${this.businessId}/message_templates`;
8896
const headers = { 'Content-Type': 'application/json', Authorization: `Bearer ${this.token}` };
97+
8998
if (method === 'GET') {
9099
const result = await axios.get(urlServer, { headers });
91100
return result.data;
@@ -94,8 +103,17 @@ export class TemplateService {
94103
return result.data;
95104
}
96105
} catch (e) {
97-
this.logger.error(e.response.data);
98-
return e.response.data.error;
106+
this.logger.error(
107+
'WhatsApp API request error: ' + (e.response?.data ? JSON.stringify(e.response?.data) : e.message),
108+
);
109+
110+
// Return the complete error response from WhatsApp API
111+
if (e.response?.data) {
112+
return e.response.data;
113+
}
114+
115+
// If no response data, throw connection error
116+
throw new Error(`Connection error: ${e.message}`);
99117
}
100118
}
101119
}

src/utils/errorResponse.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { HttpStatus } from '@api/routes/index.router';
2+
3+
export interface MetaErrorResponse {
4+
status: number;
5+
error: string;
6+
message: string;
7+
details: {
8+
whatsapp_error: string;
9+
whatsapp_code: string | number;
10+
error_user_title: string;
11+
error_user_msg: string;
12+
error_type: string;
13+
error_subcode: number | null;
14+
fbtrace_id: string | null;
15+
context: string;
16+
type: string;
17+
};
18+
timestamp: string;
19+
}
20+
21+
/**
22+
* Creates standardized error response for Meta/WhatsApp API errors
23+
*/
24+
export function createMetaErrorResponse(error: any, context: string): MetaErrorResponse {
25+
// Extract Meta/WhatsApp specific error fields
26+
const metaError = error.template || error;
27+
const errorUserTitle = metaError.error_user_title || metaError.message || 'Unknown error';
28+
const errorUserMsg = metaError.error_user_msg || metaError.message || 'Unknown error';
29+
30+
return {
31+
status: HttpStatus.BAD_REQUEST,
32+
error: 'Bad Request',
33+
message: errorUserTitle,
34+
details: {
35+
whatsapp_error: errorUserMsg,
36+
whatsapp_code: metaError.code || 'UNKNOWN_ERROR',
37+
error_user_title: errorUserTitle,
38+
error_user_msg: errorUserMsg,
39+
error_type: metaError.type || 'UNKNOWN',
40+
error_subcode: metaError.error_subcode || null,
41+
fbtrace_id: metaError.fbtrace_id || null,
42+
context,
43+
type: 'whatsapp_api_error',
44+
},
45+
timestamp: new Date().toISOString(),
46+
};
47+
}

0 commit comments

Comments
 (0)