@traxionpay/cbsmiddleware 0.0.2 → 0.0.3

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@traxionpay/cbsmiddleware",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "This is a cbs middlware for RB Banks",
5
5
  "author": "Archer",
6
6
  "private": false,
@@ -53,8 +53,8 @@ export class AccountTransferDto {
53
53
  particulars?: string;
54
54
 
55
55
  @IsOptional()
56
- @IsNumber()
57
- mobile?: number
56
+ @IsString()
57
+ mobile?: string
58
58
 
59
59
  @IsOptional()
60
60
  @IsString()
@@ -29,8 +29,8 @@ export class AccountDto {
29
29
  accountType?: string;
30
30
 
31
31
  @IsOptional()
32
- @IsNumber()
33
- mobile?: number
32
+ @IsString()
33
+ mobile?: string
34
34
 
35
35
  @IsOptional()
36
36
  @IsString()
@@ -2,7 +2,8 @@ import {
2
2
  IsDefined,
3
3
  IsString,
4
4
  IsOptional,
5
- IsNumber
5
+ IsNumber,
6
+ isString
6
7
  } from "class-validator";
7
8
 
8
9
  export class FetchBankBalanceDto {
@@ -32,8 +33,8 @@ export class FetchBankBalanceDto {
32
33
  accountType?: string;
33
34
 
34
35
  @IsOptional()
35
- @IsNumber()
36
- mobile?: number
36
+ @IsString()
37
+ mobile?: string
37
38
 
38
39
  @IsOptional()
39
40
  @IsString()
@@ -45,8 +45,8 @@ export class TransactionHistoryDto {
45
45
  page?: number;
46
46
 
47
47
  @IsOptional()
48
- @IsNumber()
49
- mobile?: number
48
+ @IsString()
49
+ mobile?: string
50
50
 
51
51
  @IsOptional()
52
52
  @IsString()
@@ -20,6 +20,15 @@ export class ASPACService implements BankService {
20
20
  ) {
21
21
  }
22
22
 
23
+ combineDateTime(date: string, time: string): string {
24
+ const isoString = `${date}T${time.padEnd(8, '0')}.000Z`; // ensure time is HH:mm:ss
25
+ const d = new Date(isoString);
26
+
27
+ // Format as: 2025-09-26T05:35:36.320+00:00
28
+ const isoWithOffset = d.toISOString().replace('Z', '+00:00');
29
+
30
+ return isoWithOffset;
31
+ }
23
32
  async generateToken(): Promise<any> {
24
33
 
25
34
  this.logger.log("Generating WelcomeBank Token");
@@ -59,8 +68,8 @@ export class ASPACService implements BankService {
59
68
  if (!refreshToken) {
60
69
  throw new HttpException({
61
70
  statusCode: HttpStatus.BAD_REQUEST,
62
- code: 4000, //TBD
63
- message: 'Bank token should not be empty.',
71
+ code: 400010205,
72
+ message: 'Refresh token is required.',
64
73
  data: { refreshToken }
65
74
  }, HttpStatus.BAD_REQUEST);
66
75
  }
@@ -97,47 +106,48 @@ export class ASPACService implements BankService {
97
106
  };
98
107
 
99
108
  } catch (error) {
109
+
110
+ if (error.response.data.message === "Invalid refresh token") {
111
+ throw new HttpException({
112
+ statusCode: HttpStatus.BAD_REQUEST,
113
+ code: 400010206,
114
+ message: 'Invalid refresh token.',
115
+ data: { refreshToken }
116
+ }, HttpStatus.BAD_REQUEST);
117
+ }
118
+
100
119
  AxiosErrorHelper.handleAxiosError(error);
101
120
  }
102
121
  }
103
122
 
104
123
  async linkAccount(accountDto: AccountDto) {
105
124
 
106
- const { token, account, accountType, mobile } = accountDto;
107
-
108
- if (!token) {
109
- throw new HttpException({
110
- statusCode: HttpStatus.UNAUTHORIZED,
111
- code: 4000, //TBD
112
- message: 'Bank token should not be empty.',
113
- data: { accountDto }
114
- }, HttpStatus.UNAUTHORIZED);
115
- }
125
+ const { account, accountType, mobile } = accountDto;
116
126
 
117
127
  if (!account) {
118
128
  throw new HttpException({
119
129
  statusCode: HttpStatus.BAD_REQUEST,
120
- code: 4000, //TBD
121
- message: 'Bank account number should not be empty.',
122
- data: { accountDto }
130
+ code: 400010306,
131
+ message: 'Account number is required.',
132
+ data: { ...accountDto }
123
133
  }, HttpStatus.BAD_REQUEST);
124
134
  }
125
135
 
126
136
  if (!accountType) {
127
137
  throw new HttpException({
128
138
  statusCode: HttpStatus.BAD_REQUEST,
129
- code: 4000, //TBD
130
- message: 'Bank account type should not be empty.',
131
- data: { accountDto }
139
+ code: 400010308,
140
+ message: 'Account type is required.',
141
+ data: { ...accountDto }
132
142
  }, HttpStatus.BAD_REQUEST);
133
143
  }
134
144
 
135
145
  if (!mobile) {
136
146
  throw new HttpException({
137
147
  statusCode: HttpStatus.BAD_REQUEST,
138
- code: 4000, //TBD
139
- message: 'Mobile Number should not be empty.',
140
- data: { accountDto }
148
+ code: 4000103011,
149
+ message: 'Mobile number is required.',
150
+ data: { ...accountDto }
141
151
  }, HttpStatus.BAD_REQUEST);
142
152
  }
143
153
 
@@ -145,7 +155,6 @@ export class ASPACService implements BankService {
145
155
 
146
156
  try {
147
157
  const headers = {
148
- 'Authorization': `Bearer ${token}`,
149
158
  'X-API-KEY': `${this.config.ASPAC_API_KEY}`,
150
159
  'X-API-VERSION': `${this.config.ASPAC_VERSION_KEY}`
151
160
  };
@@ -170,38 +179,66 @@ export class ASPACService implements BankService {
170
179
  }
171
180
  }
172
181
  catch (error) {
182
+
183
+ if (error.response.data.message === "Account number must be 14 digits" || error.response.data.message === "Account does not exist or is not active") {
184
+ throw new HttpException({
185
+ statusCode: HttpStatus.BAD_REQUEST,
186
+ code: 400010305,
187
+ message: 'Account not found',
188
+ data: { ...accountDto }
189
+ }, HttpStatus.BAD_REQUEST);
190
+ }
191
+
192
+ if (error.response.data.message === "Invalid account type. Only deposit accounts (01) allowed") {
193
+ throw new HttpException({
194
+ statusCode: HttpStatus.BAD_REQUEST,
195
+ code: 400010307,
196
+ message: 'Account type is not supported.',
197
+ data: { ...accountDto }
198
+ }, HttpStatus.BAD_REQUEST);
199
+ }
200
+
201
+ if (error.response.data.message === "Mobile number does not match registered mobile") {
202
+ throw new HttpException({
203
+ statusCode: HttpStatus.BAD_REQUEST,
204
+ code: 400010309,
205
+ message: 'Mobile number is not registered in the account.',
206
+ data: { ...accountDto }
207
+ }, HttpStatus.BAD_REQUEST);
208
+ }
209
+
210
+ if (error.response.data.message === "Mobile number must be 12 digits (63XXXXXXXXXX)") {
211
+ throw new HttpException({
212
+ statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
213
+ code: 4220103010,
214
+ message: 'Invalid mobile number format.',
215
+ data: { ...accountDto }
216
+ }, HttpStatus.UNPROCESSABLE_ENTITY);
217
+ }
218
+
173
219
  AxiosErrorHelper.handleAxiosError(error);
174
220
  }
175
221
  }
176
222
 
177
223
  async validateOtp(validateOtp: ValidateOtp): Promise<any> {
178
224
 
179
- const { token, account, otp } = validateOtp;
180
-
181
- if (!token) {
182
- throw new HttpException({
183
- statusCode: HttpStatus.UNAUTHORIZED,
184
- code: 4000, //TBD
185
- message: 'Bank token should not be empty.',
186
- data: { validateOtp }
187
- }, HttpStatus.UNAUTHORIZED);
188
- }
225
+ const { account, otp } = validateOtp;
189
226
 
190
227
  if (!account) {
191
228
  throw new HttpException({
192
229
  statusCode: HttpStatus.BAD_REQUEST,
193
- code: 4000, //TBD
194
- message: 'Bank account number should not be empty.',
195
- data: { validateOtp }
230
+ code: 400010406,
231
+ message: 'Account number is required.',
232
+ data: { ...validateOtp }
196
233
  }, HttpStatus.BAD_REQUEST);
197
234
  }
198
235
 
199
236
  if (!otp) {
200
237
  throw new HttpException({
201
238
  statusCode: HttpStatus.BAD_REQUEST,
202
- code: 4000, //TBD
203
- message: 'Bank account number should not be empty.',
204
- data: { validateOtp }
239
+ code: 400010408,
240
+ message: 'OTP is required.',
241
+ data: { ...validateOtp }
205
242
  }, HttpStatus.BAD_REQUEST);
206
243
  }
207
244
 
@@ -210,7 +247,6 @@ export class ASPACService implements BankService {
210
247
 
211
248
  try {
212
249
  const headers = {
213
- 'Authorization': `Bearer ${token}`,
214
250
  'X-API-KEY': `${this.config.ASPAC_API_KEY}`,
215
251
  'X-API-VERSION': `${this.config.ASPAC_VERSION_KEY}`
216
252
  };
@@ -242,6 +278,25 @@ export class ASPACService implements BankService {
242
278
 
243
279
  }
244
280
  catch (error) {
281
+
282
+ if (error.response.data.message === "Account number must be 14 digits" || error.response.data.message === "Account does not exist or is not active") {
283
+ throw new HttpException({
284
+ statusCode: HttpStatus.BAD_REQUEST,
285
+ code: 400010405,
286
+ message: 'Account not found.',
287
+ data: { ...validateOtp }
288
+ }, HttpStatus.BAD_REQUEST);
289
+ }
290
+
291
+ if (error.response.data.message === "Invalid OTP format. OTP must be exactly 6 digits" || error.response.data.message === "Invalid OTP code") {
292
+ throw new HttpException({
293
+ statusCode: HttpStatus.BAD_REQUEST,
294
+ code: 400010407,
295
+ message: 'Invalid or expired OTP.',
296
+ data: { ...validateOtp }
297
+ }, HttpStatus.BAD_REQUEST);
298
+ }
299
+
245
300
  AxiosErrorHelper.handleAxiosError(error);
246
301
  }
247
302
  }
@@ -253,18 +308,18 @@ export class ASPACService implements BankService {
253
308
  if (!token) {
254
309
  throw new HttpException({
255
310
  statusCode: HttpStatus.UNAUTHORIZED,
256
- code: 4000, //TBD
311
+ code: 401010506,
257
312
  message: 'Bank token should not be empty.',
258
- data: { fetchBalanceDto }
313
+ data: { ...fetchBalanceDto }
259
314
  }, HttpStatus.UNAUTHORIZED);
260
315
  }
261
316
 
262
317
  if (!account) {
263
318
  throw new HttpException({
264
319
  statusCode: HttpStatus.BAD_REQUEST,
265
- code: 4000, //TBD
266
- message: 'Bank account number should not be empty.',
267
- data: { fetchBalanceDto }
320
+ code: 400010508,
321
+ message: 'Account number is required.',
322
+ data: { ...fetchBalanceDto }
268
323
  }, HttpStatus.BAD_REQUEST);
269
324
  }
270
325
 
@@ -302,7 +357,18 @@ export class ASPACService implements BankService {
302
357
  }
303
358
  }
304
359
  catch (error) {
360
+
361
+ if (error.response.data.message === "Account number must be 14 digits" || error.response.data.message === "Account does not exist or is not active") {
362
+ throw new HttpException({
363
+ statusCode: HttpStatus.BAD_REQUEST,
364
+ code: 400010507,
365
+ message: 'Account not found.',
366
+ data: { fetchBalanceDto }
367
+ }, HttpStatus.BAD_REQUEST);
368
+ }
369
+
305
370
  AxiosErrorHelper.handleAxiosError(error);
371
+
306
372
  }
307
373
  }
308
374
 
@@ -313,36 +379,36 @@ export class ASPACService implements BankService {
313
379
  if (!token) {
314
380
  throw new HttpException({
315
381
  statusCode: HttpStatus.UNAUTHORIZED,
316
- code: 4000, //TBD
382
+ code: 401010606,
317
383
  message: 'Bank token should not be empty.',
318
- data: { accountTransferDto }
384
+ data: { ...accountTransferDto }
319
385
  }, HttpStatus.UNAUTHORIZED);
320
386
  }
321
387
 
322
388
  if (!sourceAccount) {
323
389
  throw new HttpException({
324
390
  statusCode: HttpStatus.BAD_REQUEST,
325
- code: 4000, //TBD
326
- message: 'Bank source account number should not be empty.',
327
- data: { accountTransferDto }
391
+ code: 400010608,
392
+ message: 'Account number is required',
393
+ data: { ...accountTransferDto }
328
394
  }, HttpStatus.BAD_REQUEST);
329
395
  }
330
396
 
331
397
  if (!amount) {
332
398
  throw new HttpException({
333
399
  statusCode: HttpStatus.BAD_REQUEST,
334
- code: 4000, //TBD
335
- message: 'Amount should not be empty.',
336
- data: { accountTransferDto }
400
+ code: 400010609,
401
+ message: 'Transaction amount is required.',
402
+ data: { ...accountTransferDto }
337
403
  }, HttpStatus.BAD_REQUEST);
338
404
  }
339
405
 
340
406
  if (!particulars) {
341
407
  throw new HttpException({
342
408
  statusCode: HttpStatus.BAD_REQUEST,
343
- code: 4000, //TBD
344
- message: 'Particulars should not be empty.',
345
- data: { accountTransferDto }
409
+ code: 400010611,
410
+ message: 'Transaction particulars is required.',
411
+ data: { ...accountTransferDto }
346
412
  }, HttpStatus.BAD_REQUEST);
347
413
  }
348
414
 
@@ -382,7 +448,27 @@ export class ASPACService implements BankService {
382
448
  }
383
449
  }
384
450
  catch (error) {
451
+
452
+ if (error.response.data.message === "Account number must be 14 digits" || error.response.data.message === "Account does not exist or is not active") {
453
+ throw new HttpException({
454
+ statusCode: HttpStatus.BAD_REQUEST,
455
+ code: 400010607,
456
+ message: 'Account not found.',
457
+ data: { ...accountTransferDto }
458
+ }, HttpStatus.UNAUTHORIZED);
459
+ }
460
+
461
+ if (error.response.data.message === "Amount must be between 0.01 and 500,000.00" || error.response.data.message === "Invalid amount format") {
462
+ throw new HttpException({
463
+ statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
464
+ code: 422010610,
465
+ message: 'Invalid transaction amount value.',
466
+ data: { ...accountTransferDto }
467
+ }, HttpStatus.UNPROCESSABLE_ENTITY);
468
+ }
469
+
385
470
  AxiosErrorHelper.handleAxiosError(error);
471
+
386
472
  }
387
473
  }
388
474
 
@@ -393,36 +479,36 @@ export class ASPACService implements BankService {
393
479
  if (!token) {
394
480
  throw new HttpException({
395
481
  statusCode: HttpStatus.UNAUTHORIZED,
396
- code: 4000, //TBD
482
+ code: 401010706,
397
483
  message: 'Bank token should not be empty.',
398
- data: { accountTransferDto }
484
+ data: { ...accountTransferDto }
399
485
  }, HttpStatus.UNAUTHORIZED);
400
486
  }
401
487
 
402
488
  if (!destinationAccount) {
403
489
  throw new HttpException({
404
490
  statusCode: HttpStatus.BAD_REQUEST,
405
- code: 4000, //TBD
406
- message: 'Bank destination account number should not be empty.',
407
- data: { accountTransferDto }
491
+ code: 400010708,
492
+ message: 'Account number is required.',
493
+ data: { ...accountTransferDto }
408
494
  }, HttpStatus.BAD_REQUEST);
409
495
  }
410
496
 
411
497
  if (!amount) {
412
498
  throw new HttpException({
413
499
  statusCode: HttpStatus.BAD_REQUEST,
414
- code: 4000, //TBD
415
- message: 'amount should not be empty.',
416
- data: { accountTransferDto }
500
+ code: 400010709,
501
+ message: 'Transaction amount is required.',
502
+ data: { ...accountTransferDto }
417
503
  }, HttpStatus.BAD_REQUEST);
418
504
  }
419
505
 
420
506
  if (!particulars) {
421
507
  throw new HttpException({
422
508
  statusCode: HttpStatus.BAD_REQUEST,
423
- code: 4000, //TBD
424
- message: 'Particulars should not be empty.',
425
- data: { accountTransferDto }
509
+ code: 400010711,
510
+ message: 'Transaction particulars is required.',
511
+ data: { ...accountTransferDto }
426
512
  }, HttpStatus.BAD_REQUEST);
427
513
  }
428
514
 
@@ -462,50 +548,105 @@ export class ASPACService implements BankService {
462
548
  }
463
549
  }
464
550
  catch (error) {
551
+
552
+ if (error.response.data.message === "Account number must be 14 digits" || error.response.data.message === "Account does not exist or is not active") {
553
+ throw new HttpException({
554
+ statusCode: HttpStatus.BAD_REQUEST,
555
+ code: 400010707,
556
+ message: 'Account not found.',
557
+ data: { ...accountTransferDto }
558
+ }, HttpStatus.BAD_REQUEST);
559
+ }
560
+
561
+ if (error.response.data.message === "Amount must be between 0.01 and 500,000.00" || error.response.data.message === "Invalid amount format") {
562
+ throw new HttpException({
563
+ statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
564
+ code: 422010710,
565
+ message: 'Invalid transaction amount value.',
566
+ data: { ...accountTransferDto }
567
+ }, HttpStatus.UNPROCESSABLE_ENTITY);
568
+ }
569
+
465
570
  AxiosErrorHelper.handleAxiosError(error);
466
571
  }
467
572
  }
468
573
 
469
- async getTransactionHistory(transactionHistoryDto: TransactionHistoryDto) {
574
+ async getTransactionHistory(transactionHistoryDto: TransactionHistoryDto):
575
+ Promise<{
576
+ success: boolean;
577
+ message: any;
578
+ correlationId: any;
579
+ timestamp: any;
580
+ transactions: any;
581
+ }> {
470
582
 
471
583
  const { token, account, dateFrom, dateTo, page } = transactionHistoryDto;
584
+ const dateRegex = /^\d{4}-\d{2}-\d{2}$/;
585
+
586
+ interface ReformattedTransaction {
587
+ dateTime: string;
588
+ amount: number;
589
+ type: string;
590
+ description: string;
591
+ transactionReference: string;
592
+ }
593
+
594
+ const reformattedTransactions: Record<string, ReformattedTransaction> = {};
472
595
 
473
596
  if (!token) {
474
597
  throw new HttpException({
475
598
  statusCode: HttpStatus.UNAUTHORIZED,
476
- code: 4000, //TBD
599
+ code: 401010806,
477
600
  message: 'Bank token should not be empty.',
478
- data: { transactionHistoryDto }
601
+ data: { ...transactionHistoryDto }
479
602
  }, HttpStatus.UNAUTHORIZED);
480
603
  }
481
604
 
482
605
  if (!account) {
483
606
  throw new HttpException({
484
607
  statusCode: HttpStatus.BAD_REQUEST,
485
- code: 4000, //TBD
486
- message: 'Bank account number should not be empty.',
487
- data: { transactionHistoryDto }
608
+ code: 400010808,
609
+ message: 'Account number is required.',
610
+ data: { ...transactionHistoryDto }
488
611
  }, HttpStatus.BAD_REQUEST);
489
612
  }
490
613
 
491
614
  if (!dateFrom) {
492
615
  throw new HttpException({
493
616
  statusCode: HttpStatus.BAD_REQUEST,
494
- code: 4000, //TBD
495
- message: 'Date From should not be empty.',
496
- data: { transactionHistoryDto }
617
+ code: 400010810,
618
+ message: 'Starting date is required.',
619
+ data: { ...transactionHistoryDto }
497
620
  }, HttpStatus.BAD_REQUEST);
498
621
  }
499
622
 
623
+ if (!dateRegex.test(dateFrom)) {
624
+ throw new HttpException({
625
+ statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
626
+ code: 422010809,
627
+ message: 'Invalid starting date format. Format should be in YYYY-MM-DD.',
628
+ data: { ...transactionHistoryDto }
629
+ }, HttpStatus.UNPROCESSABLE_ENTITY);
630
+ }
631
+
500
632
  if (!dateTo) {
501
633
  throw new HttpException({
502
634
  statusCode: HttpStatus.BAD_REQUEST,
503
- code: 4000, //TBD
504
- message: 'Date From should not be empty.',
505
- data: { transactionHistoryDto }
635
+ code: 400010812,
636
+ message: 'Ending date is required.',
637
+ data: { ...transactionHistoryDto }
506
638
  }, HttpStatus.BAD_REQUEST);
507
639
  }
508
640
 
641
+ if (!dateRegex.test(dateTo)) {
642
+ throw new HttpException({
643
+ statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
644
+ code: 422010811,
645
+ message: 'Invalid starting date format. Format should be in YYYY-MM-DD.',
646
+ data: { ...transactionHistoryDto }
647
+ }, HttpStatus.UNPROCESSABLE_ENTITY);
648
+ }
649
+
509
650
 
510
651
  this.logger.log("Welcome Bank transaction history");
511
652
 
@@ -538,13 +679,49 @@ export class ASPACService implements BankService {
538
679
 
539
680
  this.logger.log({ responseData: response.data }, 'Welcome Bank Transaction History Successful');
540
681
 
682
+ response.data.data.transactions.forEach((txn, index) => {
683
+ const key = `${index + 1}`;
684
+ const dateTime = this.combineDateTime(txn.tranDate, txn.tranTime);
685
+
686
+ reformattedTransactions[key] = {
687
+ dateTime,
688
+ amount: txn.tranAmount,
689
+ type: txn.tranType,
690
+ description: txn.description,
691
+ transactionReference: txn.tranReference
692
+ };
693
+ });
694
+
541
695
  return {
542
696
  success: true,
543
- ...response.data,
697
+ message: response.data.data.message,
698
+ correlationId: response.data.correlationId,
699
+ timestamp: response.data.timestamp,
700
+ transactions: reformattedTransactions,
544
701
  }
545
702
  }
546
703
  catch (error) {
704
+
705
+ if (error.response.data.message === "Account number must be 14 digits" || error.response.data.message === "Account does not exist or is not active") {
706
+ throw new HttpException({
707
+ statusCode: HttpStatus.BAD_REQUEST,
708
+ code: 400010807,
709
+ message: 'Account not found.',
710
+ data: { ...transactionHistoryDto }
711
+ }, HttpStatus.BAD_REQUEST);
712
+ }
713
+
714
+ if (error.response.data.message === "Invalid page number format") {
715
+ throw new HttpException({
716
+ statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
717
+ code: 422010813,
718
+ message: 'Invalid page number format.',
719
+ data: { ...transactionHistoryDto }
720
+ }, HttpStatus.UNPROCESSABLE_ENTITY);
721
+ }
722
+
547
723
  AxiosErrorHelper.handleAxiosError(error);
724
+
548
725
  }
549
726
  }
550
727