globalpayments-api 3.12.0 → 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 +8 -1
- package/README.md +0 -18
- package/lib/src/Terminals/Builders/TerminalAuthBuilder.d.ts +2 -0
- package/lib/src/Terminals/Builders/TerminalAuthBuilder.js +5 -1
- 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 +14 -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 +4 -1
- package/lib/src/Terminals/UPA/Reponses/TransactionResponse.js +15 -1
- package/lib/src/Terminals/UPA/Reponses/TransactionResponse.js.map +1 -1
- package/lib/src/Terminals/UPA/UpaController.js +11 -4
- package/lib/src/Terminals/UPA/UpaController.js.map +1 -1
- package/lib/test/Integration/Gateways/GpApiConnector/GpApiMMAAccount.test.js +29 -1
- package/lib/test/Integration/Gateways/GpApiConnector/GpApiMMAAccount.test.js.map +1 -1
- package/lib/test/Unit/Terminals/UPA/UpaAdmin.test.js +2233 -388
- package/lib/test/Unit/Terminals/UPA/UpaAdmin.test.js.map +1 -1
- package/lib/test/Unit/Terminals/UPA/UpaCredit.test.js +504 -1
- package/lib/test/Unit/Terminals/UPA/UpaCredit.test.js.map +1 -1
- package/package.json +1 -1
|
@@ -11,6 +11,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
11
11
|
*/
|
|
12
12
|
const src_1 = require("../../../../src");
|
|
13
13
|
const UpaHelpertest_1 = require("./UpaHelpertest");
|
|
14
|
+
const AcquisitionType_1 = require("../../../../src/Entities/Enums/AcquisitionType");
|
|
14
15
|
jest.setTimeout(240000);
|
|
15
16
|
function sleep(delayMs) {
|
|
16
17
|
return new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
@@ -429,6 +430,302 @@ afterEach(async () => {
|
|
|
429
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.`);
|
|
430
431
|
});
|
|
431
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
|
+
});
|
|
432
729
|
// ===========================================================================
|
|
433
730
|
// COMPREHENSIVE INTEGRATED TEST SCENARIOS FROM SPEC
|
|
434
731
|
// ===========================================================================
|
|
@@ -530,7 +827,6 @@ afterEach(async () => {
|
|
|
530
827
|
.withPrescriptionAmount(25.5)
|
|
531
828
|
.withClinicAmount(35.75)
|
|
532
829
|
.withDentalAmount(40.25);
|
|
533
|
-
//
|
|
534
830
|
const request = controller
|
|
535
831
|
.buildProcessTransaction(builder)
|
|
536
832
|
.getJsonRequest();
|
|
@@ -544,6 +840,7 @@ afterEach(async () => {
|
|
|
544
840
|
expect(request.data.data.transaction.dentalAmount).toBe("40.25");
|
|
545
841
|
});
|
|
546
842
|
});
|
|
843
|
+
// ===========================================================================
|
|
547
844
|
// sale() with enhanced field support
|
|
548
845
|
// ===========================================================================
|
|
549
846
|
(0, UpaHelpertest_1.describeUpaLive)("UPA Credit – sale() with enhanced fields", () => {
|
|
@@ -615,6 +912,212 @@ afterEach(async () => {
|
|
|
615
912
|
});
|
|
616
913
|
});
|
|
617
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
|
+
// ===========================================================================
|
|
618
1121
|
// processCPC serialization for Sale and PreAuth
|
|
619
1122
|
// ===========================================================================
|
|
620
1123
|
(0, UpaHelpertest_1.describeUpaLive)("UPA Credit – processCPC serialization", () => {
|