@@ -8,6 +8,9 @@ import { PaymentService, PaymentRequest } from './payment-service';
88import { RateLimiter , RateLimitConfig } from './rate-limiter' ;
99import logger , { auditLogger } from './utils/logger' ;
1010import { HealthService } from './utils/health' ;
11+ import { handleClientError , apiErrorHandler } from './middleware/errorHandler' ;
12+ import { AnalyticsService } from './services/analyticsService' ;
13+ import { getTransactionStatus , startWebsocketService , updateTransactionStatus } from './services/websocketService' ;
1114
1215// Load environment variables
1316dotenv . config ( ) ;
@@ -91,6 +94,9 @@ app.use(cors(corsOptions));
9194app . use ( express . json ( { limit : '10mb' } ) ) ;
9295app . use ( express . urlencoded ( { extended : true , limit : '10mb' } ) ) ;
9396
97+ // Client-side error logging endpoint
98+ app . post ( '/api/client-errors' , handleClientError ) ;
99+
94100// Request logging middleware
95101app . use ( ( req , res , next ) => {
96102 logger . info ( 'Incoming HTTP Request' , {
@@ -181,6 +187,9 @@ app.post('/api/payment', async (req, res) => {
181187 res . set ( 'X-Rate-Limit-Remaining' , result . rateLimitInfo ?. remainingRequests ?. toString ( ) || '0' ) ;
182188
183189 if ( result . success ) {
190+ if ( result . transactionId ) {
191+ updateTransactionStatus ( result . transactionId , 'confirmed' ) ;
192+ }
184193 return res . status ( 200 ) . json ( {
185194 success : true ,
186195 transactionId : result . transactionId ,
@@ -190,6 +199,9 @@ app.post('/api/payment', async (req, res) => {
190199 }
191200 } ) ;
192201 } else {
202+ if ( result . transactionId ) {
203+ updateTransactionStatus ( result . transactionId , 'failed' ) ;
204+ }
193205 // Handle rate limit errors with appropriate status codes
194206 if ( result . error ?. includes ( 'Rate limit exceeded' ) ) {
195207 return res . status ( 429 ) . json ( {
@@ -254,6 +266,44 @@ app.get('/api/rate-limit/:userId', (req, res) => {
254266 }
255267} ) ;
256268
269+ /**
270+ * GET /api/analytics/:userId
271+ * Provide analytics insights for a user
272+ */
273+ app . get ( '/api/analytics/:userId' , ( req , res ) => {
274+ try {
275+ const { userId } = req . params ;
276+ if ( ! userId ) {
277+ return res . status ( 400 ) . json ( { success : false , error : 'User ID is required' } ) ;
278+ }
279+
280+ const analytics = AnalyticsService . generateReport ( userId ) ;
281+ return res . status ( 200 ) . json ( analytics ) ;
282+ } catch ( error ) {
283+ logger . error ( 'Analytics report generation failed' , { error, userId : req . params . userId } ) ;
284+ return res . status ( 500 ) . json ( { success : false , error : 'Failed to generate analytics report' } ) ;
285+ }
286+ } ) ;
287+
288+ /**
289+ * GET /api/transaction-status/:transactionId
290+ * Return current transaction status for real-time updates.
291+ */
292+ app . get ( '/api/transaction-status/:transactionId' , ( req , res ) => {
293+ try {
294+ const { transactionId } = req . params ;
295+ if ( ! transactionId ) {
296+ return res . status ( 400 ) . json ( { success : false , error : 'Transaction ID is required' } ) ;
297+ }
298+
299+ const status = getTransactionStatus ( transactionId ) ;
300+ return res . status ( 200 ) . json ( { success : true , transactionId, status } ) ;
301+ } catch ( error ) {
302+ logger . error ( 'Transaction status query failed' , { error, transactionId : req . params . transactionId } ) ;
303+ return res . status ( 500 ) . json ( { success : false , error : 'Unable to retrieve transaction status' } ) ;
304+ }
305+ } ) ;
306+
257307/**
258308 * GET /api/payment/:meterId
259309 * Get total paid amount for a meter
@@ -300,27 +350,7 @@ app.get('/api/payment/:meterId', async (req, res) => {
300350} ) ;
301351
302352// Error handling middleware
303- app . use ( ( err : any , req : express . Request , res : express . Response , next : express . NextFunction ) => {
304- if ( err . name === 'UnauthorizedError' ) {
305- return res . status ( 401 ) . json ( {
306- success : false ,
307- error : 'Unauthorized'
308- } ) ;
309- }
310-
311- if ( err . message === 'Not allowed by CORS' ) {
312- return res . status ( 403 ) . json ( {
313- success : false ,
314- error : 'CORS policy violation'
315- } ) ;
316- }
317-
318- logger . error ( 'Unhandled server error' , { err, method : req . method , path : req . path } ) ;
319- return res . status ( 500 ) . json ( {
320- success : false ,
321- error : 'Internal server error'
322- } ) ;
323- } ) ;
353+ app . use ( apiErrorHandler ) ;
324354
325355// 404 handler
326356app . use ( '*' , ( req , res ) => {
@@ -408,6 +438,8 @@ function startServer() {
408438 } ) ;
409439 } ) ;
410440 }
441+
442+ startWebsocketService ( ) ;
411443}
412444
413445startServer ( ) ;
0 commit comments