@africode/core 5.0.4 → 5.0.6

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.
@@ -134,6 +134,22 @@ export class LipaNambaJourney extends EventEmitter {
134
134
 
135
135
  const validated = schema.parse(request);
136
136
 
137
+ // Deduplicate by reference when provided: return existing session if found
138
+ if (validated.reference) {
139
+ for (const session of this.sessions.values()) {
140
+ if (session.reference === validated.reference) {
141
+ return {
142
+ ok: true,
143
+ paymentRequestId: session.id,
144
+ sessionData: session,
145
+ message: 'DUPLICATE_REFERENCE',
146
+ nextStep: session.status === 'INITIATED' ? 'IDENTIFY_CUSTOMER' : undefined,
147
+ expiresIn: Math.max(0, Math.floor((new Date(session.expiresAt) - Date.now()) / 1000))
148
+ };
149
+ }
150
+ }
151
+ }
152
+
137
153
  // Verify merchant is registered and compliant
138
154
  const merchantStatus = await this._verifyMerchantCompliance(validated.merchantId);
139
155
  if (!merchantStatus.ok) {
@@ -400,7 +416,7 @@ export class LipaNambaJourney extends EventEmitter {
400
416
  try {
401
417
  // Step 1: Initiate
402
418
  const init = await this.initiatePayment(request);
403
- if (!init.ok) return init;
419
+ if (!init.ok) return { ok: false, error: init.error || 'INITIATION_FAILED', completedSteps: steps };
404
420
  steps.push({ step: 'INITIATE', ok: true });
405
421
 
406
422
  // Step 2: Identify
@@ -409,7 +425,7 @@ export class LipaNambaJourney extends EventEmitter {
409
425
  credentials.nin,
410
426
  credentials.pin
411
427
  );
412
- if (!identify.ok) return identify;
428
+ if (!identify.ok) return { ok: false, error: identify.error || 'IDENTIFICATION_FAILED', completedSteps: steps };
413
429
  steps.push({ step: 'IDENTIFY', ok: true });
414
430
 
415
431
  // Step 3: AML Screen
@@ -417,7 +433,7 @@ export class LipaNambaJourney extends EventEmitter {
417
433
  init.paymentRequestId,
418
434
  identify.customerId
419
435
  );
420
- if (!aml.ok) return aml;
436
+ if (!aml.ok) return { ok: false, error: aml.error || 'AML_SCREEN_FAILED', completedSteps: steps };
421
437
  steps.push({ step: 'AML_SCREEN', ok: true });
422
438
 
423
439
  // Step 4: Confirm
@@ -426,7 +442,7 @@ export class LipaNambaJourney extends EventEmitter {
426
442
  identify.customerId,
427
443
  confirmation.code
428
444
  );
429
- if (!confirm.ok) return confirm;
445
+ if (!confirm.ok) return { ok: false, error: confirm.error || 'CONFIRMATION_FAILED', completedSteps: steps };
430
446
  steps.push({ step: 'CONFIRM', ok: true });
431
447
 
432
448
  // Step 5: Process
@@ -434,7 +450,7 @@ export class LipaNambaJourney extends EventEmitter {
434
450
  init.paymentRequestId,
435
451
  identify.customerId
436
452
  );
437
- if (!process.ok) return process;
453
+ if (!process.ok) return { ok: false, error: process.error || 'PROCESSING_FAILED', completedSteps: steps };
438
454
  steps.push({ step: 'PROCESS', ok: true });
439
455
 
440
456
  return {
@@ -525,7 +541,13 @@ export class LipaNambaJourney extends EventEmitter {
525
541
 
526
542
  async _verifyNIDA(nin, pin) {
527
543
  // Implementation calls NIDA CIG
528
- // For now, return mock
544
+ // For now, provide a deterministic mock: valid NIN is 20 digits
545
+ const ninPattern = /^[0-9]{20}$/;
546
+ if (!nin || !ninPattern.test(nin)) {
547
+ return { verified: false, nin };
548
+ }
549
+
550
+ // Simulate successful lookup
529
551
  return { verified: true, nin, firstName: 'John', lastName: 'Doe' };
530
552
  }
531
553