globalpayments-api 3.11.4 → 3.13.0
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/CHANGELOG.md +15 -1
- package/lib/src/Builders/AuthorizationBuilder.d.ts +0 -1
- package/lib/src/Builders/AuthorizationBuilder.js +0 -4
- package/lib/src/Builders/AuthorizationBuilder.js.map +1 -1
- package/lib/src/Builders/RecurringBuilder.js +12 -1
- package/lib/src/Builders/RecurringBuilder.js.map +1 -1
- package/lib/src/Terminals/Builders/TerminalAuthBuilder.d.ts +17 -4
- package/lib/src/Terminals/Builders/TerminalAuthBuilder.js +38 -5
- package/lib/src/Terminals/Builders/TerminalAuthBuilder.js.map +1 -1
- package/lib/src/Terminals/Builders/TerminalBuilder.d.ts +0 -1
- package/lib/src/Terminals/Builders/TerminalBuilder.js +0 -1
- package/lib/src/Terminals/Builders/TerminalBuilder.js.map +1 -1
- package/lib/src/Terminals/Builders/TerminalManageBuilder.d.ts +5 -0
- package/lib/src/Terminals/Builders/TerminalManageBuilder.js +16 -0
- package/lib/src/Terminals/Builders/TerminalManageBuilder.js.map +1 -1
- package/lib/src/Terminals/TerminalResponse.d.ts +4 -0
- package/lib/src/Terminals/TerminalResponse.js +4 -0
- package/lib/src/Terminals/TerminalResponse.js.map +1 -1
- package/lib/src/Terminals/UPA/Reponses/TransactionResponse.d.ts +7 -0
- package/lib/src/Terminals/UPA/Reponses/TransactionResponse.js +38 -0
- package/lib/src/Terminals/UPA/Reponses/TransactionResponse.js.map +1 -1
- package/lib/src/Terminals/UPA/UpaController.js +116 -17
- package/lib/src/Terminals/UPA/UpaController.js.map +1 -1
- package/lib/test/Integration/Gateways/GpApiConnector/GpApiMMAAccount.test.d.ts +1 -0
- package/lib/test/Integration/Gateways/GpApiConnector/GpApiMMAAccount.test.js +177 -0
- package/lib/test/Integration/Gateways/GpApiConnector/GpApiMMAAccount.test.js.map +1 -0
- package/lib/test/Unit/Gateways/GpApiConnector/GpApiMMAAccount.test.d.ts +1 -0
- package/lib/test/Unit/Gateways/GpApiConnector/GpApiMMAAccount.test.js +29 -0
- package/lib/test/Unit/Gateways/GpApiConnector/GpApiMMAAccount.test.js.map +1 -0
- package/lib/test/Unit/Terminals/Builders/TerminalBuilderParityTests.test.d.ts +17 -0
- package/lib/test/Unit/Terminals/Builders/TerminalBuilderParityTests.test.js +325 -0
- package/lib/test/Unit/Terminals/Builders/TerminalBuilderParityTests.test.js.map +1 -0
- package/lib/test/Unit/Terminals/UPA/UpaAdmin.test.js +2246 -446
- package/lib/test/Unit/Terminals/UPA/UpaAdmin.test.js.map +1 -1
- package/lib/test/Unit/Terminals/UPA/UpaCredit.test.js +703 -26
- package/lib/test/Unit/Terminals/UPA/UpaCredit.test.js.map +1 -1
- package/package.json +2 -2
|
@@ -430,32 +430,433 @@ afterEach(async () => {
|
|
|
430
430
|
console.warn(`updateLodginDetail() ERR010 scenario not reproduced: device accepted the malformed amount with status="${response?.status}" code="${response?.deviceResponseCode}". Per UPA doc an amount missing the leading zero SHOULD be rejected — the current firmware may be tolerating the drift.`);
|
|
431
431
|
});
|
|
432
432
|
});
|
|
433
|
+
(0, UpaHelpertest_1.describeUpaLive)("UPA void test case void support and response parsing ", () => {
|
|
434
|
+
let device;
|
|
435
|
+
beforeEach(() => {
|
|
436
|
+
device = (0, UpaHelpertest_1.createTestDevice)();
|
|
437
|
+
});
|
|
438
|
+
test("void support ", async () => {
|
|
439
|
+
const saleResponse = (await device
|
|
440
|
+
.sale(75.0)
|
|
441
|
+
.withEcrId(12)
|
|
442
|
+
.withClerkId(789)
|
|
443
|
+
.execute());
|
|
444
|
+
expect(saleResponse.status).toBe("Success");
|
|
445
|
+
const voidResponse = (await device
|
|
446
|
+
.void()
|
|
447
|
+
.withEcrId(12)
|
|
448
|
+
.withTerminalRefNumber(saleResponse.terminalRefNumber)
|
|
449
|
+
.withTransactionId(saleResponse.transactionId)
|
|
450
|
+
.withAmount(saleResponse.transactionAmount)
|
|
451
|
+
.execute());
|
|
452
|
+
expect(voidResponse).not.toBeNull();
|
|
453
|
+
expect(voidResponse.status).toBe("Success");
|
|
454
|
+
});
|
|
455
|
+
});
|
|
456
|
+
(0, UpaHelpertest_1.describeUpaLive)("UPA test for capture/Authcompletion ", () => {
|
|
457
|
+
let device;
|
|
458
|
+
beforeEach(() => {
|
|
459
|
+
device = (0, UpaHelpertest_1.createTestDevice)();
|
|
460
|
+
});
|
|
461
|
+
/**
|
|
462
|
+
* Test 1: Basic Capture
|
|
463
|
+
* Per UPA Spec §12.4.16 - AuthCompletion with mandatory fields
|
|
464
|
+
* Mandatory: referenceNumber, amount
|
|
465
|
+
*/
|
|
466
|
+
test("UPA Capture - Basic (Auth → Capture)", async () => {
|
|
467
|
+
const authAmount = 10.0;
|
|
468
|
+
const captureAmount = 10.0;
|
|
469
|
+
const ecrId = "1";
|
|
470
|
+
// Step 1: Authorize to get transaction ID
|
|
471
|
+
const authResponse = await device
|
|
472
|
+
.authorize(authAmount)
|
|
473
|
+
.withEcrId(ecrId)
|
|
474
|
+
.execute();
|
|
475
|
+
expect(authResponse).toBeDefined();
|
|
476
|
+
expect(authResponse.status).toBe("Success");
|
|
477
|
+
expect(authResponse.transactionId).toBeTruthy();
|
|
478
|
+
await settleDevice();
|
|
479
|
+
// Step 2: Capture the authorized amount
|
|
480
|
+
const captureResponse = (await device
|
|
481
|
+
.capture(captureAmount)
|
|
482
|
+
.withEcrId(ecrId)
|
|
483
|
+
.withTransactionId(authResponse.transactionId)
|
|
484
|
+
.execute());
|
|
485
|
+
expect(captureResponse).toBeDefined();
|
|
486
|
+
expect(captureResponse.status).toBe("Success");
|
|
487
|
+
expect(captureResponse.deviceResponseCode).toBe("00");
|
|
488
|
+
expect(captureResponse.cardType).toBeDefined();
|
|
489
|
+
expect(captureResponse.transactionId).toBeTruthy();
|
|
490
|
+
// Note: transactionAmount may include device surcharges
|
|
491
|
+
expect(captureResponse.transactionAmount).toBeGreaterThanOrEqual(captureAmount);
|
|
492
|
+
console.log(`[Capture Basic] TransId: ${captureResponse.transactionId}, Amount: ${captureResponse.transactionAmount}`);
|
|
493
|
+
});
|
|
494
|
+
/**
|
|
495
|
+
* Test 2: Capture with Tax and Tip
|
|
496
|
+
* Per UPA Spec §12.4.16 - Optional fields: taxAmount, tipAmount
|
|
497
|
+
* Verifies proper amount aggregation
|
|
498
|
+
*/
|
|
499
|
+
test("UPA Capture - with Tax and Tip", async () => {
|
|
500
|
+
const authAmount = 50.0;
|
|
501
|
+
const taxAmount = 5.0;
|
|
502
|
+
const tipAmount = 10.0;
|
|
503
|
+
const ecrId = "1";
|
|
504
|
+
// Step 1: Authorize
|
|
505
|
+
const authResponse = await device
|
|
506
|
+
.authorize(authAmount)
|
|
507
|
+
.withEcrId(ecrId)
|
|
508
|
+
.execute();
|
|
509
|
+
expect(authResponse).toBeDefined();
|
|
510
|
+
expect(authResponse.status).toBe("Success");
|
|
511
|
+
expect(authResponse.transactionId).toBeTruthy();
|
|
512
|
+
await settleDevice();
|
|
513
|
+
// Step 2: Capture with tax and tip
|
|
514
|
+
const captureResponse = (await device
|
|
515
|
+
.capture(authAmount)
|
|
516
|
+
.withEcrId(ecrId)
|
|
517
|
+
.withTransactionId(authResponse.transactionId)
|
|
518
|
+
.withTaxAmount(taxAmount)
|
|
519
|
+
.withGratuity(tipAmount)
|
|
520
|
+
.execute());
|
|
521
|
+
expect(captureResponse).toBeDefined();
|
|
522
|
+
expect(captureResponse.status).toBe("Success");
|
|
523
|
+
expect(captureResponse.deviceResponseCode).toBe("00");
|
|
524
|
+
// Verify amounts
|
|
525
|
+
// Note: Device may or may not aggregate tax and tip into total amount
|
|
526
|
+
// At minimum, should have at least the base authorized amount
|
|
527
|
+
expect(captureResponse.transactionAmount).toBeGreaterThanOrEqual(authAmount);
|
|
528
|
+
// Log actual values received for debugging
|
|
529
|
+
console.log(`[Capture Tax+Tip] Amount: ${captureResponse.transactionAmount}, Tax: ${captureResponse.taxAmount}, Tip: ${captureResponse.tipAmount}`);
|
|
530
|
+
// Verify tax and tip if populated (may be undefined depending on device response format)
|
|
531
|
+
if (captureResponse.taxAmount !== undefined) {
|
|
532
|
+
expect(captureResponse.taxAmount).toBeCloseTo(taxAmount, 2);
|
|
533
|
+
}
|
|
534
|
+
if (captureResponse.tipAmount !== undefined) {
|
|
535
|
+
expect(captureResponse.tipAmount).toBeCloseTo(tipAmount, 2);
|
|
536
|
+
}
|
|
537
|
+
});
|
|
538
|
+
/**
|
|
539
|
+
* Test 3: Capture with Tax Indicator (Tax Exempt)
|
|
540
|
+
* Per UPA Spec §12.4.16 - taxIndicator: 0 or 1
|
|
541
|
+
* 0 = tax applicable, 1 = tax exempt
|
|
542
|
+
*/
|
|
543
|
+
test("UPA Capture - with Tax Indicator (Tax Exempt)", async () => {
|
|
544
|
+
const authAmount = 30.0;
|
|
545
|
+
const ecrId = "1";
|
|
546
|
+
const taxIndicator = 1; // 1 = tax exempt
|
|
547
|
+
// Step 1: Authorize
|
|
548
|
+
const authResponse = await device
|
|
549
|
+
.authorize(authAmount)
|
|
550
|
+
.withEcrId(ecrId)
|
|
551
|
+
.execute();
|
|
552
|
+
expect(authResponse).toBeDefined();
|
|
553
|
+
expect(authResponse.status).toBe("Success");
|
|
554
|
+
await settleDevice();
|
|
555
|
+
// Step 2: Capture with tax exempt indicator
|
|
556
|
+
const captureResponse = (await device
|
|
557
|
+
.capture(authAmount)
|
|
558
|
+
.withEcrId(ecrId)
|
|
559
|
+
.withTransactionId(authResponse.transactionId)
|
|
560
|
+
.withTaxIndicator(taxIndicator)
|
|
561
|
+
.execute());
|
|
562
|
+
expect(captureResponse).toBeDefined();
|
|
563
|
+
expect(captureResponse.status).toBe("Success");
|
|
564
|
+
// Note: Device may add surcharges, so check for >= base amount
|
|
565
|
+
expect(captureResponse.transactionAmount).toBeGreaterThanOrEqual(authAmount);
|
|
566
|
+
console.log(`[Capture TaxExempt] Amount: ${captureResponse.transactionAmount}, TaxIndicator: ${taxIndicator}`);
|
|
567
|
+
});
|
|
568
|
+
/**
|
|
569
|
+
* Test 4: Capture with Invoice Number
|
|
570
|
+
* Per UPA Spec §12.4.16 - invoiceNbr: AN(1-16)
|
|
571
|
+
*/
|
|
572
|
+
test("UPA Capture - with Invoice Number", async () => {
|
|
573
|
+
const authAmount = 25.0;
|
|
574
|
+
const ecrId = "1";
|
|
575
|
+
const invoiceNum = "INV-" + Date.now().toString().slice(-8);
|
|
576
|
+
// Step 1: Authorize
|
|
577
|
+
const authResponse = await device
|
|
578
|
+
.authorize(authAmount)
|
|
579
|
+
.withEcrId(ecrId)
|
|
580
|
+
.execute();
|
|
581
|
+
expect(authResponse).toBeDefined();
|
|
582
|
+
expect(authResponse.status).toBe("Success");
|
|
583
|
+
await settleDevice();
|
|
584
|
+
// Step 2: Capture with invoice number
|
|
585
|
+
const captureResponse = (await device
|
|
586
|
+
.capture(authAmount)
|
|
587
|
+
.withEcrId(ecrId)
|
|
588
|
+
.withTransactionId(authResponse.transactionId)
|
|
589
|
+
.withInvoiceNumber(invoiceNum)
|
|
590
|
+
.execute());
|
|
591
|
+
expect(captureResponse).toBeDefined();
|
|
592
|
+
expect(captureResponse.status).toBe("Success");
|
|
593
|
+
// Invoice number may not be returned in response - if it is, verify it matches
|
|
594
|
+
if (captureResponse.invoiceNumber !== undefined &&
|
|
595
|
+
captureResponse.invoiceNumber !== "") {
|
|
596
|
+
expect(captureResponse.invoiceNumber).toBe(invoiceNum);
|
|
597
|
+
}
|
|
598
|
+
// Amount check (with device surcharges allowance)
|
|
599
|
+
expect(captureResponse.transactionAmount).toBeGreaterThanOrEqual(authAmount);
|
|
600
|
+
console.log(`[Capture Invoice] Invoice: ${captureResponse.invoiceNumber}, Amount: ${captureResponse.transactionAmount}`);
|
|
601
|
+
});
|
|
602
|
+
/**
|
|
603
|
+
* Test 5: Capture with Processing CPC (Commercial Card Processing)
|
|
604
|
+
* Per UPA Spec §12.4.16 - processCPC: 0 or 1
|
|
605
|
+
* 0 = No, 1 = Yes
|
|
606
|
+
*/
|
|
607
|
+
test("UPA Capture - with Processing CPC", async () => {
|
|
608
|
+
const authAmount = 100.0;
|
|
609
|
+
const ecrId = "1";
|
|
610
|
+
// Step 1: Authorize
|
|
611
|
+
const authResponse = await device
|
|
612
|
+
.authorize(authAmount)
|
|
613
|
+
.withEcrId(ecrId)
|
|
614
|
+
.execute();
|
|
615
|
+
expect(authResponse).toBeDefined();
|
|
616
|
+
expect(authResponse.status).toBe("Success");
|
|
617
|
+
await settleDevice();
|
|
618
|
+
// Step 2: Capture with CPC processing
|
|
619
|
+
const captureResponse = (await device
|
|
620
|
+
.capture(authAmount)
|
|
621
|
+
.withEcrId(ecrId)
|
|
622
|
+
.withTransactionId(authResponse.transactionId)
|
|
623
|
+
.withProcessCPC(true)
|
|
624
|
+
.execute());
|
|
625
|
+
expect(captureResponse).toBeDefined();
|
|
626
|
+
expect(captureResponse.status).toBe("Success");
|
|
627
|
+
// Device may add surcharges, so check for >= base amount
|
|
628
|
+
expect(captureResponse.transactionAmount).toBeGreaterThanOrEqual(authAmount);
|
|
629
|
+
console.log(`[Capture CPC] Amount: ${captureResponse.transactionAmount}, ProcessCPC: true`);
|
|
630
|
+
});
|
|
631
|
+
/**
|
|
632
|
+
* Test 6: Capture with All Fields
|
|
633
|
+
* Per UPA Spec §12.4.16 - Comprehensive test with all optional fields
|
|
634
|
+
* Fields: amount, preAuthAmount, taxAmount, tipAmount, taxIndicator, processCPC
|
|
635
|
+
*/
|
|
636
|
+
test("UPA Capture - with All Fields", async () => {
|
|
637
|
+
const authAmount = 75.0;
|
|
638
|
+
const taxAmount = 7.5;
|
|
639
|
+
const tipAmount = 15.0;
|
|
640
|
+
const ecrId = "1";
|
|
641
|
+
const invoiceNum = "FULL-" + Date.now().toString().slice(-6);
|
|
642
|
+
const taxIndicator = 0; // 0 = tax applicable
|
|
643
|
+
// Step 1: Authorize
|
|
644
|
+
const authResponse = await device
|
|
645
|
+
.authorize(authAmount)
|
|
646
|
+
.withEcrId(ecrId)
|
|
647
|
+
.execute();
|
|
648
|
+
expect(authResponse).toBeDefined();
|
|
649
|
+
expect(authResponse.status).toBe("Success");
|
|
650
|
+
await settleDevice();
|
|
651
|
+
// Step 2: Capture with all fields
|
|
652
|
+
const captureResponse = (await device
|
|
653
|
+
.capture(authAmount)
|
|
654
|
+
.withEcrId(ecrId)
|
|
655
|
+
.withTransactionId(authResponse.transactionId)
|
|
656
|
+
.withTaxAmount(taxAmount)
|
|
657
|
+
.withGratuity(tipAmount)
|
|
658
|
+
.withTaxIndicator(taxIndicator)
|
|
659
|
+
.withInvoiceNumber(invoiceNum)
|
|
660
|
+
.withProcessCPC(true)
|
|
661
|
+
.execute());
|
|
662
|
+
expect(captureResponse).toBeDefined();
|
|
663
|
+
expect(captureResponse.status).toBe("Success");
|
|
664
|
+
expect(captureResponse.deviceResponseCode).toBe("00");
|
|
665
|
+
// Verify all fields
|
|
666
|
+
expect(captureResponse.transactionId).toBeTruthy();
|
|
667
|
+
// Device may not aggregate all tax/tip components into total - at minimum check base amount
|
|
668
|
+
expect(captureResponse.transactionAmount).toBeGreaterThanOrEqual(authAmount);
|
|
669
|
+
// Tax and tip may be undefined or may be populated
|
|
670
|
+
if (captureResponse.taxAmount !== undefined &&
|
|
671
|
+
captureResponse.taxAmount > 0) {
|
|
672
|
+
expect(captureResponse.taxAmount).toBeGreaterThanOrEqual(0);
|
|
673
|
+
}
|
|
674
|
+
if (captureResponse.tipAmount !== undefined &&
|
|
675
|
+
captureResponse.tipAmount > 0) {
|
|
676
|
+
expect(captureResponse.tipAmount).toBeGreaterThanOrEqual(0);
|
|
677
|
+
}
|
|
678
|
+
expect(captureResponse.cardType).toBeDefined();
|
|
679
|
+
expect(captureResponse.maskedCardNumber).toBeDefined();
|
|
680
|
+
console.log(`[Capture AllFields] Amount: ${captureResponse.transactionAmount}, Tax: ${captureResponse.taxAmount}, Tip: ${captureResponse.tipAmount}, Invoice: ${captureResponse.invoiceNumber}, ClerkId: ${captureResponse.clerkId}`);
|
|
681
|
+
});
|
|
682
|
+
/**
|
|
683
|
+
* Test 7: Capture Response Field Parsing
|
|
684
|
+
* Per UPA Spec §12.4.16.5 - Validates all output parameters
|
|
685
|
+
* Verifies proper response parsing from device
|
|
686
|
+
*/
|
|
687
|
+
test("UPA Capture - Response Field Parsing", async () => {
|
|
688
|
+
const authAmount = 40.0;
|
|
689
|
+
const ecrId = "1";
|
|
690
|
+
// Step 1: Authorize
|
|
691
|
+
const authResponse = await device
|
|
692
|
+
.authorize(authAmount)
|
|
693
|
+
.withEcrId(ecrId)
|
|
694
|
+
.execute();
|
|
695
|
+
expect(authResponse).toBeDefined();
|
|
696
|
+
expect(authResponse.status).toBe("Success");
|
|
697
|
+
await settleDevice();
|
|
698
|
+
// Step 2: Capture to validate response parsing
|
|
699
|
+
const captureResponse = (await device
|
|
700
|
+
.capture(authAmount)
|
|
701
|
+
.withEcrId(ecrId)
|
|
702
|
+
.withTransactionId(authResponse.transactionId)
|
|
703
|
+
.execute());
|
|
704
|
+
// Core transaction identifiers (per §12.4.16.5)
|
|
705
|
+
expect(captureResponse.transactionId).toBeTruthy(); // responseId: N16
|
|
706
|
+
expect(captureResponse.terminalRefNumber).toBeTruthy(); // tranNo: N4
|
|
707
|
+
expect(captureResponse.approvalCode).toBeTruthy(); // approvalCode: AN6
|
|
708
|
+
// Response codes (per §12.4.16.5)
|
|
709
|
+
expect(typeof captureResponse.responseCode).toBe("string");
|
|
710
|
+
expect(typeof captureResponse.responseText).toBe("string");
|
|
711
|
+
expect(typeof captureResponse.deviceResponseCode).toBe("string");
|
|
712
|
+
expect(typeof captureResponse.deviceResponseText).toBe("string");
|
|
713
|
+
// Card information (per §12.4.16.5)
|
|
714
|
+
expect(typeof captureResponse.cardType).toBe("string");
|
|
715
|
+
expect(typeof captureResponse.maskedCardNumber).toBe("string");
|
|
716
|
+
expect(captureResponse.maskedCardNumber).toMatch(/^\d{0,25}$/);
|
|
717
|
+
// Status validation
|
|
718
|
+
expect(captureResponse.status).toBe("Success");
|
|
719
|
+
expect(captureResponse.deviceResponseCode).toBe("00"); // "00" = Success
|
|
720
|
+
// Amount validation
|
|
721
|
+
expect(captureResponse.transactionAmount).toBeCloseTo(authAmount, 2);
|
|
722
|
+
expect(typeof captureResponse.transactionAmount).toBe("number");
|
|
723
|
+
// Gateway response info (per §12.4.16.5)
|
|
724
|
+
expect(typeof captureResponse.gatewayResponseCode).toBe("string");
|
|
725
|
+
expect(typeof captureResponse.gatewayResponseMessage).toBe("string");
|
|
726
|
+
console.log(`[Capture ResponseParsing] TransId: ${captureResponse.transactionId}, RefNum: ${captureResponse.terminalRefNumber}, ApprovalCode: ${captureResponse.approvalCode}, CardType: ${captureResponse.cardType}`);
|
|
727
|
+
});
|
|
728
|
+
});
|
|
433
729
|
// ===========================================================================
|
|
434
|
-
//
|
|
730
|
+
// COMPREHENSIVE INTEGRATED TEST SCENARIOS FROM SPEC
|
|
435
731
|
// ===========================================================================
|
|
436
|
-
(0, UpaHelpertest_1.describeUpaLive)("UPA Credit –
|
|
732
|
+
(0, UpaHelpertest_1.describeUpaLive)("UPA Credit – Comprehensive Builder Scenarios (Spec Compliance)", () => {
|
|
437
733
|
let device;
|
|
438
734
|
beforeEach(() => {
|
|
439
735
|
device = (0, UpaHelpertest_1.createTestDevice)();
|
|
440
736
|
});
|
|
441
|
-
test("
|
|
442
|
-
const
|
|
443
|
-
.sale(
|
|
737
|
+
test("[UpaCreditTests:SPEC-001] Sale with ClerkId + TaxAmount", async () => {
|
|
738
|
+
const builder = device
|
|
739
|
+
.sale(25.0)
|
|
740
|
+
.withEcrId(13)
|
|
741
|
+
.withClerkId(1234)
|
|
742
|
+
.withTaxAmount(2.5);
|
|
743
|
+
const response = await builder.execute();
|
|
744
|
+
expect(response.status).toBe("Success");
|
|
745
|
+
expect(response.deviceResponseCode).toBe("00");
|
|
746
|
+
});
|
|
747
|
+
test("[UpaCreditTests:SPEC-003] Sale with CardBrandTransId", async () => {
|
|
748
|
+
const request = device
|
|
749
|
+
.sale(75.0)
|
|
750
|
+
.withEcrId(13)
|
|
751
|
+
.withCardBrandTransId("MCC0484550831");
|
|
752
|
+
const response = await request.execute();
|
|
753
|
+
expect(response).toBeDefined();
|
|
754
|
+
expect(response.status).toBe("Success");
|
|
755
|
+
expect(response.deviceResponseCode).toBe("00");
|
|
756
|
+
expect(response.command).toBe("Sale");
|
|
757
|
+
expect(response.cardBrandTransId).toBeDefined();
|
|
758
|
+
});
|
|
759
|
+
test("[UpaCreditTests:SPEC-004] PreAuth with ClerkId + TaxAmount", async () => {
|
|
760
|
+
const authresponse = await device
|
|
761
|
+
.authorize(10.0)
|
|
444
762
|
.withEcrId(13)
|
|
445
|
-
.withClerkId(123)
|
|
446
763
|
.execute();
|
|
764
|
+
expect(authresponse).toBeDefined();
|
|
765
|
+
expect(authresponse.status).toBe("Success");
|
|
766
|
+
expect(authresponse.deviceResponseCode).toBe("00");
|
|
767
|
+
const controller = src_1.ServicesContainer.instance().getDeviceController();
|
|
768
|
+
const builder = device
|
|
769
|
+
.capture(100.0)
|
|
770
|
+
.withEcrId(13)
|
|
771
|
+
.withClerkId(1111)
|
|
772
|
+
.withTransactionId(authresponse.transactionId)
|
|
773
|
+
.withTaxAmount(5.0);
|
|
774
|
+
const request = controller
|
|
775
|
+
.buildProcessTransaction(builder)
|
|
776
|
+
.getJsonRequest();
|
|
777
|
+
expect(request.data.command).toBe("AuthCompletion");
|
|
778
|
+
expect(request.data.data.params.clerkId).toBe(1111);
|
|
779
|
+
expect(request.data.data.transaction.taxAmount).toBe("5.00");
|
|
780
|
+
const response = await builder.execute();
|
|
781
|
+
expect(response).toBeDefined();
|
|
782
|
+
expect(response.status).toBe("Success");
|
|
783
|
+
expect(response.deviceResponseCode).toBe("00");
|
|
784
|
+
});
|
|
785
|
+
test("[UpaCreditTests:SPEC-005] Incremental Auth with preAuthAmount - toFixed(2) validation", async () => {
|
|
786
|
+
const controller = src_1.ServicesContainer.instance().getDeviceController();
|
|
787
|
+
const builder = device
|
|
788
|
+
.authorize(10.123)
|
|
789
|
+
.withEcrId(13)
|
|
790
|
+
.withPreAuthAmount(10.123);
|
|
791
|
+
const request = controller
|
|
792
|
+
.buildProcessTransaction(builder)
|
|
793
|
+
.getJsonRequest();
|
|
794
|
+
const response = await builder.execute();
|
|
795
|
+
expect(response).toBeDefined();
|
|
796
|
+
expect(response.status).toBe("Success");
|
|
797
|
+
expect(response.deviceResponseCode).toBe("00");
|
|
798
|
+
console.log(`[UpaCreditTests:SPEC-005] PreAuth amount 10.123 formatted as:\n` +
|
|
799
|
+
JSON.stringify(request.data.data.transaction.preAuthAmount, null, 2));
|
|
800
|
+
// Verify correct toFixed(2) formatting in REQUEST (device doesn't echo preAuthAmount back)
|
|
801
|
+
expect(request.data.data.transaction.preAuthAmount).toBe("10.12");
|
|
802
|
+
// Note: preAuthAmount is request-only; device does not echo it in response
|
|
803
|
+
console.log(`[UpaCreditTests:SPEC-005] Response preAuthAmount: "${response.preAuthAmount ?? "not returned by device"}"`);
|
|
804
|
+
});
|
|
805
|
+
test("[UpaCreditTests:SPEC-011] Tax Amount Variants", async () => {
|
|
806
|
+
const controller = src_1.ServicesContainer.instance().getDeviceController();
|
|
807
|
+
const builder = device
|
|
808
|
+
.sale(100.0)
|
|
809
|
+
.withEcrId(13)
|
|
810
|
+
.withTaxAmount(5.25);
|
|
811
|
+
const request = controller
|
|
812
|
+
.buildProcessTransaction(builder)
|
|
813
|
+
.getJsonRequest();
|
|
814
|
+
console.log(`[UpaCreditTests:SPEC-011] TaxAmount Standard tax:\n` +
|
|
815
|
+
JSON.stringify(request.data.data.transaction.taxAmount));
|
|
816
|
+
const response = await builder.execute();
|
|
447
817
|
expect(response).toBeDefined();
|
|
448
818
|
expect(response.status).toBe("Success");
|
|
449
|
-
|
|
819
|
+
expect(response.deviceResponseCode).toBe("00");
|
|
820
|
+
expect(request.data.data.transaction.taxAmount).toBe("5.25");
|
|
450
821
|
});
|
|
451
|
-
test("sale()
|
|
822
|
+
test("[UpaCreditTests:506] sale() serializes prescription amount", async () => {
|
|
823
|
+
const controller = src_1.ServicesContainer.instance().getDeviceController();
|
|
824
|
+
const builder = device
|
|
825
|
+
.sale(6.0)
|
|
826
|
+
.withEcrId(13)
|
|
827
|
+
.withPrescriptionAmount(25.5)
|
|
828
|
+
.withClinicAmount(35.75)
|
|
829
|
+
.withDentalAmount(40.25);
|
|
830
|
+
const request = controller
|
|
831
|
+
.buildProcessTransaction(builder)
|
|
832
|
+
.getJsonRequest();
|
|
833
|
+
const response = await builder.execute();
|
|
834
|
+
expect(response).toBeDefined();
|
|
835
|
+
expect(response.status).toBe("Success");
|
|
836
|
+
expect(response.deviceResponseCode).toBe("00");
|
|
837
|
+
expect(request.data.command).toBe("Sale");
|
|
838
|
+
expect(request.data.data.transaction.prescriptionAmount).toBe("25.50");
|
|
839
|
+
expect(request.data.data.transaction.clinicAmount).toBe("35.75");
|
|
840
|
+
expect(request.data.data.transaction.dentalAmount).toBe("40.25");
|
|
841
|
+
});
|
|
842
|
+
});
|
|
843
|
+
// ===========================================================================
|
|
844
|
+
// sale() with enhanced field support
|
|
845
|
+
// ===========================================================================
|
|
846
|
+
(0, UpaHelpertest_1.describeUpaLive)("UPA Credit – sale() with enhanced fields", () => {
|
|
847
|
+
let device;
|
|
848
|
+
beforeEach(() => {
|
|
849
|
+
device = (0, UpaHelpertest_1.createTestDevice)();
|
|
850
|
+
});
|
|
851
|
+
test("verify() includes cardBrandTransId field", async () => {
|
|
452
852
|
const response = await device
|
|
453
|
-
.
|
|
853
|
+
.verify()
|
|
454
854
|
.withEcrId(13)
|
|
455
|
-
.withCardBrandTransId("
|
|
855
|
+
.withCardBrandTransId("MCC0484550831")
|
|
456
856
|
.execute();
|
|
457
857
|
expect(response).toBeDefined();
|
|
458
858
|
expect(response.status).toBe("Success");
|
|
859
|
+
expect(response.cardBrandTransId).toBeDefined();
|
|
459
860
|
console.log(`[Sale CardBrandTransId] Amount: ${response.transactionAmount}, Status: ${response.status}`);
|
|
460
861
|
});
|
|
461
862
|
test("sale() includes directMkt fields (shippingDate)", async () => {
|
|
@@ -464,25 +865,11 @@ afterEach(async () => {
|
|
|
464
865
|
.sale(20)
|
|
465
866
|
.withEcrId(13)
|
|
466
867
|
.withShippingDate(shippingDate)
|
|
467
|
-
.withInvoiceNumber("
|
|
868
|
+
.withInvoiceNumber("INV2025001")
|
|
468
869
|
.execute();
|
|
469
870
|
expect(response).toBeDefined();
|
|
470
871
|
expect(response.status).toBe("Success");
|
|
471
872
|
});
|
|
472
|
-
test("sale() includes acquisitionTypes in request", async () => {
|
|
473
|
-
const builder = device
|
|
474
|
-
.sale(10)
|
|
475
|
-
.withEcrId(13)
|
|
476
|
-
.withAcquisitionTypes([
|
|
477
|
-
AcquisitionType_1.AcquisitionType.Chip,
|
|
478
|
-
AcquisitionType_1.AcquisitionType.Contactless,
|
|
479
|
-
]);
|
|
480
|
-
console.log("\n===== EXECUTING SALE WITH ACQUISITION TYPES =====");
|
|
481
|
-
const response = await builder.execute();
|
|
482
|
-
console.log("Response Status:", response.status);
|
|
483
|
-
console.log("Response:", JSON.stringify(response, null, 2));
|
|
484
|
-
expect(response).toBeDefined();
|
|
485
|
-
});
|
|
486
873
|
});
|
|
487
874
|
// ===========================================================================
|
|
488
875
|
// authorize() with enhanced field support
|
|
@@ -507,7 +894,7 @@ afterEach(async () => {
|
|
|
507
894
|
const response = await device
|
|
508
895
|
.authorize(30)
|
|
509
896
|
.withEcrId(12)
|
|
510
|
-
.withCardBrandTransId("
|
|
897
|
+
.withCardBrandTransId("MCC0484550831")
|
|
511
898
|
.execute();
|
|
512
899
|
expect(response).toBeDefined();
|
|
513
900
|
expect(response.status).toBe("Success");
|
|
@@ -524,4 +911,294 @@ afterEach(async () => {
|
|
|
524
911
|
console.log(`[Auth PreAuthAmount] Amount: ${response.transactionAmount}, Status: ${response.status}`);
|
|
525
912
|
});
|
|
526
913
|
});
|
|
914
|
+
// ===========================================================================
|
|
915
|
+
// JIRA Story Requirements – Field Validation
|
|
916
|
+
// ===========================================================================
|
|
917
|
+
describe("JIRA Story: UPA Transaction Processing – Field Validation", () => {
|
|
918
|
+
let device;
|
|
919
|
+
beforeEach(() => {
|
|
920
|
+
device = (0, UpaHelpertest_1.createTestDevice)();
|
|
921
|
+
});
|
|
922
|
+
/**
|
|
923
|
+
* Requirement: clerkId
|
|
924
|
+
* Status: withClerkId() method should be available on builder
|
|
925
|
+
*/
|
|
926
|
+
test("[Requirement:clerkId] Builder has withClerkId method", async () => {
|
|
927
|
+
const builder = device.sale(10.0);
|
|
928
|
+
expect(builder).toHaveProperty("withClerkId");
|
|
929
|
+
expect(typeof builder.withClerkId).toBe("function");
|
|
930
|
+
// Should be chainable
|
|
931
|
+
const chained = builder.withClerkId(123);
|
|
932
|
+
const result = await chained.withEcrId("13").execute();
|
|
933
|
+
expect(result.status).toBe("Success");
|
|
934
|
+
expect(chained).toBeDefined();
|
|
935
|
+
expect(chained).toEqual(builder); // Returns self for chaining
|
|
936
|
+
});
|
|
937
|
+
/**
|
|
938
|
+
* Requirement: cardBrandTransId
|
|
939
|
+
* Status: withCardBrandTransId() method should exist and work
|
|
940
|
+
*/
|
|
941
|
+
test("[Requirement:cardBrandTransId] Builder has withCardBrandTransId method", async () => {
|
|
942
|
+
const builder = device.sale(10.0).withEcrId("13");
|
|
943
|
+
const transId = "ABC123XYZ";
|
|
944
|
+
expect(builder).toHaveProperty("withCardBrandTransId");
|
|
945
|
+
expect(typeof builder.withCardBrandTransId).toBe("function");
|
|
946
|
+
// Should be chainable and store value
|
|
947
|
+
const chained = builder.withCardBrandTransId(transId);
|
|
948
|
+
const response = await chained.execute();
|
|
949
|
+
expect(response.status).toBe("Success");
|
|
950
|
+
expect(chained).toBeDefined();
|
|
951
|
+
expect(chained).toEqual(builder);
|
|
952
|
+
expect(builder.cardBrandTransId).toBe(transId);
|
|
953
|
+
});
|
|
954
|
+
/**
|
|
955
|
+
* Requirement: cardOnFileIndicator
|
|
956
|
+
* Status: Should support CardHolder ('C'), Merchant ('M')
|
|
957
|
+
* Note: R (Recurring) and I (Installment) may require additional enum values
|
|
958
|
+
*/
|
|
959
|
+
test("[Requirement:cardOnFileIndicator] Builder supports CardHolder and Merchant indicators", async () => {
|
|
960
|
+
const builderCH = device
|
|
961
|
+
.sale(10.0)
|
|
962
|
+
.withCardOnFileIndicator(src_1.StoredCredentialInitiator.CardHolder);
|
|
963
|
+
const builderM = device
|
|
964
|
+
.sale(10.0)
|
|
965
|
+
.withCardOnFileIndicator(src_1.StoredCredentialInitiator.Merchant);
|
|
966
|
+
expect(builderCH.cardOnFileIndicator).toBe(src_1.StoredCredentialInitiator.CardHolder);
|
|
967
|
+
expect(builderM.cardOnFileIndicator).toBe(src_1.StoredCredentialInitiator.Merchant);
|
|
968
|
+
const responseCH = await builderCH.withEcrId("13").execute();
|
|
969
|
+
const responseM = await builderM.withEcrId("13").execute();
|
|
970
|
+
expect(responseCH.status).toBe("Success");
|
|
971
|
+
expect(responseM.status).toBe("Success");
|
|
972
|
+
});
|
|
973
|
+
/**
|
|
974
|
+
* Requirement: preAuthAmount
|
|
975
|
+
* Status: withPreAuthAmount() should exist and use proper formatting
|
|
976
|
+
*/
|
|
977
|
+
test("[Requirement:preAuthAmount] Builder has withPreAuthAmount with proper formatting", async () => {
|
|
978
|
+
const builder = device.authorize(15.0);
|
|
979
|
+
const preAuthAmt = 25.99;
|
|
980
|
+
expect(builder).toHaveProperty("withPreAuthAmount");
|
|
981
|
+
expect(typeof builder.withPreAuthAmount).toBe("function");
|
|
982
|
+
builder.withPreAuthAmount(preAuthAmt);
|
|
983
|
+
expect(builder.preAuthAmount).toBe(preAuthAmt);
|
|
984
|
+
const response = await builder.withEcrId("13").execute();
|
|
985
|
+
expect(response.status).toBe("Success");
|
|
986
|
+
});
|
|
987
|
+
/**
|
|
988
|
+
* Requirement: Processing Indicators
|
|
989
|
+
* Status: Builder should support quickChip, checkLuhn, securityCode
|
|
990
|
+
*/
|
|
991
|
+
test("[Requirement:processingIndicators] Builder supports processing indicator flags", async () => {
|
|
992
|
+
const builder = device.sale(10.0);
|
|
993
|
+
// These should be properties on the builder
|
|
994
|
+
expect(builder).toHaveProperty("isQuickChip");
|
|
995
|
+
expect(builder).toHaveProperty("hasCheckLuhn");
|
|
996
|
+
expect(builder).toHaveProperty("hasSecurityCode");
|
|
997
|
+
const response = await builder.withEcrId("13").execute();
|
|
998
|
+
expect(response.status).toBe("Success");
|
|
999
|
+
});
|
|
1000
|
+
});
|
|
1001
|
+
// ===========================================================================
|
|
1002
|
+
// JIRA Story Requirements – Method Chaining
|
|
1003
|
+
// ===========================================================================
|
|
1004
|
+
describe("JIRA Story: UPA Transaction Processing – Method Chaining", () => {
|
|
1005
|
+
let device;
|
|
1006
|
+
beforeEach(() => {
|
|
1007
|
+
device = (0, UpaHelpertest_1.createTestDevice)();
|
|
1008
|
+
});
|
|
1009
|
+
/**
|
|
1010
|
+
* All required methods should be chainable
|
|
1011
|
+
*/
|
|
1012
|
+
test("[MethodChaining] All required methods are chainable", () => {
|
|
1013
|
+
const result = device
|
|
1014
|
+
.sale(25.0)
|
|
1015
|
+
.withClerkId(101)
|
|
1016
|
+
.withCardOnFileIndicator(src_1.StoredCredentialInitiator.CardHolder)
|
|
1017
|
+
.withCardBrandTransId("TransID123")
|
|
1018
|
+
.withLineItemLeft("Item Description")
|
|
1019
|
+
.withLineItemRight("$25.00")
|
|
1020
|
+
.withLanguage("en")
|
|
1021
|
+
.withMerchantDecision("Approve")
|
|
1022
|
+
.withAcquisitionTypes([AcquisitionType_1.AcquisitionType.Contact])
|
|
1023
|
+
.withPreAuthAmount(50.0);
|
|
1024
|
+
// Verify all values are set
|
|
1025
|
+
expect(result.amount).toBe(25.0);
|
|
1026
|
+
expect(result.clerkId).toBe(101);
|
|
1027
|
+
expect(result.cardOnFileIndicator).toBe(src_1.StoredCredentialInitiator.CardHolder);
|
|
1028
|
+
expect(result.cardBrandTransId).toBe("TransID123");
|
|
1029
|
+
expect(result.lineItemLeft).toBe("Item Description");
|
|
1030
|
+
expect(result.lineItemRight).toBe("$25.00");
|
|
1031
|
+
expect(result.language).toBe("en");
|
|
1032
|
+
expect(result.merchantDecision).toBe("Approve");
|
|
1033
|
+
expect(result.acquisitionTypes).toEqual([AcquisitionType_1.AcquisitionType.Contact]);
|
|
1034
|
+
expect(result.preAuthAmount).toBe(50.0);
|
|
1035
|
+
});
|
|
1036
|
+
});
|
|
1037
|
+
// ===========================================================================
|
|
1038
|
+
// JIRA Story Requirements – Comprehensive Integration Test
|
|
1039
|
+
// ===========================================================================
|
|
1040
|
+
describe("JIRA Story: UPA Transaction Processing – Comprehensive Integration", () => {
|
|
1041
|
+
let device;
|
|
1042
|
+
beforeEach(() => {
|
|
1043
|
+
device = (0, UpaHelpertest_1.createTestDevice)();
|
|
1044
|
+
});
|
|
1045
|
+
/**
|
|
1046
|
+
* Complete transaction with all fields
|
|
1047
|
+
*/
|
|
1048
|
+
test("[Integration:Complete] Sale with all JIRA story requirements", async () => {
|
|
1049
|
+
// Build complete sale transaction matching JIRA requirements
|
|
1050
|
+
const builder = device
|
|
1051
|
+
.sale(99.99)
|
|
1052
|
+
.withClerkId(42)
|
|
1053
|
+
.withCardOnFileIndicator(src_1.StoredCredentialInitiator.CardHolder)
|
|
1054
|
+
.withCardBrandTransId("BrandTxnId-2026-001")
|
|
1055
|
+
.withPreAuthAmount(150.0)
|
|
1056
|
+
.withInvoiceNumber("INV-2026-0001")
|
|
1057
|
+
.withRequestMultiUseToken(true);
|
|
1058
|
+
// Verify all properties are accessible (without execution)
|
|
1059
|
+
const builderAsAny = builder;
|
|
1060
|
+
expect(builderAsAny.amount).toBe(99.99);
|
|
1061
|
+
expect(builderAsAny.clerkId).toBe(42);
|
|
1062
|
+
expect(builderAsAny.cardOnFileIndicator).toBe(src_1.StoredCredentialInitiator.CardHolder);
|
|
1063
|
+
expect(builderAsAny.cardBrandTransId).toBe("BrandTxnId-2026-001");
|
|
1064
|
+
expect(builderAsAny.preAuthAmount).toBe(150.0);
|
|
1065
|
+
expect(builderAsAny.invoiceNumber).toBe("INV-2026-0001");
|
|
1066
|
+
expect(builderAsAny.requestMultiUseToken).toBe(true);
|
|
1067
|
+
const response = await builder.withEcrId("13").execute();
|
|
1068
|
+
expect(response.status).toBe("Success");
|
|
1069
|
+
});
|
|
1070
|
+
/**
|
|
1071
|
+
* Refund with cardOnFileIndicator - Merchant initiated
|
|
1072
|
+
*
|
|
1073
|
+
* NOTE: Refund-by-reference with GP-API has a limitation:
|
|
1074
|
+
* - UPA spec requires referenceNumber as AN(4-16)
|
|
1075
|
+
* - Device reference numbers are 12 digits (valid for UPA)
|
|
1076
|
+
* - But GP-API's validation layer expects GatewayTxnId (29 chars)
|
|
1077
|
+
* - This creates a constraint where refund-by-reference through GP-API fails
|
|
1078
|
+
*
|
|
1079
|
+
* Solution: Use refund without reference (card-on-file without transaction ID)
|
|
1080
|
+
* This requires either:
|
|
1081
|
+
* 1. CardData for manual refund
|
|
1082
|
+
* 2. Token from previous tokenized transaction
|
|
1083
|
+
* 3. Or wait for GP-API to support device reference numbers
|
|
1084
|
+
*/
|
|
1085
|
+
test("[Integration:Refund] Refund with Merchant cardOnFileIndicator", async () => {
|
|
1086
|
+
// For now, test that refund builder supports cardOnFileIndicator properly
|
|
1087
|
+
// Full refund-by-reference will work once GP-API layer is fixed
|
|
1088
|
+
const refundBuilder = device
|
|
1089
|
+
.refund(50.0)
|
|
1090
|
+
.withClerkId(101)
|
|
1091
|
+
.withCardOnFileIndicator(src_1.StoredCredentialInitiator.Merchant)
|
|
1092
|
+
.withEcrId("13");
|
|
1093
|
+
const builderAsAny = refundBuilder;
|
|
1094
|
+
expect(builderAsAny.amount).toBe(50.0);
|
|
1095
|
+
expect(builderAsAny.clerkId).toBe(101);
|
|
1096
|
+
expect(builderAsAny.cardOnFileIndicator).toBe(src_1.StoredCredentialInitiator.Merchant);
|
|
1097
|
+
const response = await refundBuilder.execute();
|
|
1098
|
+
expect(response.status).toBe("Success");
|
|
1099
|
+
// Note: Actual refund execution requires CardData or reference that GP-API accepts
|
|
1100
|
+
// This test verifies the builder supports the JIRA requirements
|
|
1101
|
+
});
|
|
1102
|
+
/**
|
|
1103
|
+
* Pre-Authorization with all fields
|
|
1104
|
+
*/
|
|
1105
|
+
test("[Integration:PreAuth] Pre-Auth with preAuthAmount and processing indicators", async () => {
|
|
1106
|
+
const builder = device
|
|
1107
|
+
.authorize(200.0)
|
|
1108
|
+
.withClerkId(55)
|
|
1109
|
+
.withCardBrandTransId("PreAuthBrandId")
|
|
1110
|
+
.withPreAuthAmount(250.0);
|
|
1111
|
+
const builderAsAny = builder;
|
|
1112
|
+
expect(builderAsAny.amount).toBe(200.0);
|
|
1113
|
+
expect(builderAsAny.clerkId).toBe(55);
|
|
1114
|
+
expect(builderAsAny.cardBrandTransId).toBe("PreAuthBrandId");
|
|
1115
|
+
expect(builderAsAny.preAuthAmount).toBe(250.0);
|
|
1116
|
+
const response = await builder.withEcrId("13").execute();
|
|
1117
|
+
expect(response.status).toBe("Success");
|
|
1118
|
+
});
|
|
1119
|
+
});
|
|
1120
|
+
// ===========================================================================
|
|
1121
|
+
// processCPC serialization for Sale and PreAuth
|
|
1122
|
+
// ===========================================================================
|
|
1123
|
+
(0, UpaHelpertest_1.describeUpaLive)("UPA Credit – processCPC serialization", () => {
|
|
1124
|
+
let device;
|
|
1125
|
+
beforeEach(() => {
|
|
1126
|
+
device = (0, UpaHelpertest_1.createTestDevice)();
|
|
1127
|
+
});
|
|
1128
|
+
test("[UpaCreditTests:ProcessCPC-001] sale() with ProcessCPC(true) serializes processCPC as '1'", async () => {
|
|
1129
|
+
const controller = src_1.ServicesContainer.instance().getDeviceController();
|
|
1130
|
+
const builder = device
|
|
1131
|
+
.sale(10.0)
|
|
1132
|
+
.withEcrId(13)
|
|
1133
|
+
.withProcessCPC(true);
|
|
1134
|
+
// Verify request serialization (processCPC is sent to device)
|
|
1135
|
+
const request = controller
|
|
1136
|
+
.buildProcessTransaction(builder)
|
|
1137
|
+
.getJsonRequest();
|
|
1138
|
+
console.log("[UpaCreditTests:ProcessCPC-001] Sale with ProcessCPC(true) request payload:\n" +
|
|
1139
|
+
JSON.stringify(request, null, 2));
|
|
1140
|
+
expect(request.data.command).toBe("Sale");
|
|
1141
|
+
expect(request.data.data.transaction.processCPC).toBe("1");
|
|
1142
|
+
// Execute transaction and verify success
|
|
1143
|
+
const response = await builder.execute();
|
|
1144
|
+
expect(response.status).toBe("Success");
|
|
1145
|
+
expect(response.deviceResponseCode).toBe("00");
|
|
1146
|
+
console.log("[UpaCreditTests:ProcessCPC-001] Sale response:\n" +
|
|
1147
|
+
JSON.stringify(response, null, 2));
|
|
1148
|
+
// Note: processCPC is request-only; device may not echo it back in response
|
|
1149
|
+
// If device does return it, it will be populated in response.processCPC
|
|
1150
|
+
console.log(`[UpaCreditTests:ProcessCPC-001] Response processCPC value: "${response.processCPC ?? "not returned by device"}"`);
|
|
1151
|
+
});
|
|
1152
|
+
test("[UpaCreditTests:ProcessCPC-002] sale() with ProcessCPC(false) serializes processCPC as '0'", async () => {
|
|
1153
|
+
const controller = src_1.ServicesContainer.instance().getDeviceController();
|
|
1154
|
+
const builder = device
|
|
1155
|
+
.sale(10.0)
|
|
1156
|
+
.withEcrId(13)
|
|
1157
|
+
.withProcessCPC(false);
|
|
1158
|
+
const request = controller
|
|
1159
|
+
.buildProcessTransaction(builder)
|
|
1160
|
+
.getJsonRequest();
|
|
1161
|
+
const response = await builder.execute();
|
|
1162
|
+
expect(response.status).toBe("Success");
|
|
1163
|
+
expect(response.deviceResponseCode).toBe("00");
|
|
1164
|
+
expect(request.data.command).toBe("Sale");
|
|
1165
|
+
expect(request.data.data.transaction.processCPC).toBe("0");
|
|
1166
|
+
});
|
|
1167
|
+
test("[UpaCreditTests:ProcessCPC-003] sale() without ProcessCPC omits processCPC from request", async () => {
|
|
1168
|
+
const controller = src_1.ServicesContainer.instance().getDeviceController();
|
|
1169
|
+
const builder = device.sale(10.0).withEcrId(13);
|
|
1170
|
+
const response = await builder.execute();
|
|
1171
|
+
expect(response.status).toBe("Success");
|
|
1172
|
+
expect(response.deviceResponseCode).toBe("00");
|
|
1173
|
+
const request = controller
|
|
1174
|
+
.buildProcessTransaction(builder)
|
|
1175
|
+
.getJsonRequest();
|
|
1176
|
+
expect(request.data.command).toBe("Sale");
|
|
1177
|
+
expect(request.data.data.transaction.processCPC).toBeUndefined();
|
|
1178
|
+
});
|
|
1179
|
+
test("[UpaCreditTests:ProcessCPC-004] capture() uses totalAmount (not baseAmount)", async () => {
|
|
1180
|
+
const controller = src_1.ServicesContainer.instance().getDeviceController();
|
|
1181
|
+
const authresponse = await device
|
|
1182
|
+
.authorize(10.0)
|
|
1183
|
+
.withEcrId(13)
|
|
1184
|
+
.execute();
|
|
1185
|
+
expect(authresponse.status).toBe("Success");
|
|
1186
|
+
expect(authresponse.deviceResponseCode).toBe("00");
|
|
1187
|
+
const builder = device
|
|
1188
|
+
.capture()
|
|
1189
|
+
.withTransactionId(authresponse.transactionId)
|
|
1190
|
+
.withProcessCPC(true)
|
|
1191
|
+
.withAmount(10.0)
|
|
1192
|
+
.withEcrId(13);
|
|
1193
|
+
const request = controller
|
|
1194
|
+
.buildProcessTransaction(builder)
|
|
1195
|
+
.getJsonRequest();
|
|
1196
|
+
const response = await builder.execute();
|
|
1197
|
+
expect(response.status).toBe("Success");
|
|
1198
|
+
expect(response.deviceResponseCode).toBe("00");
|
|
1199
|
+
expect(request.data.command).toBe("AuthCompletion");
|
|
1200
|
+
expect(request.data.data.transaction.totalAmount).toBe("10.00");
|
|
1201
|
+
expect(request.data.data.transaction.baseAmount).toBeUndefined();
|
|
1202
|
+
});
|
|
1203
|
+
});
|
|
527
1204
|
//# sourceMappingURL=UpaCredit.test.js.map
|