Skip to content

Commit b7b3f1c

Browse files
author
ricael
committed
feat: implement standardized error handling for WhatsApp API responses
1 parent da8f22c commit b7b3f1c

File tree

4 files changed

+136
-35
lines changed

4 files changed

+136
-35
lines changed

src/api/routes/business.router.ts

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { NumberDto } from '@api/dto/chat.dto';
33
import { businessController } from '@api/server.module';
44
import { catalogSchema, collectionsSchema } from '@validate/validate.schema';
55
import { RequestHandler, Router } from 'express';
6+
import { createMetaErrorResponse } from '@utils/errorResponse';
67

78
import { HttpStatus } from './index.router';
89

@@ -11,27 +12,45 @@ 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-
});
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+
});
2022

21-
return res.status(HttpStatus.OK).json(response);
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-
});
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+
});
3142

32-
return res.status(HttpStatus.OK).json(response);
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

3655
public readonly router: Router = Router();
37-
}
56+
}

src/api/routes/template.router.ts

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { templateController } from '@api/server.module';
55
import { ConfigService } from '@config/env.config';
66
import { instanceSchema, templateSchema } from '@validate/validate.schema';
77
import { RequestHandler, Router } from 'express';
8+
import { createMetaErrorResponse } from '@utils/errorResponse';
89

910
import { HttpStatus } from './index.router';
1011

@@ -16,26 +17,44 @@ 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+
});
3546

36-
res.status(HttpStatus.OK).json(response);
47+
res.status(HttpStatus.OK).json(response);
48+
} catch (error) {
49+
// Log error for debugging
50+
console.error('Template find error:', error);
51+
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

4059
public readonly router: Router = Router();
41-
}
60+
}

src/api/services/template.service.ts

Lines changed: 21 additions & 5 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,15 @@ 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('WhatsApp API request error: ' + (e.response?.data || e.message));
107+
108+
// Return the complete error response from WhatsApp API
109+
if (e.response?.data) {
110+
return e.response.data;
111+
}
112+
113+
// If no response data, throw connection error
114+
throw new Error(`Connection error: ${e.message}`);
99115
}
100116
}
101-
}
117+
}

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)