diff --git a/CHANGELOG.md b/CHANGELOG.md
index a97d714..0733b7e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,7 +4,15 @@
# Changelog
-## Latest Version - v12.0.5 (06/18/24)
+## Latest Version - v12.0.7 (07/16/24)
+### Enhancements:
+- [GP-API] Adds avs data to "/transaction" request for digital wallet
+- [GP-API] Adds brand reference and stage time to the DisputeSummary
+
+### Bug Fixes:
+- [PAX] Correction to tip/gratuity handling in the request to device
+
+## Latest Version - v12.0.6 (06/18/24)
### Enhancements:
- [GP-ECOM] Add Multi-Capture
diff --git a/composer.json b/composer.json
index e52a916..ab57530 100644
--- a/composer.json
+++ b/composer.json
@@ -22,7 +22,6 @@
},
"require-dev": {
"phpunit/phpunit": "^7.5 || ^8.5 || ~9.4",
- "brianium/paratest": "4.0.0 || ^v6.6",
"squizlabs/php_codesniffer": "2.*",
"phpstan/phpstan": "^0.12"
},
@@ -39,7 +38,6 @@
"scripts": {
"docs": "@php sami.phar update docs-config.php",
"pretest": "@composer test:lint",
- "test": "@composer pretest && paratest --coverage-html=coverage.html --colors -f --stop-on-failure",
"test:lint": "phpcs"
},
"config": {
diff --git a/metadata.xml b/metadata.xml
index 6948c85..a4d7360 100644
--- a/metadata.xml
+++ b/metadata.xml
@@ -1,3 +1,3 @@
- 12.0.6
+ 12.0.7
\ No newline at end of file
diff --git a/src/Builders/RequestBuilder/GpApi/GpApiAuthorizationRequestBuilder.php b/src/Builders/RequestBuilder/GpApi/GpApiAuthorizationRequestBuilder.php
index 9b918bd..fca5222 100644
--- a/src/Builders/RequestBuilder/GpApi/GpApiAuthorizationRequestBuilder.php
+++ b/src/Builders/RequestBuilder/GpApi/GpApiAuthorizationRequestBuilder.php
@@ -576,7 +576,6 @@ private function createPaymentMethodParam($builder, $config)
/* digital wallet */
switch ($builder->transactionModifier) {
case TransactionModifier::ENCRYPTED_MOBILE:
- $paymentToken = null;
switch ($paymentMethodContainer->mobileType){
case EncyptedMobileType::CLICK_TO_PAY:
$paymentToken = ['data' => $paymentMethodContainer->token];
@@ -601,6 +600,10 @@ private function createPaymentMethodParam($builder, $config)
$digitalWallet['cryptogram'] = $paymentMethodContainer->cryptogram;
$digitalWallet['eci'] = !empty($paymentMethodContainer->eci) ?
$paymentMethodContainer->eci : $this->getEciCode($paymentMethodContainer);
+ $digitalWallet['avs_address'] =
+ (!empty($builder->billingAddress) ? $builder->billingAddress->streetAddress1 : '');
+ $digitalWallet['avs_postal_code'] =
+ (!empty($builder->billingAddress) ? $builder->billingAddress->postalCode : '');
break;
default:
break;
diff --git a/src/Entities/Reporting/DisputeSummary.php b/src/Entities/Reporting/DisputeSummary.php
index 6f19d86..02ba04c 100644
--- a/src/Entities/Reporting/DisputeSummary.php
+++ b/src/Entities/Reporting/DisputeSummary.php
@@ -14,22 +14,9 @@ class DisputeSummary
* @var string
*/
public $merchantHierarchy;
- /**
- * @var string
- */
- public $merchantName;
- /**
- * @var string
- */
- public $merchantDbaName;
- /**
- * @var string
- */
- public $merchantNumber;
- /**
- * @var string
- */
- public $merchantCategory;
+
+ public ?string $merchantName;
+
/**
* @var \DateTime
*/
@@ -38,14 +25,7 @@ class DisputeSummary
* @var string
*/
public $depositReference;
- /**
- * @var string
- */
- public $depositType;
- /**
- * @var string
- */
- public $type;
+
/**
* @var integer
*/
@@ -54,26 +34,16 @@ class DisputeSummary
* @var string
*/
public $caseCurrency;
- /**
- * @var string
- */
- public $caseStage;
+
+ /** This field indicates the distinct step a dispute is at, within the dispute lifecycle. */
+ public ?string $caseStage;
+
+ /** Time the current Dispute stage was created. */
+ public ?\DateTime $disputeStageTime;
/**
* @var string
*/
public $caseStatus;
- /**
- * @var string
- */
- public $caseDescription;
- /**
- * @var string
- */
- public $transactionOrderId;
- /**
- * @var \DateTime
- */
- public $transactionLocalTime;
/**
* @var \DateTime
*/
@@ -90,18 +60,9 @@ class DisputeSummary
* @var string
*/
public $transactionCurrency;
- /**
- * @var string
- */
- public $caseNumber;
- /**
- * @var \DateTime
- */
- public $caseTime;
- /**
- * @var string
- */
- public $caseId;
+
+ /** Unique identifier for the Dispute on the Global Payments system. */
+ public string $caseId;
/**
* @var \DateTime
*/
@@ -110,10 +71,7 @@ class DisputeSummary
* @var string
*/
public $caseMerchantId;
- /**
- * @var string
- */
- public $caseTerminalId;
+
/**
* @var string
*/
@@ -122,10 +80,7 @@ class DisputeSummary
* @var string
*/
public $transactionReferenceNumber;
- /**
- * @var string
- */
- public $transactionSRD;
+
/**
* @var string
*/
@@ -150,38 +105,20 @@ class DisputeSummary
* @var string
*/
public $result;
- /**
- * @var string
- */
- public $issuerComment;
- /**
- * @var string
- */
- public $issuerCaseNumber;
- /**
- * @var integer
- */
- public $disputeAmount;
- /**
- * @var string
- */
- public $disputeCurrency;
+ public array $issuerComment = [];
+ public array $issuerCaseNumber = [];
+
/**
* @var integer
*/
public $disputeCustomerAmount;
- /**
- * @var string
- */
- public $disputeCustomerCurrency;
+
+ public ?string $disputeCustomerCurrency;
/**
* @var \DateTime
*/
public $respondByDate;
- /**
- * @var string
- */
- public $caseOriginalReference;
+
/**
* @var integer
*/
@@ -198,6 +135,8 @@ class DisputeSummary
/** @var array */
public $documents;
+ public ?string $transactionBrandReference;
+
/**
* @return ManagementBuilder
*/
diff --git a/src/Gateways/GpApiConnector.php b/src/Gateways/GpApiConnector.php
index 5171f42..9130dff 100644
--- a/src/Gateways/GpApiConnector.php
+++ b/src/Gateways/GpApiConnector.php
@@ -315,7 +315,7 @@ public function doTransaction(
);
} catch (GatewayException $exception) {
if (
- strpos($exception->getMessage(), 'NOT_AUTHENTICATED') !== false &&
+ in_array($exception->responseCode, ['NOT_AUTHENTICATED', '401']) &&
!empty($this->gpApiConfig->appKey) &&
!empty($this->gpApiConfig->appKey)
) {
diff --git a/src/Mapping/GpApiMapping.php b/src/Mapping/GpApiMapping.php
index dbe5f2f..433d144 100644
--- a/src/Mapping/GpApiMapping.php
+++ b/src/Mapping/GpApiMapping.php
@@ -597,10 +597,11 @@ public static function mapDisputeSummary($response)
{
$summary = new DisputeSummary();
$summary->caseId = $response->id;
- $summary->caseIdTime = !empty($response->time_created) ? new \DateTime($response->time_created) :
- (!empty($response->stage_time_created) ? new \DateTime($response->stage_time_created) : '');
+ $summary->caseIdTime = !empty($response->time_created) ? new \DateTime($response->time_created) : null;
$summary->caseStatus = $response->status;
$summary->caseStage = $response->stage;
+ $summary->disputeStageTime =
+ (!empty($response->stage_time_created) ? new \DateTime($response->stage_time_created) : null);
$summary->caseAmount = StringUtils::toAmount($response->amount);
$summary->caseCurrency = $response->currency;
if (isset($response->system)) {
@@ -610,14 +611,11 @@ public static function mapDisputeSummary($response)
$summary->merchantName = !empty($system->name) ? $system->name : null;
}
- if (
- isset($response->payment_method) &&
- isset($response->payment_method->card)
- ) {
+ if (!empty($response->payment_method->card)) {
$card = $response->payment_method->card;
- $summary->transactionMaskedCardNumber = $card->number;
+ $summary->transactionMaskedCardNumber = $card->number ?? null;
}
- if (isset($response->transaction)) {
+ if (!empty($response->transaction)) {
$summary->transactionTime = $response->transaction->time_created;
$summary->transactionType = $response->transaction->type;
$summary->transactionAmount = StringUtils::toAmount($response->transaction->amount);
@@ -625,9 +623,9 @@ public static function mapDisputeSummary($response)
$summary->transactionReferenceNumber = $response->transaction->reference;
if (isset($response->transaction->payment_method->card)) {
$card = $response->transaction->payment_method->card;
- $summary->transactionMaskedCardNumber = !empty($card->masked_number_first6last4) ?
- $card->masked_number_first6last4 : '';
+ $summary->transactionMaskedCardNumber = $card->masked_number_first6last4 ?? null;
$summary->transactionAuthCode = $card->authcode;
+ $summary->transactionBrandReference = $card->brand_reference ?? null;
}
}
if (!empty($response->documents)) {
@@ -654,6 +652,19 @@ public static function mapDisputeSummary($response)
$summary->lastAdjustmentFunding = $response->last_adjustment_funding;
$summary->depositDate = !empty($response->deposit_time_created) ? $response->deposit_time_created : null;
$summary->depositReference = !empty($response->deposit_id) ? $response->deposit_id : null;
+ $summary->disputeCustomerAmount = !empty($response->payer_amount) ?
+ StringUtils::toAmount($response->payer_amount) : null;
+ $summary->disputeCustomerCurrency = $response->payer_currency ?? null;
+ if (!empty($response->payment_method_provider)) {
+ foreach ($response->payment_method_provider as $providerPaymentMethod) {
+ if (!empty($providerPaymentMethod->comment)) {
+ $summary->issuerComment[] = $providerPaymentMethod->comment;
+ }
+ if (!empty($providerPaymentMethod->reference)) {
+ $summary->issuerCaseNumber[] = $providerPaymentMethod->reference;
+ }
+ }
+ }
return $summary;
}
diff --git a/src/Terminals/PAX/PaxController.php b/src/Terminals/PAX/PaxController.php
index 73804dd..9ff7e72 100644
--- a/src/Terminals/PAX/PaxController.php
+++ b/src/Terminals/PAX/PaxController.php
@@ -226,6 +226,10 @@ public function processTransaction(TerminalAuthBuilder $builder) : TerminalRespo
if ($builder->signatureCapture !== null) {
$extData->details[PaxExtData::SIGNATURE_CAPTURE] = $builder->signatureCapture;
}
+
+ if (empty($builder->gratuity)) {
+ $extData->details[PaxExtData::TIP_REQUEST] = 1;
+ }
$transactionType = $this->mapTransactionType($builder->transactionType, $builder->requestMultiUseToken);
switch ($builder->paymentMethodType) {
diff --git a/test/Integration/Gateways/GpApiConnector/GpApiDigitalWalletTest.php b/test/Integration/Gateways/GpApiConnector/GpApiDigitalWalletTest.php
index 28e6d98..bec67df 100644
--- a/test/Integration/Gateways/GpApiConnector/GpApiDigitalWalletTest.php
+++ b/test/Integration/Gateways/GpApiConnector/GpApiDigitalWalletTest.php
@@ -2,6 +2,8 @@
namespace Gateways\GpApiConnector;
+use GlobalPayments\Api\Entities\Address;
+use GlobalPayments\Api\Entities\Enums\AddressType;
use GlobalPayments\Api\Entities\Enums\Channel;
use GlobalPayments\Api\Entities\Enums\EncyptedMobileType;
use GlobalPayments\Api\Entities\Enums\TransactionModifier;
@@ -167,6 +169,10 @@ public function testPayWithApplePayEncrypted()
public function testPayWithDecryptedFlow()
{
$encryptedProviders = [EncyptedMobileType::GOOGLE_PAY, EncyptedMobileType::APPLE_PAY];
+ $address = new Address();
+ $address->streetAddress1 = "123 Main St.";
+ $address->postalCode = "12345";
+
foreach ($encryptedProviders as $encryptedProvider) {
$this->card->token = '5167300431085507';
$this->card->mobileType = $encryptedProvider;
@@ -177,6 +183,7 @@ public function testPayWithDecryptedFlow()
$response = $this->card->charge($this->amount)
->withCurrency($this->currency)
->withModifier(TransactionModifier::DECRYPTED_MOBILE)
+ ->withAddress($address)
->execute();
$this->assertTransactionResponse($response, TransactionStatus::CAPTURED);
diff --git a/test/Integration/Gateways/GpApiConnector/ReportingDisputesTest.php b/test/Integration/Gateways/GpApiConnector/ReportingDisputesTest.php
index 5f78def..bd7a0f1 100644
--- a/test/Integration/Gateways/GpApiConnector/ReportingDisputesTest.php
+++ b/test/Integration/Gateways/GpApiConnector/ReportingDisputesTest.php
@@ -51,11 +51,14 @@ public static function tearDownAfterClass(): void
public function testReportDisputeDetail()
{
$disputeId = 'DIS_SAND_abcd1234';
+ /** @var DisputeSummary $response */
$response = ReportingService::disputeDetail($disputeId)
->execute();
$this->assertNotNull($response);
$this->assertInstanceOf(DisputeSummary::class, $response);
$this->assertEquals($disputeId, $response->caseId);
+ $this->assertNotNull($response->transactionBrandReference);
+ $this->assertNotNull($response->disputeStageTime);
$this->arn = $response->transactionARN;
}
@@ -648,8 +651,9 @@ public function testReportFindSettlementDisputes_FilterBy_FromAndToStageTimeCrea
$this->assertNotNull($summary);
$this->assertInstanceOf(PagedResult::class, $summary);
+ /** @var DisputeSummary $dispute */
foreach ($summary->result as $dispute) {
- $this->assertTrue($dispute->caseTime <= $this->endDate);
+ $this->assertTrue($dispute->caseIdTime <= $this->endDate);
}
}
diff --git a/test/Integration/Gateways/Terminals/PAX/PaxCreditTests.php b/test/Integration/Gateways/Terminals/PAX/PaxCreditTests.php
index 2e165a5..8d4a30c 100644
--- a/test/Integration/Gateways/Terminals/PAX/PaxCreditTests.php
+++ b/test/Integration/Gateways/Terminals/PAX/PaxCreditTests.php
@@ -427,4 +427,47 @@ public function testPartialAuthHandling() : void
$this->assertEquals(55, $response->amountDue);
$this->assertEquals(100, $response->transactionAmount);
}
+
+ /**
+ * This test should demonstrates that the device IS prompting for a tip
+ * when a gratuity amount isn't provided to the builder. This assumes that
+ * the device has been configured for gratuity, which is something that is
+ * set at the terminal file level.
+ *
+ * **Requires end-user confirmation**
+ *
+ * @return void
+ * @throws InvalidArgumentException
+ * @throws ExpectationFailedException
+ */
+ public function testTipPropmpt() : void
+ {
+ $response = $this->device->sale("12.34")
+ ->execute();
+
+ $this->assertNotNull($response);
+ $this->assertEquals("00", $response->responseCode);
+ }
+
+ /**
+ * This test should demonstrate that a the device is NOT prompting for a
+ * tip when a gratuity amount IS provided to the builder. This assumes that
+ * the device is configured for gratuity which is something that is set at
+ * the terminal file level.
+ *
+ * **Requires end-user confirmation**
+ *
+ * @return void
+ * @throws InvalidArgumentException
+ * @throws ExpectationFailedException
+ */
+ public function testTipNoPropmpt() : void
+ {
+ $response = $this->device->sale("15.34")
+ ->withGratuity("3.00") // this makes for an $18.34 sale on device
+ ->execute();
+
+ $this->assertNotNull($response);
+ $this->assertEquals("00", $response->responseCode);
+ }
}