From ca910d08e9be5d8c0458bd922e8c9b0c3e89c889 Mon Sep 17 00:00:00 2001 From: securesubmit-buildmaster Date: Thu, 30 Sep 2021 08:03:27 -0400 Subject: [PATCH] OctopusDeploy release: 2.3.14 --- CHANGELOG.md | 14 +- metadata.xml | 2 +- phpunit.xml.dist | 1 + src/Builders/TransactionReportBuilder.php | 16 +- .../Enums/{GpApi => }/ActionSortProperty.php | 2 +- src/Entities/Enums/AlternativePaymentType.php | 1 + .../Enums/{GpApi => }/CaptureMode.php | 4 +- .../Enums/{GpApi/Channels.php => Channel.php} | 7 +- .../Enums/{GpApi => }/DepositSortProperty.php | 2 +- .../Enums/{GpApi => }/DepositStatus.php | 2 +- .../Enums/{GpApi => }/DisputeSortProperty.php | 2 +- .../Enums/{GpApi => }/DisputeStage.php | 2 +- .../Enums/{GpApi => }/DisputeStatus.php | 2 +- src/Entities/Enums/EmvLastChipRead.php | 19 - src/Entities/Enums/ManualEntryMethod.php | 11 + .../EntryMode.php => PaymentEntryMode.php} | 6 +- .../Enums/{GpApi => }/SortDirection.php | 2 +- .../Enums/StoredCredentialInitiator.php | 16 - .../StoredPaymentMethodSortProperty.php | 2 +- .../{GpApi => }/TransactionSortProperty.php | 2 +- .../GpApiAuthorizationRequestBuilder.php | 93 ++- .../GpApi/GpApiManagementRequestBuilder.php | 2 +- src/Entities/GpApi/GpApiRequest.php | 1 + .../GpApi/GpApiSecure3DRequestBuilder.php | 9 +- .../Reporting/SearchCriteriaBuilder.php | 14 +- src/Entities/Reporting/TransactionSummary.php | 4 +- src/Gateways/GpApiConnector.php | 5 + src/Mapping/EnumMapping.php | 45 ++ src/Mapping/GpApiMapping.php | 5 + src/PaymentMethods/Credit.php | 5 + src/PaymentMethods/CreditTrackData.php | 1 - src/PaymentMethods/DebitTrackData.php | 6 - src/PaymentMethods/EBT.php | 5 + src/PaymentMethods/EBTTrackData.php | 30 +- src/ServiceConfigs/Gateways/GpApiConfig.php | 3 + src/Services/GpApiService.php | 4 + src/Utils/CardUtils.php | 52 +- src/Utils/EmvData.php | 127 ++++ src/Utils/EmvUtils.php | 266 ++++++++ src/Utils/StringUtils.php | 10 + src/Utils/TlvData.php | 55 ++ test/Data/GpApiAvsCheckTestCards.php | 35 ++ .../GpApiConnector/AccessTokenTest.php | 3 + .../CapabilitiesCardPresentTest.php | 4 +- .../GpApiSdkCertificationTest.php | 4 +- .../CreditCardNotPresentTest.php | 126 +++- .../GpApiConnector/CreditCardPresentTest.php | 586 ++++-------------- .../Gateways/GpApiConnector/DebitCardTest.php | 6 +- .../Gateways/GpApiConnector/EbtCardTest.php | 4 +- .../Gateways/GpApiConnector/GpApi3DS1Test.php | 4 +- .../Gateways/GpApiConnector/GpApi3DS2Test.php | 8 +- .../GpApiConnector/GpApi3DSecureTest.php | 20 +- .../Gateways/GpApiConnector/GpApiAchTest.php | 40 +- .../GpApiConnector/GpApiBatchTests.php | 387 ++++++++++++ .../GpApiConnector/GpApiDigitalWalletTest.php | 123 ++-- .../GpApiConnector/PartnershipModeTest.php | 219 +++++++ .../GpApiConnector/ReportingActionsTest.php | 20 +- .../GpApiConnector/ReportingDepositsTest.php | 4 +- .../GpApiConnector/ReportingDisputesTest.php | 20 +- .../ReportingSettlementTransactionsTest.php | 31 +- .../ReportingStoredPaymentMethodsTest.php | 14 +- .../ReportingTransactionsTest.php | 22 +- .../RealexConnector/RealexApmTest.php | 19 + test/Integration/TrackDataTest.php | 152 +++++ 64 files changed, 1949 insertions(+), 759 deletions(-) rename src/Entities/Enums/{GpApi => }/ActionSortProperty.php (71%) rename src/Entities/Enums/{GpApi => }/CaptureMode.php (68%) rename src/Entities/Enums/{GpApi/Channels.php => Channel.php} (52%) rename src/Entities/Enums/{GpApi => }/DepositSortProperty.php (81%) rename src/Entities/Enums/{GpApi => }/DepositStatus.php (84%) rename src/Entities/Enums/{GpApi => }/DisputeSortProperty.php (91%) rename src/Entities/Enums/{GpApi => }/DisputeStage.php (89%) rename src/Entities/Enums/{GpApi => }/DisputeStatus.php (85%) create mode 100644 src/Entities/Enums/ManualEntryMethod.php rename src/Entities/Enums/{GpApi/EntryMode.php => PaymentEntryMode.php} (70%) rename src/Entities/Enums/{GpApi => }/SortDirection.php (72%) rename src/Entities/Enums/{GpApi => }/StoredPaymentMethodSortProperty.php (73%) rename src/Entities/Enums/{GpApi => }/TransactionSortProperty.php (82%) create mode 100644 src/Utils/EmvData.php create mode 100644 src/Utils/EmvUtils.php create mode 100644 src/Utils/TlvData.php create mode 100644 test/Data/GpApiAvsCheckTestCards.php create mode 100644 test/Integration/Gateways/GpApiConnector/GpApiBatchTests.php create mode 100644 test/Integration/Gateways/GpApiConnector/PartnershipModeTest.php create mode 100644 test/Integration/TrackDataTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index b1d739e6..710e4d36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,9 +7,19 @@ ## Latest version -- Removed unwanted aftifacts files +- Add "paybybankapp" APM (GP-ECOM) +- Add AVS missing mapping to response when creating a transaction (GP-API) +- Refacto on enum classes (GP-API) +- Update "entry_mode" functionality and add manual entry methods: MOTO, PHONE, MAIL (GP-API) +- Add merchantId on GpApiConfig for partnership active -## v2.3.12 (08/09/2021) +## v2.3.13 (09/23/2021) + +#### Bug Fixes: + +- Removed unwanted artefacts files + +## v2.3.12 (09/09/2021) - Add sanitize data diff --git a/metadata.xml b/metadata.xml index a48103a5..82ffe734 100644 --- a/metadata.xml +++ b/metadata.xml @@ -1,3 +1,3 @@ - 2.3.13 + 2.3.14 \ No newline at end of file diff --git a/phpunit.xml.dist b/phpunit.xml.dist index d2666d04..5dca361e 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -26,6 +26,7 @@ ./test/Integration/Gateways/PorticoConnector/Certifications/ ./test/Integration/Gateways/RealexConnector/Certifications/ + ./test/Integration/Gateways/GpApiConnector/Certifications/ ./test/Integration/Gateways/PorticoConnector/ diff --git a/src/Builders/TransactionReportBuilder.php b/src/Builders/TransactionReportBuilder.php index 7f667a21..11faa836 100644 --- a/src/Builders/TransactionReportBuilder.php +++ b/src/Builders/TransactionReportBuilder.php @@ -2,19 +2,15 @@ namespace GlobalPayments\Api\Builders; -use GlobalPayments\Api\Entities\Enums\GpApi\ActionSortProperty; -use GlobalPayments\Api\Entities\Enums\GpApi\DepositSortProperty; -use GlobalPayments\Api\Entities\Enums\GpApi\DisputeSortProperty; -use GlobalPayments\Api\Entities\Enums\GpApi\SortDirection; -use GlobalPayments\Api\Entities\Enums\GpApi\StoredPaymentMethodSortProperty; -use GlobalPayments\Api\Entities\Enums\GpApi\TransactionSortProperty; +use GlobalPayments\Api\Entities\Enums\ActionSortProperty; +use GlobalPayments\Api\Entities\Enums\DepositSortProperty; +use GlobalPayments\Api\Entities\Enums\DisputeSortProperty; +use GlobalPayments\Api\Entities\Enums\SortDirection; +use GlobalPayments\Api\Entities\Enums\StoredPaymentMethodSortProperty; +use GlobalPayments\Api\Entities\Enums\TransactionSortProperty; use GlobalPayments\Api\Entities\Enums\ReportType; use GlobalPayments\Api\Entities\Enums\TimeZoneConversion; -use GlobalPayments\Api\Entities\Exceptions\ApiException; -use GlobalPayments\Api\ServicesContainer; -use GlobalPayments\Api\Entities\Reporting\SearchCriteria; use GlobalPayments\Api\Entities\Reporting\SearchCriteriaBuilder; -use phpDocumentor\Parser\Exception; class TransactionReportBuilder extends ReportBuilder { diff --git a/src/Entities/Enums/GpApi/ActionSortProperty.php b/src/Entities/Enums/ActionSortProperty.php similarity index 71% rename from src/Entities/Enums/GpApi/ActionSortProperty.php rename to src/Entities/Enums/ActionSortProperty.php index 3dcc2041..cec30586 100644 --- a/src/Entities/Enums/GpApi/ActionSortProperty.php +++ b/src/Entities/Enums/ActionSortProperty.php @@ -1,6 +1,6 @@ [ - Target::GP_API => 'PREV_SUCCESS', - Target::Portico => 'CHIP_FAILED_PREV_SUCCESS', - Target::Transit => 'SUCCESSFUL' - ], - self::FAILED => [ - Target::GP_API => 'PREV_FAILED', - Target::Portico => 'CHIP_FAILED_PREV_FAILED', - Target::Transit => 'FAILED' - ], - self::NOT_A_CHIP_TRANSACTION => [ - Target::Transit => 'NOT_A_CHIP_TRANSACTION' - ], - self::UNKNOWN => [ - Target::Transit => 'UNKNOWN' - ] - ]; } \ No newline at end of file diff --git a/src/Entities/Enums/ManualEntryMethod.php b/src/Entities/Enums/ManualEntryMethod.php new file mode 100644 index 00000000..6fceadde --- /dev/null +++ b/src/Entities/Enums/ManualEntryMethod.php @@ -0,0 +1,11 @@ + [ - Target::Realex => self::CARDHOLDER, - Target::Portico => 'C', - Target::GP_API => self::PAYER - ], - self::MERCHANT => [ - Target::Realex => self::MERCHANT, - Target::Portico => 'M', - Target::GP_API => self::MERCHANT - ], - self::SCHEDULED => [ - Target::Realex => self::SCHEDULED - ] - ]; } diff --git a/src/Entities/Enums/GpApi/StoredPaymentMethodSortProperty.php b/src/Entities/Enums/StoredPaymentMethodSortProperty.php similarity index 73% rename from src/Entities/Enums/GpApi/StoredPaymentMethodSortProperty.php rename to src/Entities/Enums/StoredPaymentMethodSortProperty.php index d6d87f2f..df62cd45 100644 --- a/src/Entities/Enums/GpApi/StoredPaymentMethodSortProperty.php +++ b/src/Entities/Enums/StoredPaymentMethodSortProperty.php @@ -1,7 +1,7 @@ clientTransactionId : GenerationUtils::getGuid(); $requestBody['currency'] = $builder->currency; $requestBody['country'] = $config->country; - $requestBody['payment_method'] = $this->createPaymentMethodParam($builder); + $requestBody['payment_method'] = $this->createPaymentMethodParam($builder, $config); return $requestBody; } @@ -142,15 +145,14 @@ private function createFromAuthorizationBuilder($builder, GpApiConfig $config) $requestBody['convenience_amount'] = StringUtils::toNumeric($builder->convenienceAmount); $requestBody['cashback_amount'] = StringUtils::toNumeric($builder->cashBackAmount); $requestBody['ip_address'] = $builder->customerIpAddress; - $requestBody['payment_method'] = $this->createPaymentMethodParam($builder); + $requestBody['payment_method'] = $this->createPaymentMethodParam($builder, $config); if ($builder->paymentMethod instanceof ECheck) { $requestBody['payer'] = $this->setPayerInformation($builder); } if (!empty($builder->storedCredential)) { - $requestBody['initiator'] = - !empty(StoredCredentialInitiator::$mapInitiator[$builder->storedCredential->initiator]) ? - strtoupper(StoredCredentialInitiator::$mapInitiator[$builder->storedCredential->initiator][Target::GP_API]) : ''; + $initiator = EnumMapping::mapStoredCredentialInitiator(GatewayProvider::GP_API, $builder->storedCredential->initiator); + $requestBody['initiator'] = !empty($initiator) ? $initiator : null; $requestBody['stored_credential'] = [ 'model' => strtoupper($builder->storedCredential->type), 'reason' => strtoupper($builder->storedCredential->reason), @@ -227,15 +229,16 @@ private function getPhoneNumber($builder, $type) /** * @param AuthorizationBuilder $builder + * @param GpApiConfig $config * * @return PaymentMethod */ - private function createPaymentMethodParam($builder) + private function createPaymentMethodParam($builder, $config) { /** @var CreditCardData|CreditTrackData|DebitTrackData|ECheck $paymentMethodContainer */ $paymentMethodContainer = $builder->paymentMethod; $paymentMethod = new PaymentMethod(); - $paymentMethod->entry_mode = $this->getEntryMode($builder); + $paymentMethod->entry_mode = $this->getEntryMode($builder, $config->channel); $paymentMethod->name = !empty($paymentMethodContainer->cardHolderName) ? $paymentMethodContainer->cardHolderName : null; switch (get_class($paymentMethodContainer)) { @@ -307,7 +310,7 @@ private function createPaymentMethodParam($builder) } if (is_null($paymentMethod->id)) { - $paymentMethod->card = CardUtils::generateCard($builder); + $paymentMethod->card = CardUtils::generateCard($builder, GatewayProvider::GP_API); } } else { /* digital wallet */ @@ -371,26 +374,62 @@ private function getEciCode($paymentMethod) return $eciCode; } - private function getEntryMode(AuthorizationBuilder $builder) + /** + * @param AuthorizationBuilder $builder + * @param string $channel + * @return string + */ + private function getEntryMode(AuthorizationBuilder $builder, $channel) { - if ($builder->paymentMethod instanceof ICardData) { - if ($builder->paymentMethod->readerPresent) { - return $builder->paymentMethod->cardPresent ? EntryMode::MANUAL : EntryMode::IN_APP; - } else { - return $builder->paymentMethod->cardPresent ? EntryMode::MANUAL : EntryMode::ECOM; + if ($channel == Channel::CardPresent) { + if ($builder->paymentMethod instanceof ITrackData) { + if (!empty($builder->tagData)) { + if ($builder->paymentMethod->entryMethod == EntryMethod::PROXIMITY) { + return PaymentEntryMode::CONTACTLESS_CHIP; + } + $emvData = EmvUtils::parseTagData($builder->tagData); + if ($emvData->isContactlessMsd()) { + return PaymentEntryMode::CONTACTLESS_SWIPE; + } + + return PaymentEntryMode::CHIP; + } + if ($builder->paymentMethod->entryMethod == PaymentEntryMode::SWIPE) { + return PaymentEntryMode::SWIPE; + } } - } elseif ($builder->paymentMethod instanceof ITrackData) { - if (!empty($builder->tagData)) { - return ($builder->paymentMethod->entryMethod == EntryMode::SWIPE) ? - EntryMode::CHIP : EntryMode::CONTACTLESS_CHIP; - } elseif (!empty($builder->hasEmvFallbackData())) { - return EntryMode::CONTACTLESS_SWIPE; - } else { - return EntryMode::SWIPE; + if ($builder->paymentMethod instanceof ICardData && $builder->paymentMethod->cardPresent) { + return PaymentEntryMode::MANUAL; } + + return PaymentEntryMode::SWIPE; + } elseif ($channel == Channel::CardNotPresent) { + if ($builder->paymentMethod instanceof ICardData) { + if ($builder->paymentMethod->readerPresent === true) { + return PaymentEntryMode::ECOM; + } + if( + $builder->paymentMethod->readerPresent === false && + !is_null($builder->paymentMethod->entryMethod) + ) { + switch ($builder->paymentMethod->entryMethod) { + case ManualEntryMethod::PHONE: + return PaymentEntryMode::PHONE; + case ManualEntryMethod::MOTO: + return PaymentEntryMode::MOTO; + case ManualEntryMethod::MAIL: + return PaymentEntryMode::MAIL; + default: + break; + } + } + + } + + return PaymentEntryMode::ECOM; } - return EntryMode::ECOM; + throw new ApiException("Please configure the channel!"); } private function getCaptureMode(AuthorizationBuilder $builder) diff --git a/src/Entities/GpApi/GpApiManagementRequestBuilder.php b/src/Entities/GpApi/GpApiManagementRequestBuilder.php index 141e5702..2c9eb79a 100644 --- a/src/Entities/GpApi/GpApiManagementRequestBuilder.php +++ b/src/Entities/GpApi/GpApiManagementRequestBuilder.php @@ -37,7 +37,7 @@ public static function canProcess($builder) */ public function buildRequest(BaseBuilder $builder, $config) { - $payload = []; + $payload = null; /** * @var ManagementBuilder $builder */ diff --git a/src/Entities/GpApi/GpApiRequest.php b/src/Entities/GpApi/GpApiRequest.php index 18f5e472..9b0d9685 100644 --- a/src/Entities/GpApi/GpApiRequest.php +++ b/src/Entities/GpApi/GpApiRequest.php @@ -15,6 +15,7 @@ class GpApiRequest const AUTHENTICATIONS_ENDPOINT = '/authentications'; const BATCHES_ENDPOINT = '/batches'; const ACTIONS_ENDPOINT = '/actions'; + const MERCHANT_MANAGEMENT_ENDPOINT = '/merchants'; public $endpoint; public $requestBody; diff --git a/src/Entities/GpApi/GpApiSecure3DRequestBuilder.php b/src/Entities/GpApi/GpApiSecure3DRequestBuilder.php index 17f25aa4..5ce4e24e 100644 --- a/src/Entities/GpApi/GpApiSecure3DRequestBuilder.php +++ b/src/Entities/GpApi/GpApiSecure3DRequestBuilder.php @@ -4,11 +4,11 @@ use GlobalPayments\Api\Builders\BaseBuilder; use GlobalPayments\Api\Builders\Secure3dBuilder; -use GlobalPayments\Api\Entities\Enums\StoredCredentialInitiator; -use GlobalPayments\Api\Entities\Enums\Target; +use GlobalPayments\Api\Entities\Enums\GatewayProvider; use GlobalPayments\Api\Entities\Enums\TransactionType; use GlobalPayments\Api\Entities\GpApi\DTO\PaymentMethod; use GlobalPayments\Api\Entities\IRequestBuilder; +use GlobalPayments\Api\Mapping\EnumMapping; use GlobalPayments\Api\PaymentMethods\Interfaces\ICardData; use GlobalPayments\Api\PaymentMethods\Interfaces\ITokenizable; use GlobalPayments\Api\ServiceConfigs\Gateways\GpApiConfig; @@ -81,9 +81,8 @@ private function verifyEnrolled(Secure3dBuilder $builder, GpApiConfig $config) ]; if (!empty($builder->storedCredential)) { - $threeDS['initiator'] = - !empty(StoredCredentialInitiator::$mapInitiator[$builder->storedCredential->initiator]) ? - strtoupper(StoredCredentialInitiator::$mapInitiator[$builder->storedCredential->initiator][Target::GP_API]) : ''; + $initiator = EnumMapping::mapStoredCredentialInitiator(GatewayProvider::GP_API, $builder->storedCredential->initiator); + $threeDS['initiator'] = !empty($initiator) ? $initiator : null; $threeDS['stored_credential'] = [ 'model' => strtoupper($builder->storedCredential->type), 'reason' => strtoupper($builder->storedCredential->reason), diff --git a/src/Entities/Reporting/SearchCriteriaBuilder.php b/src/Entities/Reporting/SearchCriteriaBuilder.php index 265a1729..186b6f34 100644 --- a/src/Entities/Reporting/SearchCriteriaBuilder.php +++ b/src/Entities/Reporting/SearchCriteriaBuilder.php @@ -3,11 +3,11 @@ use GlobalPayments\Api\Builders\TransactionReportBuilder; use GlobalPayments\Api\Entities\Enums\CardType; -use GlobalPayments\Api\Entities\Enums\GpApi\Channels; -use GlobalPayments\Api\Entities\Enums\GpApi\DepositStatus; -use GlobalPayments\Api\Entities\Enums\GpApi\DisputeStage; -use GlobalPayments\Api\Entities\Enums\GpApi\DisputeStatus; -use GlobalPayments\Api\Entities\Enums\GpApi\EntryMode; +use GlobalPayments\Api\Entities\Enums\Channel; +use GlobalPayments\Api\Entities\Enums\DepositStatus; +use GlobalPayments\Api\Entities\Enums\DisputeStage; +use GlobalPayments\Api\Entities\Enums\DisputeStatus; +use GlobalPayments\Api\Entities\Enums\PaymentEntryMode; use GlobalPayments\Api\Entities\Enums\PaymentType; use GlobalPayments\Api\Entities\Enums\PaymentMethodName; use GlobalPayments\Api\Entities\Enums\TransactionStatus; @@ -118,7 +118,7 @@ class SearchCriteriaBuilder public $cardTypes; /** - * @var Channels + * @var Channel */ public $channel; @@ -298,7 +298,7 @@ class SearchCriteriaBuilder public $oderId; /** - * @var EntryMode + * @var PaymentEntryMode */ public $paymentEntryMode; diff --git a/src/Entities/Reporting/TransactionSummary.php b/src/Entities/Reporting/TransactionSummary.php index 597da16a..679889bf 100644 --- a/src/Entities/Reporting/TransactionSummary.php +++ b/src/Entities/Reporting/TransactionSummary.php @@ -2,7 +2,7 @@ namespace GlobalPayments\Api\Entities\Reporting; use GlobalPayments\Api\Entities\AlternativePaymentResponse; -use GlobalPayments\Api\Entities\Enums\GpApi\EntryMode; +use GlobalPayments\Api\Entities\Enums\PaymentEntryMode; class TransactionSummary { @@ -425,7 +425,7 @@ class TransactionSummary public $currency; /** - * @var EntryMode + * @var PaymentEntryMode */ public $entryMode; diff --git a/src/Gateways/GpApiConnector.php b/src/Gateways/GpApiConnector.php index ef85fd8d..5a35778d 100644 --- a/src/Gateways/GpApiConnector.php +++ b/src/Gateways/GpApiConnector.php @@ -143,6 +143,10 @@ private function executeProcess($builder) * @var GpApiRequest $request */ $request = $requestBuilder->buildRequest($builder, $this->gpApiConfig); + $merchantUrl = !empty($this->gpApiConfig->merchantId) ? + GpApiRequest::MERCHANT_MANAGEMENT_ENDPOINT . '/' . $this->gpApiConfig->merchantId : ''; + $request->endpoint = $merchantUrl . $request->endpoint; + if (empty($request)) { throw new ApiException("Request was not generated!"); } @@ -231,6 +235,7 @@ public function signIn() { $accessTokenInfo = $this->gpApiConfig->accessTokenInfo; if (!empty($accessTokenInfo) && !empty($accessTokenInfo->accessToken)) { + $this->headers['Authorization'] = sprintf('Bearer %s', $accessTokenInfo->accessToken); return; } $response = $this->getAccessToken(); diff --git a/src/Mapping/EnumMapping.php b/src/Mapping/EnumMapping.php index c4f0607a..47d9becc 100644 --- a/src/Mapping/EnumMapping.php +++ b/src/Mapping/EnumMapping.php @@ -3,8 +3,10 @@ namespace GlobalPayments\Api\Mapping; use GlobalPayments\Api\Entities\Enums\AccountType; +use GlobalPayments\Api\Entities\Enums\EmvLastChipRead; use GlobalPayments\Api\Entities\Enums\EncyptedMobileType; use GlobalPayments\Api\Entities\Enums\GatewayProvider; +use GlobalPayments\Api\Entities\Enums\StoredCredentialInitiator; class EnumMapping { @@ -50,4 +52,47 @@ public static function mapDigitalWalletType($gateway, $type) } } + /** + * @param GatewayProvider $gateway + * @param StoredCredentialInitiator $value + * @return string|null + */ + public static function mapStoredCredentialInitiator($gateway, $value) + { + switch ($gateway) { + case GatewayProvider::GP_API: + switch ($value) { + case StoredCredentialInitiator::CARDHOLDER: + return strtoupper(StoredCredentialInitiator::PAYER); + case StoredCredentialInitiator::MERCHANT: + return strtoupper(StoredCredentialInitiator::MERCHANT); + default: + return null; + } + default: + return null; + } + } + + /** + * @param GatewayProvider $gateway + * @param EmvLastChipRead $value + * @return string|null + */ + public static function mapEmvLastChipRead($gateway, $value) + { + switch ($gateway) { + case GatewayProvider::GP_API: + switch ($value) { + case EmvLastChipRead::SUCCESSFUL: + return 'PREV_SUCCESS'; + case EmvLastChipRead::FAILED: + return 'PREV_FAILED'; + default: + return null; + } + default: + return null; + } + } } \ No newline at end of file diff --git a/src/Mapping/GpApiMapping.php b/src/Mapping/GpApiMapping.php index 2482a257..bb6deeed 100644 --- a/src/Mapping/GpApiMapping.php +++ b/src/Mapping/GpApiMapping.php @@ -64,8 +64,13 @@ public static function mapResponse($response) $card->masked_number_last4 : null; $transaction->cardType = !empty($card->brand) ? $card->brand : null; $transaction->cvnResponseCode = !empty($card->cvv) ? $card->cvv : null; + $transaction->cvnResponseMessage = !empty($card->cvv_result) ? $card->cvv_result : null; $transaction->cardBrandTransactionId = !empty($card->brand_reference) ? $card->brand_reference : null; + $transaction->avsResponseCode = !empty($card->avs_postal_code_result) ? + $card->avs_postal_code_result : null; + $transaction->avsAddressResponse = !empty($card->avs_address_result) ? $card->avs_address_result : null; + $transaction->avsResponseMessage = !empty($card->avs_action) ? $card->avs_action : null; } if (!empty($response->payment_method->bank_transfer)) { $bankTransfer = $response->payment_method->bank_transfer; diff --git a/src/PaymentMethods/Credit.php b/src/PaymentMethods/Credit.php index 1e903d4d..a8bf8256 100644 --- a/src/PaymentMethods/Credit.php +++ b/src/PaymentMethods/Credit.php @@ -5,6 +5,8 @@ use GlobalPayments\Api\Builders\AuthorizationBuilder; use GlobalPayments\Api\Builders\ManagementBuilder; use GlobalPayments\Api\Entities\Enums\DigitalWalletTokenFormat; +use GlobalPayments\Api\Entities\Enums\EntryMethod; +use GlobalPayments\Api\Entities\Enums\ManualEntryMethod; use GlobalPayments\Api\Entities\Enums\PaymentMethodUsageMode; use GlobalPayments\Api\Entities\ThreeDSecure; use GlobalPayments\Api\Entities\Enums\PaymentMethodType; @@ -81,6 +83,9 @@ abstract class Credit implements /** @var bool */ public $isFleet; + /** @var EntryMethod|ManualEntryMethod */ + public $entryMethod; + /** @return boolean */ /** diff --git a/src/PaymentMethods/CreditTrackData.php b/src/PaymentMethods/CreditTrackData.php index d72d79a4..8a12abbe 100644 --- a/src/PaymentMethods/CreditTrackData.php +++ b/src/PaymentMethods/CreditTrackData.php @@ -7,7 +7,6 @@ class CreditTrackData extends Credit implements ITrackData { - public $entryMethod; public $value; public $discretionaryData; public $expiry; diff --git a/src/PaymentMethods/DebitTrackData.php b/src/PaymentMethods/DebitTrackData.php index a2bc1833..49397684 100644 --- a/src/PaymentMethods/DebitTrackData.php +++ b/src/PaymentMethods/DebitTrackData.php @@ -30,11 +30,5 @@ public function setValue($value) $this->value = $value; CardUtils::parseTrackData($this); $this->cardType = CardUtils::getCardType($this->pan); - $this->isFleet = CardUtils::isFleet($this->cardType, $this->pan); - - if ($this->cardType == 'WexFleet' && $this->discretionaryData != null && - strlen($this->discretionaryData) >= 8) { - $this->purchaseDeviceSequenceNumber = substr($this->discretionaryData, 3, 8); - } } } diff --git a/src/PaymentMethods/EBT.php b/src/PaymentMethods/EBT.php index 27169ae0..15380e42 100644 --- a/src/PaymentMethods/EBT.php +++ b/src/PaymentMethods/EBT.php @@ -4,7 +4,9 @@ use GlobalPayments\Api\Builders\AuthorizationBuilder; use GlobalPayments\Api\Entities\Enums\EbtCardType; +use GlobalPayments\Api\Entities\Enums\EntryMethod; use GlobalPayments\Api\Entities\Enums\InquiryType; +use GlobalPayments\Api\Entities\Enums\ManualEntryMethod; use GlobalPayments\Api\Entities\Enums\PaymentMethodType; use GlobalPayments\Api\Entities\Enums\TransactionType; use GlobalPayments\Api\Entities\Exceptions\NotImplementedException; @@ -35,6 +37,9 @@ abstract class EBT implements */ public $ebtCardType; + /** @var EntryMethod|ManualEntryMethod */ + public $entryMethod; + /** * Adds value to the payment method * diff --git a/src/PaymentMethods/EBTTrackData.php b/src/PaymentMethods/EBTTrackData.php index 641b0fcd..d1e08b07 100644 --- a/src/PaymentMethods/EBTTrackData.php +++ b/src/PaymentMethods/EBTTrackData.php @@ -7,6 +7,7 @@ use GlobalPayments\Api\Entities\Enums\TrackNumber; use GlobalPayments\Api\PaymentMethods\Interfaces\IEncryptable; use GlobalPayments\Api\PaymentMethods\Interfaces\ITrackData; +use GlobalPayments\Api\Utils\CardUtils; class EBTTrackData extends EBT implements ITrackData, IEncryptable { @@ -18,8 +19,7 @@ class EBTTrackData extends EBT implements ITrackData, IEncryptable /** * @var EntryMethod $entryMethod */ - public $entryMethod; - public $value; + protected $value; public $expire; public $pan; public $purchaseDeviceSequenceNumber; @@ -27,4 +27,30 @@ class EBTTrackData extends EBT implements ITrackData, IEncryptable * @var TrackNumber $trackNumber */ public $trackNumber; + protected $trackData; + + public function __get($property) + { + if (property_exists($this, $property)) { + return $this->{$property}; + } + } + + public function __set($property, $value) + { + switch ($property) { + case 'value': + $this->{$property} = $value; + CardUtils::parseTrackData($this); + break; + case 'trackData': + if (is_null($this->value)) { + $this->value = $value; + CardUtils::parseTrackData($this); + } else { + $this->{$property} = $value; + } + break; + } + } } diff --git a/src/ServiceConfigs/Gateways/GpApiConfig.php b/src/ServiceConfigs/Gateways/GpApiConfig.php index 633071ea..98dd42a6 100644 --- a/src/ServiceConfigs/Gateways/GpApiConfig.php +++ b/src/ServiceConfigs/Gateways/GpApiConfig.php @@ -73,6 +73,9 @@ class GpApiConfig extends GatewayConfig */ public $gatewayProvider; + /** @var string */ + public $merchantId; + public function __construct() { $this->gatewayProvider = GatewayProvider::GP_API; diff --git a/src/Services/GpApiService.php b/src/Services/GpApiService.php index fccf4f84..d1c03c44 100644 --- a/src/Services/GpApiService.php +++ b/src/Services/GpApiService.php @@ -18,6 +18,10 @@ public static function generateTransactionKey(GpApiConfig $config) $gateway->serviceUrl = ($config->environment == Environment::PRODUCTION) ? ServiceEndpoints::GP_API_PRODUCTION : ServiceEndpoints::GP_API_TEST; } + $gateway->requestLogger = $config->requestLogger; + $gateway->webProxy = $config->webProxy; + $gateway->dynamicHeaders = $config->dynamicHeaders; + $data = $gateway->getAccessToken(); $accessTokenInfo = new AccessTokenInfo(); diff --git a/src/Utils/CardUtils.php b/src/Utils/CardUtils.php index a450bd64..96fe5388 100644 --- a/src/Utils/CardUtils.php +++ b/src/Utils/CardUtils.php @@ -6,22 +6,23 @@ use GlobalPayments\Api\Builders\ManagementBuilder; use GlobalPayments\Api\Entities\Enums\CvnPresenceIndicator; use GlobalPayments\Api\Entities\Enums\EmvLastChipRead; +use GlobalPayments\Api\Entities\Enums\GatewayProvider; use GlobalPayments\Api\Entities\Enums\PaymentMethodType; use GlobalPayments\Api\Entities\Enums\Target; use GlobalPayments\Api\Entities\Enums\TrackNumber; use GlobalPayments\Api\Entities\Enums\TransactionType; use GlobalPayments\Api\Entities\GpApi\DTO\Card; +use GlobalPayments\Api\Mapping\EnumMapping; use GlobalPayments\Api\PaymentMethods\Interfaces\ICardData; use GlobalPayments\Api\PaymentMethods\Interfaces\IPinProtected; use GlobalPayments\Api\PaymentMethods\Interfaces\ITrackData; -use Zend\Filter\Compress\Tar; class CardUtils { private static $trackOnePattern = "/%?[B0]?([\d]+)\\^[^\\^]+\\^([\\d]{4})([^?]+)?/"; - private static $trackTwoPattern = "/;([\d]+)=([\d]{4})([^?]+)?/"; + private static $trackTwoPattern = "/;?([\d]+)=([\d]{4})([^?]+)?/"; private static $fleetBinMap = [ 'Visa' => [ @@ -56,43 +57,48 @@ class CardUtils */ private static $cardTypes = [ 'Visa' => '/^4/', - 'MC' => '/^(5[1-5]|2[2-7])/', + 'MC' => '/^(?:5[1-5]|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)/', 'Amex' => '/^3[47]/', - 'DinersClub' => '/^3[0689]/', + 'DinersClub' => '/^3(?:0[0-5]|[68][0-9])/', 'EnRoute' => '/^2(014|149)/', - 'Discover' => '/^6([045]|22)/', - 'Jcb' => '/^35/', + 'Discover' => '/^6(?:011|5[0-9]{2})/', + 'Jcb' => '/^(?:2131|1800|35\d{3})/', 'Wex' => '/^(?:690046|707138)/', + 'Voyager' => '/^70888[5-9]/' ]; public static function parseTrackData($paymentMethod) { $trackData = $paymentMethod->value; preg_match(static::$trackTwoPattern, $trackData, $matches); - if (!empty($matches[1]) && !empty($matches[2]) && !empty($matches[3])) { + if (!empty($matches[1]) && !empty($matches[2])) { $pan = $matches[1]; $expiry = $matches[2]; - $discretionary = $matches[3]; + $discretionary = !empty($matches[3]) ? $matches[3] : null; if (!empty($discretionary)) { if (strlen($pan.$expiry.$discretionary) == 37 && substr(strtolower($discretionary), -1) == 'f') { $discretionary = substr($discretionary, 0, strlen($discretionary) - 1); } + + $paymentMethod->discretionaryData = $discretionary; } $paymentMethod->trackNumber = TrackNumber::TRACK_TWO; $paymentMethod->pan = $pan; $paymentMethod->expiry = $expiry; - $paymentMethod->discretionaryData = $discretionary; - $paymentMethod->trackData = sprintf("%s=%s%s?", $pan, $expiry, $discretionary); + $paymentMethod->trackData = $paymentMethod instanceof GiftCard ? + ltrim($pan, ';') : sprintf("%s=%s%s?", $pan, $expiry, $discretionary); } else { preg_match(static::$trackOnePattern, $trackData, $matches); - if (!empty($matches[1]) && !empty($matches[2]) && !empty($matches[3])) { + if (!empty($matches[1]) && !empty($matches[2])) { $paymentMethod->trackNumber = TrackNumber::TRACK_ONE; $paymentMethod->pan = $matches[1]; $paymentMethod->expiry = $matches[2]; - $paymentMethod->discretionaryData = $matches[3]; + if (!$paymentMethod instanceof GiftCard && !empty($matches[3])) { + $paymentMethod->discretionaryData = $matches[3]; + } $paymentMethod->trackData = str_replace('%', '', $matches[0]); } } @@ -113,20 +119,19 @@ public static function getCardType($number) $number ); - $type = 'Unknown'; + $rvalue = 'Unknown'; foreach (static::$cardTypes as $type => $regex) { if (1 === preg_match($regex, $number)) { - return $type; + $rvalue = $type; } } - - if ($type === "Unknown") { - if (static::isFleet($type, $number)) { - $type += "Fleet"; + if ($rvalue !== "Unknown") { + if (static::isFleet($rvalue, $number)) { + $rvalue .= "Fleet"; } } - return $type; + return $rvalue; } public static function isFleet($cardType, $pan) @@ -151,10 +156,11 @@ public static function isFleet($cardType, $pan) * Generate a card * * @param AuthorizationBuilder|ManagementBuilder $builder + * @param GatewayProvider $gatewayProvider * * @return Card */ - public static function generateCard($builder) + public static function generateCard($builder, $gatewayProvider) { $paymentMethod = $builder->paymentMethod; $transactionType = $builder->transactionType; @@ -163,7 +169,7 @@ public static function generateCard($builder) if ($paymentMethod instanceof ITrackData) { $card->track = $paymentMethod->value; if ($transactionType == TransactionType::SALE) { - if (empty($paymentMethod->value)) { + if (empty($card->track)) { $card->number = $paymentMethod->pan; if (!empty($paymentMethod->expiry)) { $card->expiry_month = substr($paymentMethod->expiry, 2, 2); @@ -171,7 +177,7 @@ public static function generateCard($builder) } } if (!empty($builder->emvChipCondition)) { - $card->chip_condition = EmvLastChipRead::$emvLastChipRead[$builder->emvChipCondition][Target::GP_API]; + $card->chip_condition = EnumMapping::mapEmvLastChipRead($gatewayProvider, $builder->emvChipCondition); } $card->funding = $funding; } @@ -188,7 +194,7 @@ public static function generateCard($builder) $card->funding = $funding; //we can't have tag and chip_condition in the same time in the request if (!empty($builder->emvLastChipRead) && empty($builder->tagData)) { - $card->chip_condition = EmvLastChipRead::$emvLastChipRead[$builder->emvLastChipRead][Target::GP_API]; + $card->chip_condition = EnumMapping::mapEmvLastChipRead($gatewayProvider, $builder->emvLastChipRead); } } diff --git a/src/Utils/EmvData.php b/src/Utils/EmvData.php new file mode 100644 index 00000000..2565083c --- /dev/null +++ b/src/Utils/EmvData.php @@ -0,0 +1,127 @@ + */ + private $tlvData = []; + /** @var array */ + private $removedTags = []; + /** @var boolean */ + private $standInStatus; + /** @var string */ + private $standInStatusReason; + + public function getTag($tagName) + { + if (isset($this->tlvData[$tagName])) { + return $this->tlvData[$tagName]; + } + + return null; + } + + public function getAcceptedTagData() + { + if (empty($this->tlvData)) { + return null; + } + $rvalue = ""; + /** @var TlvData $tag */ + foreach ($this->tlvData as $tag) { + $rvalue .= $tag->getFullValue(); + } + + return $rvalue; + } + + public function getAcceptedTags() + { + return $this->tlvData; + } + + public function getRemovedTags() + { + return $this->removedTags; + } + + public function getStandInStatus() + { + return $this->standInStatus; + } + + public function getStandInStatusReason() + { + return $this->standInStatusReason; + } + + public function setStandInStatus($value, $reason) + { + $this->standInStatus = $value; + $this->standInStatusReason = $reason; + } + + public function getCardSequenceNumber() + { + if (isset($this->tlvData["5F34"])) { + return $this->tlvData["5F34"]; + } + + return null; + } + + public function getSendBuffer() + { + return StringUtils::bytesFromHex($this->getAcceptedTagData()); + } + + /** + * @param string $tag + * @param string $length + * @param string $value + * @param string $description + */ + public function addTag($tag, $length, $value, $description = null) + { + $this->addTagData(new TlvData($tag, $length, $value, $description)); + } + + /** + * @param TlvData $tagData + */ + public function addTagData($tagData) + { + $this->tlvData[$tagData->getTag()] = $tagData; + } + + public function addRemovedTag($tag, $length, $value, $description = null) + { + $this->addRemovedTagData(new TlvData($tag, $length, $value, $description)); + } + + /** + * @param TlvData $tagData + */ + public function addRemovedTagData($tagData) + { + $this->removedTags[$tagData->getTag()] = $tagData; + } + + public function isContactlessMsd() + { + $entryMode = $this->getEntryMode(); + + return !is_null($entryMode) ? $entryMode == "91" : false; + } + + public function getEntryMode() + { + $posEntryMode = $this->getTag("9F39"); + if (!is_null($posEntryMode)) { + return $posEntryMode->getValue(); + } + + return null; + } +} \ No newline at end of file diff --git a/src/Utils/EmvUtils.php b/src/Utils/EmvUtils.php new file mode 100644 index 00000000..1224ad78 --- /dev/null +++ b/src/Utils/EmvUtils.php @@ -0,0 +1,266 @@ + "Track 2 Equivalent Data", + "5A" => "Application Primary Account Number (PAN)", + "99" => "Transaction PIN Data", + "5F20" => "Cardholder Name", + "5F24" => "Application Expiration Date", + "9F0B" => "Cardholder Name Extended", + "9F1F" => "Track 1 Discretionary Data", + "9F20" => "Track 2 Discretionary Data", + ]; + + public static $knownTags = [ + "4F" => "Application Dedicated File (ADF) Name", + "50" => "Application Label", + "6F" => "File Control Information (FCI) Template", + "71" => "Issuer Script Template 1", + "72" => "Issuer Script Template 2", + "82" => "Application Interchange Profile", + "84" => "Dedicated File (DF) Name", + "86" => "Issuer Script Command", + "87" => "Application Priority Indicator", + "88" => "Short File Identifier (SFI)", + "8A" => "Authorization Response Code (ARC)", + "8C" => "Card Rick Management Data Object List 1 (CDOL1)", + "8D" => "Card Rick Management Data Object List 2 (CDOL2)", + "8E" => "Cardholder Verification Method (CVM) List", + "8F" => "Certification Authority Public Key Index", + "90" => "Issuer Public Key Certificate", + "91" => "Issuer Authentication Data", + "92" => "Issuer Public Key Remainder", + "93" => "Signed Static Application Data", + "94" => "Application File Locator (AFL)", + "95" => "Terminal Verification Results (TVR)", + "97" => "Transaction Certification Data Object List (TDOL)", + "9A" => "Transaction Date", + "9B" => "Transaction Status Indicator", + "9C" => "Transaction Type", + "9D" => "Directory Definition File (DDF) Name", + "5F25" => "Application Effective Date", + "5F28" => "Issuer Country Code", + "5F2A" => "Transaction Currency Code", + "5F2D" => "Language Preference", + "5F30" => "Service Code", + "5F34" => "Application Primary Account Number (PAN) Sequence Number", + "5F36" => "Transaction Currency Exponent", + "9F01" => "Unknown", + "9F02" => "Amount, Authorized", + "9F03" => "Amount, Other", + "9F05" => "Application Discretionary Data", + "9F06" => "Application Identifier (AID)", + "9F07" => "Application Usage Control", + "9F08" => "Application Version Number", + "9F09" => "Application Version Number", + "9F0D" => "Issuer Action Code (IAC) - Default", + "9F0E" => "Issuer Action Code (IAC) - Denial", + "9F0F" => "Issuer Action Code (IAC) - Online", + "9F10" => "Issuer Application Data", + "9F11" => "Issuer Code Table Index", + "9F12" => "Application Preferred Name", + "9F13" => "Last Online Application Transaction Counter (ATC) Register", + "9F14" => "Lower Consecutive Offline Limit", + "9F16" => "Unknown", + "9F17" => "Personal Identification Number (PIN) Try Counter", + "9F1A" => "Terminal Country Code", + "9F1B" => "Terminal Floor Limit", + "9F1C" => "Unknown", + "9F1D" => "Terminal Risk Management Data", + "9F1E" => "Interface Device (IFD) Serial Number", + "9F21" => "Transaction Time", + "9F22" => "Certification Authority Public Key Modulus", + "9F23" => "Upper Consecutive Offline Limit", + "9F26" => "Application Cryptogram", + "9F27" => "Cryptogram Information Data", + "9F2D" => "Integrated Circuit Card (ICC) PIN Encipherment Public Key Certificate", + "9F2E" => "Integrated Circuit Card (ICC) PIN Encipherment Public Key Exponent", + "9F2F" => "Integrated Circuit Card (ICC) PIN Encipherment Public Key Remainder", + "9F32" => "Issuer Public Key Exponent", + "9F33" => "Terminal Capabilities", + "9F34" => "Cardholder Verification Method (CVM) Results", + "9F35" => "Terminal Type", + "9F36" => "Application Transaction Counter (ATC)", + "9F37" => "Unpredictable Number", + "9F38" => "Processing Options Data Object List (PDOL)", + "9F39" => "Point-Of-Service (POS) Entry Mode", + "9F3B" => "Application Reference Currency", + "9F3C" => "Transaction Reference Currency Code", + "9F3D" => "Transaction Reference Currency Conversion", + "9F40" => "Additional Terminal Capabilities", + "9F41" => "Transaction Sequence Counter", + "9F42" => "Application Currency Code", + "9F43" => "Application Reference Currency Exponent", + "9F44" => "Application Currency Exponent", + "9F46" => "Integrated Circuit Card (ICC) Public Key Certificate", + "9F47" => "Integrated Circuit Card (ICC) Public Key Exponent", + "9F48" => "Integrated Circuit Card (ICC) Public Key Remainder", + "9F49" => "Dynamic Data Authentication Data Object List (DDOL)", + "9F4A" => "Signed Data Authentication Tag List", + "9F4B" => "Signed Dynamic Application Data", + "9F4C" => "ICC Dynamic Number", + "9F4E" => "Unknown", + "9F5B" => "Issuer Script Results", + "9F6E" => "Form Factor Indicator/Third Party Data", + "9F7C" => "Customer Exclusive Data", + "FFC6" => "Terminal Action Code (TAC) Default", + "FFC7" => "Terminal Action Code (TAC) Denial", + "FFC8" => "Terminal Action Code (TAC) Online", + // WEX EMV + "42" => "Issuer Identification Number (IIN or BIN)", + "61" => "Directory entry Template", + "70" => "Record Template", + "73" => "Directory Discretionary Template", + "9F4D" => "Log Entry", + "9F4F" => "Transaction Log Format", + "9F52" => "Card Verification Results (CVR)", + "9F7E" => "Issuer Life Cycle Data", + "A5" => "FCI Proprietary Template", + "BF0C" => "FCI Issuer Discretionary Data", + "BF20" => "PRO 00", + "BF27" => "PRO 07", + "BF2E" => "PRO 14", + "C1" => "Application Control", + "C4" => "Default Contact Profile31", + "CA" => "Previous Transaction History", + "CB" => "CRM Country Code", + "CD" => "CRM Currency Code", + "D3" => "PDOL Related data Length", + "D8" => "CAFL", + "DF01" => "Proprietary Data Element n°1", + "DF02" => "Proprietary Data Element n°2", + "DF03" => "Proprietary Data Element n°3", + "DF04" => "Proprietary Data Element n°4", + "DF05" => "Proprietary Data Element n°5", + "DF06" => "Proprietary Data Element n°6", + "DF07" => "Proprietary Data Element n°7", + "DF08" => "Proprietary Data Element n°8", + "DF10" => "Profile Selection Table", + "DF11" => "Currency Conversion Code 1", + "DF12" => "Currency Conversion Code 2", + "DF13" => "COTN counter", + "DF14" => "COTA accumulator", + "DF15" => "CIAC – Denial", + "DF16" => "CIAC – Default", + "DF17" => "CIAC – Online", + "DF18" => "LCOTA limit ", + "DF19" => "UCOTA limit", + "DF1A" => "MTAL limit ", + "DF1B" => "LCOL limit", + "DF1C" => "Upper Consecutive Offline Limit (UCOL)", + "DF1D" => "IADOL", + "DF1E" => "Derivation key Index", + "DF30" => "Fuel Card usage bitmap [Prompting], ATC Limit", + "DF31" => "Encrypted PIN cryptography failure limit", + "DF32" => "Purchase Restrictions (WEX refers to this as Chip Offline Purchase Restriction), Failed MAC limit", + "DF33" => "Lifetime MAC Limit", + "DF34" => "Chip Offline Purchase Restrictions Amount for Fuel*, Session MAC Limit", + "DF35" => "Chip Offline Purchase Restrictions Amount for non-Fuel*", + "DF36" => "Relationship Codes*", + "DF37" => "3rd Party Reference Data Generation 2*", + "DF38" => "Loyalty ID*", + "DF39" => "Purchase Device Sequence Number (with the suffix)* ", + "DF40" => "DDOL Related Data Length", + "DF41" => "CCDOL2 Related Data Length", + "DF4D" => "Transaction Log Setting parameter31" + ]; + + public static $dataTypes = [ + "82" => "b", + "8E" => "b", + "95" => "b", + "9B" => "b", + "9F07" => "b", + "9F33" => "b", + "9F40" => "b", + "9F5B" => "b" + ]; + + /** + * @param $tagData + * @param false $verbose + * @return EmvData|null + */ + public static function parseTagData($tagData, $verbose = false) + { + if (empty($tagData)) { + return null; + } + $tagData = strtoupper($tagData); + $rvalue = new EmvData(); + + for ($i = 0; $i < strlen($tagData);) { + try { + $tagName = substr($tagData, $i, 2); + $i += 2; + if ((base_convert($tagName, 16, 10) & 0x1F) == 0x1F) { + $tagName .= substr($tagData, $i, 2); + $i += 2; + } + $lengthStr = substr($tagData,$i, 2); + $i += 2; + $length = base_convert($lengthStr,16,10); + if ($length > 127) { + $bytesLength = $length - 128; + $lengthStr = substr($tagData, $bytesLength * 2); + $i += $bytesLength * 2; + $length = base_convert($lengthStr, 16,10); + } + $length *= 2; + $value = substr($tagData, $i, $length); + $i += $length; + if (!array_key_exists($tagName, self::$blackList)) { + $approvedTag = new TlvData($tagName, $lengthStr, $value, self::$knownTags[$tagName]); + if ($tagName == "5F28" && $value !== "840") { + $rvalue->setStandInStatus(false, "Card is not domestically issued"); + } elseif ($tagName == "95") { + $valueBuffer = StringUtils::bytesFromHex($value); + $maskBuffer = StringUtils::bytesFromHex("FC50FC2000"); + for ($idx = 0; $idx < strlen($valueBuffer); $idx++) { + if (($valueBuffer[$idx] & $maskBuffer[$idx]) != 0x00) { + $rvalue->setStandInStatus(false, sprintf("Invalid TVR status in byte %s of tag 95", $idx + 1)); + } + } + } elseif ($tagName == "9B") { + $valueBuffer = StringUtils::bytesFromHex($value); + $maskBuffer = StringUtils::bytesFromHex("E800"); + for ($idx = 0; $idx < strlen($valueBuffer); $idx++) { + if (($valueBuffer[$idx] & $maskBuffer[$idx]) != $maskBuffer[$idx]) { + $rvalue->setStandInStatus(false, sprintf("Invalid TSI status in byte %s of tag 9B", $idx + 1)); + } + } + } + + $rvalue->addTagData($approvedTag); + } else { + $rvalue->addRemovedTag($tagName, $lengthStr, $value, self::$blackList[$tagName]); + } + } catch (\Exception $exc) {} + } + + if ($verbose) { + echo "Accepted Tags:" . PHP_EOL; + foreach (array_keys($rvalue->getAcceptedTags()) as $tagName) { + /** @var TlvData $tag */ + $tag = $rvalue->getTag($tagName); + $appendBinary = array_key_exists($tagName, self::$dataTypes); + echo sprintf("TAG: %s - %s", $tagName, $tag->getDescription()); + echo sprintf("%s: %s%s\r\n",$tag->getLength(), $tag->getValue(), $appendBinary ? sprintf(" [%s]", $tag->getBinaryValue()) : ""); + } + echo "Removed Tags:" . PHP_EOL; + $removedTags = $rvalue->getRemovedTags(); + foreach (array_keys($removedTags) as $tagName) { + /** @var TlvData $tag */ + $tag = $removedTags[$tagName]; + echo sprintf("TAG: %s - %s", $tagName, $tag->getDescription()); + echo sprintf('%s: %s\r\n',$tag->getLength(), $tag->getValue()); + } + } + + return $rvalue; + } +} \ No newline at end of file diff --git a/src/Utils/StringUtils.php b/src/Utils/StringUtils.php index 2a840f3f..b93be6ac 100644 --- a/src/Utils/StringUtils.php +++ b/src/Utils/StringUtils.php @@ -85,4 +85,14 @@ public static function validateToNumber($value) { return preg_replace("/[^0-9]/", "", $value); } + + /** + * @param string $hexString + * @return mixed + */ + public static function bytesFromHex($hexString) + { + return pack("H*" , strtolower($hexString)); + } + } diff --git a/src/Utils/TlvData.php b/src/Utils/TlvData.php new file mode 100644 index 00000000..9ab67081 --- /dev/null +++ b/src/Utils/TlvData.php @@ -0,0 +1,55 @@ +tag = $tag; + $this->length = $length; + $this->value = $value; + $this->description = $description; + } + + public function getTag() + { + return $this->tag; + } + + public function getValue() + { + return $this->value; + } + + public function getLength() + { + return $this->length; + } + + public function getDescription() + { + return $this->description; + } + + public function getBinaryValue() + { + $sb = ''; + $bytes = StringUtils::bytesFromHex($this->value); + foreach ($bytes as $byte) { + $sb .= substring(decbin($byte & 0xFF) + 0x100, 1); + } + + return $sb; + } + + public function getFullValue() + { + return sprintf("%s%s%s", $this->tag, $this->length, $this->value); + } +} \ No newline at end of file diff --git a/test/Data/GpApiAvsCheckTestCards.php b/test/Data/GpApiAvsCheckTestCards.php new file mode 100644 index 00000000..35987f95 --- /dev/null +++ b/test/Data/GpApiAvsCheckTestCards.php @@ -0,0 +1,35 @@ +transactionProcessingAccountName = "Transaction_Processing"; $config = new GpApiConfig(); $config->accessTokenInfo = $accessTokenInfo; + $config->channel = Channel::CardNotPresent; ServicesContainer::configureService($config); @@ -152,6 +154,7 @@ public function testUseInvalidAccessToken() $accessTokenInfo->transactionProcessingAccountName = "Transaction_Processing"; $config = new GpApiConfig(); $config->accessTokenInfo = $accessTokenInfo; + $config->channel = Channel::CardNotPresent; ServicesContainer::configureService($config); diff --git a/test/Integration/Gateways/GpApiConnector/Certifications/CapabilitiesCardPresentTest.php b/test/Integration/Gateways/GpApiConnector/Certifications/CapabilitiesCardPresentTest.php index 32c7fdae..4f15bf52 100644 --- a/test/Integration/Gateways/GpApiConnector/Certifications/CapabilitiesCardPresentTest.php +++ b/test/Integration/Gateways/GpApiConnector/Certifications/CapabilitiesCardPresentTest.php @@ -5,7 +5,7 @@ use GlobalPayments\Api\Entities\Enums\EmvLastChipRead; use GlobalPayments\Api\Entities\Enums\EntryMethod; use GlobalPayments\Api\Entities\Enums\Environment; -use GlobalPayments\Api\Entities\Enums\GpApi\Channels; +use GlobalPayments\Api\Entities\Enums\Channel; use GlobalPayments\Api\Entities\Enums\TransactionStatus; use GlobalPayments\Api\PaymentMethods\CreditCardData; use GlobalPayments\Api\PaymentMethods\DebitTrackData; @@ -34,7 +34,7 @@ public function setUpConfig() $config->appId = 'i872l4VgZRtSrykvSn8Lkah8RE1jihvT'; $config->appKey = '9pArW2uWoA8enxKc'; $config->environment = Environment::TEST; - $config->channel = Channels::CardPresent; + $config->channel = Channel::CardPresent; return $config; } diff --git a/test/Integration/Gateways/GpApiConnector/Certifications/GpApiSdkCertificationTest.php b/test/Integration/Gateways/GpApiConnector/Certifications/GpApiSdkCertificationTest.php index 05e737a6..9e1bcc19 100644 --- a/test/Integration/Gateways/GpApiConnector/Certifications/GpApiSdkCertificationTest.php +++ b/test/Integration/Gateways/GpApiConnector/Certifications/GpApiSdkCertificationTest.php @@ -6,7 +6,7 @@ use GlobalPayments\Api\Entities\Enums\CvnPresenceIndicator; use GlobalPayments\Api\Entities\Enums\Environment; -use GlobalPayments\Api\Entities\Enums\GpApi\Channels; +use GlobalPayments\Api\Entities\Enums\Channel; use GlobalPayments\Api\Entities\Enums\TransactionStatus; use GlobalPayments\Api\PaymentMethods\CreditCardData; use GlobalPayments\Api\ServiceConfigs\Gateways\GpApiConfig; @@ -39,7 +39,7 @@ public function setUpConfig() $config->appId = 'i872l4VgZRtSrykvSn8Lkah8RE1jihvT'; $config->appKey = '9pArW2uWoA8enxKc'; $config->environment = Environment::TEST; - $config->channel = Channels::CardNotPresent; + $config->channel = Channel::CardNotPresent; return $config; } diff --git a/test/Integration/Gateways/GpApiConnector/CreditCardNotPresentTest.php b/test/Integration/Gateways/GpApiConnector/CreditCardNotPresentTest.php index 65843e0a..31239c87 100644 --- a/test/Integration/Gateways/GpApiConnector/CreditCardNotPresentTest.php +++ b/test/Integration/Gateways/GpApiConnector/CreditCardNotPresentTest.php @@ -6,7 +6,8 @@ use GlobalPayments\Api\Builders\ManagementBuilder; use GlobalPayments\Api\Entities\Address; use GlobalPayments\Api\Entities\Enums\Environment; -use GlobalPayments\Api\Entities\Enums\GpApi\Channels; +use GlobalPayments\Api\Entities\Enums\ManualEntryMethod; +use GlobalPayments\Api\Entities\Enums\Channel; use GlobalPayments\Api\Entities\Enums\PaymentMethodUsageMode; use GlobalPayments\Api\Entities\Enums\StoredCredentialInitiator; use GlobalPayments\Api\Entities\Enums\StoredCredentialReason; @@ -21,6 +22,7 @@ use GlobalPayments\Api\PaymentMethods\CreditCardData; use GlobalPayments\Api\ServiceConfigs\Gateways\GpApiConfig; use GlobalPayments\Api\ServicesContainer; +use GlobalPayments\Api\Tests\Data\GpApiAvsCheckTestCards; use GlobalPayments\Api\Utils\GenerationUtils; use GlobalPayments\Api\Utils\Logging\Logger; use GlobalPayments\Api\Utils\Logging\SampleRequestLogger; @@ -85,15 +87,11 @@ public function testCreditAuthorization() public function testAuthorizationThenCapture() { - try { - $transaction = $this->card->authorize(42) - ->withCurrency($this->currency) - ->withOrderId('123456-78910') - ->withAllowDuplicates(true) - ->execute(); - } catch (ApiException $e) { - $this->fail("Card Authorization Failed"); - } + $transaction = $this->card->authorize(42) + ->withCurrency($this->currency) + ->withOrderId('123456-78910') + ->withAllowDuplicates(true) + ->execute(); $this->assertNotNull($transaction); $this->assertEquals('SUCCESS', $transaction->responseCode); @@ -209,14 +207,14 @@ public function testCreditRefund_WithIdempotencyKey() $this->assertContains('Idempotency Key seen before', $e->getMessage()); } } - + public function testCreditSale_WithoutPermissions() { $config = new GpApiConfig(); $config->appId = 'i872l4VgZRtSrykvSn8Lkah8RE1jihvT'; $config->appKey = '9pArW2uWoA8enxKc'; $config->environment = Environment::TEST; - $config->channel = Channels::CardNotPresent; + $config->channel = Channel::CardNotPresent; $config->country = 'GB'; $config->permissions = ["TRN_POST_Capture"]; @@ -257,8 +255,6 @@ public function testTransactionThenRefund() ->withCurrency($this->currency) ->execute(); - - $this->assertNotNull($partialRefund); $this->assertEquals('SUCCESS', $partialRefund->responseCode); $this->assertEquals(TransactionStatus::CAPTURED, $partialRefund->responseMessage); @@ -632,6 +628,7 @@ public function testCreditVerifyWithIdempotencyKey() public function testCardTokenizationThenDeletion() { + $this->markTestSkipped('Permission not enabled to execute action for this appId/appKey'); // process an auto-capture authorization $response = $this->card->tokenize() ->execute(); @@ -649,6 +646,7 @@ public function testCardTokenizationThenDeletion() public function testCardTokenizationThenDeletion_WithIdempotencyKey() { + $this->markTestSkipped(' Permission not enabled to execute action for this appId/appKey'); // process an auto-capture authorization $response = $this->card->tokenize() ->execute(); @@ -665,7 +663,7 @@ public function testCardTokenizationThenDeletion_WithIdempotencyKey() $this->assertEquals('DELETED', $response->responseMessage); try { - $tokenizedCard = (new ManagementBuilder(TransactionType::TOKEN_DELETE)) + (new ManagementBuilder(TransactionType::TOKEN_DELETE)) ->withPaymentMethod($tokenizedCard) ->withIdempotencyKey($this->idempotencyKey) ->execute(); @@ -751,7 +749,7 @@ public function testCardTokenizationThenUpdateWithIdempotencyKey() $this->assertEquals('ACTIVE', $response->responseMessage); try { - $response = (new ManagementBuilder(TransactionType::TOKEN_UPDATE)) + (new ManagementBuilder(TransactionType::TOKEN_UPDATE)) ->withPaymentMethod($tokenizedCard) ->withIdempotencyKey($this->idempotencyKey) ->execute(); @@ -994,7 +992,7 @@ public function testCaptureHigherAmount() $this->assertEquals(TransactionStatus::PREAUTHORIZED, $transaction->responseMessage); try { - $capture = $transaction->capture('40') + $transaction->capture('40') ->execute(); } catch (GatewayException $e) { $this->assertEquals('50020', $e->responseCode); @@ -1040,13 +1038,13 @@ public function testChargeThenRefundHigherAmount() $this->assertEquals(TransactionStatus::CAPTURED, $transaction->responseMessage); try { - $response = $transaction->refund(60) + $transaction->refund(60) ->withCurrency($this->currency) ->withAllowDuplicates(true) ->execute(); } catch (GatewayException $e) { $this->assertEquals('40087', $e->responseCode); - $this->assertContains("INVALID_REQUEST_DATA - You may only refund up to 100% of the original amount", $e->getMessage()); + $this->assertContains("INVALID_REQUEST_DATA - You may only refund up to 115% of the original amount", $e->getMessage()); } } @@ -1083,6 +1081,94 @@ public function testCaptureThenRefundHigherAmount() $this->assertEquals(TransactionStatus::CAPTURED, $capture->responseMessage); } } + public function testManualTransactions() + { + $entryModes = [ManualEntryMethod::MOTO, ManualEntryMethod::MAIL, ManualEntryMethod::PHONE]; + foreach ($entryModes as $entryMode) { + $this->card->entryMethod = $entryMode; + + $response = $this->card->charge(69) + ->withCurrency($this->currency) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('SUCCESS', $response->responseCode); + $this->assertEquals(TransactionStatus::CAPTURED, $response->responseMessage); + } + } + + /** + * Avs test cards scenario + * + * @dataProvider AvsCardTests + * @param $cardNumber + * @param $cvnResponseMessage + * @param $avsResponseCode + * @param $avsAddressResponse + * @param $status + * @param $transactionStatus + */ + public function testCreditSale_CVVResult($cardNumber, $cvnResponseMessage, $avsResponseCode, $avsAddressResponse, $status, $transactionStatus) + { + $address = new Address(); + $address->streetAddress1 = "123 Main St."; + $address->city = "Downtown"; + $address->state = "NJ"; + $address->country = "US"; + $address->postalCode = "12345"; + + $this->card->number = $cardNumber; + + $response = $this->card->charge(5) + ->withCurrency($this->currency) + ->withAddress($address) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals($status, $response->responseCode); + $this->assertEquals($transactionStatus, $response->responseMessage); + $this->assertEquals($cvnResponseMessage, $response->cvnResponseMessage); + $this->assertEquals($avsResponseCode, $response->avsResponseCode); + $this->assertEquals($avsAddressResponse, $response->avsAddressResponse); + } + + /** + * AVS test cards + * + */ + public function AvsCardTests() + { + return [ + [GpApiAvsCheckTestCards::AVS_MASTERCARD_1, "MATCHED", "NOT_CHECKED", "NOT_CHECKED", 'SUCCESS', TransactionStatus::CAPTURED], + [GpApiAvsCheckTestCards::AVS_MASTERCARD_2, "MATCHED", "NOT_CHECKED", "NOT_CHECKED", 'SUCCESS', TransactionStatus::CAPTURED], + [GpApiAvsCheckTestCards::AVS_MASTERCARD_3, "MATCHED", "NOT_CHECKED", "NOT_CHECKED", 'SUCCESS', TransactionStatus::CAPTURED], + [GpApiAvsCheckTestCards::AVS_MASTERCARD_4, "MATCHED", "MATCHED", "MATCHED", 'SUCCESS', TransactionStatus::CAPTURED], + [GpApiAvsCheckTestCards::AVS_MASTERCARD_5, "MATCHED", "MATCHED", "NOT_MATCHED", 'SUCCESS', TransactionStatus::CAPTURED], + [GpApiAvsCheckTestCards::AVS_MASTERCARD_6, "MATCHED", "NOT_MATCHED", "MATCHED", 'SUCCESS', TransactionStatus::CAPTURED], + [GpApiAvsCheckTestCards::AVS_MASTERCARD_7, "MATCHED", "NOT_MATCHED", "NOT_MATCHED", 'SUCCESS', TransactionStatus::CAPTURED], + [GpApiAvsCheckTestCards::AVS_MASTERCARD_8, "NOT_MATCHED", "NOT_MATCHED", "MATCHED", 'SUCCESS', TransactionStatus::CAPTURED], + [GpApiAvsCheckTestCards::AVS_MASTERCARD_9, "NOT_MATCHED", "NOT_CHECKED", "NOT_CHECKED", 'SUCCESS', TransactionStatus::CAPTURED], + [GpApiAvsCheckTestCards::AVS_MASTERCARD_10, "NOT_MATCHED", "NOT_CHECKED", "NOT_CHECKED", 'SUCCESS', TransactionStatus::CAPTURED], + [GpApiAvsCheckTestCards::AVS_MASTERCARD_11, "NOT_MATCHED", "NOT_CHECKED", "NOT_CHECKED", 'SUCCESS', TransactionStatus::CAPTURED], + [GpApiAvsCheckTestCards::AVS_MASTERCARD_12, "NOT_MATCHED", "MATCHED", "MATCHED", 'SUCCESS', TransactionStatus::CAPTURED], + [GpApiAvsCheckTestCards::AVS_MASTERCARD_13, "NOT_MATCHED", "MATCHED", "NOT_MATCHED", 'SUCCESS', TransactionStatus::CAPTURED], + [GpApiAvsCheckTestCards::AVS_MASTERCARD_14, "NOT_MATCHED", "NOT_MATCHED", "NOT_MATCHED", 'SUCCESS', TransactionStatus::CAPTURED], + [GpApiAvsCheckTestCards::AVS_VISA_1, "NOT_CHECKED", "NOT_CHECKED", "NOT_CHECKED", 'DECLINED', TransactionStatus::DECLINED], + [GpApiAvsCheckTestCards::AVS_VISA_2, "NOT_CHECKED", "NOT_CHECKED", "NOT_CHECKED", 'DECLINED', TransactionStatus::DECLINED], + [GpApiAvsCheckTestCards::AVS_VISA_3, "NOT_CHECKED", "NOT_CHECKED", "NOT_CHECKED", 'DECLINED', TransactionStatus::DECLINED], + [GpApiAvsCheckTestCards::AVS_VISA_4, "NOT_CHECKED", "MATCHED", "MATCHED", 'DECLINED', TransactionStatus::DECLINED], + [GpApiAvsCheckTestCards::AVS_VISA_5, "NOT_CHECKED", "MATCHED", "NOT_MATCHED", 'DECLINED', TransactionStatus::DECLINED], + [GpApiAvsCheckTestCards::AVS_VISA_6, "NOT_CHECKED", "NOT_MATCHED", "MATCHED", 'DECLINED', TransactionStatus::DECLINED], + [GpApiAvsCheckTestCards::AVS_VISA_7, "NOT_CHECKED", "NOT_MATCHED", "NOT_MATCHED", 'DECLINED', TransactionStatus::DECLINED], + [GpApiAvsCheckTestCards::AVS_VISA_8, "NOT_CHECKED", "NOT_CHECKED", "NOT_CHECKED", 'DECLINED', TransactionStatus::DECLINED], + [GpApiAvsCheckTestCards::AVS_VISA_9, "NOT_CHECKED", "NOT_CHECKED", "NOT_CHECKED", 'DECLINED', TransactionStatus::DECLINED], + [GpApiAvsCheckTestCards::AVS_VISA_10, "NOT_CHECKED", "NOT_CHECKED", "NOT_CHECKED", 'DECLINED', TransactionStatus::DECLINED], + [GpApiAvsCheckTestCards::AVS_VISA_11, "NOT_CHECKED", "MATCHED", "MATCHED", 'DECLINED', TransactionStatus::DECLINED], + [GpApiAvsCheckTestCards::AVS_VISA_12, "NOT_CHECKED", "MATCHED", "NOT_MATCHED", 'DECLINED', TransactionStatus::DECLINED], + [GpApiAvsCheckTestCards::AVS_VISA_13, "NOT_CHECKED", "NOT_MATCHED", "MATCHED", 'DECLINED', TransactionStatus::DECLINED], + [GpApiAvsCheckTestCards::AVS_VISA_14, "NOT_CHECKED", "NOT_MATCHED", "NOT_MATCHED", 'DECLINED', TransactionStatus::DECLINED] + ]; + } public function setUpConfig() { @@ -1090,7 +1176,7 @@ public function setUpConfig() $config->appId = 'oDVjAddrXt3qPJVPqQvrmgqM2MjMoHQS'; $config->appKey = 'DHUGdzpjXfTbjZeo'; $config->environment = Environment::TEST; - $config->channel = Channels::CardNotPresent; + $config->channel = Channel::CardNotPresent; $config->country = 'GB'; //DO NO DELETE - usage example for some settings // $config->dynamicHeaders = [ diff --git a/test/Integration/Gateways/GpApiConnector/CreditCardPresentTest.php b/test/Integration/Gateways/GpApiConnector/CreditCardPresentTest.php index a743c040..9adc876b 100644 --- a/test/Integration/Gateways/GpApiConnector/CreditCardPresentTest.php +++ b/test/Integration/Gateways/GpApiConnector/CreditCardPresentTest.php @@ -5,9 +5,9 @@ use GlobalPayments\Api\Entities\Enums\EmvLastChipRead; use GlobalPayments\Api\Entities\Enums\EntryMethod; use GlobalPayments\Api\Entities\Enums\Environment; -use GlobalPayments\Api\Entities\Enums\GpApi\Channels; -use GlobalPayments\Api\Entities\Enums\GpApi\SortDirection; -use GlobalPayments\Api\Entities\Enums\GpApi\TransactionSortProperty; +use GlobalPayments\Api\Entities\Enums\Channel; +use GlobalPayments\Api\Entities\Enums\SortDirection; +use GlobalPayments\Api\Entities\Enums\TransactionSortProperty; use GlobalPayments\Api\Entities\Enums\TransactionStatus; use GlobalPayments\Api\Entities\Exceptions\GatewayException; use GlobalPayments\Api\Entities\Reporting\SearchCriteria; @@ -16,14 +16,18 @@ use GlobalPayments\Api\PaymentMethods\CreditCardData; use GlobalPayments\Api\PaymentMethods\CreditTrackData; use GlobalPayments\Api\ServiceConfigs\Gateways\GpApiConfig; -use GlobalPayments\Api\Services\BatchService; use GlobalPayments\Api\Services\ReportingService; use GlobalPayments\Api\ServicesContainer; use GlobalPayments\Api\Utils\GenerationUtils; use PHPUnit\Framework\TestCase; +use GlobalPayments\Api\Utils\Logging\Logger; +use GlobalPayments\Api\Utils\Logging\SampleRequestLogger; class CreditCardPresentTest extends TestCase { + private $currency = 'USD'; + private $amount = 15.11; + public function setup() { ServicesContainer::configureService($this->setUpConfig()); @@ -35,480 +39,118 @@ public function setUpConfig() $config->appId = 'oDVjAddrXt3qPJVPqQvrmgqM2MjMoHQS'; $config->appKey = 'DHUGdzpjXfTbjZeo'; $config->environment = Environment::TEST; - $config->channel = Channels::CardPresent; + $config->channel = Channel::CardPresent; +// $config->requestLogger = new SampleRequestLogger(new Logger("logs")); return $config; } public function testCardPresentWithChipTransaction() { - $card = new CreditTrackData(); - $card->setTrackData('%B4012002000060016^VI TEST CREDIT^251210118039000000000396?;4012002000060016=25121011803939600000?'); - $card->entryMethod = EntryMethod::SWIPE; + $card = $this->initCreditTrackData(); - $response = $card->charge(19) - ->withCurrency("EUR") + $response = $card->charge($this->amount) + ->withCurrency($this->currency) ->withChipCondition(EmvLastChipRead::SUCCESSFUL) ->withAllowDuplicates(true) ->execute(); - $this->assertEquals('SUCCESS', $response->responseCode); + $this->assertTransactionResponse($response, 'SUCCESS', TransactionStatus::CAPTURED); } public function testCardPresentWithSwipeTransaction() { - $card = new CreditTrackData(); - $card->setTrackData('%B4012002000060016^VI TEST CREDIT^251210118039000000000396?;4012002000060016=25121011803939600000?'); - $card->entryMethod = EntryMethod::SWIPE; + $card = $this->initCreditTrackData(); - $response = $card->authorize(16) - ->withCurrency("EUR") + $response = $card->authorize($this->amount) + ->withCurrency($this->currency) ->withOrderId("124214-214221") ->withAllowDuplicates(true) ->execute(); - $this->assertEquals('SUCCESS', $response->responseCode); + $this->assertTransactionResponse($response, 'SUCCESS', TransactionStatus::PREAUTHORIZED); } public function testRefundOnCardPresentChipCard() { - $card = new CreditTrackData(); - $card->setTrackData('%B4012002000060016^VI TEST CREDIT^251210118039000000000396?;4012002000060016=25121011803939600000?'); + $card = $this->initCreditTrackData(); $tag = '9F4005F000F0A0019F02060000000025009F03060000000000009F2608D90A06501B48564E82027C005F3401019F360200029F0702FF009F0802008C9F0902008C9F34030403029F2701809F0D05F0400088009F0E0508000000009F0F05F0400098005F280208409F390105FFC605DC4000A800FFC7050010000000FFC805DC4004F8009F3303E0B8C89F1A0208409F350122950500000080005F2A0208409A031409109B02E8009F21030811539C01009F37045EED3A8E4F07A00000000310109F0607A00000000310108407A00000000310109F100706010A03A400029F410400000001'; - $response = $card->refund(19) - ->withCurrency("EUR") + $response = $card->refund($this->amount) + ->withCurrency($this->currency) ->withOrderId("124214-214221") ->withTagData($tag) ->execute(); - $this->assertEquals('SUCCESS', $response->responseCode); + $this->assertTransactionResponse($response, 'SUCCESS', TransactionStatus::CAPTURED); } public function testCreditVerification_CardPresent() { - $card = new CreditTrackData(); - $card->setTrackData('%B4012002000060016^VI TEST CREDIT^251210118039000000000396?;4012002000060016=25121011803939600000?'); - $card->entryMethod = EntryMethod::SWIPE; + $card = $this->initCreditTrackData(); $response = $card->verify() - ->withCurrency("USD") + ->withCurrency($this->currency) ->execute(); - $this->assertNotNull($response); - $this->assertEquals('SUCCESS', $response->responseCode); - $this->assertEquals("VERIFIED", $response->responseMessage); + $this->assertTransactionResponse($response, 'SUCCESS', 'VERIFIED'); } public function testCreditVerification_CardPresent_CVNNotMatched() { - $card = new CreditCardData(); - $card->number = "4263970000005262"; - $card->expMonth = date('m'); - $card->expYear = date('Y', strtotime('+1 year')); - $card->cvn = "852"; - $card->cardHolderName = "James Mason"; + $card = $this->initCreditCardData(); + $card->number = "30450000000985"; $response = $card->verify() - ->withCurrency("USD") - ->execute(); - - $this->assertNotNull($response); - $this->assertEquals('NOT_VERIFIED', $response->responseCode); - $this->assertEquals("NOT_VERIFIED", $response->responseMessage); - } - - public function testAuthorizationCaptureBatchClose() - { - $card = new CreditCardData(); - $card->number = "5425230000004415"; - $card->expMonth = date('m'); - $card->expYear = date('Y', strtotime('+1 year')); - $card->cvn = "852"; - $card->cardHolderName = "James Mason"; - - $transaction = $card->authorize(2.11) - ->withCurrency('USD') - ->execute(); - - $this->assertTransactionResponse($transaction, TransactionStatus::PREAUTHORIZED); - - $capture = $transaction->capture(2.11) - ->execute(); - - $this->assertTransactionResponse($capture, TransactionStatus::CAPTURED); - $this->assertNotEmpty($capture->batchSummary->batchReference); - - $batch = BatchService::closeBatch($capture->batchSummary->batchReference); - $this->assertBatchCloseResponse($batch, 2.11); - } - - public function testBatchClose() - { - $card = new CreditTrackData(); - $card->setTrackData('%B4012002000060016^VI TEST CREDIT^251210118039000000000396?;4012002000060016=25121011803939600000?'); - $card->entryMethod = EntryMethod::SWIPE; - - $transaction = $card->charge(2.11) - ->withCurrency('USD') - ->execute(); - $this->assertTransactionResponse($transaction, TransactionStatus::CAPTURED); - - sleep(2); - - $batch = BatchService::closeBatch($transaction->batchSummary->batchReference); - $this->assertBatchCloseResponse($batch, 2.11); - } - - public function testBatchClose_ChipTransaction() - { - $tag = '9F4005F000F0A0019F02060000000025009F03060000000000009F2608D90A06501B48564E82027C005F3401019F360200029F0702FF009F0802008C9F0902008C9F34030403029F2701809F0D05F0400088009F0E0508000000009F0F05F0400098005F280208409F390105FFC605DC4000A800FFC7050010000000FFC805DC4004F8009F3303E0B8C89F1A0208409F350122950500000080005F2A0208409A031409109B02E8009F21030811539C01009F37045EED3A8E4F07A00000000310109F0607A00000000310108407A00000000310109F100706010A03A400029F410400000001'; - - $card = new CreditTrackData(); - $card->setTrackData('%B4012002000060016^VI TEST CREDIT^251210118039000000000396?;4012002000060016=25121011803939600000?'); - $card->entryMethod = EntryMethod::SWIPE; - - $transaction = $card->charge(2.11) - ->withCurrency('USD') - ->withTagData($tag) - ->execute(); - $this->assertTransactionResponse($transaction, TransactionStatus::CAPTURED); - - sleep(1); - - $batch = BatchService::closeBatch($transaction->batchSummary->batchReference); - $this->assertBatchCloseResponse($batch, 2.11); - } - - public function testBatchClose_MultipleChargeCreditTrackData() - { - $card = new CreditTrackData(); - $card->setTrackData('%B4012002000060016^VI TEST CREDIT^251210118039000000000396?;4012002000060016=25121011803939600000?'); - $card->entryMethod = EntryMethod::SWIPE; - - $transaction = $card->charge(2.11) - ->withCurrency('USD') - ->execute(); - $this->assertTransactionResponse($transaction, TransactionStatus::CAPTURED); - - $transaction = $card->charge(2.11) - ->withCurrency('USD') - ->execute(); - $this->assertTransactionResponse($transaction, TransactionStatus::CAPTURED); - - sleep(2); - - $batch = BatchService::closeBatch($transaction->batchSummary->batchReference); - $this->assertBatchCloseResponse($batch, 4.22); - } - - public function testBatchClose_Refund_CreditTrackData() - { - $card = new CreditTrackData(); - $card->setTrackData('%B4012002000060016^VI TEST CREDIT^251210118039000000000396?;4012002000060016=25121011803939600000?'); - $card->entryMethod = EntryMethod::SWIPE; - - $transaction = $card->charge(2.11) - ->withCurrency('USD') - ->execute(); - $this->assertTransactionResponse($transaction, TransactionStatus::CAPTURED); - - $transaction = $transaction->refund() - ->withCurrency('USD') - ->execute(); - $this->assertTransactionResponse($transaction, TransactionStatus::CAPTURED); - - $batch = BatchService::closeBatch($transaction->batchSummary->batchReference); - $this->assertBatchCloseResponse($batch, 0); - } - - public function testBatchClose_Reverse_CreditCardData() - { - $card = new CreditCardData(); - $card->number = "4263970000005262"; - $card->expMonth = date('m'); - $card->expYear = date('Y', strtotime('+1 year')); - $card->cvn = "123"; - $card->cardHolderName = "James Mason"; - - $transaction = $card->authorize(2.11) - ->withCurrency('USD') - ->execute(); - $this->assertTransactionResponse($transaction, TransactionStatus::PREAUTHORIZED); - - $transaction = $transaction->reverse() - ->withCurrency('USD') - ->execute(); - $this->assertTransactionResponse($transaction, TransactionStatus::REVERSED); - - sleep(1); - - $exceptionCaught = false; - try { - BatchService::closeBatch($transaction->batchSummary->batchReference); - } catch (GatewayException $e) { - $exceptionCaught = true; - $this->assertEquals('40223', $e->responseCode); - $this->assertEquals('Status Code: MANDATORY_DATA_MISSING - Request expects the batch_id', $e->getMessage()); - } finally { - $this->assertTrue($exceptionCaught); - } - } - - public function testBatchClose_WithIdempotency() - { - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - - $idempotencyKey = GenerationUtils::getGuid(); - $card = new CreditTrackData(); - $card->setTrackData('%B4012002000060016^VI TEST CREDIT^251210118039000000000396?;4012002000060016=25121011803939600000?'); - $card->entryMethod = EntryMethod::SWIPE; - - $transaction = $card->charge(2.11) - ->withCurrency('USD') - ->execute(); - - $this->assertTransactionResponse($transaction, TransactionStatus::CAPTURED); - - $batch = BatchService::closeBatch($transaction->batchSummary->batchReference); - //TODO - set idempotency key - - $this->assertBatchCloseResponse($batch, 2.11); - - $exceptionCaught = false; - try { - BatchService::closeBatch($transaction->batchSummary->batchReference); - //TODO - set idempotency key - } catch (GatewayException $e) { - $exceptionCaught = true; - $this->assertEquals('40039', $e->responseCode); - $this->assertContains('Status Code: DUPLICATE_ACTION - Idempotency Key seen before: ', $e->getMessage()); - } finally { - $this->assertTrue($exceptionCaught); - } - } - - public function testBatchClose_WithCardNumberDetails() - { - $card = new CreditCardData(); - $card->number = "4263970000005262"; - $card->expMonth = date('m'); - $card->expYear = date('Y', strtotime('+1 year')); - $card->cvn = "123"; - $card->cardHolderName = "James Mason"; - - $transaction = $card->charge(3.2) - ->withCurrency('USD') - ->execute(); - $this->assertTransactionResponse($transaction, TransactionStatus::CAPTURED); - - sleep(2); - - $batch = BatchService::closeBatch($transaction->batchSummary->batchReference); - $this->assertBatchCloseResponse($batch, 3.2); - } - - public function testBatchClose_WithCardNumberDetails_DeclinedTransaction() - { - $card = new CreditCardData(); - $card->number = "4263970000005262"; - $card->expMonth = date('m'); - $card->expYear = date('Y', strtotime('+1 year')); - $card->cvn = "800"; - $card->cardHolderName = "James Mason"; - - $transaction = $card->charge(3.2) - ->withCurrency('USD') + ->withCurrency($this->currency) ->execute(); - $this->assertNotNull($transaction); - $this->assertEquals('DECLINED', $transaction->responseCode); - $this->assertEquals(TransactionStatus::DECLINED, $transaction->responseMessage); - - sleep(2); - - $exceptionCaught = false; - try { - BatchService::closeBatch($transaction->batchSummary->batchReference); - } catch (GatewayException $e) { - $exceptionCaught = true; - $this->assertEquals('40212', $e->responseCode); - $this->assertEquals('Status Code: INVALID_BATCH_ACTION - 9,No transaction associated with batch', $e->getMessage()); - } finally { - $this->assertTrue($exceptionCaught); - } + $this->assertTransactionResponse($response, 'NOT_VERIFIED', 'NOT_VERIFIED'); } - public function testBatchClose_WithClosedBatchReference() + public function testReauthAReversedSale() { - $card = new CreditTrackData(); - $card->setTrackData('%B4012002000060016^VI TEST CREDIT^251210118039000000000396?;4012002000060016=25121011803939600000?'); - $card->entryMethod = EntryMethod::SWIPE; + $card = $this->initCreditCardData(); - $transaction = $card->charge(2.11) - ->withCurrency('USD') + $transaction = $card->charge($this->amount) + ->withCurrency($this->currency) + ->withAllowDuplicates(true) ->execute(); - $this->assertTransactionResponse($transaction, TransactionStatus::CAPTURED); - - $batch = BatchService::closeBatch($transaction->batchSummary->batchReference); - $this->assertBatchCloseResponse($batch, 2.11); - - $exceptionCaught = false; - try { - BatchService::closeBatch($transaction->batchSummary->batchReference); - } catch (GatewayException $e) { - $exceptionCaught = true; - $this->assertEquals('40014', $e->responseCode); - $this->assertEquals('Status Code: INVALID_BATCH_ACTION - 5,No current batch', $e->getMessage()); - } finally { - $this->assertTrue($exceptionCaught); - } - } - public function testBatchClose_Verify_MissingBatchId() - { - $card = new CreditTrackData(); - $card->setTrackData('%B4012002000060016^VI TEST CREDIT^251210118039000000000396?;4012002000060016=25121011803939600000?'); - $card->entryMethod = EntryMethod::SWIPE; + $this->assertTransactionResponse($transaction, 'SUCCESS', TransactionStatus::CAPTURED); - $transaction = $card->verify() - ->withCurrency('USD') + $reverse = $transaction->reverse() ->execute(); - $this->assertNotNull($transaction); - $this->assertEquals('SUCCESS', $transaction->responseCode); - $this->assertEquals('VERIFIED', $transaction->responseMessage); - - sleep(1); - - $exceptionCaught = false; - try { - BatchService::closeBatch($transaction->batchSummary->batchReference); - } catch (GatewayException $e) { - $exceptionCaught = true; - $this->assertEquals('40223', $e->responseCode); - $this->assertEquals('Status Code: MANDATORY_DATA_MISSING - Request expects the batch_id', $e->getMessage()); - } finally { - $this->assertTrue($exceptionCaught); - } - } - - public function testBatchClose_CardNotPresentChannel() - { - $config = new GpApiConfig(); - $config->appId = 'i872l4VgZRtSrykvSn8Lkah8RE1jihvT'; - $config->appKey = '9pArW2uWoA8enxKc'; - $config->environment = Environment::TEST; - $config->channel = Channels::CardNotPresent; - - ServicesContainer::configureService($config); + $this->assertTransactionResponse($reverse, 'SUCCESS', TransactionStatus::REVERSED); - $card = new CreditCardData(); - $card->number = "4263970000005262"; - $card->expMonth = date('m'); - $card->expYear = date('Y', strtotime('+1 year')); - $card->cvn = "800"; - $card->cardHolderName = "James Mason"; - - $transaction = $card->charge(1) - ->withCurrency('USD') + $response = $reverse->reauthorized() ->execute(); - $this->assertTransactionResponse($transaction, TransactionStatus::CAPTURED); - - sleep(1); - - $exceptionCaught = false; - try { - BatchService::closeBatch($transaction->batchSummary->batchReference); - } catch (GatewayException $e) { - $exceptionCaught = true; - $this->assertEquals('50002', $e->responseCode); - $this->assertEquals('Status Code: UNAUTHORIZED_DOWNSTREAM - -2,Authentication error—Verify and correct credentials', $e->getMessage()); - } finally { - $this->assertTrue($exceptionCaught); - } - } - public function testBatchClose_WithInvalidBatchReference() - { - $batchReference = GenerationUtils::getGuid(); - $exceptionCaught = false; - try { - BatchService::closeBatch($batchReference); - } catch (GatewayException $e) { - $exceptionCaught = true; - $this->assertEquals('40118', $e->responseCode); - $this->assertEquals(sprintf('Status Code: RESOURCE_NOT_FOUND - Batch %s not found at this location.', $batchReference), $e->getMessage()); - } finally { - $this->assertTrue($exceptionCaught); - } - } - - private function assertBatchCloseResponse($batch, $amount) - { - $this->assertNotNull($batch); - $this->assertEquals('CLOSED', $batch->responseMessage); - $this->assertGreaterThanOrEqual($amount, $batch->batchSummary->totalAmount); - $this->assertGreaterThanOrEqual(1, $batch->batchSummary->transactionCount); + $this->assertTransactionResponse($response, 'SUCCESS', TransactionStatus::CAPTURED); } - private function assertTransactionResponse($transaction, $transactionStatus) - { - $this->assertNotNull($transaction); - $this->assertEquals('SUCCESS', $transaction->responseCode); - $this->assertEquals($transactionStatus, $transaction->responseMessage); - } - - public function testReauthAReversedSale() + public function testReauthAReversedAuthorizedTransaction() { $card = $this->initCreditCardData(); - $transaction = $card->charge(42) - ->withCurrency('USD') + $transaction = $card->authorize($this->amount) + ->withCurrency($this->currency) ->withAllowDuplicates(true) ->execute(); - $this->assertNotNull($transaction); - $this->assertEquals('SUCCESS', $transaction->responseCode); - $this->assertEquals(TransactionStatus::CAPTURED, $transaction->responseMessage); - - $reverse = $transaction->reverse()->execute(); + $this->assertTransactionResponse($transaction, 'SUCCESS', TransactionStatus::PREAUTHORIZED); - $this->assertNotNull($reverse); - $this->assertEquals('SUCCESS', $reverse->responseCode); - $this->assertEquals(TransactionStatus::REVERSED, $reverse->responseMessage); - - $response = $reverse->reauthorized()->execute(); - $this->assertNotNull($response); - $this->assertEquals('SUCCESS', $response->responseCode); - $this->assertEquals(TransactionStatus::CAPTURED, $response->responseMessage); - } - - public function testReauthAReversedAuthorizedTransaction() - { - $card = $this->initCreditCardData(); - - $transaction = $card->authorize(42) - ->withCurrency('USD') - ->withAllowDuplicates(true) + $reverse = $transaction->reverse() + ->withCurrency($this->currency) ->execute(); - $this->assertNotNull($transaction); - $this->assertEquals('SUCCESS', $transaction->responseCode); - $this->assertEquals(TransactionStatus::PREAUTHORIZED, $transaction->responseMessage); - - $reverse = $transaction->reverse()->withCurrency('USD')->execute(); + $this->assertTransactionResponse($reverse, 'SUCCESS', TransactionStatus::REVERSED); - $this->assertNotNull($reverse); - $this->assertEquals('SUCCESS', $reverse->responseCode); - $this->assertEquals(TransactionStatus::REVERSED, $reverse->responseMessage); + $reauthorized = $reverse->reauthorized() + ->execute(); - $reauthorized = $reverse->reauthorized()->execute(); - $this->assertNotNull($reauthorized); - $this->assertEquals('SUCCESS', $reauthorized->responseCode); - $this->assertEquals(TransactionStatus::PREAUTHORIZED, $reauthorized->responseMessage); + $this->assertTransactionResponse($reauthorized, 'SUCCESS', TransactionStatus::PREAUTHORIZED); } public function testReauthorizedAnExistingTransaction() @@ -518,7 +160,7 @@ public function testReauthorizedAnExistingTransaction() $response = ReportingService::findTransactionsPaged(1, 100) ->orderBy(TransactionSortProperty::TIME_CREATED, SortDirection::DESC) ->where(SearchCriteria::TRANSACTION_STATUS, TransactionStatus::PREAUTHORIZED) - ->andWith(SearchCriteria::CHANNEL, Channels::CardPresent) + ->andWith(SearchCriteria::CHANNEL, Channel::CardPresent) ->andWith(SearchCriteria::START_DATE, $startDate) ->execute(); @@ -531,16 +173,16 @@ public function testReauthorizedAnExistingTransaction() $transaction = new Transaction(); $transaction->transactionId = $result->transactionId; - $reverse = $transaction->reverse()->withCurrency('USD')->execute(); + $reverse = $transaction->reverse() + ->withCurrency($this->currency) + ->execute(); - $this->assertNotNull($reverse); - $this->assertEquals('SUCCESS', $reverse->responseCode); - $this->assertEquals(TransactionStatus::REVERSED, $reverse->responseMessage); + $this->assertTransactionResponse($reverse, 'SUCCESS', TransactionStatus::REVERSED); - $response = $reverse->reauthorized($result->amount)->execute(); - $this->assertNotNull($response); - $this->assertEquals('SUCCESS', $response->responseCode); - $this->assertEquals(TransactionStatus::PREAUTHORIZED, $response->responseMessage); + $response = $reverse->reauthorized($result->amount) + ->execute(); + + $this->assertTransactionResponse($response, 'SUCCESS', TransactionStatus::PREAUTHORIZED); } public function testReauthAReversedAuthorizedTransaction_WithIdempotencyKey() @@ -548,27 +190,24 @@ public function testReauthAReversedAuthorizedTransaction_WithIdempotencyKey() $idempotencyKey = GenerationUtils::getGuid(); $card = $this->initCreditCardData(); - $transaction = $card->authorize(42) - ->withCurrency('USD') + $transaction = $card->authorize($this->amount) + ->withCurrency($this->currency) ->withAllowDuplicates(true) ->execute(); - $this->assertNotNull($transaction); - $this->assertEquals('SUCCESS', $transaction->responseCode); - $this->assertEquals(TransactionStatus::PREAUTHORIZED, $transaction->responseMessage); + $this->assertTransactionResponse($transaction, 'SUCCESS', TransactionStatus::PREAUTHORIZED); - $reverse = $transaction->reverse()->withCurrency('USD')->execute(); + $reverse = $transaction->reverse() + ->withCurrency($this->currency) + ->execute(); - $this->assertNotNull($reverse); - $this->assertEquals('SUCCESS', $reverse->responseCode); - $this->assertEquals(TransactionStatus::REVERSED, $reverse->responseMessage); + $this->assertTransactionResponse($reverse, 'SUCCESS', TransactionStatus::REVERSED); $reauthorized = $reverse->reauthorized() ->withIdempotencyKey($idempotencyKey) ->execute(); - $this->assertNotNull($reauthorized); - $this->assertEquals('SUCCESS', $reauthorized->responseCode); - $this->assertEquals(TransactionStatus::PREAUTHORIZED, $reauthorized->responseMessage); + + $this->assertTransactionResponse($reauthorized, 'SUCCESS', TransactionStatus::PREAUTHORIZED); $exceptionCaught = false; try { @@ -588,26 +227,23 @@ public function testReauthAReversedSale_WithAmount() { $card = $this->initCreditCardData(); - $transaction = $card->charge(42) - ->withCurrency('USD') + $transaction = $card->charge($this->amount) + ->withCurrency($this->currency) ->withAllowDuplicates(true) ->execute(); - $this->assertNotNull($transaction); - $this->assertEquals('SUCCESS', $transaction->responseCode); - $this->assertEquals(TransactionStatus::CAPTURED, $transaction->responseMessage); + $this->assertTransactionResponse($transaction, 'SUCCESS', TransactionStatus::CAPTURED); - $reverse = $transaction->reverse()->execute(); + $reverse = $transaction->reverse() + ->execute(); - $this->assertNotNull($reverse); - $this->assertEquals('SUCCESS', $reverse->responseCode); - $this->assertEquals(TransactionStatus::REVERSED, $reverse->responseMessage); + $this->assertTransactionResponse($reverse, 'SUCCESS', TransactionStatus::REVERSED); $this->assertEquals($reverse->transactionId, $transaction->transactionId); - $response = $reverse->reauthorized(15)->execute(); - $this->assertNotNull($response); - $this->assertEquals('SUCCESS', $response->responseCode); - $this->assertEquals(TransactionStatus::CAPTURED, $response->responseMessage); + $response = $reverse->reauthorized(15) + ->execute(); + + $this->assertTransactionResponse($response, 'SUCCESS', TransactionStatus::CAPTURED); $this->assertEquals(15, $response->balanceAmount); $this->assertNotEquals($reverse->transactionId, $response->transactionId); } @@ -616,13 +252,12 @@ public function testReauthAReversedRefund() { $card = $this->initCreditCardData(); - $refund = $card->refund(42) - ->withCurrency('USD') + $refund = $card->refund($this->amount) + ->withCurrency($this->currency) ->withAllowDuplicates(true) ->execute(); - $this->assertNotNull($refund); - $this->assertEquals('SUCCESS', $refund->responseCode); - $this->assertEquals(TransactionStatus::CAPTURED, $refund->responseMessage); + + $this->assertTransactionResponse($refund, 'SUCCESS', TransactionStatus::CAPTURED); $exceptionCaught = false; try { @@ -640,14 +275,12 @@ public function testReauthASale_WithCapturedStatus() { $card = $this->initCreditCardData(); - $transaction = $card->charge(42) - ->withCurrency('USD') + $transaction = $card->charge($this->amount) + ->withCurrency($this->currency) ->withAllowDuplicates(true) ->execute(); - $this->assertNotNull($transaction); - $this->assertEquals('SUCCESS', $transaction->responseCode); - $this->assertEquals(TransactionStatus::CAPTURED, $transaction->responseMessage); + $this->assertTransactionResponse($transaction, 'SUCCESS', TransactionStatus::CAPTURED); $exceptionCaught = false; try { @@ -678,6 +311,40 @@ public function testReauthASale_NonExistentId() } } + public function testCreditSaleContactlessChip() + { + $card = new CreditTrackData(); + $card->setTrackData('%B4012002000060016^VI TEST CREDIT^251210118039000000000396?;4012002000060016=25121011803939600000?'); + $tagData = '9F4005F000F0A0019F02060000000025009F03060000000000009F2608D90A06501B48564E82027C005F3401019F360200029F0702FF009F0802008C9F0902008C9F34030403029F2701809F0D05F0400088009F0E0508000000009F0F05F0400098005F280208409F390105FFC605DC4000A800FFC7050010000000FFC805DC4004F8009F3303E0B8C89F1A0208409F350122950500000080005F2A0208409A031409109B02E8009F21030811539C01009F37045EED3A8E4F07A00000000310109F0607A00000000310108407A00000000310109F100706010A03A400029F410400000001'; + $card->entryMethod = EntryMethod::PROXIMITY; + + $response = $card->charge(10) + ->withCurrency("USD") + ->withAllowDuplicates(true) + ->withTagData($tagData) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('SUCCESS', $response->responseCode); + $this->assertEquals(TransactionStatus::CAPTURED, $response->responseMessage); + } + + public function testCreditSaleContactlessSwipe() + { + $card = new CreditTrackData(); + $card->setTrackData('%B4012002000060016^VI TEST CREDIT^251210118039000000000396?;4012002000060016=25121011803939600000?'); + $tagData = '9F4005F000F0A0019F02060000000025009F03060000000000009F2608D90A06501B48564E82027C005F3401019F360200029F0702FF009F0802008C9F0902008C9F34030403029F2701809F0D05F0400088009F0E0508000000009F0F05F0400098005F280208409F390191FFC605DC4000A800FFC7050010000000FFC805DC4004F8009F3303E0B8C89F1A0208409F350122950500000080005F2A0208409A031409109B02E8009F21030811539C01009F37045EED3A8E4F07A00000000310109F0607A00000000310108407A00000000310109F100706010A03A400029F410400000001'; + $response = $card->charge(10) + ->withCurrency("USD") + ->withAllowDuplicates(true) + ->withTagData($tagData) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('SUCCESS', $response->responseCode); + $this->assertEquals(TransactionStatus::CAPTURED, $response->responseMessage); + } + private function initCreditCardData() { $card = new CreditCardData(); @@ -686,8 +353,25 @@ private function initCreditCardData() $card->expYear = date('Y', strtotime('+1 year')); $card->cvn = "852"; $card->cardHolderName = "James Mason"; + $card->cardPresent = true; + + return $card; + } + + private function initCreditTrackData() + { + $card = new CreditTrackData(); + $card->setTrackData('%B4012002000060016^VI TEST CREDIT^251210118039000000000396?;4012002000060016=25121011803939600000?'); + $card->entryMethod = EntryMethod::SWIPE; return $card; } + private function assertTransactionResponse($transaction, $transactionResponseCode, $transactionStatus) + { + $this->assertNotNull($transaction); + $this->assertEquals($transactionResponseCode, $transaction->responseCode); + $this->assertEquals($transactionStatus, $transaction->responseMessage); + } + } \ No newline at end of file diff --git a/test/Integration/Gateways/GpApiConnector/DebitCardTest.php b/test/Integration/Gateways/GpApiConnector/DebitCardTest.php index 8ec380f4..73882c4d 100644 --- a/test/Integration/Gateways/GpApiConnector/DebitCardTest.php +++ b/test/Integration/Gateways/GpApiConnector/DebitCardTest.php @@ -7,7 +7,7 @@ use GlobalPayments\Api\Entities\EncryptionData; use GlobalPayments\Api\Entities\Enums\EntryMethod; use GlobalPayments\Api\Entities\Enums\Environment; -use GlobalPayments\Api\Entities\Enums\GpApi\Channels; +use GlobalPayments\Api\Entities\Enums\Channel; use GlobalPayments\Api\Entities\Enums\TransactionStatus; use GlobalPayments\Api\PaymentMethods\DebitTrackData; use GlobalPayments\Api\ServiceConfigs\Gateways\GpApiConfig; @@ -76,7 +76,7 @@ public function testDebitRefundChip() public function testDebitReverse() { $debitCard = new DebitTrackData(); - $debitCard->value = '%B4012002000060016^VI TEST CREDIT^251210118039000000000396?;4012002000060016=25121011803939600000?'; + $debitCard->setValue('%B4012002000060016^VI TEST CREDIT^251210118039000000000396?;4012002000060016=25121011803939600000?'); $debitCard->pinBlock = '32539F50C245A6A93D123412324000AA'; $debitCard->entryMethod = EntryMethod::SWIPE; @@ -189,7 +189,7 @@ public function setUpConfig() $config->appId = 'i872l4VgZRtSrykvSn8Lkah8RE1jihvT'; $config->appKey = '9pArW2uWoA8enxKc'; $config->environment = Environment::TEST; - $config->channel = Channels::CardPresent; + $config->channel = Channel::CardPresent; return $config; } diff --git a/test/Integration/Gateways/GpApiConnector/EbtCardTest.php b/test/Integration/Gateways/GpApiConnector/EbtCardTest.php index 5c56aa66..6ed59cf2 100644 --- a/test/Integration/Gateways/GpApiConnector/EbtCardTest.php +++ b/test/Integration/Gateways/GpApiConnector/EbtCardTest.php @@ -3,7 +3,7 @@ namespace Gateways\GpApiConnector; use GlobalPayments\Api\Entities\Enums\Environment; -use GlobalPayments\Api\Entities\Enums\GpApi\Channels; +use GlobalPayments\Api\Entities\Enums\Channel; use GlobalPayments\Api\Entities\Enums\TransactionStatus; use GlobalPayments\Api\ServiceConfigs\Gateways\GpApiConfig; use GlobalPayments\Api\ServicesContainer; @@ -33,7 +33,7 @@ public function setUpConfig() $config->appId = 'VuKlC2n1cr5LZ8fzLUQhA7UObVks6tFF'; $config->appKey = 'NmGM0kg92z2gA7Og'; $config->environment = Environment::TEST; - $config->channel = Channels::CardPresent; + $config->channel = Channel::CardPresent; return $config; } diff --git a/test/Integration/Gateways/GpApiConnector/GpApi3DS1Test.php b/test/Integration/Gateways/GpApiConnector/GpApi3DS1Test.php index bd20f68b..c0fa8273 100644 --- a/test/Integration/Gateways/GpApiConnector/GpApi3DS1Test.php +++ b/test/Integration/Gateways/GpApiConnector/GpApi3DS1Test.php @@ -2,7 +2,7 @@ use GlobalPayments\Api\Entities\Enums\ChallengeRequestIndicator; use GlobalPayments\Api\Entities\Enums\Environment; -use GlobalPayments\Api\Entities\Enums\GpApi\Channels; +use GlobalPayments\Api\Entities\Enums\Channel; use GlobalPayments\Api\Entities\Enums\Secure3dVersion; use GlobalPayments\Api\Entities\Enums\StoredCredentialInitiator; use GlobalPayments\Api\Entities\Enums\StoredCredentialReason; @@ -63,7 +63,7 @@ public function setUpConfig() $config->appKey = 'DHUGdzpjXfTbjZeo'; $config->environment = Environment::TEST; $config->country = 'GB'; - $config->channel = Channels::CardNotPresent; + $config->channel = Channel::CardNotPresent; $config->challengeNotificationUrl = 'https://ensi808o85za.x.pipedream.net/'; $config->methodNotificationUrl = 'https://ensi808o85za.x.pipedream.net/'; $config->merchantContactUrl = 'https://enp4qhvjseljg.x.pipedream.net/'; diff --git a/test/Integration/Gateways/GpApiConnector/GpApi3DS2Test.php b/test/Integration/Gateways/GpApiConnector/GpApi3DS2Test.php index a004dc6e..26fc5163 100644 --- a/test/Integration/Gateways/GpApiConnector/GpApi3DS2Test.php +++ b/test/Integration/Gateways/GpApiConnector/GpApi3DS2Test.php @@ -9,7 +9,7 @@ use GlobalPayments\Api\Entities\Enums\ColorDepth; use GlobalPayments\Api\Entities\Enums\DeliveryTimeFrame; use GlobalPayments\Api\Entities\Enums\Environment; -use GlobalPayments\Api\Entities\Enums\GpApi\Channels; +use GlobalPayments\Api\Entities\Enums\Channel; use GlobalPayments\Api\Entities\Enums\MethodUrlCompletion; use GlobalPayments\Api\Entities\Enums\Secure3dVersion; use GlobalPayments\Api\Entities\Enums\ShippingMethod; @@ -105,7 +105,7 @@ public function setUpConfig() $config->appKey = 'DHUGdzpjXfTbjZeo'; $config->environment = Environment::TEST; $config->country = 'GB'; - $config->channel = Channels::CardNotPresent; + $config->channel = Channel::CardNotPresent; $config->challengeNotificationUrl = 'https://ensi808o85za.x.pipedream.net/'; $config->methodNotificationUrl = 'https://ensi808o85za.x.pipedream.net/'; $config->merchantContactUrl = 'https://enp4qhvjseljg.x.pipedream.net/'; @@ -116,7 +116,7 @@ public function setUpConfig() /** * Frictionless scenario * - * @throws \GlobalPayments\Api\Entities\Exceptions\ApiException + * @throws ApiException */ public function testFullCycle_v2_Frictionless() { @@ -247,7 +247,7 @@ public function testFullCycle_v2_WithCardTokenization() /** * Challenge scenario * - * @throws \GlobalPayments\Api\Entities\Exceptions\ApiException + * @throws ApiException */ public function testFullCycle_CardHolderEnrolled_ChallengeRequired_v2() { diff --git a/test/Integration/Gateways/GpApiConnector/GpApi3DSecureTest.php b/test/Integration/Gateways/GpApiConnector/GpApi3DSecureTest.php index e549acdf..139b7cf7 100644 --- a/test/Integration/Gateways/GpApiConnector/GpApi3DSecureTest.php +++ b/test/Integration/Gateways/GpApiConnector/GpApi3DSecureTest.php @@ -7,7 +7,7 @@ use GlobalPayments\Api\Entities\Enums\ChallengeWindowSize; use GlobalPayments\Api\Entities\Enums\ColorDepth; use GlobalPayments\Api\Entities\Enums\Environment; -use GlobalPayments\Api\Entities\Enums\GpApi\Channels; +use GlobalPayments\Api\Entities\Enums\Channel; use GlobalPayments\Api\Entities\Enums\MethodUrlCompletion; use GlobalPayments\Api\Entities\Enums\OrderTransactionType; use GlobalPayments\Api\Entities\Enums\Secure3dVersion; @@ -27,6 +27,7 @@ use GlobalPayments\Api\Tests\Integration\Gateways\ThreeDSecureAcsClient; use GlobalPayments\Api\Utils\GenerationUtils; use GlobalPayments\Api\Entities\Enums\Secure3dStatus; +use GlobalPayments\Api\Entities\Enums\ManualEntryMethod; use PHPUnit\Framework\TestCase; class GpApi3DSecureTest extends TestCase @@ -102,7 +103,7 @@ public function setUpConfig() $config->appKey = 'DHUGdzpjXfTbjZeo'; $config->environment = Environment::TEST; $config->country = 'GB'; - $config->channel = Channels::CardNotPresent; + $config->channel = Channel::CardNotPresent; $config->challengeNotificationUrl = 'https://ensi808o85za.x.pipedream.net/'; $config->methodNotificationUrl = 'https://ensi808o85za.x.pipedream.net/'; $config->merchantContactUrl = 'https://enp4qhvjseljg.x.pipedream.net/'; @@ -185,7 +186,7 @@ public function testCardHolderEnrolled_ChallengeRequired_AuthenticationSuccessfu * @dataProvider ChallengeRequiredFailed3DSV1CardTests * @param $acsClientResultCode * @param $status - * @throws \GlobalPayments\Api\Entities\Exceptions\ApiException + * @throws ApiException */ public function testCardHolderEnrolled_ChallengeRequired_AuthenticationFailed_v1($acsClientResultCode, $status) { @@ -279,7 +280,7 @@ public function testCardHolderNotEnrolled_v1() * @dataProvider FrictionlessSuccessful3DSV2CardTests * @param $cardNumber * @param $status - * @throws \GlobalPayments\Api\Entities\Exceptions\ApiException + * @throws ApiException */ public function testFrictionlessFullCycle_v2($cardNumber, $status) { @@ -328,7 +329,7 @@ public function testFrictionlessFullCycle_v2($cardNumber, $status) * @dataProvider FrictionlessFailed3DSV2CardTests * @param $cardNumber * @param $status - * @throws \GlobalPayments\Api\Entities\Exceptions\ApiException + * @throws ApiException */ public function testFrictionlessFullCycle_v2_Failed($cardNumber, $status) { @@ -379,7 +380,7 @@ public function testFrictionlessFullCycle_v2_Failed($cardNumber, $status) * @dataProvider ChallengeSuccessful3DSV2CardTests * @param $cardNumber * @param $status - * @throws \GlobalPayments\Api\Entities\Exceptions\ApiException + * @throws ApiException */ public function testCardHolderEnrolled_ChallengeRequired_v2($cardNumber, $status) { @@ -433,7 +434,7 @@ public function testCardHolderEnrolled_ChallengeRequired_v2($cardNumber, $status /** * Challenge failed scenario * - * @throws \GlobalPayments\Api\Entities\Exceptions\ApiException + * @throws ApiException */ public function testChallengeRequired_GetResultFailed_v2() { @@ -475,7 +476,7 @@ public function testChallengeRequired_GetResultFailed_v2() /** * Frictionless scenario with tokenize card * - * @throws \GlobalPayments\Api\Entities\Exceptions\ApiException + * @throws ApiException */ public function testFullCycle_WithCardTokenization_v2() { @@ -528,7 +529,7 @@ public function testFullCycle_WithCardTokenization_v2() /** * Frictionless scenario different amount between /auth and /initiate * - * @throws \GlobalPayments\Api\Entities\Exceptions\ApiException + * @throws ApiException */ public function testFrictionlessFullCycle_v2_DifferentAmount() { @@ -631,6 +632,7 @@ public function testCardHolderEnrolled_ChallengeRequired_v2_DuplicateAcsRequest( public function testCreditSaleTokenized_WithStoredCredentials_Recurring() { $this->card->number = GpApi3DSTestCards::CARD_AUTH_SUCCESSFUL_V2_1; + $this->card->entryMethod = ManualEntryMethod::MOTO; $storeCredentials = new StoredCredential(); $storeCredentials->initiator = StoredCredentialInitiator::MERCHANT; diff --git a/test/Integration/Gateways/GpApiConnector/GpApiAchTest.php b/test/Integration/Gateways/GpApiConnector/GpApiAchTest.php index 63fb4223..79e1209c 100644 --- a/test/Integration/Gateways/GpApiConnector/GpApiAchTest.php +++ b/test/Integration/Gateways/GpApiConnector/GpApiAchTest.php @@ -2,8 +2,8 @@ use GlobalPayments\Api\Entities\Customer; use GlobalPayments\Api\Entities\Enums\AccountType; -use GlobalPayments\Api\Entities\Enums\GpApi\SortDirection; -use GlobalPayments\Api\Entities\Enums\GpApi\TransactionSortProperty; +use GlobalPayments\Api\Entities\Enums\SortDirection; +use GlobalPayments\Api\Entities\Enums\TransactionSortProperty; use GlobalPayments\Api\Entities\Enums\PaymentMethodName; use GlobalPayments\Api\Entities\Enums\SecCode; use GlobalPayments\Api\Entities\Exceptions\ApiException; @@ -13,7 +13,7 @@ use GlobalPayments\Api\ServicesContainer; use GlobalPayments\Api\ServiceConfigs\Gateways\GpApiConfig; use GlobalPayments\Api\Entities\Enums\Environment; -use GlobalPayments\Api\Entities\Enums\GpApi\Channels; +use GlobalPayments\Api\Entities\Enums\Channel; use GlobalPayments\Api\PaymentMethods\ECheck; use GlobalPayments\Api\Entities\Address; use GlobalPayments\Api\Entities\Enums\TransactionStatus; @@ -81,7 +81,7 @@ public function setUpConfig() $config->appId = 'oDVjAddrXt3qPJVPqQvrmgqM2MjMoHQS'; $config->appKey = 'DHUGdzpjXfTbjZeo'; $config->environment = Environment::TEST; - $config->channel = Channels::CardNotPresent; + $config->channel = Channel::CardNotPresent; $config->requestLogger = new SampleRequestLogger(new Logger("logs")); return $config; @@ -114,9 +114,10 @@ public function testCheckRefund() public function testCheckRefundExistingSale() { - $this->markTestSkipped('GP-API sandbox limitation'); - $startDate = (new \DateTime())->modify('-1 year'); - $endDate = (new \DateTime())->modify('-2 days'); + $this->markTestSkipped('GP-API sandbox limitation'); + $startDate = (new DateTime())->modify('-1 year'); + $endDate = (new DateTime())->modify('-2 days'); + try { $response = ReportingService::findTransactionsPaged(1, 10) ->orderBy(TransactionSortProperty::TIME_CREATED, SortDirection::DESC) @@ -148,8 +149,8 @@ public function testCheckReauthorize() $this->eCheck->secCode = SecCode::PPD; $this->eCheck->accountNumber = '051904524'; $this->eCheck->routingNumber = '123456780'; - $startDate = (new \DateTime())->modify('-1 year'); - $endDate = (new \DateTime())->modify('-2 days'); + $startDate = (new DateTime())->modify('-1 year'); + $endDate = (new DateTime())->modify('-2 days'); $amount = '1.29'; try { $response = ReportingService::findTransactionsPaged(1, 10) @@ -179,5 +180,26 @@ public function testCheckReauthorize() $this->assertEquals('SUCCESS', $response->responseCode); } + public function testCheckSaleThenRefund() + { + $response = $this->eCheck->charge(11) + ->withCurrency('USD') + ->withAddress($this->address) + ->withCustomerData($this->customer) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('SUCCESS', $response->responseCode); + $this->assertEquals(TransactionStatus::CAPTURED, $response->responseMessage); + + $refund = $response->refund() + ->withCurrency('USD') + ->execute(); + + $this->assertNotNull($refund); + $this->assertEquals('DECLINED', $refund->responseCode); + $this->assertEquals(TransactionStatus::DECLINED, $refund->responseMessage); + $this->assertEquals('D0005', $refund->authorizationCode); + } } \ No newline at end of file diff --git a/test/Integration/Gateways/GpApiConnector/GpApiBatchTests.php b/test/Integration/Gateways/GpApiConnector/GpApiBatchTests.php new file mode 100644 index 00000000..cd9eb38b --- /dev/null +++ b/test/Integration/Gateways/GpApiConnector/GpApiBatchTests.php @@ -0,0 +1,387 @@ +setUpConfig()); + + $this->creditTrackData = new CreditTrackData(); + $this->creditTrackData->setTrackData('%B4012002000060016^VI TEST CREDIT^251210118039000000000396?;4012002000060016=25121011803939600000?'); + $this->creditTrackData->entryMethod = EntryMethod::SWIPE; + + $this->creditCardData = new CreditCardData(); + $this->creditCardData->number = "4263970000005262"; + $this->creditCardData->expMonth = date('m'); + $this->creditCardData->expYear = date('Y', strtotime('+1 year')); + $this->creditCardData->cvn = "123"; + $this->creditCardData->cardHolderName = "James Mason"; + } + + public function setUpConfig() + { + $config = new GpApiConfig(); + $config->appId = 'i872l4VgZRtSrykvSn8Lkah8RE1jihvT'; + $config->appKey = '9pArW2uWoA8enxKc'; + $config->environment = Environment::TEST; + $config->channel = Channel::CardPresent; +// $config->requestLogger = new SampleRequestLogger(new Logger("logs")); + + return $config; + } + + public function testBatchClose() + { + $transaction = $this->creditTrackData->charge($this->amount) + ->withCurrency($this->currency) + ->execute(); + $this->assertTransactionResponse($transaction, TransactionStatus::CAPTURED); + + sleep(2); + + $batch = BatchService::closeBatch($transaction->batchSummary->batchReference); + $this->assertBatchCloseResponse($batch, $this->amount); + } + + public function testAuthorizationCaptureBatchClose() + { + $transaction = $this->creditCardData->authorize($this->amount) + ->withCurrency($this->currency) + ->execute(); + + $this->assertTransactionResponse($transaction, TransactionStatus::PREAUTHORIZED); + + $capture = $transaction->capture($this->amount) + ->execute(); + + $this->assertTransactionResponse($capture, TransactionStatus::CAPTURED); + $this->assertNotEmpty($capture->batchSummary->batchReference); + + sleep(2); + + $batch = BatchService::closeBatch($capture->batchSummary->batchReference); + $this->assertBatchCloseResponse($batch, $this->amount); + } + + public function testBatchClose_ChipTransaction() + { + $transaction = $this->creditTrackData->charge($this->amount) + ->withCurrency($this->currency) + ->withTagData($this->tag) + ->execute(); + $this->assertTransactionResponse($transaction, TransactionStatus::CAPTURED); + + sleep(1); + + $batch = BatchService::closeBatch($transaction->batchSummary->batchReference); + $this->assertBatchCloseResponse($batch, $this->amount); + } + + public function testBatchClose_ContactlessTransaction() + { + $card = new DebitTrackData(); + $card->setValue(';4024720012345671=18125025432198712345?'); + $card->entryMethod = EntryMethod::PROXIMITY; + $card->pinBlock = 'AFEC374574FC90623D010000116001EE'; + + $transaction = $card->charge($this->amount) + ->withCurrency($this->currency) + ->withTagData($this->tag) + ->execute(); + $this->assertTransactionResponse($transaction, TransactionStatus::CAPTURED); + + sleep(2); + + $batch = BatchService::closeBatch($transaction->batchSummary->batchReference); + $this->assertBatchCloseResponse($batch, $this->amount); + } + + public function testBatchClose_MultipleChargeCreditTrackData() + { + $transaction = $this->creditTrackData->charge($this->amount) + ->withCurrency($this->currency) + ->execute(); + $this->assertTransactionResponse($transaction, TransactionStatus::CAPTURED); + + $transaction = $this->creditTrackData->charge($this->amount) + ->withCurrency($this->currency) + ->execute(); + $this->assertTransactionResponse($transaction, TransactionStatus::CAPTURED); + + sleep(2); + + $batch = BatchService::closeBatch($transaction->batchSummary->batchReference); + $this->assertBatchCloseResponse($batch, $this->amount * 2); + } + + public function testBatchClose_Refund_CreditTrackData() + { + $transaction = $this->creditTrackData->charge($this->amount) + ->withCurrency($this->currency) + ->execute(); + $this->assertTransactionResponse($transaction, TransactionStatus::CAPTURED); + + $transaction = $transaction->refund() + ->withCurrency($this->currency) + ->execute(); + $this->assertTransactionResponse($transaction, TransactionStatus::CAPTURED); + + $batch = BatchService::closeBatch($transaction->batchSummary->batchReference); + $this->assertBatchCloseResponse($batch, 0); + } + + public function testBatchClose_Reverse_CreditCardData() + { + $transaction = $this->creditCardData->authorize($this->amount) + ->withCurrency($this->currency) + ->execute(); + $this->assertTransactionResponse($transaction, TransactionStatus::PREAUTHORIZED); + + $transaction = $transaction->reverse() + ->withCurrency($this->currency) + ->execute(); + $this->assertTransactionResponse($transaction, TransactionStatus::REVERSED); + + sleep(1); + + $exceptionCaught = false; + try { + BatchService::closeBatch($transaction->batchSummary->batchReference); + } catch (GatewayException $e) { + $exceptionCaught = true; + $this->assertEquals('40223', $e->responseCode); + $this->assertEquals('Status Code: MANDATORY_DATA_MISSING - Request expects the batch_id', $e->getMessage()); + } finally { + $this->assertTrue($exceptionCaught); + } + } + + public function testBatchClose_WithIdempotency() + { + $idempotencyKey = GenerationUtils::getGuid(); + + $transaction = $this->creditTrackData->charge($this->amount) + ->withCurrency($this->currency) + ->execute(); + + $this->assertTransactionResponse($transaction, TransactionStatus::CAPTURED); + + $batch = (new ManagementBuilder(TransactionType::BATCH_CLOSE)) + ->withBatchReference($transaction->batchSummary->batchReference) + ->withIdempotencyKey($idempotencyKey) + ->execute(); + + $this->assertBatchCloseResponse($batch, $this->amount); + + $exceptionCaught = false; + try { + (new ManagementBuilder(TransactionType::BATCH_CLOSE)) + ->withBatchReference($transaction->batchSummary->batchReference) + ->withIdempotencyKey($idempotencyKey) + ->execute(); + } catch (GatewayException $e) { + $exceptionCaught = true; + $this->assertEquals('40039', $e->responseCode); + $this->assertContains('Status Code: DUPLICATE_ACTION - Idempotency Key seen before: ', $e->getMessage()); + } finally { + $this->assertTrue($exceptionCaught); + } + } + + public function testBatchClose_WithCardNumberDetails() + { + $transaction = $this->creditCardData->charge($this->amount) + ->withCurrency($this->currency) + ->execute(); + $this->assertTransactionResponse($transaction, TransactionStatus::CAPTURED); + + sleep(2); + + $batch = BatchService::closeBatch($transaction->batchSummary->batchReference); + $this->assertBatchCloseResponse($batch, $this->amount); + } + + public function testBatchClose_WithCardNumberDetails_DeclinedTransaction() + { + $this->creditCardData->cvn = "800"; + + $transaction = $this->creditCardData->charge($this->amount) + ->withCurrency($this->currency) + ->execute(); + + $this->assertNotNull($transaction); + $this->assertEquals('DECLINED', $transaction->responseCode); + $this->assertEquals(TransactionStatus::DECLINED, $transaction->responseMessage); + + sleep(2); + + $exceptionCaught = false; + try { + BatchService::closeBatch($transaction->batchSummary->batchReference); + } catch (GatewayException $e) { + $exceptionCaught = true; + $this->assertEquals('40017', $e->responseCode); + $this->assertEquals('Status Code: INVALID_BATCH_ACTION - 9,No transaction associated with batch', $e->getMessage()); + } finally { + $this->assertTrue($exceptionCaught); + } + } + + public function testBatchClose_WithClosedBatchReference() + { + $transaction = $this->creditTrackData->charge($this->amount) + ->withCurrency($this->currency) + ->execute(); + $this->assertTransactionResponse($transaction, TransactionStatus::CAPTURED); + + $batch = BatchService::closeBatch($transaction->batchSummary->batchReference); + $this->assertBatchCloseResponse($batch, $this->amount); + + $exceptionCaught = false; + try { + BatchService::closeBatch($transaction->batchSummary->batchReference); + } catch (GatewayException $e) { + $exceptionCaught = true; + $this->assertEquals('40014', $e->responseCode); + $this->assertEquals('Status Code: INVALID_BATCH_ACTION - 5,No current batch', $e->getMessage()); + } finally { + $this->assertTrue($exceptionCaught); + } + } + + public function testBatchClose_Verify_MissingBatchId() + { + $transaction = $this->creditTrackData->verify() + ->withCurrency('USD') + ->execute(); + + $this->assertNotNull($transaction); + $this->assertEquals('SUCCESS', $transaction->responseCode); + $this->assertEquals('VERIFIED', $transaction->responseMessage); + + sleep(1); + + $exceptionCaught = false; + try { + BatchService::closeBatch($transaction->batchSummary->batchReference); + } catch (GatewayException $e) { + $exceptionCaught = true; + $this->assertEquals('40223', $e->responseCode); + $this->assertEquals('Status Code: MANDATORY_DATA_MISSING - Request expects the batch_id', $e->getMessage()); + } finally { + $this->assertTrue($exceptionCaught); + } + } + + public function testBatchClose_CardNotPresentChannel() + { + $config = new GpApiConfig(); + $config->appId = 'i872l4VgZRtSrykvSn8Lkah8RE1jihvT'; + $config->appKey = '9pArW2uWoA8enxKc'; + $config->environment = Environment::TEST; + $config->channel = Channel::CardNotPresent; + + ServicesContainer::configureService($config); + + $transaction = $this->creditCardData->charge($this->amount) + ->withCurrency($this->currency) + ->execute(); + $this->assertTransactionResponse($transaction, TransactionStatus::CAPTURED); + + sleep(1); + + $exceptionCaught = false; + try { + BatchService::closeBatch($transaction->batchSummary->batchReference); + } catch (GatewayException $e) { + $exceptionCaught = true; + $this->assertEquals('50002', $e->responseCode); + $this->assertEquals('Status Code: UNAUTHORIZED_DOWNSTREAM - -2,Authentication error—Verify and correct credentials', $e->getMessage()); + } finally { + $this->assertTrue($exceptionCaught); + } + } + + public function testBatchClose_WithInvalidBatchReference() + { + $batchReference = GenerationUtils::getGuid(); + $exceptionCaught = false; + try { + BatchService::closeBatch($batchReference); + } catch (GatewayException $e) { + $exceptionCaught = true; + $this->assertEquals('40118', $e->responseCode); + $this->assertEquals(sprintf('Status Code: RESOURCE_NOT_FOUND - Batch %s not found at this location.', $batchReference), $e->getMessage()); + } finally { + $this->assertTrue($exceptionCaught); + } + } + + public function testBatchClose_ActionNotAuthorized() + { + $transaction = $this->creditTrackData->charge($this->amount) + ->withCurrency($this->currency) + ->execute(); + $this->assertTransactionResponse($transaction, TransactionStatus::CAPTURED); + + sleep(2); + + $exceptionCaught = false; + try { + BatchService::closeBatch($transaction->batchSummary->batchReference); + } catch (GatewayException $e) { + $exceptionCaught = true; + $this->assertEquals('40212', $e->responseCode); + $this->assertEquals('Status Code: ACTION_NOT_AUTHORIZED - Permission not enabled to execute action', $e->getMessage()); + } finally { + $this->assertTrue($exceptionCaught); + } + } + + private function assertBatchCloseResponse($batch, $amount) + { + $this->assertNotNull($batch); + $this->assertEquals('CLOSED', $batch->responseMessage); + $this->assertGreaterThanOrEqual($amount, $batch->batchSummary->totalAmount); + $this->assertGreaterThanOrEqual(1, $batch->batchSummary->transactionCount); + } + + private function assertTransactionResponse($transaction, $transactionStatus) + { + $this->assertNotNull($transaction); + $this->assertEquals('SUCCESS', $transaction->responseCode); + $this->assertEquals($transactionStatus, $transaction->responseMessage); + } + +} \ No newline at end of file diff --git a/test/Integration/Gateways/GpApiConnector/GpApiDigitalWalletTest.php b/test/Integration/Gateways/GpApiConnector/GpApiDigitalWalletTest.php index 2ed5e781..43ded9a5 100644 --- a/test/Integration/Gateways/GpApiConnector/GpApiDigitalWalletTest.php +++ b/test/Integration/Gateways/GpApiConnector/GpApiDigitalWalletTest.php @@ -2,20 +2,22 @@ use GlobalPayments\Api\Entities\Enums\EncyptedMobileType; use GlobalPayments\Api\Entities\Enums\Environment; -use GlobalPayments\Api\Entities\Enums\GpApi\Channels; +use GlobalPayments\Api\Entities\Enums\Channel; use GlobalPayments\Api\Entities\Enums\TransactionModifier; +use GlobalPayments\Api\Entities\Enums\TransactionStatus; use GlobalPayments\Api\PaymentMethods\CreditCardData; use GlobalPayments\Api\ServiceConfigs\Gateways\GpApiConfig; use GlobalPayments\Api\ServicesContainer; -use GlobalPayments\Api\Entities\Enums\GatewayProvider; -use GlobalPayments\Api\Entities\Enums\TransactionStatus; -use PHPUnit\Framework\TestCase; use GlobalPayments\Api\Utils\Logging\Logger; use GlobalPayments\Api\Utils\Logging\SampleRequestLogger; +use PHPUnit\Framework\TestCase; class GpApiDigitalWalletTest extends TestCase { private $card; + private $currency = 'EUR'; + private $amount = 10; + private $googlePayToken; public function setup() { @@ -24,7 +26,11 @@ public function setup() $this->card->expMonth = date('m'); $this->card->expYear = date('Y', strtotime('+1 year')); $this->card->cardHolderName = "James Mason"; - + $this->googlePayToken = '{ + "signature": "MEUCIQDRwolbHgD116pBJDKEF2TG/l0KbTBErR9PNta9gHVDbwIgQlQZZLPd/5QRsz56w5xCPtzRa8yBzJRRc9ujw7iM/K4=", + "protocolVersion": "ECv1", + "signedMessage": "{\"encryptedMessage\":\"u8U1a6dijdpfA7Jxwi4sO19666Bwis2/spCFAAUEP+llEINKD6ZLWgg8bMuNavicX5Jps57lmhZXhkg0oHxCAdUyAdW2nJx00Q4x5tN+lRfajIHyXSp0E1+29F1OOgbtGqV5qW7yoRUq3rAJwqVYotC5YfCpdNe/SZZV+pIMzfBV8Tm2bl9X4IHYkjzhH55xz0zQkX0Y4uxNSNuybK4n5E3n9+9dKG2bXuklxcTNylFBwaThbJL944EU3qPG0gEH5tTloqaGlqk75qnZgph7MGIxcZmb60yJYu8fKfLvbab5ClbX/5J5Fx8j6UNpGF+c400FjkZZuWCdGCetjfl9RdPIAFM8cqKnWJDTmdqGyGe+xc3o0yrIAXmfgTNpBU/B5qLYn0PKfrPh8+1UUYbPChCmVI3n/MziYDu+y6YVucHiZikWRY9e/OraBBVIpfFoPGnq\",\"ephemeralPublicKey\":\"BK/aN903Xa7imoEEXi38nfkzkOnwBVQZ0MYw8D9QG9D2q6kKtzTgZVR3s03r0MXwPqwVPmx6aKid8y+alT9XCVo\\u003d\",\"tag\":\"AyMdTQznnVLDzZmp+jXz9JhagWAokb+7DEg61vbdNwo\\u003d\"}" + }'; } public function setUpConfig() @@ -33,7 +39,7 @@ public function setUpConfig() $config->appId = 'i872l4VgZRtSrykvSn8Lkah8RE1jihvT'; $config->appKey = '9pArW2uWoA8enxKc'; $config->environment = Environment::TEST; - $config->channel = Channels::CardNotPresent; + $config->channel = Channel::CardNotPresent; $config->requestLogger = new SampleRequestLogger(new Logger("logs")); return $config; @@ -45,15 +51,12 @@ public function testPayWithApplePayEncrypted() $this->card->token = '{"version":"EC_v1","data":"Jguh2VrQWIpbjtmooCKw2B3yxhBQPwj0tU2FXhtJQatMmRiibhWyVcz1RwolGk2MH+zEL8o4Q3vvXQqb7XUFVaregAGm4mLn5unoTTw6/ltJjozThJ99BuNHo1QhHk6asnlNWy1JTliKq69uGvHcV9ZbBKA4pbUbcsLJu7rB5kakZXvNCLItGAFk2Iue2PMAJMGblTD76FhXbcDTpBFCJeSrupoBoEHk83HgbptaJUzUxsSCHnz0T0BPyLDcMk9cK0nzRowsUYEuH/X+lxjh6yJfkCnL6i6eFjZoonZsZXg37Mnt9kmcIammlHbGtxKXl76AeKieMuPwDMAcMDhnY9xPPM+QZo14dNksBxOV8GWuDLVYSBXmqzZ3GOruYQ29q6gpfZuqIZeiKTYArOhKH0S/ro+aX8fUbPDUP7xAkzc=","signature":"MIAGCSqGSIb3DQEHAqCAMIACAQExDzANBglghkgBZQMEAgEFADCABgkqhkiG9w0BBwEAAKCAMIID5DCCA4ugAwIBAgIIWdihvKr0480wCgYIKoZIzj0EAwIwejEuMCwGA1UEAwwlQXBwbGUgQXBwbGljYXRpb24gSW50ZWdyYXRpb24gQ0EgLSBHMzEmMCQGA1UECwwdQXBwbGUgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEzARBgNVBAoMCkFwcGxlIEluYy4xCzAJBgNVBAYTAlVTMB4XDTIxMDQyMDE5MzcwMFoXDTI2MDQxOTE5MzY1OVowYjEoMCYGA1UEAwwfZWNjLXNtcC1icm9rZXItc2lnbl9VQzQtU0FOREJPWDEUMBIGA1UECwwLaU9TIFN5c3RlbXMxEzARBgNVBAoMCkFwcGxlIEluYy4xCzAJBgNVBAYTAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgjD9q8Oc914gLFDZm0US5jfiqQHdbLPgsc1LUmeY+M9OvegaJajCHkwz3c6OKpbC9q+hkwNFxOh6RCbOlRsSlaOCAhEwggINMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUI/JJxE+T5O8n5sT2KGw/orv9LkswRQYIKwYBBQUHAQEEOTA3MDUGCCsGAQUFBzABhilodHRwOi8vb2NzcC5hcHBsZS5jb20vb2NzcDA0LWFwcGxlYWljYTMwMjCCAR0GA1UdIASCARQwggEQMIIBDAYJKoZIhvdjZAUBMIH+MIHDBggrBgEFBQcCAjCBtgyBs1JlbGlhbmNlIG9uIHRoaXMgY2VydGlmaWNhdGUgYnkgYW55IHBhcnR5IGFzc3VtZXMgYWNjZXB0YW5jZSBvZiB0aGUgdGhlbiBhcHBsaWNhYmxlIHN0YW5kYXJkIHRlcm1zIGFuZCBjb25kaXRpb25zIG9mIHVzZSwgY2VydGlmaWNhdGUgcG9saWN5IGFuZCBjZXJ0aWZpY2F0aW9uIHByYWN0aWNlIHN0YXRlbWVudHMuMDYGCCsGAQUFBwIBFipodHRwOi8vd3d3LmFwcGxlLmNvbS9jZXJ0aWZpY2F0ZWF1dGhvcml0eS8wNAYDVR0fBC0wKzApoCegJYYjaHR0cDovL2NybC5hcHBsZS5jb20vYXBwbGVhaWNhMy5jcmwwHQYDVR0OBBYEFAIkMAua7u1GMZekplopnkJxghxFMA4GA1UdDwEB/wQEAwIHgDAPBgkqhkiG92NkBh0EAgUAMAoGCCqGSM49BAMCA0cAMEQCIHShsyTbQklDDdMnTFB0xICNmh9IDjqFxcE2JWYyX7yjAiBpNpBTq/ULWlL59gBNxYqtbFCn1ghoN5DgpzrQHkrZgTCCAu4wggJ1oAMCAQICCEltL786mNqXMAoGCCqGSM49BAMCMGcxGzAZBgNVBAMMEkFwcGxlIFJvb3QgQ0EgLSBHMzEmMCQGA1UECwwdQXBwbGUgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEzARBgNVBAoMCkFwcGxlIEluYy4xCzAJBgNVBAYTAlVTMB4XDTE0MDUwNjIzNDYzMFoXDTI5MDUwNjIzNDYzMFowejEuMCwGA1UEAwwlQXBwbGUgQXBwbGljYXRpb24gSW50ZWdyYXRpb24gQ0EgLSBHMzEmMCQGA1UECwwdQXBwbGUgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEzARBgNVBAoMCkFwcGxlIEluYy4xCzAJBgNVBAYTAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8BcRhBnXZIXVGl4lgQd26ICi7957rk3gjfxLk+EzVtVmWzWuItCXdg0iTnu6CP12F86Iy3a7ZnC+yOgphP9URaOB9zCB9DBGBggrBgEFBQcBAQQ6MDgwNgYIKwYBBQUHMAGGKmh0dHA6Ly9vY3NwLmFwcGxlLmNvbS9vY3NwMDQtYXBwbGVyb290Y2FnMzAdBgNVHQ4EFgQUI/JJxE+T5O8n5sT2KGw/orv9LkswDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS7sN6hWDOImqSKmd6+veuv2sskqzA3BgNVHR8EMDAuMCygKqAohiZodHRwOi8vY3JsLmFwcGxlLmNvbS9hcHBsZXJvb3RjYWczLmNybDAOBgNVHQ8BAf8EBAMCAQYwEAYKKoZIhvdjZAYCDgQCBQAwCgYIKoZIzj0EAwIDZwAwZAIwOs9yg1EWmbGG+zXDVspiv/QX7dkPdU2ijr7xnIFeQreJ+Jj3m1mfmNVBDY+d6cL+AjAyLdVEIbCjBXdsXfM4O5Bn/Rd8LCFtlk/GcmmCEm9U+Hp9G5nLmwmJIWEGmQ8Jkh0AADGCAYswggGHAgEBMIGGMHoxLjAsBgNVBAMMJUFwcGxlIEFwcGxpY2F0aW9uIEludGVncmF0aW9uIENBIC0gRzMxJjAkBgNVBAsMHUFwcGxlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRMwEQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUwIIWdihvKr0480wDQYJYIZIAWUDBAIBBQCggZUwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMjEwODIwMTUxMTI2WjAqBgkqhkiG9w0BCTQxHTAbMA0GCWCGSAFlAwQCAQUAoQoGCCqGSM49BAMCMC8GCSqGSIb3DQEJBDEiBCBbTnwDQ9EWz3DkgyYvt+knEgQVQi2YNez43Rg4rcv6nDAKBggqhkjOPQQDAgRGMEQCIETqwIAFQnXmvQB9uY4tqbRxu1oUFyflu92Eo6Do/LYaAiArImza1J6zlYjt4aNw/LkrOTk/LD1s2i2/8NMPmeAsQgAAAAAAAA==","header":{"ephemeralPublicKey":"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEHM7m7LSYllJofL8/T7Ajf6OC1J48iOvXKw4IRCJ5YK+7hkVV0iDwdLijJjtVrCp22EywLXk1VFFeJFU1X/mbMg==","publicKeyHash":"rEYX/7PdO7F7xL7rH0LZVak/iXTrkeU89Ck7E9dGFO4=","transactionId":"c943bc79e49bd3c023988a0681be4df68a30ee64c8360feba1920a320cc29bd0"}}'; $this->card->mobileType = EncyptedMobileType::APPLE_PAY; - $response = $this->card->charge(10) - ->withCurrency("EUR") + $response = $this->card->charge($this->amount) + ->withCurrency($this->currency) ->withModifier(TransactionModifier::ENCRYPTED_MOBILE) ->execute(); - $this->assertNotNull($response); - $this->assertEquals(TransactionStatus::CAPTURED, $response->responseMessage); - $this->assertEquals("SUCCESS", $response->responseCode); - $this->assertNotEmpty($response->transactionId); + $this->assertTransactionResponse($response, TransactionStatus::CAPTURED); } public function testPayWithDecryptedFlow() @@ -66,88 +69,92 @@ public function testPayWithDecryptedFlow() $this->card->eci = '5'; // process an auto-settle authorization - $response = $this->card->charge(5) - ->withCurrency("EUR") + $response = $this->card->charge($this->amount) + ->withCurrency($this->currency) ->withModifier(TransactionModifier::DECRYPTED_MOBILE) ->execute(); - $this->assertNotNull($response); - $this->assertEquals(TransactionStatus::CAPTURED, $response->responseMessage); - $this->assertEquals("SUCCESS", $response->responseCode); - $this->assertNotEmpty($response->transactionId); + $this->assertTransactionResponse($response, TransactionStatus::CAPTURED); $this->assertNotEmpty($response->authorizationCode); } } public function testPayWithGooglePayEncrypted() { - $this->card->token = '{ - "signature": "MEQCIE2fezqrrJr4//TzG6aYsp1Ihd+QXdVUJgdPxQfpDCJpAiALr2hGjQ4OohXMcuVyiuk4/oHun4eztmJ1V7lFYETeGg==", - "protocolVersion": "ECv1", - "signedMessage": "{\"encryptedMessage\":\"9N10ff2I6MVWZe+xJFUPRBKEiE7P3huy5qa4kWuUq12mVAyw0NxLoHMZ4y9m+nmbLGjywA4gSTlPCoXL1Eb+sX25XvftUtfO3bvvhGDsIgXrT/Cu3+oPRCm07kb+UNWwcVYJOVKB6FNr91oevuAT8rvPZ7Vx/jtdqiUWvpmEr+J3V9T+rYBSH4PwEL7387vbqjiFflE0wYYdzeuXVIs8CbHsxNa9YO4pZzM6jk5bsTRtl36PKrQ1aNZzheuOJvQVeaxkcjk2+rSHD8cU1WNo2FrxyEyvUgvN/PYxv30cKusKk5k/2YMMeZTncjBeGLhgqZ3Hl7NIv+mhisJmWTtANGwXE/xoqy5vpxyf7eYOaFWgMcQ7ZcDh05fqVVlsVN7Mm/ZDr+zBfN/YiLJvtrySVEo6dvWDvTF+V/mB9cBkX/M3mGFAs7PC1qmOY3fvbJGRUCUc\",\"ephemeralPublicKey\":\"BOtdvu/2vDRZK8ElgehukThcehz8Zww485/u+0GNkXHNhpw5BY/Lkf9XEx+mH/eRtmNn9ze4UdQbvob7JpWVDFQ\\u003d\",\"tag\":\"FtGB7h7vG/VKzDOV6/9ucdwaA2JKbGOaUw2Rx0kbA9c\\u003d\"}" - }'; + $this->card->token = $this->googlePayToken; $this->card->mobileType = EncyptedMobileType::GOOGLE_PAY; - $response = $this->card->charge(10) - ->withCurrency("EUR") + $response = $this->card->charge($this->amount) + ->withCurrency($this->currency) ->withModifier(TransactionModifier::ENCRYPTED_MOBILE) ->execute(); - $this->assertNotNull($response); - $this->assertEquals(TransactionStatus::CAPTURED, $response->responseMessage); - $this->assertEquals("SUCCESS", $response->responseCode); - $this->assertNotEmpty($response->transactionId); + $this->assertTransactionResponse($response, TransactionStatus::CAPTURED); } public function testGooglePayEncrypted_LinkedRefund() { - $this->card->token = '{ - "signature": "MEQCIE2fezqrrJr4//TzG6aYsp1Ihd+QXdVUJgdPxQfpDCJpAiALr2hGjQ4OohXMcuVyiuk4/oHun4eztmJ1V7lFYETeGg==", - "protocolVersion": "ECv1", - "signedMessage": "{\"encryptedMessage\":\"9N10ff2I6MVWZe+xJFUPRBKEiE7P3huy5qa4kWuUq12mVAyw0NxLoHMZ4y9m+nmbLGjywA4gSTlPCoXL1Eb+sX25XvftUtfO3bvvhGDsIgXrT/Cu3+oPRCm07kb+UNWwcVYJOVKB6FNr91oevuAT8rvPZ7Vx/jtdqiUWvpmEr+J3V9T+rYBSH4PwEL7387vbqjiFflE0wYYdzeuXVIs8CbHsxNa9YO4pZzM6jk5bsTRtl36PKrQ1aNZzheuOJvQVeaxkcjk2+rSHD8cU1WNo2FrxyEyvUgvN/PYxv30cKusKk5k/2YMMeZTncjBeGLhgqZ3Hl7NIv+mhisJmWTtANGwXE/xoqy5vpxyf7eYOaFWgMcQ7ZcDh05fqVVlsVN7Mm/ZDr+zBfN/YiLJvtrySVEo6dvWDvTF+V/mB9cBkX/M3mGFAs7PC1qmOY3fvbJGRUCUc\",\"ephemeralPublicKey\":\"BOtdvu/2vDRZK8ElgehukThcehz8Zww485/u+0GNkXHNhpw5BY/Lkf9XEx+mH/eRtmNn9ze4UdQbvob7JpWVDFQ\\u003d\",\"tag\":\"FtGB7h7vG/VKzDOV6/9ucdwaA2JKbGOaUw2Rx0kbA9c\\u003d\"}" - }'; + $this->card->token = $this->googlePayToken; $this->card->mobileType = EncyptedMobileType::GOOGLE_PAY; - $transaction = $this->card->charge(10) - ->withCurrency("EUR") + $transaction = $this->card->charge($this->amount) + ->withCurrency($this->currency) ->withModifier(TransactionModifier::ENCRYPTED_MOBILE) ->execute(); - $this->assertNotNull($transaction); - $this->assertEquals(TransactionStatus::CAPTURED, $transaction->responseMessage); - $this->assertEquals("SUCCESS", $transaction->responseCode); - $this->assertNotEmpty($transaction->transactionId); + $this->assertTransactionResponse($transaction, TransactionStatus::CAPTURED); - $refund = $transaction->refund()->withCurrency('EUR')->execute(); + $refund = $transaction->refund() + ->withCurrency($this->currency) + ->execute(); - $this->assertNotNull($refund); - $this->assertEquals('SUCCESS', $refund->responseCode); - $this->assertEquals(TransactionStatus::CAPTURED, $refund->responseMessage); + $this->assertTransactionResponse($refund, TransactionStatus::CAPTURED); } public function testGooglePayEncrypted_Reverse() { - $this->card->token = '{ - "signature": "MEQCIE2fezqrrJr4//TzG6aYsp1Ihd+QXdVUJgdPxQfpDCJpAiALr2hGjQ4OohXMcuVyiuk4/oHun4eztmJ1V7lFYETeGg==", - "protocolVersion": "ECv1", - "signedMessage": "{\"encryptedMessage\":\"9N10ff2I6MVWZe+xJFUPRBKEiE7P3huy5qa4kWuUq12mVAyw0NxLoHMZ4y9m+nmbLGjywA4gSTlPCoXL1Eb+sX25XvftUtfO3bvvhGDsIgXrT/Cu3+oPRCm07kb+UNWwcVYJOVKB6FNr91oevuAT8rvPZ7Vx/jtdqiUWvpmEr+J3V9T+rYBSH4PwEL7387vbqjiFflE0wYYdzeuXVIs8CbHsxNa9YO4pZzM6jk5bsTRtl36PKrQ1aNZzheuOJvQVeaxkcjk2+rSHD8cU1WNo2FrxyEyvUgvN/PYxv30cKusKk5k/2YMMeZTncjBeGLhgqZ3Hl7NIv+mhisJmWTtANGwXE/xoqy5vpxyf7eYOaFWgMcQ7ZcDh05fqVVlsVN7Mm/ZDr+zBfN/YiLJvtrySVEo6dvWDvTF+V/mB9cBkX/M3mGFAs7PC1qmOY3fvbJGRUCUc\",\"ephemeralPublicKey\":\"BOtdvu/2vDRZK8ElgehukThcehz8Zww485/u+0GNkXHNhpw5BY/Lkf9XEx+mH/eRtmNn9ze4UdQbvob7JpWVDFQ\\u003d\",\"tag\":\"FtGB7h7vG/VKzDOV6/9ucdwaA2JKbGOaUw2Rx0kbA9c\\u003d\"}" - }'; + $this->card->token = $this->googlePayToken; $this->card->mobileType = EncyptedMobileType::GOOGLE_PAY; - $transaction = $this->card->charge(10) - ->withCurrency("EUR") + $transaction = $this->card->charge($this->amount) + ->withCurrency($this->currency) ->withModifier(TransactionModifier::ENCRYPTED_MOBILE) ->execute(); + $this->assertTransactionResponse($transaction, TransactionStatus::CAPTURED); + + $reverse = $transaction->reverse() + ->withCurrency($this->currency) + ->execute(); + + $this->assertTransactionResponse($reverse, TransactionStatus::REVERSED); + } + + public function testGooglePayEncrypted_AuthAndReverse() + { + $this->card->token = $this->googlePayToken; + $this->card->mobileType = EncyptedMobileType::GOOGLE_PAY; + + $transaction = $this->card->authorize($this->amount) + ->withCurrency($this->currency) + ->withModifier(TransactionModifier::ENCRYPTED_MOBILE) + ->execute(); + + $this->assertTransactionResponse($transaction, TransactionStatus::PREAUTHORIZED); + + $reverse = $transaction->reverse() + ->withCurrency($this->currency) + ->execute(); + + $this->assertTransactionResponse($reverse, TransactionStatus::REVERSED); + } + + private function assertTransactionResponse($transaction, $transactionStatus) + { $this->assertNotNull($transaction); - $this->assertEquals(TransactionStatus::CAPTURED, $transaction->responseMessage); $this->assertEquals("SUCCESS", $transaction->responseCode); + $this->assertEquals($transactionStatus, $transaction->responseMessage); $this->assertNotEmpty($transaction->transactionId); - - $refund = $transaction->reverse()->withCurrency('EUR')->execute(); - - $this->assertNotNull($refund); - $this->assertEquals('SUCCESS', $refund->responseCode); - $this->assertEquals(TransactionStatus::REVERSED, $refund->responseMessage); } + } \ No newline at end of file diff --git a/test/Integration/Gateways/GpApiConnector/PartnershipModeTest.php b/test/Integration/Gateways/GpApiConnector/PartnershipModeTest.php new file mode 100644 index 00000000..1ee4ae7e --- /dev/null +++ b/test/Integration/Gateways/GpApiConnector/PartnershipModeTest.php @@ -0,0 +1,219 @@ +baseConfig = $this->setUpConfig(); + /** @var \GlobalPayments\Api\Entities\GpApi\AccessTokenInfo $accessTokenInfo */ + $accessTokenInfo = GpApiService::generateTransactionKey($this->baseConfig); + $this->accessToken = $accessTokenInfo->accessToken; + + $this->card = new CreditCardData(); + $this->card->number = "4263970000005262"; + $this->card->expMonth = date('m'); + $this->card->expYear = date('Y', strtotime('+1 year')); + $this->card->cvn = "131"; + $this->card->cardHolderName = "James Mason"; + $this->currency = 'EUR'; + $this->amount = '10.01'; + + $this->shippingAddress = new Address(); + $this->shippingAddress->streetAddress1 = "Apartment 852"; + $this->shippingAddress->streetAddress2 = "Complex 741"; + $this->shippingAddress->streetAddress3 = "no"; + $this->shippingAddress->city = "Chicago"; + $this->shippingAddress->postalCode = "5001"; + $this->shippingAddress->state = "IL"; + $this->shippingAddress->countryCode = "840"; + + $this->browserData = new BrowserData(); + $this->browserData->acceptHeader = "text/html,application/xhtml+xml,application/xml;q=9,image/webp,img/apng,*/*;q=0.8"; + $this->browserData->colorDepth = ColorDepth::TWENTY_FOUR_BITS; + $this->browserData->ipAddress = "123.123.123.123"; + $this->browserData->javaEnabled = true; + $this->browserData->javaScriptEnabled = true; + $this->browserData->language = "en"; + $this->browserData->screenHeight = 1080; + $this->browserData->screenWidth = 1920; + $this->browserData->challengWindowSize = ChallengeWindowSize::WINDOWED_600X400; + $this->browserData->timeZone = "0"; + $this->browserData->userAgent = "Mozilla/5.0 (Windows NT 6.1; Win64, x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36"; + } + + public function setUpConfig() + { + $config = new GpApiConfig(); + $config->appId = 'oDVjAddrXt3qPJVPqQvrmgqM2MjMoHQS'; + $config->appKey = 'DHUGdzpjXfTbjZeo'; + $config->environment = Environment::TEST; + $config->channel = Channel::CardNotPresent; + $config->requestLogger = new SampleRequestLogger(new Logger("logs")); + + return $config; + } + + public function testCreditSaleWithPartnerMode() + { + $this->markTestSkipped('Partner mode not enabled on this appId/appKey'); + $merchants = ['MER_7e3e2c7df34f42819b3edee31022ee3f','MER_c4c0df11039c48a9b63701adeaa296c3']; + $address = new Address(); + $address->streetAddress1 = "123 Main St."; + $address->city = "Downtown"; + $address->state = "NJ"; + $address->country = "US"; + $address->postalCode = "12345"; + foreach ($merchants as $merchantId) { + $config = clone($this->baseConfig); + $config->merchantId = $merchantId; + $config->accessTokenInfo = new AccessTokenInfo(); + $config->accessTokenInfo->accessToken = $this->accessToken; + $config->accessTokenInfo->transactionProcessingAccountName = 'transaction_processing'; + $configName = 'config_' . $merchantId; + ServicesContainer::configureService($config, $configName); + + $response = $this->card->charge(69) + ->withCurrency($this->currency) + ->withAddress($address) + ->execute($configName); + + $this->assertNotNull($response); + $this->assertEquals('SUCCESS', $response->responseCode); + $this->assertEquals(TransactionStatus::CAPTURED, $response->responseMessage); + unset($config); + } + } + + public function testFullCycle3DSChallenge_v2_PartnerMode() + { + $this->markTestSkipped('Partner mode not enabled on this appId/appKey'); + $this->card->number = '4222000001227408'; + $merchantId = 'MER_7e3e2c7df34f42819b3edee31022ee3f'; + + $config = clone($this->baseConfig); + $config->merchantId = $merchantId; + $config->accessTokenInfo = new AccessTokenInfo(); + $config->accessTokenInfo->accessToken = $this->accessToken; + $config->accessTokenInfo->transactionProcessingAccountName = 'transaction_processing'; + $config->challengeNotificationUrl = 'https://ensi808o85za.x.pipedream.net/'; + $config->methodNotificationUrl = 'https://ensi808o85za.x.pipedream.net/'; + $config->merchantContactUrl = 'https://enp4qhvjseljg.x.pipedream.net/'; + + $configName = 'config_' . $merchantId; + ServicesContainer::configureService($config, $configName); + + $secureEcom = Secure3dService::checkEnrollment($this->card) + ->withCurrency($this->currency) + ->withAmount($this->amount) + ->execute($configName); + + $this->assertNotNull($secureEcom); + $this->assertEquals(Secure3dStatus::ENROLLED, $secureEcom->enrolled); + $this->assertEquals(Secure3dVersion::TWO, $secureEcom->getVersion()); + $this->assertEquals(Secure3dStatus::AVAILABLE, $secureEcom->status); + + $initAuth = Secure3dService::initiateAuthentication($this->card, $secureEcom) + ->withAmount($this->amount) + ->withCurrency($this->currency) + ->withAuthenticationSource(AuthenticationSource::BROWSER) + ->withMethodUrlCompletion(MethodUrlCompletion::YES) + ->withOrderCreateDate(date('Y-m-d H:i:s')) + ->withAddress($this->shippingAddress, AddressType::SHIPPING) + ->withBrowserData($this->browserData) + ->execute($configName); + + $this->assertNotNull($initAuth); + $this->assertEquals(Secure3dStatus::CHALLENGE_REQUIRED, $initAuth->status); + $this->assertNotNull($initAuth->issuerAcsUrl); + $this->assertNotNull($initAuth->payerAuthenticationRequest); + + $authClient = new ThreeDSecureAcsClient($secureEcom->issuerAcsUrl); + $authClient->setGatewayProvider($config->getGatewayProvider()); + $authResponse = $authClient->authenticate_v2($initAuth); + $this->assertTrue($authResponse->getStatus()); + $this->assertNotEmpty($authResponse->getMerchantData()); + + $secureEcom = Secure3dService::getAuthenticationData() + ->withServerTransactionId($authResponse->getMerchantData()) + ->execute($configName); + $this->card->threeDSecure = $secureEcom; + + $this->assertEquals(Secure3dStatus::SUCCESS_AUTHENTICATED, $secureEcom->status); + $this->assertEquals('YES', $secureEcom->liabilityShift); + + $response = $this->card->charge($this->amount)->withCurrency($this->currency)->execute($configName); + $this->assertNotNull($response); + $this->assertEquals('SUCCESS', $response->responseCode); + $this->assertEquals(TransactionStatus::CAPTURED, $response->responseMessage); + } + + public function testVerifyTokenizedPaymentMethodWithPartnerMode() + { + $this->markTestSkipped('Partner mode not enabled on this appId/appKey'); + $merchantId = 'MER_7e3e2c7df34f42819b3edee31022ee3f'; + + $config = clone($this->baseConfig); + $config->merchantId = $merchantId; + $config->accessTokenInfo = new AccessTokenInfo(); + $config->accessTokenInfo->accessToken = $this->accessToken; + $config->accessTokenInfo->transactionProcessingAccountName = 'transaction_processing'; + + $configName = 'config_' . $merchantId; + ServicesContainer::configureService($config, $configName); + + $response = $this->card->tokenize()->execute($configName); + $this->assertNotNull($response); + $this->assertEquals('SUCCESS', $response->responseCode); + $this->assertEquals('ACTIVE', $response->responseMessage); + + $tokenizedCard = new CreditCardData(); + $tokenizedCard->token = $response->token; + + $response = $tokenizedCard->verify() + ->withCurrency($this->currency) + ->execute($configName); + + $this->assertNotNull($response); + $this->assertEquals('SUCCESS', $response->responseCode); + $this->assertEquals('VERIFIED', $response->responseMessage); + } +} \ No newline at end of file diff --git a/test/Integration/Gateways/GpApiConnector/ReportingActionsTest.php b/test/Integration/Gateways/GpApiConnector/ReportingActionsTest.php index c9f83bb3..b657cedf 100644 --- a/test/Integration/Gateways/GpApiConnector/ReportingActionsTest.php +++ b/test/Integration/Gateways/GpApiConnector/ReportingActionsTest.php @@ -1,8 +1,8 @@ modify('-30 days')->setTime(0, 0, 0); - $endDate = (new \DateTime())->modify('-3 days')->setTime(0, 0, 0); + $startDate = (new DateTime())->modify('-30 days')->setTime(0, 0, 0); + $endDate = (new DateTime())->modify('-3 days')->setTime(0, 0, 0); $response = ReportingService::findActionsPaged(1, 10) ->orderBy(StoredPaymentMethodSortProperty::TIME_CREATED, SortDirection::ASC) @@ -108,7 +108,7 @@ public function testFindActions_FilterBy_RandomId() $this->assertNotNull($response); $this->assertTrue(empty($response->result)); - $this->assertEquals(0, count($response->result)); + $this->assertCount(0, $response->result); } public function testFindActions_FilterBy_Type() @@ -136,7 +136,7 @@ public function testFindActions_FilterBy_RandomType() $this->assertNotNull($response); $this->assertEmpty($response->result); - $this->assertEquals(0, count($response->result)); + $this->assertCount(0, $response->result); } public function testFindActions_FilterBy_Resource() @@ -197,7 +197,7 @@ public function testFindActions_FilterBy_RandomResourceId() $this->assertNotNull($response); $this->assertTrue(is_array($response->result)); - $this->assertEquals(0, count($response->result)); + $this->assertCount(0, $response->result); } public function testFindActions_FilterBy_MerchantName() @@ -298,7 +298,7 @@ public function testFindActions_FilterBy_WrongVersion() $this->assertNotNull($response); $this->assertTrue(is_array($response->result)); - $this->assertEquals(0, count($response->result)); + $this->assertCount(0, $response->result); } public function testFindActions_FilterBy_ResponseCode() @@ -389,8 +389,8 @@ public function testFindActions_FilterBy_MultipleFilters() $resource = 'TRANSACTIONS'; $actionType = 'AUTHORIZE'; $resource_status = 'DECLINED'; - $startDate = (new \DateTime())->modify('-30 days'); - $endDate = (new \DateTime())->modify('-3 days'); + $startDate = (new DateTime())->modify('-30 days'); + $endDate = (new DateTime())->modify('-3 days'); $response = ReportingService::findActionsPaged(1, 10) ->where(SearchCriteria::RESOURCE, $resource) diff --git a/test/Integration/Gateways/GpApiConnector/ReportingDepositsTest.php b/test/Integration/Gateways/GpApiConnector/ReportingDepositsTest.php index 65e9ee52..1d3b4f67 100644 --- a/test/Integration/Gateways/GpApiConnector/ReportingDepositsTest.php +++ b/test/Integration/Gateways/GpApiConnector/ReportingDepositsTest.php @@ -3,8 +3,8 @@ namespace Gateways\GpApiConnector; use GlobalPayments\Api\Entities\Enums\Environment; -use GlobalPayments\Api\Entities\Enums\GpApi\DepositSortProperty; -use GlobalPayments\Api\Entities\Enums\GpApi\SortDirection; +use GlobalPayments\Api\Entities\Enums\DepositSortProperty; +use GlobalPayments\Api\Entities\Enums\SortDirection; use GlobalPayments\Api\Entities\Exceptions\ApiException; use GlobalPayments\Api\Entities\Reporting\DataServiceCriteria; use GlobalPayments\Api\Entities\Reporting\DepositSummary; diff --git a/test/Integration/Gateways/GpApiConnector/ReportingDisputesTest.php b/test/Integration/Gateways/GpApiConnector/ReportingDisputesTest.php index 8a8c9941..243bdc6d 100644 --- a/test/Integration/Gateways/GpApiConnector/ReportingDisputesTest.php +++ b/test/Integration/Gateways/GpApiConnector/ReportingDisputesTest.php @@ -5,10 +5,10 @@ use GlobalPayments\Api\Entities\DisputeDocument; use GlobalPayments\Api\Entities\Enums\CardType; use GlobalPayments\Api\Entities\Enums\Environment; -use GlobalPayments\Api\Entities\Enums\GpApi\DisputeSortProperty; -use GlobalPayments\Api\Entities\Enums\GpApi\DisputeStage; -use GlobalPayments\Api\Entities\Enums\GpApi\DisputeStatus; -use GlobalPayments\Api\Entities\Enums\GpApi\SortDirection; +use GlobalPayments\Api\Entities\Enums\DisputeSortProperty; +use GlobalPayments\Api\Entities\Enums\DisputeStage; +use GlobalPayments\Api\Entities\Enums\DisputeStatus; +use GlobalPayments\Api\Entities\Enums\SortDirection; use GlobalPayments\Api\Entities\Exceptions\GatewayException; use GlobalPayments\Api\Entities\GpApi\PagedResult; use GlobalPayments\Api\Entities\Reporting\DataServiceCriteria; @@ -22,7 +22,6 @@ class ReportingDisputesTest extends TestCase { private $arn; - private $depositReference; public function setup() { @@ -48,7 +47,6 @@ public function testReportDisputeDetail() $this->assertInstanceOf(DisputeSummary::class, $response); $this->assertEquals($disputeId, $response->caseId); $this->arn = $response->transactionARN; - $this->depositReference = $response->depositReference; } public function testReportDisputeDetailWrongId() @@ -771,18 +769,18 @@ public function testReportDisputeChallengeWrongId() public function testFindSettlementDisputesPaged_FilterBy_DepositId() { - $this->markTestSkipped('GP-API sandbox limitation'); $startDate = (new \DateTime())->modify('-2 year +1 day'); - + $depositReference = 'DEP_2342423443'; $disputes = ReportingService::findSettlementDisputesPaged(1, 10) ->where(DataServiceCriteria::START_STAGE_DATE, $startDate) - ->andWith(DataServiceCriteria::DEPOSIT_REFERENCE, $this->depositReference) + ->andWith(DataServiceCriteria::DEPOSIT_REFERENCE, $depositReference) ->execute(); $this->assertNotNull($disputes); - $this->assertNotEquals(0 , count($disputes->result)); + /** @var DisputeSummary $dispute */ + $this->assertNotCount(0, $disputes->result); foreach ($disputes->result as $dispute) { - $this->assertEquals($this->depositReference, $dispute->depositReference); + $this->assertEquals($depositReference, $dispute->depositReference); } } } \ No newline at end of file diff --git a/test/Integration/Gateways/GpApiConnector/ReportingSettlementTransactionsTest.php b/test/Integration/Gateways/GpApiConnector/ReportingSettlementTransactionsTest.php index 4b83da87..b815c99b 100644 --- a/test/Integration/Gateways/GpApiConnector/ReportingSettlementTransactionsTest.php +++ b/test/Integration/Gateways/GpApiConnector/ReportingSettlementTransactionsTest.php @@ -3,9 +3,9 @@ namespace Gateways\GpApiConnector; use GlobalPayments\Api\Entities\Enums\Environment; -use GlobalPayments\Api\Entities\Enums\GpApi\DepositStatus; -use GlobalPayments\Api\Entities\Enums\GpApi\SortDirection; -use GlobalPayments\Api\Entities\Enums\GpApi\TransactionSortProperty; +use GlobalPayments\Api\Entities\Enums\DepositStatus; +use GlobalPayments\Api\Entities\Enums\SortDirection; +use GlobalPayments\Api\Entities\Enums\TransactionSortProperty; use GlobalPayments\Api\Entities\Enums\TransactionStatus; use GlobalPayments\Api\Entities\Exceptions\ApiException; use GlobalPayments\Api\Entities\Exceptions\GatewayException; @@ -208,7 +208,7 @@ public function testReportFindSettlementTransactions_FilterBy_Wrong_CardBrand() } $this->assertNotNull($response->result); $this->assertTrue(is_array($response->result)); - $this->assertEquals(0, count($response->result)); + $this->assertCount(0, $response->result); } public function testReportFindSettlementTransactions_FilterBy_ARN() @@ -249,7 +249,7 @@ public function testReportFindSettlementTransactions_FilterBy_Wrong_ARN() } $this->assertNotNull($response); $this->assertTrue(is_array($response->result)); - $this->assertEquals(0, count($response->result)); + $this->assertCount(0, $response->result); } public function testReportFindSettlementTransactions_FilterBy_BrandReference() @@ -291,7 +291,7 @@ public function testReportFindSettlementTransactions_FilterBy_Wrong_BrandReferen } $this->assertNotNull($response); $this->assertTrue(is_array($response->result)); - $this->assertEquals(0, count($response->result)); + $this->assertCount(0, $response->result); } public function testReportFindSettlementTransactions_FilterBy_AuthCode() @@ -355,16 +355,17 @@ public function testReportFindSettlementTransactions_FilterBy_Random_Reference() } $this->assertNotNull($response); $this->assertTrue(is_array($response->result)); - $this->assertEquals(0, count($response->result)); + $this->assertCount(0, $response->result); } + /** + * Settlement transactions report supports filter by transaction status only for values FUNDED and REJECTED + */ public function testReportFindSettlementTransactions_FilterBy_Status() { - //only for Status = FUNDED and REJECTED $startDate = (new \DateTime())->modify('-30 days'); - $transactionStatus = new TransactionStatus(); - $reflectionClass = new ReflectionClass($transactionStatus); - foreach ($reflectionClass->getConstants() as $value) { + $settleTransactionStatus = [TransactionStatus::FUNDED, TransactionStatus::REJECTED]; + foreach ($settleTransactionStatus as $value) { try { $response = ReportingService::findSettlementTransactionsPaged(1, 10) ->orderBy(TransactionSortProperty::TIME_CREATED, SortDirection::DESC) @@ -381,7 +382,7 @@ public function testReportFindSettlementTransactions_FilterBy_Status() foreach ($response->result as $rs) { $this->assertInstanceOf(TransactionSummary::class, $rs); $this->assertGreaterThanOrEqual($startDate, $rs->transactionDate); - $this->assertEquals(TransactionStatus::$mapTransactionStatusResponse[$value], $rs->transactionStatus); + $this->assertEquals($value, $rs->transactionStatus); } } } @@ -425,7 +426,7 @@ public function testReportFindSettlementTransactions_FilterBy_Random_DepositID() } $this->assertNotNull($response); $this->assertTrue(is_array($response->result)); - $this->assertEquals(0, count($response->result)); + $this->assertCount(0, $response->result); } public function testReportFindSettlementTransactions_FilterBy_FromDepositTimeCreated_And_ToDepositTimeCreated() @@ -513,7 +514,7 @@ public function testReportFindSettlementTransactions_FilterBy_Random_MerchantID( } $this->assertNotNull($response); $this->assertTrue(is_array($response->result)); - $this->assertEquals(0, count($response->result)); + $this->assertCount(0, $response->result); } public function testReportFindSettlementTransactions_FilterBy_Random_SystemHierarchy() @@ -532,7 +533,7 @@ public function testReportFindSettlementTransactions_FilterBy_Random_SystemHiera } $this->assertNotNull($response); $this->assertTrue(is_array($response->result)); - $this->assertEquals(0, count($response->result)); + $this->assertCount(0, $response->result); } public function testReportFindSettlementTransactions_FilterBy_Invalid_MerchantID() diff --git a/test/Integration/Gateways/GpApiConnector/ReportingStoredPaymentMethodsTest.php b/test/Integration/Gateways/GpApiConnector/ReportingStoredPaymentMethodsTest.php index 1a9236e4..2c3bb832 100644 --- a/test/Integration/Gateways/GpApiConnector/ReportingStoredPaymentMethodsTest.php +++ b/test/Integration/Gateways/GpApiConnector/ReportingStoredPaymentMethodsTest.php @@ -2,8 +2,8 @@ use GlobalPayments\Api\Entities\Enums\Environment; -use GlobalPayments\Api\Entities\Enums\GpApi\SortDirection; -use GlobalPayments\Api\Entities\Enums\GpApi\StoredPaymentMethodSortProperty; +use GlobalPayments\Api\Entities\Enums\SortDirection; +use GlobalPayments\Api\Entities\Enums\StoredPaymentMethodSortProperty; use GlobalPayments\Api\Entities\Exceptions\GatewayException; use GlobalPayments\Api\Entities\Reporting\SearchCriteria; use GlobalPayments\Api\Entities\Reporting\StoredPaymentMethodSummary; @@ -32,8 +32,8 @@ public function setUpConfig() public function testFindStoredPaymentMethod_By_StartDateAndEndDate() { - $startDate = (new \DateTime())->modify('-30 days')->setTime(0, 0, 0); - $endDate = (new \DateTime())->modify('-3 days')->setTime(0, 0, 0); + $startDate = (new DateTime())->modify('-30 days')->setTime(0, 0, 0); + $endDate = (new DateTime())->modify('-3 days')->setTime(0, 0, 0); $response = ReportingService::findStoredPaymentMethodsPaged(1, 10) ->orderBy(StoredPaymentMethodSortProperty::TIME_CREATED, SortDirection::ASC) @@ -58,8 +58,8 @@ public function testFindStoredPaymentMethod_By_StartDateAndEndDate() public function testFindStoredPaymentMethod_By_LastUpdated() { - $startDate = (new \DateTime())->modify('-30 days')->setTime(0, 0, 0); - $endDate = (new \DateTime())->modify('-3 days')->setTime(0, 0, 0); + $startDate = (new DateTime())->modify('-30 days')->setTime(0, 0, 0); + $endDate = (new DateTime())->modify('-3 days')->setTime(0, 0, 0); $response = ReportingService::findStoredPaymentMethodsPaged(1, 10) ->orderBy(StoredPaymentMethodSortProperty::TIME_CREATED, SortDirection::ASC) @@ -74,7 +74,7 @@ public function testFindStoredPaymentMethod_By_LastUpdated() public function testFindStoredPaymentMethod_By_LastUpdated_CurrentDay() { - $currentDay = (new \DateTime()); + $currentDay = (new DateTime()); $response = ReportingService::findStoredPaymentMethodsPaged(1, 10) ->orderBy(StoredPaymentMethodSortProperty::TIME_CREATED, SortDirection::ASC) diff --git a/test/Integration/Gateways/GpApiConnector/ReportingTransactionsTest.php b/test/Integration/Gateways/GpApiConnector/ReportingTransactionsTest.php index 7bdfa419..def584b7 100644 --- a/test/Integration/Gateways/GpApiConnector/ReportingTransactionsTest.php +++ b/test/Integration/Gateways/GpApiConnector/ReportingTransactionsTest.php @@ -3,11 +3,11 @@ namespace Gateways\GpApiConnector; use GlobalPayments\Api\Entities\Enums\Environment; -use GlobalPayments\Api\Entities\Enums\GpApi\Channels; -use GlobalPayments\Api\Entities\Enums\GpApi\EntryMode; +use GlobalPayments\Api\Entities\Enums\Channel; +use GlobalPayments\Api\Entities\Enums\PaymentEntryMode; use GlobalPayments\Api\Entities\Enums\PaymentType; -use GlobalPayments\Api\Entities\Enums\GpApi\SortDirection; -use GlobalPayments\Api\Entities\Enums\GpApi\TransactionSortProperty; +use GlobalPayments\Api\Entities\Enums\SortDirection; +use GlobalPayments\Api\Entities\Enums\TransactionSortProperty; use GlobalPayments\Api\Entities\Enums\PaymentMethodName; use GlobalPayments\Api\Entities\Enums\TransactionStatus; use GlobalPayments\Api\Entities\Exceptions\ApiException; @@ -93,7 +93,7 @@ public function testReportFindTransactionsById() $this->assertNotNull($response); $this->assertTrue(is_array($response->result)); - $this->assertEquals(1, count($response->result)); + $this->assertCount(1, $response->result); $this->assertEquals($transactionId, $response->result[0]->transactionId); } @@ -112,7 +112,7 @@ public function testReportFindTransactionsById_WrongId() $this->assertNotNull($response); $this->assertTrue(is_array($response->result)); - $this->assertEquals(0, count($response->result)); + $this->assertCount(0, $response->result); } public function testReportFindTransactionsByBatchId() @@ -209,7 +209,7 @@ public function testReportFindTransactionsByAmountAndCurrencyAndCountry() public function testReportFindTransactionsByChannel() { - $channel = Channels::CardNotPresent; + $channel = Channel::CardNotPresent; $startDate = new \DateTime('2020-11-01 midnight'); try { $response = ReportingService::findTransactionsPaged(1, 10) @@ -228,7 +228,7 @@ public function testReportFindTransactionsByChannel() $this->assertEquals($channel, $rs->channel); } - $channelCP = Channels::CardPresent; + $channelCP = Channel::CardPresent; try { $responseCP = ReportingService::findTransactionsPaged(1, 10) ->orderBy(TransactionSortProperty::TIME_CREATED, SortDirection::DESC) @@ -386,7 +386,7 @@ public function testReportFindTransactionsBy_WrongReference() $this->assertNotNull($response); $this->assertTrue(is_array($response->result)); - $this->assertEquals(0, count($response->result)); + $this->assertCount(0, $response->result); } public function testReportFindTransactionsByBrandReference() @@ -427,13 +427,13 @@ public function testReportFindTransactionsBy_WrongBrandReference() $this->assertNotNull($response); $this->assertTrue(is_array($response->result)); - $this->assertEquals(0, count($response->result)); + $this->assertCount(0, $response->result); } public function testReportFindTransactionsByEntryMode() { $startDate = new \DateTime('2020-11-01 midnight'); - $entryMode = new EntryMode(); + $entryMode = new PaymentEntryMode(); $reflectionClass = new ReflectionClass($entryMode); foreach ($reflectionClass->getConstants() as $value) { try { diff --git a/test/Integration/Gateways/RealexConnector/RealexApmTest.php b/test/Integration/Gateways/RealexConnector/RealexApmTest.php index 67755dd0..fccdb5ee 100644 --- a/test/Integration/Gateways/RealexConnector/RealexApmTest.php +++ b/test/Integration/Gateways/RealexConnector/RealexApmTest.php @@ -163,6 +163,25 @@ public function testAPMRefundPendingTransaction() ->execute(); } + public function testAPMPayByBankApp() + { + $paymentMethod = new AlternativePaymentMethod(AlternativePaymentType::PAYBYBANKAPP); + + $paymentMethod->returnUrl = 'https://www.example.com/returnUrl'; + $paymentMethod->statusUpdateUrl = 'https://www.example.com/statusUrl'; + $paymentMethod->descriptor = 'Test Transaction'; + $paymentMethod->country = 'GB'; + $paymentMethod->accountHolderName = 'James Mason'; + + $response = $paymentMethod->charge(10) + ->withCurrency("EUR") + ->withDescription('New APM') + ->execute(); + + $this->assertNotEquals(null, $response); + $this->assertEquals("01", $response->responseCode); + } + public function testApmForRefund() { // a settle request requires the original order id diff --git a/test/Integration/TrackDataTest.php b/test/Integration/TrackDataTest.php new file mode 100644 index 00000000..d390a239 --- /dev/null +++ b/test/Integration/TrackDataTest.php @@ -0,0 +1,152 @@ +setValue('%B5473500000000014^MC TEST CARD^251210199998888777766665555444433332?'); + $this->assertEquals('MC', $track->cardType); + $this->assertEquals('5473500000000014', $track->pan); + $this->assertEquals('2512', $track->expiry); + $this->assertFalse($track->isFleet); + $this->assertNotNull($track->trackData); + } + public function testMastercardTrack1Truncated() + { + $track = new CreditTrackData(); + $track->setValue('B5473500000000014^MC TEST CARD^2512'); + $this->assertEquals('5473500000000014', $track->pan); + $this->assertEquals('2512', $track->expiry); + $this->assertEquals('MC', $track->cardType); + $this->assertFalse($track->isFleet); + $this->assertNotNull($track->trackData); + } + + public function testMastercardTrack2() + { + $track = new CreditTrackData(); + $track->setValue(';5473500000000014=25121019999888877776?'); + $this->assertEquals('MC', $track->cardType); + $this->assertEquals('5473500000000014', $track->pan); + $this->assertEquals('2512', $track->expiry); + $this->assertFalse($track->isFleet); + $this->assertNotNull($track->trackData); + } + + public function testMastercardTrack2Truncated() + { + $track = new CreditTrackData(); + $track->setValue('5473500000000014=2512'); + $this->assertEquals('MC', $track->cardType); + $this->assertEquals('5473500000000014', $track->pan); + $this->assertEquals('2512', $track->expiry); + $this->assertFalse($track->isFleet); + $this->assertNotNull($track->trackData); + } + + public function testMastercardFleet() + { + $track = new CreditTrackData(); + $track->setValue('5532320000001113=20121019999888877712'); + $this->assertEquals('MCFleet', $track->cardType); + $this->assertEquals('5532320000001113', $track->pan); + $this->assertEquals('2012', $track->expiry); + $this->assertTrue($track->isFleet); + $this->assertNotNull($track->trackData); + } + + public function testVisaTrack1() + { + $track = new CreditTrackData(); + $track->setValue('%B4012002000060016^VI TEST CREDIT^251210118039000000000396?'); + $this->assertEquals('Visa', $track->cardType); + $this->assertEquals('4012002000060016', $track->pan); + $this->assertEquals('2512', $track->expiry); + $this->assertFalse($track->isFleet); + $this->assertNotNull($track->trackData); + } + + public function testVisaTrack2() + { + $track = new CreditTrackData(); + $track->setValue('4012002000060016=25121011803939600000'); + $this->assertEquals('Visa', $track->cardType); + $this->assertEquals('4012002000060016', $track->pan); + $this->assertEquals('1011803939600000', $track->discretionaryData); + $this->assertEquals('2512', $track->expiry); + $this->assertFalse($track->isFleet); + $this->assertNotNull($track->trackData); + } + + public function testVisaBothTracks() + { + $track = new CreditTrackData(); + $track->setValue('%B4012002000060016^VI TEST CREDIT^251210118039000000000396?;4012002000060016=25121011803939600000?'); + $this->assertEquals('Visa', $track->cardType); + $this->assertEquals('4012002000060016', $track->pan); + $this->assertEquals('2512', $track->expiry); + $this->assertFalse($track->isFleet); + $this->assertNotNull($track->trackData); + } + + public function testVisaFleet() + { + $track = new CreditTrackData(); + $track->setValue('%B4485531111111118^VISA TEST CARD/GOOD^20121019206100000000003?'); + $this->assertEquals('VisaFleet', $track->cardType); + $this->assertEquals('4485531111111118', $track->pan); + $this->assertEquals('2012', $track->expiry); + $this->assertTrue($track->isFleet); + $this->assertNotNull($track->trackData); + } + + public function testWexFleetTrack1() + { + $track = new CreditTrackData(); + $track->setValue("%B6900460000001113^WEX FLEET TEST^20121019999888877712?"); + $this->assertEquals('WexFleet', $track->cardType); + $this->assertEquals('6900460000001113', $track->pan); + $this->assertEquals('2012', $track->expiry); + $this->assertTrue($track->isFleet); + $this->assertNotNull($track->trackData); + } + + public function testWexFleetTrack2() + { + $track = new CreditTrackData(); + $track->setValue("6900460000001113=20121019999888877712"); + $this->assertEquals('WexFleet', $track->cardType); + $this->assertEquals('6900460000001113', $track->pan); + $this->assertEquals('2012', $track->expiry); + $this->assertTrue($track->isFleet); + $this->assertNotNull($track->trackData); + } + + public function testVoyagerFleetTrack1() + { + $track = new CreditTrackData(); + $track->setValue("B7088890000001113^VOYAGER FLEET TEST^20121019999888877712"); + + $this->assertEquals('VoyagerFleet', $track->cardType); + $this->assertEquals('7088890000001113', $track->pan); + $this->assertEquals('2012', $track->expiry); + $this->assertTrue($track->isFleet); + $this->assertNotNull($track->trackData); + } + + public function testVoyagerFleetTrack2() + { + $track = new CreditTrackData(); + $track->setValue("7088850000001113=20121019999888877712"); + + $this->assertEquals('VoyagerFleet', $track->cardType); + $this->assertEquals('7088850000001113', $track->pan); + $this->assertEquals('2012', $track->expiry); + $this->assertTrue($track->isFleet); + $this->assertNotNull($track->trackData); + } +} \ No newline at end of file