diff --git a/CHANGELOG.md b/CHANGELOG.md index e7f1c1aa..fdf95fca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,12 @@ ## Latest Version #### Enhancements: +- GP-API: Manage merchant accounts for partner solution + (https://developer.globalpay.com/api/accounts) +- GP-ECOM: Add to the mapping response fields: acs_reference_number & acs_signed_content for the authentication source MOBILE_SDK + +## v7.0.1 (04/04/2023) +#### Enhancements: - Portico/Heartland: improvements to transaction request building logic - GP-API: Unit tests update on fraud management and APMs - GP-ECOM: Unit test update on 3DS diff --git a/metadata.xml b/metadata.xml index aa6a849c..377cccb1 100644 --- a/metadata.xml +++ b/metadata.xml @@ -1,3 +1,3 @@ - 7.0.1 + 7.0.2 \ No newline at end of file diff --git a/src/Builders/PayFacBuilder.php b/src/Builders/PayFacBuilder.php index 0c6a56fa..8c1bdd80 100644 --- a/src/Builders/PayFacBuilder.php +++ b/src/Builders/PayFacBuilder.php @@ -1,7 +1,10 @@ getPayFac($configName); - switch ($this->transactionModifier) - { - case TransactionModifier::MERCHANT: - return $client->processBoardingUser($this); - default: - return $client->processPayFac($this); + if ( + method_exists($client, "hasBuiltInMerchantManagementService") && + $client->hasBuiltInMerchantManagementService() + ) { + return $client->processBoardingUser($this); } + + return $client->processPayFac($this); } public function __get($name) @@ -254,6 +261,12 @@ protected function setupValidations() ) ->with(TransactionModifier::MERCHANT) ->check('userId')->isNotNull(); + + $this->validations->of( + TransactionType::CREATE + ) + ->with(TransactionModifier::MERCHANT) + ->check('userPersonalData')->isNotNull(); } /* @@ -562,4 +575,15 @@ public function withIdempotencyKey($value) return $this; } + + public function withAddress(Address $address, $type = AddressType::BILLING) + { + if (!isset($this->addresses)) { + $this->addresses = new AddressCollection(); + } + + $this->addresses->add($address, $type); + + return $this; + } } diff --git a/src/Builders/ReportBuilder.php b/src/Builders/ReportBuilder.php index 5ccd1505..1ae46091 100644 --- a/src/Builders/ReportBuilder.php +++ b/src/Builders/ReportBuilder.php @@ -5,6 +5,7 @@ use GlobalPayments\Api\Entities\Enums\ReportType; use GlobalPayments\Api\Entities\Enums\TimeZoneConversion; use GlobalPayments\Api\Entities\Enums\TransactionType; +use GlobalPayments\Api\Entities\Reporting\SearchCriteriaBuilder; use GlobalPayments\Api\ServicesContainer; abstract class ReportBuilder extends BaseBuilder @@ -64,6 +65,14 @@ public function execute($configName = 'default') return $client->processReport($this); } + /** + * @return SearchCriteriaBuilder + */ + public function where($criteria, $value) + { + return $this->searchBuilder->andWith($criteria, $value); + } + /** * Set the gateway paging criteria for the report * @param $page diff --git a/src/Builders/RequestBuilder/GpApi/GpApiPayFacRequestBuilder.php b/src/Builders/RequestBuilder/GpApi/GpApiPayFacRequestBuilder.php index e1b0e9b3..a688689e 100644 --- a/src/Builders/RequestBuilder/GpApi/GpApiPayFacRequestBuilder.php +++ b/src/Builders/RequestBuilder/GpApi/GpApiPayFacRequestBuilder.php @@ -55,7 +55,7 @@ public function buildRequest(BaseBuilder $builder, $config) $requestData = $queryParams = null; switch ($builder->transactionType) { case TransactionType::CREATE: - if (TransactionModifier::MERCHANT) { + if ($builder->transactionModifier == TransactionModifier::MERCHANT) { $endpoint = GpApiRequest::MERCHANT_MANAGEMENT_ENDPOINT; $verb = 'POST'; if (empty($builder->userPersonalData)) { @@ -64,21 +64,37 @@ public function buildRequest(BaseBuilder $builder, $config) $requestData = $this->buildCreateMerchantRequest(); } break; - case TransactionType::EDIT: - if (TransactionModifier::MERCHANT) { - $endpoint = GpApiRequest::MERCHANT_MANAGEMENT_ENDPOINT . '/' . $builder->userReference->userId; - $verb = 'PATCH'; - $requestData = $this->buildEditMerchantRequest(); - } - break; case TransactionType::FETCH: - if (TransactionModifier::MERCHANT) { + if ($builder->transactionModifier == TransactionModifier::MERCHANT) { $endpoint = GpApiRequest::MERCHANT_MANAGEMENT_ENDPOINT . '/' . $builder->userId; $verb = 'GET'; } break; + case TransactionType::EDIT: + $verb = 'PATCH'; + if ($builder->transactionModifier == TransactionModifier::MERCHANT) { + $endpoint = GpApiRequest::MERCHANT_MANAGEMENT_ENDPOINT . '/' . $builder->userReference->userId; + $requestData = $this->buildEditMerchantRequest(); + } else { + $endpoint = ''; + if (!empty($builder->userReference->userId)) { + $endpoint = GpApiRequest::MERCHANT_MANAGEMENT_ENDPOINT . '/' . $builder->userReference->userId; + } + $endpoint .= GpApiRequest::ACCOUNTS_ENDPOINT . '/' . $builder->accountNumber; + $requestData['payer'] = [ + 'payment_method' => [ + 'name' => $this->builder->creditCardInformation instanceof CreditCardData ? + $this->builder->creditCardInformation->cardHolderName : null, + 'card' => $this->builder->creditCardInformation instanceof CreditCardData ? + $this->mapCreditCardInfo($this->builder->creditCardInformation) : null + ], + 'billing_address' => + !empty($this->builder->addresses) && $this->builder->addresses->offsetExists(AddressType::BILLING) ? + $this->mapAddress($this->builder->addresses->get(AddressType::BILLING), 'alpha2') : null + ]; + } default: - return ''; + break; } if (empty($endpoint)) { @@ -120,16 +136,8 @@ private function mapBankTransferInfo(BankAccountData $bankAccountData) 'name' => $bankAccountData->bankName, 'code' => $bankAccountData->routingNumber, //@TODO confirmantion from GP-API team 'international_code' => '', //@TODO - 'address' => [ - 'line_1' => $bankAccountData->bankAddress->streetAddress1 ?? null, - 'line_2' => $bankAccountData->bankAddress->streetAddress2 ?? null, - 'line_3' => $bankAccountData->bankAddress->streetAddress3 ?? null, - 'city' => $bankAccountData->bankAddress->city ?? null, - 'postal_code' => $bankAccountData->bankAddress->postalCode ?? null, - 'state' => $bankAccountData->bankAddress->state ?? null, - 'country' => !empty($bankAccountData->bankAddress) ? - CountryUtils::getCountryCodeByCountry($bankAccountData->bankAddress->countryCode) : '', - ] + 'address' => !empty($bankAccountData->bankAddress) ? + $this->mapAddress($bankAccountData->bankAddress, 'alpha2') : null, ] ]; } @@ -137,10 +145,12 @@ private function mapBankTransferInfo(BankAccountData $bankAccountData) private function mapCreditCardInfo(CreditCardData $creditCardInformation) { return [ - 'name' => $creditCardInformation->cardHolderName, 'number' => $creditCardInformation->number, - 'expiry_month' => substr($creditCardInformation->expMonth, 2, 2), - 'expiry_year' => substr($creditCardInformation->expYear, 0, 2) + 'expiry_month' => !empty($creditCardInformation->expMonth) ? + substr($creditCardInformation->expMonth, 0, 2) : null, + 'expiry_year' => !empty($creditCardInformation->expYear) ? + substr($creditCardInformation->expYear, 2, 2) : null, + 'cvv' => $creditCardInformation->cvn ?? null ]; } @@ -179,20 +189,33 @@ private function setAddressList() } /** @var Address $address */ foreach ($addressList as $addressType => $address) { - $addresses[] = [ - 'line_1' => $address->streetAddress1, - 'line_2' => $address->streetAddress2, - 'city' => $address->city, - 'postal_code' => $address->postalCode, - 'state' => $address->state, - 'country' => CountryUtils::getCountryCodeByCountry($address->countryCode), - 'functions' => [$addressType] - ]; + $addresses[] = $this->mapAddress($address, 'alpha2') + ['functions' => [$addressType]]; } return $addresses ?? []; } + private function mapAddress(Address $address, $countryCodeType = null) + { + switch ($countryCodeType) + { + case 'alpha2': + $countryCode = CountryUtils::getCountryCodeByCountry($address->countryCode); + break; + default: + $countryCode = $address->countryCode; + } + return [ + 'line_1' => $address->streetAddress1, + 'line_2' => $address->streetAddress2, + 'line_3' => $address->streetAddress3, + 'city' => $address->city, + 'state' => $address->state, + 'postal_code' => $address->postalCode, + 'country' => $countryCode, + ]; + } + /** * Request body for POST /merchants * @@ -271,15 +294,7 @@ private function setPersonList() 'job_title' => $person->jobTitle ]; if (!empty($person->address)) { - $personInfo['address'] = [ - 'line_1' => $person->address->streetAddress1, - 'line_2' => $person->address->streetAddress2, - 'line_3' => $person->address->streetAddress3, - 'city' => $person->address->city, - 'state' => $person->address->state, - 'postal_code' => $person->address->postalCode, - 'country' => $person->address->countryCode, - ]; + $personInfo['address'] = self::mapAddress($person->address); } if (!empty($person->homePhone)) { $personInfo['contact_phone'] = [ diff --git a/src/Builders/RequestBuilder/GpApi/GpApiReportRequestBuilder.php b/src/Builders/RequestBuilder/GpApi/GpApiReportRequestBuilder.php index 14c7e6a1..e8c9c500 100644 --- a/src/Builders/RequestBuilder/GpApi/GpApiReportRequestBuilder.php +++ b/src/Builders/RequestBuilder/GpApi/GpApiReportRequestBuilder.php @@ -241,8 +241,42 @@ public function buildRequest(BaseBuilder $builder, $config) case ReportType::FIND_MERCHANTS_PAGED: $endpoint = GpApiRequest::MERCHANT_MANAGEMENT_ENDPOINT; $verb = 'GET'; - $queryParams['page'] = $builder->page; - $queryParams['page_size'] = $builder->pageSize; + $this->addBasicParams($queryParams, $builder); + $queryParams['status'] = $builder->searchBuilder->accountStatus ?? null; + $queryParams['order'] = $builder->order ?? null; + $queryParams['order_by'] = $builder->accountOrderBy ?? null; + break; + case ReportType::FIND_ACCOUNTS_PAGED: + $endpoint = GpApiRequest::ACCOUNTS_ENDPOINT; + if (!empty($builder->searchBuilder->merchantId)) { + $endpoint = GpApiRequest::MERCHANT_MANAGEMENT_ENDPOINT . '/' . + $builder->searchBuilder->merchantId . $endpoint; + } + $verb = 'GET'; + $this->addBasicParams($queryParams, $builder); + $queryParams['order'] = $builder->order ?? null; + $queryParams['order_by'] = $builder->accountOrderBy ?? null; + $queryParams['from_time_created'] = !empty($builder->searchBuilder->startDate) ? + $builder->searchBuilder->startDate->format('Y-m-d') : null; + $queryParams['to_time_created'] = !empty($builder->searchBuilder->endDate) ? + $builder->searchBuilder->endDate->format('Y-m-d') : null; + $queryParams['status'] = $builder->searchBuilder->accountStatus ?? null; + $queryParams['name'] = $builder->searchBuilder->accountName ?? null; + $queryParams['id'] = $builder->searchBuilder->resourceId ?? null; + break; + case ReportType::FIND_ACCOUNT_DETAIL: + $endpoint = GpApiRequest::ACCOUNTS_ENDPOINT. '/'. $builder->searchBuilder->accountId; + if (!empty($builder->searchBuilder->address)) { + $endpoint .= '/addresses'; + $queryParams = [ + 'page' => $builder->page, + 'page_size' => $builder->pageSize, + 'postal_code' => $builder->searchBuilder->address->postalCode ?? null, + 'line_1' => $builder->searchBuilder->address->streetAddress1 ?? null, + 'line_2' => $builder->searchBuilder->address->streetAddress2 ?? null + ]; + } + $verb = 'GET'; break; default: throw new ArgumentException(sprintf("Unknown report type!")); diff --git a/src/Builders/TransactionReportBuilder.php b/src/Builders/TransactionReportBuilder.php index 5da5eace..13f58254 100644 --- a/src/Builders/TransactionReportBuilder.php +++ b/src/Builders/TransactionReportBuilder.php @@ -2,6 +2,7 @@ namespace GlobalPayments\Api\Builders; +use GlobalPayments\Api\Entities\Enums\MerchantAccountsSortProperty; use GlobalPayments\Api\Entities\Enums\ActionSortProperty; use GlobalPayments\Api\Entities\Enums\DepositSortProperty; use GlobalPayments\Api\Entities\Enums\DisputeSortProperty; @@ -288,37 +289,32 @@ public function withPayLinkId($payLinkId) */ public function orderBy($sortProperty, $sortDirection = SortDirection::DESC) { + $this->order = $sortDirection; switch ($this->reportType) { case ReportType::FIND_TRANSACTIONS: case ReportType::FIND_TRANSACTIONS_PAGED: case ReportType::FIND_SETTLEMENT_TRANSACTIONS: case ReportType::FIND_SETTLEMENT_TRANSACTIONS_PAGED: $this->transactionOrderBy = $sortProperty; - $this->order = $sortDirection; break; case ReportType::FIND_DEPOSITS: case ReportType::FIND_DEPOSITS_PAGED: $this->depositOrderBy = $sortProperty; - $this->order = $sortDirection; break; case ReportType::FIND_DISPUTES: case ReportType::FIND_DISPUTES_PAGED: case ReportType::FIND_SETTLEMENT_DISPUTES: case ReportType::FIND_SETTLEMENT_DISPUTES_PAGED: $this->disputeOrderBy = $sortProperty; - $this->order = $sortDirection; break; case ReportType::FIND_STORED_PAYMENT_METHODS_PAGED: $this->storedPaymentMethodOrderBy = $sortProperty; - $this->order = $sortDirection; break; case ReportType::FIND_ACTIONS_PAGED: $this->actionOrderBy = $sortProperty; - $this->order = $sortDirection; break; case ReportType::FIND_PAYLINK_PAGED: $this->payLinkOrderBy = $sortProperty; - $this->order = $sortDirection; break; default: throw new \InvalidArgumentException("Invalid order found"); @@ -327,14 +323,6 @@ public function orderBy($sortProperty, $sortDirection = SortDirection::DESC) return $this; } - /** - * @return SearchCriteriaBuilder - */ - public function where($criteria, $value) - { - return $this->searchBuilder->andWith($criteria, $value); - } - protected function setupValidations() { $this->validations->of(ReportType::TRANSACTION_DETAIL) diff --git a/src/Builders/UserReportBuilder.php b/src/Builders/UserReportBuilder.php index 95ad5809..39f860ac 100644 --- a/src/Builders/UserReportBuilder.php +++ b/src/Builders/UserReportBuilder.php @@ -2,8 +2,11 @@ namespace GlobalPayments\Api\Builders; +use GlobalPayments\Api\Entities\Enums\MerchantAccountsSortProperty; +use GlobalPayments\Api\Entities\Enums\ReportType; use GlobalPayments\Api\Entities\Enums\SortDirection; use GlobalPayments\Api\Entities\Enums\TransactionModifier; +use GlobalPayments\Api\Entities\Reporting\SearchCriteriaBuilder; class UserReportBuilder extends ReportBuilder { @@ -12,12 +15,21 @@ class UserReportBuilder extends ReportBuilder */ public $order; + /** @var MerchantAccountsSortProperty */ + public $accountOrderBy; + /** * @internal * @var string */ public $transactionType; + /** + * @internal + * @var SearchCriteriaBuilder + */ + public $searchBuilder; + public $transactionModifier = TransactionModifier::NONE; public function __construct($reportType) @@ -25,6 +37,7 @@ public function __construct($reportType) parent::__construct($reportType); $this->transactionType = $reportType; + $this->searchBuilder = new SearchCriteriaBuilder($this); } protected function setupValidations() @@ -38,4 +51,32 @@ public function withModifier($transactionModifier) return $this; } + + public function withAccountId($accountId) + { + $this->searchBuilder->accountId = $accountId; + + return $this; + } + + /** + * Set the gateway order for the criteria + * @param string $sortProperty sorting property + * @param string $sortDirection sorting direction + * @return $this + */ + public function orderBy($sortProperty, $sortDirection = SortDirection::DESC) + { + $this->order = $sortDirection; + switch ($this->reportType) { + case ReportType::FIND_ACCOUNTS_PAGED: + case ReportType::FIND_MERCHANTS_PAGED: + $this->accountOrderBy = $sortProperty; + break; + default: + throw new \InvalidArgumentException("Invalid order found"); + } + + return $this; + } } \ No newline at end of file diff --git a/src/Entities/AddressCollection.php b/src/Entities/AddressCollection.php new file mode 100644 index 00000000..f40b7729 --- /dev/null +++ b/src/Entities/AddressCollection.php @@ -0,0 +1,20 @@ +offsetSet($type, $address); + } + + public function get(string $type) : Address + { + return $this->offsetGet($type); + } +} \ No newline at end of file diff --git a/src/Entities/Enums/MerchantAccountStatus.php b/src/Entities/Enums/MerchantAccountStatus.php new file mode 100644 index 00000000..c48a19a0 --- /dev/null +++ b/src/Entities/Enums/MerchantAccountStatus.php @@ -0,0 +1,11 @@ +getAccountID(self::RIKS_ASSESSMENT_ACCOUNT_NAME_PREFIX); } + public function getMerchantManagementAccountName() + { + return $this->getAccountName(self::MERCHANT_MANAGEMENT_ACCOUNT_PREFIX); + } + + public function getMerchantManagementAccountID() + { + return $this->getAccountID(self::MERCHANT_MANAGEMENT_ACCOUNT_PREFIX); + } public function getToken() { diff --git a/src/Entities/Reporting/MerchantAccountSummary.php b/src/Entities/Reporting/MerchantAccountSummary.php new file mode 100644 index 00000000..c99ab8f1 --- /dev/null +++ b/src/Entities/Reporting/MerchantAccountSummary.php @@ -0,0 +1,51 @@ + */ + public $paymentMethods; + + /** @var array */ + public $configurations; + + /** @var AddressCollection */ + public $addresses; +} \ No newline at end of file diff --git a/src/Entities/Reporting/SearchCriteria.php b/src/Entities/Reporting/SearchCriteria.php index 69cae739..92859155 100644 --- a/src/Entities/Reporting/SearchCriteria.php +++ b/src/Entities/Reporting/SearchCriteria.php @@ -84,4 +84,6 @@ class SearchCriteria extends Enum const PAYLINK_STATUS = 'payLinkStatus'; const DESCRIPTION = 'description'; const EXPIRATION_DATE = 'expirationDate'; + const ACCOUNT_STATUS = 'accountStatus'; + const ADDRESS = 'address'; } diff --git a/src/Entities/Reporting/SearchCriteriaBuilder.php b/src/Entities/Reporting/SearchCriteriaBuilder.php index f16e6313..af1a5e08 100644 --- a/src/Entities/Reporting/SearchCriteriaBuilder.php +++ b/src/Entities/Reporting/SearchCriteriaBuilder.php @@ -1,7 +1,10 @@ reportBuilder = $reportBuilder; } diff --git a/src/Entities/User.php b/src/Entities/User.php index 7f590207..db3a8a8d 100644 --- a/src/Entities/User.php +++ b/src/Entities/User.php @@ -172,6 +172,7 @@ public static function fromId(string $userId,string $userType) public function edit() { $builder = (new PayFacBuilder(TransactionType::EDIT)) + ->withModifier(TransactionModifier::MERCHANT) ->withUserReference($this->userReference); if ($this->userReference->userType !== null) { diff --git a/src/Gateways/Gp3DSProvider.php b/src/Gateways/Gp3DSProvider.php index df21fde9..ebcd7349 100644 --- a/src/Gateways/Gp3DSProvider.php +++ b/src/Gateways/Gp3DSProvider.php @@ -3,6 +3,7 @@ namespace GlobalPayments\Api\Gateways; use GlobalPayments\Api\Builders\Secure3dBuilder; +use GlobalPayments\Api\Entities\Enums\AuthenticationSource; use GlobalPayments\Api\Entities\Enums\ExemptionReason; use GlobalPayments\Api\Entities\Enums\ExemptStatus; use GlobalPayments\Api\Entities\MessageExtension; @@ -372,7 +373,6 @@ private function mapResponse($rawResponse) { $doc = json_decode($rawResponse, true); $secureEcom = new ThreeDSecure(); - // check enrolled $secureEcom->serverTransactionId = isset($doc['server_trans_id']) ? $doc['server_trans_id'] : null; if (array_key_exists('enrolled', $doc)) { @@ -452,6 +452,14 @@ private function mapResponse($rawResponse) $secureEcom->payerAuthenticationRequest = isset($doc['encoded_creq']) ? $doc['encoded_creq'] : null; } + if ($secureEcom->authenticationSource == AuthenticationSource::MOBILE_SDK) + { + $secureEcom->payerAuthenticationRequest = $doc['acs_signed_content'] ?? null; + $secureEcom->acsInterface = $doc['acs_rendering_type']['acs_interface'] ?? null; + $secureEcom->acsUiTemplate = $doc['acs_rendering_type']['acs_ui_template'] ?? null; + } + $secureEcom->acsReferenceNumber = $doc['acs_reference_number'] ?? null; + $response = new Transaction(); $response->threeDSecure = $secureEcom; return $response; diff --git a/src/Gateways/GpApiConnector.php b/src/Gateways/GpApiConnector.php index d4668fb3..4e512fc0 100644 --- a/src/Gateways/GpApiConnector.php +++ b/src/Gateways/GpApiConnector.php @@ -11,7 +11,6 @@ use GlobalPayments\Api\Builders\Secure3dBuilder; use GlobalPayments\Api\Entities\Enums\PaymentMethodType; use GlobalPayments\Api\Entities\Enums\Secure3dVersion; -use GlobalPayments\Api\Entities\Enums\TransactionType; use GlobalPayments\Api\Entities\Exceptions\ApiException; use GlobalPayments\Api\Entities\Exceptions\GatewayException; use GlobalPayments\Api\Entities\Exceptions\UnsupportedTransactionException; @@ -23,8 +22,8 @@ use GlobalPayments\Api\Entities\IRequestBuilder; use GlobalPayments\Api\Entities\Reporting\DepositSummary; use GlobalPayments\Api\Entities\Reporting\DisputeSummary; +use GlobalPayments\Api\Entities\Reporting\MerchantAccountSummary; use GlobalPayments\Api\Entities\RiskAssessment; -use GlobalPayments\Api\Entities\ThreeDSecure; use GlobalPayments\Api\Entities\Transaction; use GlobalPayments\Api\Entities\Reporting\TransactionSummary; use GlobalPayments\Api\Entities\User; @@ -42,12 +41,18 @@ class GpApiConnector extends RestGateway implements IPaymentGateway, ISecure3dPr */ private $gpApiConfig; private $accessToken; + private $builtInMerchantManagementService = true; public function supportsOpenBanking() : bool { return true; } + public function hasBuiltInMerchantManagementService() + { + return $this->builtInMerchantManagementService; + } + public function __construct(GpApiConfig $gpApiConfig) { parent::__construct(); @@ -136,7 +141,7 @@ public function manageTransaction(ManagementBuilder $builder) * * @param ReportBuilder $builder * - * @return PagedResult|DepositSummary|DisputeSummary|TransactionSummary + * @return PagedResult|DepositSummary|DisputeSummary|TransactionSummary|MerchantAccountSummary * @throws ApiException * @throws GatewayException */ @@ -195,8 +200,11 @@ private function executeProcess($builder) * @var GpApiRequest $request */ $request = $requestBuilder->buildRequest($builder, $this->gpApiConfig); - $merchantUrl = !empty($this->gpApiConfig->merchantId) ? + $merchantUrl = ( + !empty($this->gpApiConfig->merchantId) && + strpos($request->endpoint, GpApiRequest::MERCHANT_MANAGEMENT_ENDPOINT) === false) ? GpApiRequest::MERCHANT_MANAGEMENT_ENDPOINT . '/' . $this->gpApiConfig->merchantId : ''; + $request->endpoint = $merchantUrl . $request->endpoint; if (empty($request)) { @@ -330,6 +338,12 @@ public function signIn() $accessTokenInfo->riskAssessmentAccountID = $response->getRiskAssessmentAccountID(); } + if ( + empty($accessTokenInfo->merchantManagementAccountID) && + empty($accessTokenInfo->merchantManagementAccountName) + ) { + $accessTokenInfo->merchantManagementAccountID = $response->getMerchantManagementAccountID(); + } $this->gpApiConfig->accessTokenInfo = $accessTokenInfo; } diff --git a/src/Mapping/GpApiMapping.php b/src/Mapping/GpApiMapping.php index e91327ae..8d9dc7e1 100644 --- a/src/Mapping/GpApiMapping.php +++ b/src/Mapping/GpApiMapping.php @@ -3,6 +3,7 @@ namespace GlobalPayments\Api\Mapping; use GlobalPayments\Api\Entities\Address; +use GlobalPayments\Api\Entities\AddressCollection; use GlobalPayments\Api\Entities\AlternativePaymentResponse; use GlobalPayments\Api\Entities\BankPaymentResponse; use GlobalPayments\Api\Entities\BatchSummary; @@ -37,6 +38,7 @@ use GlobalPayments\Api\Entities\Reporting\ActionSummary; use GlobalPayments\Api\Entities\Reporting\DepositSummary; use GlobalPayments\Api\Entities\Reporting\DisputeSummary; +use GlobalPayments\Api\Entities\Reporting\MerchantAccountSummary; use GlobalPayments\Api\Entities\Reporting\MerchantSummary; use GlobalPayments\Api\Entities\Reporting\PayLinkSummary; use GlobalPayments\Api\Entities\Reporting\StoredPaymentMethodSummary; @@ -64,6 +66,7 @@ class GpApiMapping const MERCHANT_SINGLE = 'MERCHANT_SINGLE'; const MERCHANT_EDIT = 'MERCHANT_EDIT'; const MERCHANT_EDIT_INITIATED = 'MERCHANT_EDIT_INITIATED'; + const ADDRESS_LOOKUP = 'ADDRESS_LIST'; /** * Map a response to a Transaction object for further chaining @@ -368,6 +371,14 @@ public static function mapReportResponse($response, $reportType) array_push($report->result, self::mapMerchantSummary($merchant)); } return $report; + case ReportType::FIND_ACCOUNTS_PAGED: + $report = self::setPagingInfo($response); + foreach ($response->accounts as $account) { + array_push($report->result, self::mapMerchantAccountSummary($account)); + } + return $report; + case ReportType::FIND_ACCOUNT_DETAIL: + return self::mapMerchantAccountSummary($response); default: throw new ApiException("Report type not supported!"); } @@ -981,6 +992,30 @@ private static function mapBNPLResponse($response,Transaction $transaction) return $transaction; } + private static function mapMerchantAccountSummary($account) + { + $merchantAccountSummary = new MerchantAccountSummary(); + $merchantAccountSummary->id = $account->id ?? null; + $merchantAccountSummary->type = $account->type ?? null; + $merchantAccountSummary->name = $account->name ?? null; + $merchantAccountSummary->status = $account->status ?? null; + $merchantAccountSummary->permissions = $account->permissions ?? null; + $merchantAccountSummary->countries = $account->countries ?? null; + $merchantAccountSummary->channels = $account->channels ?? null; + $merchantAccountSummary->currencies = $account->currencies ?? null; + $merchantAccountSummary->paymentMethods = $account->payment_methods ?? null; + $merchantAccountSummary->configurations = $account->configurations ?? null; + if (!empty($account->addresses)) { + $addresses = new AddressCollection(); + foreach ($account->addresses as $key => $address) { + $addresses->add(self::mapAddressObject($address), $key); + } + $merchantAccountSummary->addresses = $addresses; + } + + return $merchantAccountSummary; + } + private static function mapMerchantSummary($merchant): MerchantSummary { $merchantInfo = new MerchantSummary(); diff --git a/src/Services/GpApiService.php b/src/Services/GpApiService.php index 5ba4857a..7925040d 100644 --- a/src/Services/GpApiService.php +++ b/src/Services/GpApiService.php @@ -31,11 +31,13 @@ public static function generateTransactionKey(GpApiConfig $config) $accessTokenInfo->transactionProcessingAccountName = $data->getTransactionProcessingAccountName(); $accessTokenInfo->tokenizationAccountName = $data->getTokenizationAccountName(); $accessTokenInfo->riskAssessmentAccountName = $data->getRiskAssessmentAccountName(); + $accessTokenInfo->merchantManagementAccountName = $data->getMerchantManagementAccountName(); $accessTokenInfo->dataAccountID = $data->getDataAccountID(); $accessTokenInfo->disputeManagementAccountID = $data->getDisputeManagementAccountID(); $accessTokenInfo->transactionProcessingAccountID = $data->getTransactionProcessingAccountID(); $accessTokenInfo->tokenizationAccountID = $data->getTokenizationAccountID(); $accessTokenInfo->riskAssessmentAccountID = $data->getRiskAssessmentAccountID(); + $accessTokenInfo->merchantManagementAccountID = $data->getMerchantManagementAccountID(); return $accessTokenInfo; } diff --git a/src/Services/PayFacService.php b/src/Services/PayFacService.php index e60d8b9b..752566a6 100644 --- a/src/Services/PayFacService.php +++ b/src/Services/PayFacService.php @@ -14,15 +14,15 @@ public static function createAccount() { return new PayFacBuilder(TransactionType::CREATE_ACCOUNT); } - - /* + + /** * This transaction type requires an X.509 certificate as additional authentication * Only one group should be passed per request. - * If a group is passed, the API user must pass all data elements that comprise that group. + * If a group is passed, the API user must pass all data elements that comprise that group. * If a value from a group is missing, then the data not included in your request is cleared from the ProPay record. - * Allowance to perform an edit of each group is subject to approval. + * Allowance to perform an edit of each group is subject to approval. * If you try to perform an edit for a disallowed group, your request will fail. - * + * */ public static function editAccount() { diff --git a/src/Services/ReportingService.php b/src/Services/ReportingService.php index b1febd76..ca6c9194 100644 --- a/src/Services/ReportingService.php +++ b/src/Services/ReportingService.php @@ -144,4 +144,16 @@ public static function findMerchants($page, $pageSize) ->withModifier(TransactionModifier::MERCHANT) ->withPaging($page, $pageSize); } + + public static function findAccounts($page, $pageSize) + { + return (new UserReportBuilder(ReportType::FIND_ACCOUNTS_PAGED)) + ->withPaging($page, $pageSize); + } + + public static function accountDetail(string $accountId) + { + return (new UserReportBuilder(ReportType::FIND_ACCOUNT_DETAIL)) + ->withAccountId($accountId); + } } diff --git a/test/Data/BaseGpApiTestConfig.php b/test/Data/BaseGpApiTestConfig.php index 953cabc1..d95a32a0 100644 --- a/test/Data/BaseGpApiTestConfig.php +++ b/test/Data/BaseGpApiTestConfig.php @@ -14,6 +14,9 @@ class BaseGpApiTestConfig const APP_ID = '4gPqnGBkppGYvoE5UX9EWQlotTxGUDbs'; const APP_KEY = 'FQyJA5VuEQfcji2M'; + const PARTNER_SOLUTION_APP_ID = 'A1feRdMmEB6m0Y1aQ65H0bDi9ZeAEB2t'; + const PARTNER_SOLUTION_APP_KEY = '5jPt1OpB6LLitgi7'; + public static $appId = self::APP_ID; public static $appKey = self::APP_KEY; diff --git a/test/Integration/Gateways/GpApiConnector/DebitCardTest.php b/test/Integration/Gateways/GpApiConnector/DebitCardTest.php index 1c5d894a..85a5f782 100644 --- a/test/Integration/Gateways/GpApiConnector/DebitCardTest.php +++ b/test/Integration/Gateways/GpApiConnector/DebitCardTest.php @@ -91,6 +91,8 @@ public function testDebitReverse() $this->assertEquals('SUCCESS', $transaction->responseCode); $this->assertEquals(TransactionStatus::CAPTURED, $transaction->responseMessage); + sleep(1); + $response = $transaction->reverse() ->withCurrency("USD") ->execute(); diff --git a/test/Integration/Gateways/GpApiConnector/GpApiBNPLTest.php b/test/Integration/Gateways/GpApiConnector/GpApiBNPLTest.php index 4d93365e..1c3a1dc0 100644 --- a/test/Integration/Gateways/GpApiConnector/GpApiBNPLTest.php +++ b/test/Integration/Gateways/GpApiConnector/GpApiBNPLTest.php @@ -511,7 +511,7 @@ public function testBNPL_InvalidStatusForCapture_NoRedirect() public function testGetBNPLTransactionById() { - $id = 'TRN_EryDeQRtqagH27G87DkSfZGL1kiE21'; + $id = 'TRN_o7PsaRAgOviqLCPHBaxDcqYO70oUhu'; $trnInfo = ReportingService::transactionDetail($id)->execute(); diff --git a/test/Integration/Gateways/GpApiConnector/GpApiBatchTest.php b/test/Integration/Gateways/GpApiConnector/GpApiBatchTest.php index 7ef5e2c5..6124b63f 100644 --- a/test/Integration/Gateways/GpApiConnector/GpApiBatchTest.php +++ b/test/Integration/Gateways/GpApiConnector/GpApiBatchTest.php @@ -155,6 +155,8 @@ public function testBatchClose_Refund_CreditTrackData() ->execute(); $this->assertTransactionResponse($transaction, TransactionStatus::CAPTURED); + sleep(2); + $batch = BatchService::closeBatch($transaction->batchSummary->batchReference); $this->assertBatchCloseResponse($batch, 0); } diff --git a/test/Integration/Gateways/GpApiConnector/GpApiMerchantAccountsTest.php b/test/Integration/Gateways/GpApiConnector/GpApiMerchantAccountsTest.php new file mode 100644 index 00000000..ae92b568 --- /dev/null +++ b/test/Integration/Gateways/GpApiConnector/GpApiMerchantAccountsTest.php @@ -0,0 +1,519 @@ +setUpConfig(); + ServicesContainer::configureService($this->config); + $this->startDate = (new \DateTime())->modify('-1 year')->setTime(0, 0, 0); + $this->endDate = (new \DateTime())->modify('-3 days')->setTime(0, 0, 0); + + $response = ReportingService::findAccounts(1, 10) + ->orderBy(MerchantAccountsSortProperty::TIME_CREATED, SortDirection::ASC) + ->where(SearchCriteria::START_DATE, $this->startDate) + ->andWith(SearchCriteria::END_DATE, $this->endDate) + ->andWith(SearchCriteria::ACCOUNT_STATUS, MerchantAccountStatus::ACTIVE) + ->execute(); + + $this->accountId = count($response->result) > 0 ? (reset($response->result))->id : null; + } + + public static function tearDownAfterClass(): void + { + BaseGpApiTestConfig::resetGpApiConfig(); + } + + public function setUpConfig() + { + BaseGpApiTestConfig::$appId = BaseGpApiTestConfig::PARTNER_SOLUTION_APP_ID; + BaseGpApiTestConfig::$appKey = BaseGpApiTestConfig::PARTNER_SOLUTION_APP_KEY; + + $this->config = BaseGpApiTestConfig::gpApiSetupConfig(Channel::CardNotPresent); + } + + public function testFindAccountsInfo() + { + $response = ReportingService::findAccounts(1, 10) + ->orderBy(MerchantAccountsSortProperty::TIME_CREATED, SortDirection::ASC) + ->where(SearchCriteria::START_DATE, $this->startDate) + ->andWith(SearchCriteria::END_DATE, $this->endDate) + ->execute(); + + $this->assertNotNull($response); + /** @var MerchantAccountSummary $rs */ + foreach ($response->result as $index => $rs) { + $this->assertEquals(MerchantAccountStatus::ACTIVE, $rs->status); + } + } + + public function testFindAccountsInfo_SearchByStatusActive() + { + $response = ReportingService::findAccounts(1, 10) + ->orderBy(MerchantAccountsSortProperty::TIME_CREATED, SortDirection::ASC) + ->where(SearchCriteria::START_DATE, $this->startDate) + ->andWith(SearchCriteria::END_DATE, $this->endDate) + ->andWith(SearchCriteria::ACCOUNT_STATUS, MerchantAccountStatus::ACTIVE) + ->execute(); + + $this->assertNotNull($response); + /** @var MerchantAccountSummary $rs */ + foreach ($response->result as $index => $rs) { + $this->assertEquals(MerchantAccountStatus::ACTIVE, $rs->status); + } + } + + public function testFindAccountsInfo_SearchByStatusInactive() + { + $response = ReportingService::findAccounts(1, 10) + ->orderBy(MerchantAccountsSortProperty::TIME_CREATED, SortDirection::ASC) + ->where(SearchCriteria::START_DATE, $this->startDate) + ->andWith(SearchCriteria::END_DATE, $this->endDate) + ->andWith(SearchCriteria::ACCOUNT_STATUS, MerchantAccountStatus::INACTIVE) + ->execute(); + + $this->assertNotNull($response); + $this->assertEmpty($response->result); + $this->assertCount(0, $response->result); + } + + public function testFindAccountsInfo_SearchByName() + { + $response = ReportingService::findAccounts(1, 10) + ->orderBy(MerchantAccountsSortProperty::TIME_CREATED, SortDirection::ASC) + ->where(SearchCriteria::START_DATE, $this->startDate) + ->andWith(SearchCriteria::END_DATE, $this->endDate) + ->andWith(SearchCriteria::ACCOUNT_NAME, "Sandbox FMA") + ->execute(); + + $this->assertNotNull($response); + /** @var MerchantAccountSummary $rs */ + foreach ($response->result as $index => $rs) { + $this->assertEquals(MerchantAccountStatus::ACTIVE, $rs->status); + } + } + + public function testFindAccountsInfo_SearchById() + { + $response = ReportingService::findAccounts(1, 10) + ->orderBy(MerchantAccountsSortProperty::TIME_CREATED, SortDirection::ASC) + ->where(SearchCriteria::START_DATE, $this->startDate) + ->andWith(SearchCriteria::END_DATE, $this->endDate) + ->andWith(SearchCriteria::RESOURCE_ID, "FMA_a07e67cdfdc641c4a5fe77a7f9f96cdd") + ->execute(); + + $this->assertNotNull($response); + /** @var MerchantAccountSummary $rs */ + foreach ($response->result as $index => $rs) { + $this->assertEquals(MerchantAccountStatus::ACTIVE, $rs->status); + } + } + + public function testAccountDetails() + { + /** @var MerchantAccountSummary $response */ + $response = ReportingService::accountDetail($this->accountId) + ->execute(); + + $this->assertEquals($this->accountId, $response->id); + } + + public function testAccountDetails_RandomId() + { + $accountId = GenerationUtils::getGuid(); + + /** @var MerchantAccountSummary $response */ + $errorFound = false; + try { + ReportingService::accountDetail($accountId) + ->execute(); + } catch (GatewayException $e) { + $errorFound = true; + $this->assertEquals("Status Code: INVALID_TRANSACTION_ACTION - Retrieve information about this transaction is not supported", $e->getMessage()); + $this->assertEquals('40042', $e->responseCode); + } finally { + $this->assertTrue($errorFound); + } + } + + public function testAccountDetails_NullId() + { + $errorFound = false; + try { + ReportingService::accountDetail('null') + ->execute(); + } catch (GatewayException $e) { + $errorFound = true; + $this->assertEquals("Status Code: INVALID_REQUEST_DATA - Account details does not exist for null", $e->getMessage()); + $this->assertEquals('40041', $e->responseCode); + } finally { + $this->assertTrue($errorFound); + } + } + + public function testEditAccountInformation() + { + $this->markTestSkipped('GP-API sandbox limitation. Edit account is not enabled in sandbox.'); + + $billingAddress = new Address(); + $billingAddress->streetAddress1 = "Address 1"; + $billingAddress->streetAddress3 = "foyer"; + $billingAddress->city = 'Atlanta'; + $billingAddress->state = 'GA'; + $billingAddress->postalCode = '30346'; + $billingAddress->country = 'US'; + + $creditCardInformation = TestAccountData::getCreditCardData(); + + $merchants = ReportingService::findMerchants(1, 10) + ->orderBy(MerchantAccountsSortProperty::TIME_CREATED, SortDirection::ASC) + ->where(SearchCriteria::ACCOUNT_STATUS, MerchantAccountStatus::ACTIVE) + ->execute(); + + $this->assertTrue(count($merchants->result) > 0); + $merchant = User::fromId(reset($merchants->result)->id, UserType::MERCHANT); + + $response = ReportingService::findAccounts(1, 10) + ->orderBy(MerchantAccountsSortProperty::TIME_CREATED, SortDirection::ASC) + ->where(SearchCriteria::START_DATE, $this->startDate) + ->andWith(SearchCriteria::END_DATE, $this->endDate) + ->andWith(DataServiceCriteria::MERCHANT_ID, reset($merchants->result)->id) + ->andWith(SearchCriteria::ACCOUNT_STATUS, MerchantAccountStatus::ACTIVE) + ->execute(); + + $this->assertTrue(count($response->result) > 0); + /** @var MerchantAccountSummary $accountSummary */ + $index = array_search( + MerchantAccountType::FUND_MANAGEMENT, array_column($response->result, 'type') + ); + if ($index === false) { + $this->fail(sprintf( + "Account type %s not found in order to perform the edit action", + MerchantAccountType::FUND_MANAGEMENT + )); + } + $accountSummary = $response->result[$index]; + if ($accountSummary->type == MerchantAccountType::FUND_MANAGEMENT) { + $response = PayFacService::editAccount() + ->withAccountNumber($accountSummary->id) + ->withUserReference($merchant->userReference) + ->withAddress($billingAddress) + ->withCreditCardData($creditCardInformation) + ->execute(); + + $this->assertNotNull($response); + } + } + + /** Address Lookup is available only for MMA accounts and returns a list of addresses */ + public function testAccountAddressLookup() + { + $address = new Address(); + $address->postalCode = 'CB6 1AS'; + $address->streetAddress1 = '2649'; + $address->streetAddress2 = 'Primrose'; + /** @var MerchantAccountSummary $response */ + $response = ReportingService::accountDetail($this->config->accessTokenInfo->merchantManagementAccountID) + ->withPaging(1, 10) + ->where(SearchCriteria::ADDRESS, $address) + ->execute(); + + $this->assertNotCount(0, $response->addresses); + $this->assertEquals($address->postalCode, $response->addresses->offsetGet(0)->postalCode); + } + + public function testAccountAddressLookup_WithoutPostalCode() + { + $address = new Address(); + $address->streetAddress1 = '2649'; + $address->streetAddress2 = 'Primrose'; + + $errorFound = false; + try { + ReportingService::accountDetail($this->config->accessTokenInfo->merchantManagementAccountID) + ->withPaging(1, 10) + ->where(SearchCriteria::ADDRESS, $address) + ->execute(); + } catch (GatewayException $e) { + $errorFound = true; + $this->assertEquals("Status Code: MANDATORY_DATA_MISSING - Request expects the following fields:postal_code.", $e->getMessage()); + $this->assertEquals('40251', $e->responseCode); + } finally { + $this->assertTrue($errorFound); + } + } + + public function testAccountAddressLookup_WithoutAddressLine1And2() + { + $address = new Address(); + $address->postalCode = 'CB6 1AS'; + + $errorFound = false; + try { + ReportingService::accountDetail($this->config->accessTokenInfo->merchantManagementAccountID) + ->withPaging(1, 10) + ->where(SearchCriteria::ADDRESS, $address) + ->execute(); + } catch (GatewayException $e) { + $errorFound = true; + $this->assertEquals("Status Code: MANDATORY_DATA_MISSING - Request expects the following fields:line_1 or line_2.", $e->getMessage()); + $this->assertEquals('40251', $e->responseCode); + } finally { + $this->assertTrue($errorFound); + } + } + + public function testEditAccountInformation_WithoutCardDetails() + { + $billingAddress = new Address(); + $billingAddress->streetAddress1 = "Address 1"; + $billingAddress->streetAddress3 = "foyer"; + $billingAddress->city = 'Atlanta'; + $billingAddress->state = 'GA'; + $billingAddress->postalCode = '30346'; + $billingAddress->country = 'US'; + + $merchants = ReportingService::findMerchants(1, 10) + ->orderBy(MerchantAccountsSortProperty::TIME_CREATED, SortDirection::ASC) + ->where(SearchCriteria::ACCOUNT_STATUS, MerchantAccountStatus::ACTIVE) + ->execute(); + + $this->assertTrue(count($merchants->result) > 0); + $merchant = User::fromId(reset($merchants->result)->id, UserType::MERCHANT); + + $response = ReportingService::findAccounts(1, 10) + ->orderBy(MerchantAccountsSortProperty::TIME_CREATED, SortDirection::ASC) + ->where(SearchCriteria::START_DATE, $this->startDate) + ->andWith(SearchCriteria::END_DATE, $this->endDate) + ->andWith(DataServiceCriteria::MERCHANT_ID, reset($merchants->result)->id) + ->andWith(SearchCriteria::ACCOUNT_STATUS, MerchantAccountStatus::ACTIVE) + ->execute(); + + $this->assertTrue(count($response->result) > 0); + /** @var MerchantAccountSummary $accountSummary */ + $index = array_search( + MerchantAccountType::FUND_MANAGEMENT, array_column($response->result, 'type') + ); + if ($index === false) { + $this->fail(sprintf( + "Account type %s not found in order to perform the edit action", + MerchantAccountType::FUND_MANAGEMENT + )); + } + $accountSummary = $response->result[$index]; + + if ($accountSummary->type == MerchantAccountType::FUND_MANAGEMENT) { + $errorFound = false; + try { + PayFacService::editAccount() + ->withAccountNumber($accountSummary->id) + ->withUserReference($merchant->userReference) + ->withAddress($billingAddress) + ->execute(); + } catch (GatewayException $e) { + $errorFound = true; + $this->assertEquals("Status Code: MANDATORY_DATA_MISSING - Request expects the following fields payer.payment_method.name", $e->getMessage()); + $this->assertEquals('40005', $e->responseCode); + } finally { + $this->assertTrue($errorFound); + } + } + } + + public function testEditAccountInformation_WithoutAddress() + { + $creditCardInformation = TestAccountData::getCreditCardData(); + + $merchants = ReportingService::findMerchants(1, 10) + ->orderBy(MerchantAccountsSortProperty::TIME_CREATED, SortDirection::ASC) + ->where(SearchCriteria::ACCOUNT_STATUS, MerchantAccountStatus::ACTIVE) + ->execute(); + + $this->assertTrue(count($merchants->result) > 0); + $merchant = User::fromId(reset($merchants->result)->id, UserType::MERCHANT); + + $response = ReportingService::findAccounts(1, 10) + ->orderBy(MerchantAccountsSortProperty::TIME_CREATED, SortDirection::ASC) + ->where(SearchCriteria::START_DATE, $this->startDate) + ->andWith(SearchCriteria::END_DATE, $this->endDate) + ->andWith(DataServiceCriteria::MERCHANT_ID, reset($merchants->result)->id) + ->andWith(SearchCriteria::ACCOUNT_STATUS, MerchantAccountStatus::ACTIVE) + ->execute(); + + $this->assertTrue(count($response->result) > 0); + /** @var MerchantAccountSummary $accountSummary */ + $index = array_search( + MerchantAccountType::FUND_MANAGEMENT, array_column($response->result, 'type') + ); + if ($index === false) { + $this->fail(sprintf( + "Account type %s not found in order to perform the edit action", + MerchantAccountType::FUND_MANAGEMENT + )); + } + $accountSummary = $response->result[$index]; + + if ($accountSummary->type == MerchantAccountType::FUND_MANAGEMENT) { + $errorFound = false; + try { + PayFacService::editAccount() + ->withAccountNumber($accountSummary->id) + ->withUserReference($merchant->userReference) + ->withCreditCardData($creditCardInformation) + ->execute(); + } catch (GatewayException $e) { + $errorFound = true; + $this->assertEquals("Status Code: MANDATORY_DATA_MISSING - Request expects the following fields payer.billing_address.line_1", $e->getMessage()); + $this->assertEquals('40005', $e->responseCode); + } finally { + $this->assertTrue($errorFound); + } + } + } + + public function testEditAccountInformation_WithoutId() + { + $billingAddress = new Address(); + $billingAddress->streetAddress1 = "Address 1"; + $billingAddress->streetAddress3 = "foyer"; + $billingAddress->city = 'Atlanta'; + $billingAddress->state = 'GA'; + $billingAddress->postalCode = '30346'; + $billingAddress->country = 'US'; + + $creditCardInformation = TestAccountData::getCreditCardData(); + + $merchants = ReportingService::findMerchants(1, 10) + ->orderBy(MerchantAccountsSortProperty::TIME_CREATED, SortDirection::ASC) + ->where(SearchCriteria::ACCOUNT_STATUS, MerchantAccountStatus::ACTIVE) + ->execute(); + + $this->assertTrue(count($merchants->result) > 0); + $merchant = User::fromId(reset($merchants->result)->id, UserType::MERCHANT); + + $response = ReportingService::findAccounts(1, 10) + ->orderBy(MerchantAccountsSortProperty::TIME_CREATED, SortDirection::ASC) + ->where(SearchCriteria::START_DATE, $this->startDate) + ->andWith(SearchCriteria::END_DATE, $this->endDate) + ->andWith(DataServiceCriteria::MERCHANT_ID, reset($merchants->result)->id) + ->andWith(SearchCriteria::ACCOUNT_STATUS, MerchantAccountStatus::ACTIVE) + ->execute(); + + $this->assertTrue(count($response->result) > 0); + /** @var MerchantAccountSummary $accountSummary */ + $index = array_search( + MerchantAccountType::FUND_MANAGEMENT, array_column($response->result, 'type') + ); + if ($index === false) { + $this->fail(sprintf( + "Account type %s not found in order to perform the edit action", + MerchantAccountType::FUND_MANAGEMENT + )); + } + $accountSummary = $response->result[$index]; + + if ($accountSummary->type == MerchantAccountType::FUND_MANAGEMENT) { + $errorFound = false; + try { + PayFacService::editAccount() + ->withUserReference($merchant->userReference) + ->withAddress($billingAddress) + ->withCreditCardData($creditCardInformation) + ->execute(); + } catch (BuilderException $e) { + $errorFound = true; + $this->assertEquals("accountNumber cannot be null for this transaction type.", $e->getMessage()); + } finally { + $this->assertTrue($errorFound); + } + } + } + + public function testEditAccountInformation_WithoutUserRef() + { + $billingAddress = new Address(); + $billingAddress->streetAddress1 = "Address 1"; + $billingAddress->streetAddress3 = "foyer"; + $billingAddress->city = 'Atlanta'; + $billingAddress->state = 'GA'; + $billingAddress->postalCode = '30346'; + $billingAddress->country = 'US'; + + $creditCardInformation = TestAccountData::getCreditCardData(); + + $merchants = ReportingService::findMerchants(1, 10) + ->orderBy(MerchantAccountsSortProperty::TIME_CREATED, SortDirection::ASC) + ->where(SearchCriteria::ACCOUNT_STATUS, MerchantAccountStatus::ACTIVE) + ->execute(); + + $this->assertTrue(count($merchants->result) > 0); + + $response = ReportingService::findAccounts(1, 10) + ->orderBy(MerchantAccountsSortProperty::TIME_CREATED, SortDirection::ASC) + ->where(SearchCriteria::START_DATE, $this->startDate) + ->andWith(SearchCriteria::END_DATE, $this->endDate) + ->andWith(DataServiceCriteria::MERCHANT_ID, reset($merchants->result)->id) + ->andWith(SearchCriteria::ACCOUNT_STATUS, MerchantAccountStatus::ACTIVE) + ->execute(); + + $this->assertTrue(count($response->result) > 0); + /** @var MerchantAccountSummary $accountSummary */ + $index = array_search( + MerchantAccountType::FUND_MANAGEMENT, array_column($response->result, 'type') + ); + if ($index === false) { + $this->fail(sprintf( + "Account type %s not found in order to perform the edit action", + MerchantAccountType::FUND_MANAGEMENT + )); + } + $accountSummary = $response->result[$index]; + + if ($accountSummary->type == MerchantAccountType::FUND_MANAGEMENT) { + $errorFound = false; + try { + PayFacService::editAccount() + ->withAccountNumber($accountSummary->id) + ->withAddress($billingAddress) + ->withCreditCardData($creditCardInformation) + ->execute(); + } catch (GatewayException $e) { + $errorFound = true; + $this->assertEquals("Status Code: INVALID_TRANSACTION_ACTION - Retrieve information about this transaction is not supported", $e->getMessage()); + $this->assertEquals('40042', $e->responseCode); + } finally { + $this->assertTrue($errorFound); + } + } + } +} \ No newline at end of file diff --git a/test/Integration/Gateways/GpApiConnector/GpApiMerchantsOnboardTest.php b/test/Integration/Gateways/GpApiConnector/GpApiMerchantsOnboardTest.php index 27048956..3def24b3 100644 --- a/test/Integration/Gateways/GpApiConnector/GpApiMerchantsOnboardTest.php +++ b/test/Integration/Gateways/GpApiConnector/GpApiMerchantsOnboardTest.php @@ -13,6 +13,7 @@ use GlobalPayments\Api\Entities\Enums\UserStatus; use GlobalPayments\Api\Entities\Enums\UserType; use GlobalPayments\Api\Entities\Exceptions\ArgumentException; +use GlobalPayments\Api\Entities\Exceptions\BuilderException; use GlobalPayments\Api\Entities\Exceptions\GatewayException; use GlobalPayments\Api\Entities\PayFac\BankAccountData; use GlobalPayments\Api\Entities\PayFac\UserPersonalData; @@ -26,10 +27,12 @@ use GlobalPayments\Api\Services\PayFacService; use GlobalPayments\Api\Services\ReportingService; use GlobalPayments\Api\ServicesContainer; +use GlobalPayments\Api\Tests\Data\BaseGpApiTestConfig; use GlobalPayments\Api\Tests\Integration\Gateways\ProPay\TestData\TestAccountData; use GlobalPayments\Api\Utils\GenerationUtils; use GlobalPayments\Api\Utils\Logging\Logger; use GlobalPayments\Api\Utils\Logging\SampleRequestLogger; +use GlobalPayments\Api\PaymentMethods\Interfaces\IPaymentMethod; use PHPUnit\Framework\TestCase; class GpApiMerchantsOnboardTest extends TestCase @@ -41,17 +44,13 @@ public function setup(): void public function setUpConfig() { - $config = new GpApiConfig(); - $config->appId = "A1feRdMmEB6m0Y1aQ65H0bDi9ZeAEB2t"; - $config->appKey = "5jPt1OpB6LLitgi7"; - $config->environment = Environment::TEST; - $config->channel = Channel::CardNotPresent; - $config->requestLogger = new SampleRequestLogger(new Logger("logs")); + BaseGpApiTestConfig::$appId = BaseGpApiTestConfig::PARTNER_SOLUTION_APP_ID; + BaseGpApiTestConfig::$appKey = BaseGpApiTestConfig::PARTNER_SOLUTION_APP_KEY; - return $config; + return BaseGpApiTestConfig::gpApiSetupConfig(Channel::CardNotPresent); } - public function testBoardMerchant() + public function testBoardMerchantX() { $merchantData = $this->getMerchantData(); $products = $this->getProductList(); @@ -159,7 +158,7 @@ public function testGetMerchantInfo() $paymentMethodList = $merchant->paymentMethodList->getIterator(); if($paymentMethodList->valid()) { $paymentMethodList->seek(1); - $this->assertInstanceOf(\GlobalPayments\Api\PaymentMethods\Interfaces\IPaymentMethod::class, + $this->assertInstanceOf(IPaymentMethod::class, $paymentMethodList->current()['payment_method'] ); } } @@ -345,9 +344,9 @@ public function testBoardMerchant_WithoutMerchantData() ->withPersonsData($persons) ->withPaymentStatistics($paymentStatistics) ->execute(); - } catch (ArgumentException $e) { + } catch (BuilderException $e) { $errorFound = true; - $this->assertEquals('Merchant data is mandatory!', $e->getMessage()); + $this->assertEquals('userPersonalData cannot be null for this transaction type.', $e->getMessage()); } finally { $this->assertTrue($errorFound); } @@ -489,33 +488,6 @@ public function testBoardMerchant_WithoutWebsite() } } - public function testBoardMerchant_WithoutTaxIdReference() - { - $merchantData = $this->getMerchantData(); - $merchantData->taxIdReference = null; - - $products = $this->getProductList(); - $persons = $this->getPersonList(); - $paymentStatistics = $this->getPaymentStatistics(); - - $errorFound = false; - try { - PayFacService::createMerchant() - ->withUserPersonalData($merchantData) - ->withDescription('Merchant Business Description') - ->withProductData($products) - ->withPersonsData($persons) - ->withPaymentStatistics($paymentStatistics) - ->execute(); - } catch (GatewayException $e) { - $errorFound = true; - $this->assertEquals('Status Code: MANDATORY_DATA_MISSING - Request expects the following fields tax_id_reference', $e->getMessage()); - $this->assertEquals('40005', $e->responseCode); - } finally { - $this->assertTrue($errorFound); - } - } - public function testBoardMerchant_WithoutNotificationStatusUrl() { $merchantData = $this->getMerchantData(); @@ -789,7 +761,7 @@ private function getBankAccountData() $bankAccountInformation->accountHolderName = 'Bank Account Holder Name'; $bankAccountInformation->accountNumber = '123456788'; $bankAccountInformation->accountOwnershipType = 'Personal'; - $bankAccountInformation->accountType = AccountType::SAVINGS; + $bankAccountInformation->accountType = AccountType::CHECKING; $bankAccountInformation->routingNumber = '102000076'; return $bankAccountInformation; diff --git a/test/Integration/Gateways/GpApiConnector/PartnershipModeTest.php b/test/Integration/Gateways/GpApiConnector/PartnershipModeTest.php index 066129ff..679ca42e 100644 --- a/test/Integration/Gateways/GpApiConnector/PartnershipModeTest.php +++ b/test/Integration/Gateways/GpApiConnector/PartnershipModeTest.php @@ -9,15 +9,22 @@ use GlobalPayments\Api\Entities\Enums\ChallengeWindowSize; use GlobalPayments\Api\Entities\Enums\Channel; use GlobalPayments\Api\Entities\Enums\ColorDepth; +use GlobalPayments\Api\Entities\Enums\MerchantAccountsSortProperty; +use GlobalPayments\Api\Entities\Enums\MerchantAccountStatus; +use GlobalPayments\Api\Entities\Enums\MerchantAccountType; use GlobalPayments\Api\Entities\Enums\MethodUrlCompletion; +use GlobalPayments\Api\Entities\Enums\PaymentMethodName; use GlobalPayments\Api\Entities\Enums\Secure3dStatus; use GlobalPayments\Api\Entities\Enums\Secure3dVersion; +use GlobalPayments\Api\Entities\Enums\SortDirection; use GlobalPayments\Api\Entities\Enums\TransactionStatus; use GlobalPayments\Api\Entities\Exceptions\GatewayException; use GlobalPayments\Api\Entities\GpApi\AccessTokenInfo; +use GlobalPayments\Api\Entities\Reporting\DataServiceCriteria; +use GlobalPayments\Api\Entities\Reporting\SearchCriteria; use GlobalPayments\Api\PaymentMethods\CreditCardData; use GlobalPayments\Api\ServiceConfigs\Gateways\GpApiConfig; -use GlobalPayments\Api\Services\GpApiService; +use GlobalPayments\Api\Services\ReportingService; use GlobalPayments\Api\Services\Secure3dService; use GlobalPayments\Api\ServicesContainer; use GlobalPayments\Api\Tests\Data\BaseGpApiTestConfig; @@ -31,8 +38,7 @@ class PartnershipModeTest extends TestCase private $card; /** @var string */ private $currency; - /** @var string */ - private $accessToken; + /** @var GpApiConfig */ private $baseConfig; private $amount; @@ -43,20 +49,17 @@ class PartnershipModeTest extends TestCase /** @var BrowserData */ private $browserData; - private $merchantId = 'MER_7e3e2c7df34f42819b3edee31022ee3f'; + private $merchantId; - public function setup() : void + public function setup(): void { $this->baseConfig = $this->setUpConfig(); - /** @var \GlobalPayments\Api\Entities\GpApi\AccessTokenInfo $accessTokenInfo */ - $accessTokenInfo = GpApiService::generateTransactionKey($this->baseConfig); - $this->accessToken = $accessTokenInfo->accessToken; + ServicesContainer::configureService($this->baseConfig); $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'; @@ -82,6 +85,47 @@ public function setup() : void $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"; + + $merchants = ReportingService::findMerchants(1, 10) + ->orderBy(MerchantAccountsSortProperty::TIME_CREATED, SortDirection::ASC) + ->where(SearchCriteria::ACCOUNT_STATUS, MerchantAccountStatus::ACTIVE) + ->execute(); + + if (count($merchants->result) > 0) { + $this->merchantId = reset($merchants->result)->id; + $this->setUpConfigMerchant(); + } + } + + private function setUpConfigMerchant() + { + $config = clone $this->baseConfig; + $config->challengeNotificationUrl = 'https://ensi808o85za.x.pipedream.net/'; + $config->methodNotificationUrl = 'https://ensi808o85za.x.pipedream.net/'; + $config->merchantContactUrl = 'https://enp4qhvjseljg.x.pipedream.net/'; + $config->merchantId = $this->merchantId; + + $accounts = ReportingService::findAccounts(1, 10) + ->orderBy(MerchantAccountsSortProperty::TIME_CREATED, SortDirection::ASC) + ->where(DataServiceCriteria::MERCHANT_ID, $this->merchantId) + ->andWith(SearchCriteria::ACCOUNT_STATUS, MerchantAccountStatus::ACTIVE) + ->execute(); + + $transactionAccounts = array_filter( + $accounts->result, + function ($account) { + return ( + $account->type == MerchantAccountType::TRANSACTION_PROCESSING && + in_array(PaymentMethodName::CARD, $account->paymentMethods) + ); + } + ); + + $config->accessTokenInfo->transactionProcessingAccountID = + (count($transactionAccounts) > 0 ? reset($transactionAccounts)->id : null); + + $configName = 'config_' . $this->merchantId; + ServicesContainer::configureService($config, $configName); } public static function tearDownAfterClass(): void @@ -89,59 +133,39 @@ public static function tearDownAfterClass(): void BaseGpApiTestConfig::resetGpApiConfig(); } - public function setUpConfig() + public function setUpConfig(): GpApiConfig { - BaseGpApiTestConfig::$appId = 'zKxybfLqH7vAOtBQrApxD5AUpS3ITaPz'; - BaseGpApiTestConfig::$appKey = 'GAMlgEojm6hxZTLI'; + BaseGpApiTestConfig::$appId = BaseGpApiTestConfig::PARTNER_SOLUTION_APP_ID; + BaseGpApiTestConfig::$appKey = BaseGpApiTestConfig::PARTNER_SOLUTION_APP_KEY; return BaseGpApiTestConfig::gpApiSetupConfig(Channel::CardNotPresent); } public function testCreditSaleWithPartnerMode() { - $merchants = ['MER_7e3e2c7df34f42819b3edee31022ee3f']; - $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); - } + $response = $this->card->charge(69) + ->withCurrency($this->currency) + ->withAddress($address) + ->execute('config_' . $this->merchantId); + + $this->assertNotNull($response); + $this->assertEquals('SUCCESS', $response->responseCode); + $this->assertEquals(TransactionStatus::CAPTURED, $response->responseMessage); } public function testCreditSaleRefundWithPartnerMode() { - $config = clone($this->baseConfig); - $config->merchantId = $this->merchantId; - $config->accessTokenInfo = new AccessTokenInfo(); - $config->accessTokenInfo->accessToken = $this->accessToken; - $config->accessTokenInfo->transactionProcessingAccountName = 'transaction_processing'; - $configName = 'config_' . $this->merchantId; - ServicesContainer::configureService($config, $configName); - $response = $this->card->charge(11) ->withCurrency($this->currency) ->withAddress($this->shippingAddress) - ->execute($configName); + ->execute('config_' . $this->merchantId); $this->assertNotNull($response); $this->assertEquals('SUCCESS', $response->responseCode); @@ -149,7 +173,7 @@ public function testCreditSaleRefundWithPartnerMode() $refundResponse = $response->refund(11) ->withCurrency($this->currency) - ->execute($configName); + ->execute('config_' . $this->merchantId); $this->assertNotNull($refundResponse); $this->assertEquals('SUCCESS', $refundResponse->responseCode); @@ -159,17 +183,9 @@ public function testCreditSaleRefundWithPartnerMode() public function testCreditRefundWithPartnerMode() { - $config = clone($this->baseConfig); - $config->merchantId = $this->merchantId; - $config->accessTokenInfo = new AccessTokenInfo(); - $config->accessTokenInfo->accessToken = $this->accessToken; - $config->accessTokenInfo->transactionProcessingAccountName = 'transaction_processing'; - $configName = 'config_' . $this->merchantId; - ServicesContainer::configureService($config, $configName); - $refundResponse = $this->card->refund(11) ->withCurrency($this->currency) - ->execute($configName); + ->execute('config_' . $this->merchantId); $this->assertNotNull($refundResponse); $this->assertEquals('SUCCESS', $refundResponse->responseCode); @@ -179,17 +195,9 @@ public function testCreditRefundWithPartnerMode() public function testCreditAuthAndCaptureWithPartnerMode() { - $config = clone($this->baseConfig); - $config->merchantId = $this->merchantId; - $config->accessTokenInfo = new AccessTokenInfo(); - $config->accessTokenInfo->accessToken = $this->accessToken; - $config->accessTokenInfo->transactionProcessingAccountName = 'transaction_processing'; - $configName = 'config_' . $this->merchantId; - ServicesContainer::configureService($config, $configName); - $authResponse = $this->card->authorize(11) ->withCurrency($this->currency) - ->execute($configName); + ->execute('config_' . $this->merchantId); $this->assertNotNull($authResponse); $this->assertEquals('SUCCESS', $authResponse->responseCode); @@ -197,7 +205,7 @@ public function testCreditAuthAndCaptureWithPartnerMode() $captureResponse = $authResponse->capture(11) ->withCurrency($this->currency) - ->execute($configName); + ->execute('config_' . $this->merchantId); $this->assertNotNull($captureResponse); $this->assertEquals('SUCCESS', $captureResponse->responseCode); @@ -208,17 +216,9 @@ public function testCreditAuthAndCaptureWithPartnerMode() public function testCreditAuthAndReverseWithPartnerMode() { - $config = clone($this->baseConfig); - $config->merchantId = $this->merchantId; - $config->accessTokenInfo = new AccessTokenInfo(); - $config->accessTokenInfo->accessToken = $this->accessToken; - $config->accessTokenInfo->transactionProcessingAccountName = 'transaction_processing'; - $configName = 'config_' . $this->merchantId; - ServicesContainer::configureService($config, $configName); - $authResponse = $this->card->authorize(11) ->withCurrency($this->currency) - ->execute($configName); + ->execute('config_' . $this->merchantId); $this->assertNotNull($authResponse); $this->assertEquals('SUCCESS', $authResponse->responseCode); @@ -226,7 +226,7 @@ public function testCreditAuthAndReverseWithPartnerMode() $reverseResponse = $authResponse->reverse(11) ->withCurrency($this->currency) - ->execute($configName); + ->execute('config_' . $this->merchantId); $this->assertNotNull($reverseResponse); $this->assertEquals('SUCCESS', $reverseResponse->responseCode); @@ -236,17 +236,9 @@ public function testCreditAuthAndReverseWithPartnerMode() public function testCreditReAuthWithPartnerMode() { - $config = clone($this->baseConfig); - $config->merchantId = $this->merchantId; - $config->accessTokenInfo = new AccessTokenInfo(); - $config->accessTokenInfo->accessToken = $this->accessToken; - $config->accessTokenInfo->transactionProcessingAccountName = 'transaction_processing'; - $configName = 'config_' . $this->merchantId; - ServicesContainer::configureService($config, $configName); - $authResponse = $this->card->authorize(11) ->withCurrency($this->currency) - ->execute($configName); + ->execute('config_' . $this->merchantId); $this->assertNotNull($authResponse); $this->assertEquals('SUCCESS', $authResponse->responseCode); @@ -254,7 +246,7 @@ public function testCreditReAuthWithPartnerMode() $reverseResponse = $authResponse->reverse(11) ->withCurrency($this->currency) - ->execute($configName); + ->execute('config_' . $this->merchantId); $this->assertNotNull($reverseResponse); $this->assertEquals('SUCCESS', $reverseResponse->responseCode); @@ -262,7 +254,7 @@ public function testCreditReAuthWithPartnerMode() $reAuthResponse = $reverseResponse->reauthorized(11) ->withCurrency($this->currency) - ->execute($configName); + ->execute('config_' . $this->merchantId); $this->assertNotNull($reAuthResponse); $this->assertEquals('SUCCESS', $reAuthResponse->responseCode); @@ -274,22 +266,10 @@ public function testFullCycle3DSChallenge_v2_PartnerMode() { $this->card->number = '4222000001227408'; - $config = clone($this->baseConfig); - $config->merchantId = $this->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_' . $this->merchantId; - ServicesContainer::configureService($config, $configName); - $secureEcom = Secure3dService::checkEnrollment($this->card) ->withCurrency($this->currency) ->withAmount($this->amount) - ->execute($configName); + ->execute('config_' . $this->merchantId); $this->assertNotNull($secureEcom); $this->assertEquals(Secure3dStatus::ENROLLED, $secureEcom->enrolled); @@ -304,7 +284,7 @@ public function testFullCycle3DSChallenge_v2_PartnerMode() ->withOrderCreateDate(date('Y-m-d H:i:s')) ->withAddress($this->shippingAddress, AddressType::SHIPPING) ->withBrowserData($this->browserData) - ->execute($configName); + ->execute('config_' . $this->merchantId); $this->assertNotNull($initAuth); $this->assertEquals(Secure3dStatus::CHALLENGE_REQUIRED, $initAuth->status); @@ -312,20 +292,20 @@ public function testFullCycle3DSChallenge_v2_PartnerMode() $this->assertNotNull($initAuth->payerAuthenticationRequest); $authClient = new ThreeDSecureAcsClient($secureEcom->issuerAcsUrl); - $authClient->setGatewayProvider($config->getGatewayProvider()); + $authClient->setGatewayProvider($this->baseConfig->getGatewayProvider()); $authResponse = $authClient->authenticate_v2($initAuth); $this->assertTrue($authResponse->getStatus()); $this->assertNotEmpty($authResponse->getMerchantData()); $secureEcom = Secure3dService::getAuthenticationData() ->withServerTransactionId($authResponse->getMerchantData()) - ->execute($configName); + ->execute('config_' . $this->merchantId); $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); + $response = $this->card->charge($this->amount)->withCurrency($this->currency)->execute('config_' . $this->merchantId); $this->assertNotNull($response); $this->assertEquals('SUCCESS', $response->responseCode); $this->assertEquals(TransactionStatus::CAPTURED, $response->responseMessage); @@ -333,16 +313,7 @@ public function testFullCycle3DSChallenge_v2_PartnerMode() public function testVerifyTokenizedPaymentMethodWithPartnerMode() { - $config = clone($this->baseConfig); - $config->merchantId = $this->merchantId; - $config->accessTokenInfo = new AccessTokenInfo(); - $config->accessTokenInfo->accessToken = $this->accessToken; - $config->accessTokenInfo->transactionProcessingAccountName = 'transaction_processing'; - - $configName = 'config_' . $this->merchantId; - ServicesContainer::configureService($config, $configName); - - $response = $this->card->tokenize()->execute($configName); + $response = $this->card->tokenize()->execute('config_' . $this->merchantId); $this->assertNotNull($response); $this->assertEquals('SUCCESS', $response->responseCode); $this->assertEquals('ACTIVE', $response->responseMessage); @@ -352,7 +323,7 @@ public function testVerifyTokenizedPaymentMethodWithPartnerMode() $response = $tokenizedCard->verify() ->withCurrency($this->currency) - ->execute($configName); + ->execute('config_' . $this->merchantId); $this->assertNotNull($response); $this->assertEquals('SUCCESS', $response->responseCode); @@ -365,9 +336,6 @@ public function testCreditSaleWithPartnerMode_WrongMerchant() $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); @@ -390,9 +358,7 @@ public function testCreditSaleWithPartnerMode_MisConfiguration() { $config = clone($this->baseConfig); $config->merchantId = $this->merchantId; - $config->accessTokenInfo = new AccessTokenInfo(); - $config->accessTokenInfo->accessToken = $this->accessToken; - $config->accessTokenInfo->transactionProcessingAccountName = 'tokenization'; + $config->accessTokenInfo->transactionProcessingAccountID = '123566789'; $configName = 'config_' . $this->merchantId; ServicesContainer::configureService($config, $configName); @@ -404,7 +370,7 @@ public function testCreditSaleWithPartnerMode_MisConfiguration() } catch (GatewayException $e) { $exceptionCaught = true; $this->assertEquals('40041', $e->responseCode); - $this->assertStringContainsString(' INVALID_REQUEST_DATA - Merchant configuration does not exist', $e->getMessage()); + $this->assertStringContainsString('Merchant configuration does not exist for the following combination', $e->getMessage()); } finally { $this->assertTrue($exceptionCaught); } @@ -416,8 +382,6 @@ public function testCreditSaleWithPartnerMode_MissingAccountName() $config = clone($this->baseConfig); $config->merchantId = $this->merchantId; $config->accessTokenInfo = new AccessTokenInfo(); - $config->accessTokenInfo->accessToken = $this->accessToken; - $config->accessTokenInfo->tokenizationAccountName = 'tokenization'; $configName = 'config_' . $this->merchantId; ServicesContainer::configureService($config, $configName); diff --git a/test/Integration/Gateways/GpEcomConnector/Secure3dServiceTest.php b/test/Integration/Gateways/GpEcomConnector/Secure3dServiceTest.php index cb0e1909..2a681eec 100644 --- a/test/Integration/Gateways/GpEcomConnector/Secure3dServiceTest.php +++ b/test/Integration/Gateways/GpEcomConnector/Secure3dServiceTest.php @@ -800,6 +800,7 @@ public function testOptionalPayerLoginData() public function testOptionalMobileFields() { + $this->card->number = '4012001038488884'; $secureEcom = Secure3dService::checkEnrollment($this->card) ->execute('default', Secure3dVersion::TWO); $this->assertNotNull($secureEcom); @@ -836,16 +837,20 @@ public function testOptionalMobileFields() ->execute(); $this->assertNotNull($initAuth); - $this->assertEquals('AUTHENTICATION_SUCCESSFUL', $initAuth->status); + $this->assertEquals('CHALLENGE_REQUIRED', $initAuth->status); $this->assertNotNull($initAuth->payerAuthenticationRequest); $this->assertNotNull($initAuth->acsTransactionId); + $this->assertNotNull($initAuth->payerAuthenticationRequest); + $this->assertNotNull($initAuth->acsUiTemplate); + $this->assertNotNull($initAuth->acsInterface); + $this->assertNotNull($initAuth->acsReferenceNumber); // get authentication data $secureEcom = Secure3dService::getAuthenticationData() ->withServerTransactionId($initAuth->serverTransactionId) ->execute(); - $this->assertEquals('AUTHENTICATION_SUCCESSFUL', $initAuth->status); + $this->assertEquals('CHALLENGE_REQUIRED', $initAuth->status); $this->card->threeDSecure = $secureEcom; $response = $this->card->charge(10.01)