From 57994ad6043acf177156dd266e51775fa47bba09 Mon Sep 17 00:00:00 2001 From: securesubmit-buildmaster Date: Thu, 11 Mar 2021 18:36:52 +0530 Subject: [PATCH] 20210311 deployment --- src/Builders/PayFacBuilder.php | 387 +++++++++++ src/ConfiguredServices.php | 23 + src/Entities/Enums/ProPayAccountStatus.php | 24 + .../Enums/Secure3dPaymentDataSource.php | 4 +- src/Entities/Enums/ServiceEndpoints.php | 4 + src/Entities/Enums/TransactionType.php | 26 +- .../PayFac/AccountBalanceResponseData.php | 11 + src/Entities/PayFac/AccountPermissions.php | 125 ++++ src/Entities/PayFac/BankAccountData.php | 65 ++ src/Entities/PayFac/BeneficialOwnerData.php | 22 + src/Entities/PayFac/BusinessData.php | 89 +++ .../PayFac/FlashFundsPaymentCardData.php | 18 + .../PayFac/GrossBillingInformation.php | 22 + .../PayFac/OwnerDetailsResponseData.php | 9 + src/Entities/PayFac/OwnersData.php | 70 ++ src/Entities/PayFac/PayFacResponseData.php | 54 ++ src/Entities/PayFac/RenewAccountData.php | 60 ++ src/Entities/PayFac/SignificantOwnerData.php | 34 + src/Entities/PayFac/SingleSignOnData.php | 29 + src/Entities/PayFac/ThreatRiskData.php | 27 + src/Entities/PayFac/UploadDocumentData.php | 35 + src/Entities/PayFac/UserPersonalData.php | 134 ++++ src/Entities/RecurringEntity.php | 2 +- src/Entities/Transaction.php | 7 + src/Gateways/GeniusConnector.php | 12 +- src/Gateways/IPayFacProvider.php | 17 + src/Gateways/PayPlanConnector.php | 2 +- src/Gateways/PorticoConnector.php | 13 +- src/Gateways/ProPayConnector.php | 646 ++++++++++++++++++ src/PaymentMethods/GiftCard.php | 2 +- src/PaymentMethods/RecurringPaymentMethod.php | 7 + src/ServiceConfigs/AcceptorConfig.php | 3 +- src/ServiceConfigs/Configuration.php | 3 +- src/ServiceConfigs/Gateways/PorticoConfig.php | 24 + src/Services/PayFacService.php | 146 ++++ src/ServicesContainer.php | 12 + .../Gateways/ProPay/ProPayAccountTests.php | 290 ++++++++ .../Gateways/ProPay/ProPayFundsTests.php | 74 ++ .../ProPay/ProPayGetInformationTests.php | 73 ++ .../Gateways/ProPay/ProPayNetworkTests.php | 82 +++ .../ProPay/TestData/ChargebackDispute.jpg | Bin 0 -> 51094 bytes .../ProPay/TestData/TestAccountData.php | 304 +++++++++ .../ProPay/TestData/TestFundsData.php | 27 + .../ProPay/TestData/selfSignedCertificate.crt | 18 + 44 files changed, 3018 insertions(+), 18 deletions(-) create mode 100644 src/Builders/PayFacBuilder.php create mode 100644 src/Entities/Enums/ProPayAccountStatus.php create mode 100644 src/Entities/PayFac/AccountBalanceResponseData.php create mode 100644 src/Entities/PayFac/AccountPermissions.php create mode 100644 src/Entities/PayFac/BankAccountData.php create mode 100644 src/Entities/PayFac/BeneficialOwnerData.php create mode 100644 src/Entities/PayFac/BusinessData.php create mode 100644 src/Entities/PayFac/FlashFundsPaymentCardData.php create mode 100644 src/Entities/PayFac/GrossBillingInformation.php create mode 100644 src/Entities/PayFac/OwnerDetailsResponseData.php create mode 100644 src/Entities/PayFac/OwnersData.php create mode 100644 src/Entities/PayFac/PayFacResponseData.php create mode 100644 src/Entities/PayFac/RenewAccountData.php create mode 100644 src/Entities/PayFac/SignificantOwnerData.php create mode 100644 src/Entities/PayFac/SingleSignOnData.php create mode 100644 src/Entities/PayFac/ThreatRiskData.php create mode 100644 src/Entities/PayFac/UploadDocumentData.php create mode 100644 src/Entities/PayFac/UserPersonalData.php create mode 100644 src/Gateways/IPayFacProvider.php create mode 100644 src/Gateways/ProPayConnector.php create mode 100644 src/Services/PayFacService.php create mode 100644 test/Integration/Gateways/ProPay/ProPayAccountTests.php create mode 100644 test/Integration/Gateways/ProPay/ProPayFundsTests.php create mode 100644 test/Integration/Gateways/ProPay/ProPayGetInformationTests.php create mode 100644 test/Integration/Gateways/ProPay/ProPayNetworkTests.php create mode 100644 test/Integration/Gateways/ProPay/TestData/ChargebackDispute.jpg create mode 100644 test/Integration/Gateways/ProPay/TestData/TestAccountData.php create mode 100644 test/Integration/Gateways/ProPay/TestData/TestFundsData.php create mode 100644 test/Integration/Gateways/ProPay/TestData/selfSignedCertificate.crt diff --git a/src/Builders/PayFacBuilder.php b/src/Builders/PayFacBuilder.php new file mode 100644 index 00000000..5ab380fa --- /dev/null +++ b/src/Builders/PayFacBuilder.php @@ -0,0 +1,387 @@ +transactionType = $type; + $this->transactionModifier = TransactionModifier::NONE; + } + + /** + * Executes the builder against the gateway. + * + * @return mixed + */ + public function execute(string $configName = 'default') + { + parent::execute($configName); + + $client = ServicesContainer::instance()->getPayFac($configName); + return $client->processPayFac($this); + } + + protected function setupValidations() + { + $this->validations->of( + TransactionType::CREATE_ACCOUNT + ) + ->with(TransactionModifier::NONE) + ->check('beneficialOwnerData')->isNotNull() + ->check('businessData')->isNotNull() + ->check('userPersonalData')->isNotNull() + ->check('creditCardInformation')->isNotNull(); + + $this->validations->of( + TransactionType::EDIT | + TransactionType::RESET_PASSWORD | + TransactionType::RENEW_ACCOUNT | + TransactionType::UPDATE_OWNERSHIP_DETAILS | + TransactionType::DEACTIVATE | + TransactionType::UPLOAD_CHARGEBACK_DOCUMENT | + TransactionType::OBTAIN_SSO_KEY | + TransactionType::UPDATE_BANK_ACCOUNT_OWNERSHIP | + TransactionType::ADD_FUNDS | + TransactionType::SWEEP_FUNDS | + TransactionType::ADD_CARD_FLASH_FUNDS | + TransactionType::PUSH_MONEY_FLASH_FUNDS | + TransactionType::SPEND_BACK | + TransactionType::REVERSE_SPLITPAY | + TransactionType::SPLIT_FUNDS | + TransactionType::GET_ACCOUNT_BALANCE + ) + ->with(TransactionModifier::NONE) + ->check('accountNumber')->isNotNull(); + + $this->validations->of( + TransactionType::UPDATE_OWNERSHIP_DETAILS + ) + ->with(TransactionModifier::NONE) + ->check('beneficialOwnerData')->isNotNull(); + + $this->validations->of( + TransactionType::UPLOAD_CHARGEBACK_DOCUMENT + ) + ->with(TransactionModifier::NONE) + ->check('uploadDocumentData')->isNotNull(); + + $this->validations->of( + TransactionType::OBTAIN_SSO_KEY + ) + ->with(TransactionModifier::NONE) + ->check('singleSignOnData')->isNotNull(); + + $this->validations->of( + TransactionType::UPDATE_BANK_ACCOUNT_OWNERSHIP + ) + ->with(TransactionModifier::NONE) + ->check('beneficialOwnerData')->isNotNull(); + + $this->validations->of( + TransactionType::ADD_FUNDS | + TransactionType::SWEEP_FUNDS | + TransactionType::PUSH_MONEY_FLASH_FUNDS | + TransactionType::SPEND_BACK | + TransactionType::REVERSE_SPLITPAY | + TransactionType::SPLIT_FUNDS + ) + ->with(TransactionModifier::NONE) + ->check('amount')->isNotNull(); + + $this->validations->of(TransactionType::ADD_CARD_FLASH_FUNDS) + ->with(TransactionModifier::NONE) + ->check('flashFundsPaymentCardData')->isNotNull(); + + $this->validations->of(TransactionType::DISBURSE_FUNDS) + ->with(TransactionModifier::NONE) + ->check('receivingAccountNumber')->isNotNull(); + + $this->validations->of(TransactionType::SPEND_BACK) + ->with(TransactionModifier::NONE) + ->check('allowPending')->isNotNull() + ->check('receivingAccountNumber')->isNotNull(); + + $this->validations->of(TransactionType::SPLIT_FUNDS) + ->with(TransactionModifier::NONE) + ->check('transNum')->isNotNull() + ->check('receivingAccountNumber')->isNotNull(); + + $this->validations->of(TransactionType::REVERSE_SPLITPAY) + ->with(TransactionModifier::NONE) + ->check('transNum')->isNotNull() + ->check('requireCCRefund')->isNotNull() + ->check('ccAmount')->isNotNull(); + + } + + /* + * Primary Bank Account Information – Optional. Used to add a bank account to which funds can be settled + * + * var Object GlobalPayments\Api\Entities\PayFac\BankAccountData; + */ + public function withBankAccountData(BankAccountData $bankAccountData) + { + $this->bankAccountData = $bankAccountData; + return $this; + } + /* + * Merchant Beneficiary Owner Information – Required for all merchants validating KYC based off of personal data + * + * var Object GlobalPayments\Api\Entities\PayFac\BeneficialOwnerData; + */ + public function withBeneficialOwnerData(BeneficialOwnerData $beneficialOwnerData) + { + $this->beneficialOwnerData = $beneficialOwnerData; + return $this; + } + /* + * Business Data – Required for business validated accounts. May also be required for personal validated accounts + * by ProPay Risk Team + * + * var Object GlobalPayments\Api\Entities\PayFac\BusinessData; + */ + public function withBusinessData(BusinessData $businessData) + { + $this->businessData = $businessData; + return $this; + } + /* + * Significant Owner Information – May be required for some partners based on ProPay Risk decision + * + * var Object GlobalPayments\Api\Entities\PayFac\SignificantOwnerData; + */ + public function withSignificantOwnerData(SignificantOwnerData $significantOwnerData) + { + $this->significantOwnerData = $significantOwnerData; + return $this; + } + /* + * Threat Risk Assessment Information – May be required based on ProPay Risk Decision + * + * var Object GlobalPayments\Api\Entities\PayFac\ThreatRiskData; + */ + public function withThreatRiskData(ThreatRiskData $threatRiskData) + { + $this->threatRiskData = $threatRiskData; + return $this; + } + + /* + * User / Merchant Personal Data + * + * var Object GlobalPayments\Api\Entities\PayFac\UserPersonalData; + */ + public function withUserPersonalData(UserPersonalData $userPersonalData) + { + $this->userPersonalData = $userPersonalData; + return $this; + } + + public function withCreditCardData($creditCardInformation) + { + $this->creditCardInformation = $creditCardInformation; + return $this; + } + + public function withACHData($achInformation) + { + $this->achInformation = $achInformation; + return $this; + } + + public function withSecondaryBankAccountData($secondaryBankInformation) + { + $this->secondaryBankInformation = $secondaryBankInformation; + return $this; + } + + public function withGrossBillingSettleData($grossBillingInformation) + { + $this->grossBillingInformation = $grossBillingInformation; + return $this; + } + + /* + * The ProPay account to be updated + * + * var int + */ + public function withAccountNumber($accountNumber) + { + $this->accountNumber = $accountNumber; + return $this; + } + + /* + * Temporary password which will allow a onetime login to ProPay’s website. Must be at least eight characters. + * Must not contain part or the entire first or last name. Must contain at least one capital letter, + * one lower case letter, and either one symbol or one number + * + * var string + */ + public function withPassword($password) + { + $this->password = $password; + return $this; + } + + public function withAccountPermissions($accountPermissions) + { + $this->accountPermissions = $accountPermissions; + return $this; + } + + /* + * amount must be greater than zero + */ + public function withNegativeLimit($negativeLimit) + { + $this->negativeLimit = $negativeLimit; + return $this; + } + + public function withRenewalAccountData($renewalAccountData) + { + $this->renewalAccountData = $renewalAccountData; + return $this; + } + + + /* + * Document details + * + * var GlobalPayments\Api\Entities\PayFac\UploadDocumentData + */ + public function withUploadDocumentData($uploadDocumentData) + { + //file validations + if (!file_exists($uploadDocumentData->documentLocation)) { + throw new BuilderException('File not found!'); + } elseif (filesize($uploadDocumentData->documentLocation) > 5000000) { + throw new BuilderException('Max file size 5MB exceeded'); + } + + $fileType = pathinfo($uploadDocumentData->documentLocation, PATHINFO_EXTENSION); + if (!in_array($fileType, self::UPLOAD_FILE_TYPES)) { + throw new BuilderException('File type is not supported.'); + } + + $this->uploadDocumentData = $uploadDocumentData; + return $this; + } + + public function withSingleSignOnData($singleSignOnData) + { + $this->singleSignOnData = $singleSignOnData; + return $this; + } + + public function withAmount($amount) + { + $this->amount = $amount; + return $this; + } + + public function withReceivingAccountNumber($receivingAccountNumber) + { + $this->receivingAccountNumber = $receivingAccountNumber; + return $this; + } + + public function withAllowPending($allowPending) + { + $this->allowPending = $allowPending; + return $this; + } + + public function withCCAmount($ccAmount) + { + $this->ccAmount = $ccAmount; + return $this; + } + + public function withRequireCCRefund($requireCCRefund) + { + $this->requireCCRefund = $requireCCRefund; + return $this; + } + + public function withTransNum($transNum) + { + $this->transNum = $transNum; + return $this; + } + + public function withFlashFundsPaymentCardData($flashFundsPaymentCardData) + { + $this->flashFundsPaymentCardData = $flashFundsPaymentCardData; + return $this; + } + + public function withExternalId($externalId) + { + $this->externalId = $externalId; + return $this; + } + + public function withSourceEmail($sourceEmail) + { + $this->sourceEmail = $sourceEmail; + return $this; + } +} diff --git a/src/ConfiguredServices.php b/src/ConfiguredServices.php index 8060702e..ee877ad4 100644 --- a/src/ConfiguredServices.php +++ b/src/ConfiguredServices.php @@ -10,6 +10,9 @@ class ConfiguredServices { private $secure3dProviders; + + /** @var IPayFacProvider */ + private $payFacProvider; /** @var IPaymentGateway */ public $gatewayConnector; @@ -59,4 +62,24 @@ public function setSecure3dProvider($version, $provider) { $this->secure3dProviders[$version] = $provider; } + + /** + * @return void + */ + public function setPayFacProvider($provider) + { + $this->payFacProvider = $provider; + } + + /** + * @return IPayFacProvider + */ + public function getPayFacProvider() + { + $provider = $this->payFacProvider; + if ($provider != null) { + return $provider; + } + return null; + } } diff --git a/src/Entities/Enums/ProPayAccountStatus.php b/src/Entities/Enums/ProPayAccountStatus.php new file mode 100644 index 00000000..fd8275e7 --- /dev/null +++ b/src/Entities/Enums/ProPayAccountStatus.php @@ -0,0 +1,24 @@ +businessAddress = new Address(); + } +} diff --git a/src/Entities/PayFac/FlashFundsPaymentCardData.php b/src/Entities/PayFac/FlashFundsPaymentCardData.php new file mode 100644 index 00000000..4d52fea5 --- /dev/null +++ b/src/Entities/PayFac/FlashFundsPaymentCardData.php @@ -0,0 +1,18 @@ +creditCard = new CreditCardData(); + $this->cardholderAddress = new Address(); + } +} diff --git a/src/Entities/PayFac/GrossBillingInformation.php b/src/Entities/PayFac/GrossBillingInformation.php new file mode 100644 index 00000000..f59d961d --- /dev/null +++ b/src/Entities/PayFac/GrossBillingInformation.php @@ -0,0 +1,22 @@ +grossSettleAddress = new Address(); + $this->grossSettleBankData = new BankAccountData(); + $this->grossSettleCreditCardData = new CreditCardData(); + } +} diff --git a/src/Entities/PayFac/OwnerDetailsResponseData.php b/src/Entities/PayFac/OwnerDetailsResponseData.php new file mode 100644 index 00000000..f8ab1115 --- /dev/null +++ b/src/Entities/PayFac/OwnerDetailsResponseData.php @@ -0,0 +1,9 @@ +ownerAddress = new Address(); + } +} diff --git a/src/Entities/PayFac/PayFacResponseData.php b/src/Entities/PayFac/PayFacResponseData.php new file mode 100644 index 00000000..71e75efb --- /dev/null +++ b/src/Entities/PayFac/PayFacResponseData.php @@ -0,0 +1,54 @@ +physicalAddress = new Address(); + $this->aCHOut = new AccountBalanceResponseData(); + $this->flashFunds = new AccountBalanceResponseData(); + } +} diff --git a/src/Entities/PayFac/RenewAccountData.php b/src/Entities/PayFac/RenewAccountData.php new file mode 100644 index 00000000..4c27b2d2 --- /dev/null +++ b/src/Entities/PayFac/RenewAccountData.php @@ -0,0 +1,60 @@ +creditCard = new CreditCardData(); + } +} diff --git a/src/Entities/PayFac/SignificantOwnerData.php b/src/Entities/PayFac/SignificantOwnerData.php new file mode 100644 index 00000000..e421b8fb --- /dev/null +++ b/src/Entities/PayFac/SignificantOwnerData.php @@ -0,0 +1,34 @@ +significantOwnerData = new OwnersData(); + } +} diff --git a/src/Entities/PayFac/SingleSignOnData.php b/src/Entities/PayFac/SingleSignOnData.php new file mode 100644 index 00000000..ee8015aa --- /dev/null +++ b/src/Entities/PayFac/SingleSignOnData.php @@ -0,0 +1,29 @@ + if userId is not +provided. + * + * @var string + */ + public $userId; + + /** + * Business Physical Address + * + * @var GlobalPayments\Api\Entities\Address + */ + public $userAddress; + + /** + * Business Physical Address + * + * @var GlobalPayments\Api\Entities\Address + */ + public $mailingAddress; + + + public function __construct() + { + $this->userAddress = new Address(); + $this->mailingAddress = new Address(); + } +} diff --git a/src/Entities/RecurringEntity.php b/src/Entities/RecurringEntity.php index cfd3bcc8..4771393b 100644 --- a/src/Entities/RecurringEntity.php +++ b/src/Entities/RecurringEntity.php @@ -64,7 +64,7 @@ public static function find($id, $configName = 'default') ->execute(); foreach ($response as $entity) { - if ($entity->id === $id) { + if ($entity->id === (string) $id) { return RecurringService::get($entity); } } diff --git a/src/Entities/Transaction.php b/src/Entities/Transaction.php index c299ddbd..c2ae8ffa 100644 --- a/src/Entities/Transaction.php +++ b/src/Entities/Transaction.php @@ -259,6 +259,13 @@ class Transaction * */ public $cardBrandTransactionId; + + /** + * The response from Propay + * + * @var PayFacResponseData + */ + public $payFacData; public $cardNumber; diff --git a/src/Gateways/GeniusConnector.php b/src/Gateways/GeniusConnector.php index 9a85fbe3..b67aad5f 100644 --- a/src/Gateways/GeniusConnector.php +++ b/src/Gateways/GeniusConnector.php @@ -348,14 +348,14 @@ public function processReport($builder) } private function setGatewayParams($paymentMethod) - { + { if (!empty($paymentMethod->paymentMethodType) && $paymentMethod->paymentMethodType === PaymentMethodType::GIFT) { $this->xmlNamespace = 'http://schemas.merchantwarehouse.com/merchantware/46/Giftcard'; $this->serviceUrl .= self::GIFT_SERVICE_END_POINT; - } else { - $this->serviceUrl .= self::CREDIT_SERVICE_END_POINT; - } + } else { + $this->serviceUrl .= self::CREDIT_SERVICE_END_POINT; + } } private function hydratePaymentData($xml, $paymentData, $paymentMethod) @@ -365,7 +365,7 @@ private function hydratePaymentData($xml, $paymentData, $paymentMethod) if ($card->valueType === 'CardNbr') { $paymentData->appendChild($xml->createElement('Source', 'Keyed')); $paymentData->appendChild($xml->createElement('CardNumber', $card->number)); - $paymentData->appendChild($xml->createElement('GiftCardPin', $card->pin)); + $paymentData->appendChild($xml->createElement('GiftCardPin', $card->pin)); } elseif ($card->valueType === 'TrackData') { $paymentData->appendChild($xml->createElement('Source', 'READER')); $paymentData->appendChild($xml->createElement('TrackData', $card->value)); @@ -400,5 +400,5 @@ private function hydratePaymentData($xml, $paymentData, $paymentMethod) $paymentData->appendChild($xml->createElement('TrackData', $track->value)); } } - } + } } diff --git a/src/Gateways/IPayFacProvider.php b/src/Gateways/IPayFacProvider.php new file mode 100644 index 00000000..e46ab52c --- /dev/null +++ b/src/Gateways/IPayFacProvider.php @@ -0,0 +1,17 @@ +format('mdY') : null; $request[$name] = $value; - } + } } return $request; } diff --git a/src/Gateways/PorticoConnector.php b/src/Gateways/PorticoConnector.php index 3ff802a4..76845e69 100644 --- a/src/Gateways/PorticoConnector.php +++ b/src/Gateways/PorticoConnector.php @@ -40,6 +40,7 @@ use GlobalPayments\Api\Services\ReportingService; use GlobalPayments\Api\Entities\Enums\StoredCredentialInitiator; use GlobalPayments\Api\Entities\Exceptions\BuilderException; +use GlobalPayments\Api\Entities\PayFac\PayFacResponseData; class PorticoConnector extends XmlGateway implements IPaymentGateway { @@ -411,6 +412,10 @@ public function processAuthorization(AuthorizationBuilder $builder) $block1->appendChild($data); } + if ($method->paymentType === "ACH" && !empty($method->secCode)) { + $block1->appendChild($xml->createElement('SECCode', $method->secCode)); + } + $data = $xml->createElement('RecurringData'); if ($builder->scheduleId !== null) { $data->appendChild($xml->createElement('ScheduleID', $builder->scheduleId)); @@ -1173,7 +1178,13 @@ protected function mapResponse($rawResponse, BaseBuilder $builder, $request) if (isset($item) && isset($item->CardBrandTxnId)) { $result->cardBrandTransactionId = (string)$item->CardBrandTxnId; } - + + if(!empty($root->PaymentFacilitatorTxnId) || !empty($root->PaymentFacilitatorTxnNbr)){ + $result->payFacData = new PayFacResponseData(); + $result->payFacData->transactionId = !empty($root->PaymentFacilitatorTxnId) ? (string) $root->PaymentFacilitatorTxnId : ''; + $result->payFacData->transactionNumber = !empty($root->PaymentFacilitatorTxnNbr) ? (string) $root->PaymentFacilitatorTxnNbr : ''; + } + return $result; } diff --git a/src/Gateways/ProPayConnector.php b/src/Gateways/ProPayConnector.php new file mode 100644 index 00000000..f71667bd --- /dev/null +++ b/src/Gateways/ProPayConnector.php @@ -0,0 +1,646 @@ +updateGatewaySettings($builder); + + $xml = new DOMDocument(); + $transaction = $xml->createElement('XMLRequest'); + + // Credentials + $transaction->appendChild($xml->createElement('certStr', $this->certStr)); + $transaction->appendChild($xml->createElement('termid', $this->termId)); + $transaction->appendChild($xml->createElement('class', 'partner')); + + // Transaction + $xmlTrans = $xml->createElement('XMLTrans'); + $xmlTrans->appendChild($xml->createElement('transType', $this->mapRequestType($builder))); + + $this->hydrateCommonFields($xml, $xmlTrans, $builder); + + if ($builder->transactionType === TransactionType::CREATE_ACCOUNT) { + $this->hydrateAccountDetails($xml, $xmlTrans, $builder); + } elseif ($builder->transactionType === TransactionType::EDIT) { + $this->hydrateAccountEditDetails($xml, $xmlTrans, $builder); + } elseif ($builder->transactionType === TransactionType::RENEW_ACCOUNT && !empty($builder->renewalAccountData)) { + $this->hydrateAccountRenewDetails($xml, $xmlTrans, $builder->renewalAccountData); + } elseif ($builder->transactionType === TransactionType::UPDATE_OWNERSHIP_DETAILS + && !empty($builder->beneficialOwnerData)) { + $this->hydrateBeneficialOwnerData($xml, $xmlTrans, $builder->beneficialOwnerData); + } elseif (!empty($builder->uploadDocumentData)) { + $this->hydrateUploadDocument($xml, $xmlTrans, $builder->uploadDocumentData); + } elseif (!empty($builder->singleSignOnData)) { + $this->hydrateSingleSignOnData($xml, $xmlTrans, $builder->singleSignOnData); + } elseif ($builder->transactionType === TransactionType::UPDATE_BANK_ACCOUNT_OWNERSHIP + && !empty($builder->beneficialOwnerData)) { + $this->updateBankAccountOwnershipInfo($xml, $xmlTrans, $builder->beneficialOwnerData); + } elseif (!empty($builder->flashFundsPaymentCardData)) { + $this->hydrateFlashFundsData($xml, $xmlTrans, $builder->flashFundsPaymentCardData); + } elseif ($builder->transactionType === TransactionType::GET_ACCOUNT_DETAILS + && empty($builder->accountNumber)) { + if(!empty($builder->externalId)){ + $xmlTrans->appendChild($xml->createElement('externalId', $builder->externalId)); + } elseif(!empty($builder->sourceEmail)){ + $xmlTrans->appendChild($xml->createElement('sourceEmail', $builder->sourceEmail)); + } + } + + $transaction->appendChild($xmlTrans); + + $requestXML = $xml->saveXML($transaction); + $response = $this->doTransaction($requestXML); + + return $this->mapResponse($builder, $response); + } + + public function mapRequestType($builder) + { + switch ($builder->transactionType) { + case TransactionType::CREATE_ACCOUNT: + return '01'; + case TransactionType::EDIT: + return '42'; + case TransactionType::RESET_PASSWORD: + return '32'; + case TransactionType::RENEW_ACCOUNT: + return '39'; + case TransactionType::UPDATE_OWNERSHIP_DETAILS: + return '44'; + case TransactionType::DEACTIVATE: + return '41'; + case TransactionType::UPLOAD_CHARGEBACK_DOCUMENT: + return '46'; + case TransactionType::UPLOAD_DOCUMENT: + return '47'; + case TransactionType::OBTAIN_SSO_KEY: + return '300'; + case TransactionType::UPDATE_BANK_ACCOUNT_OWNERSHIP: + return '210'; + case TransactionType::ADD_FUNDS: + return "37"; + case TransactionType::SWEEP_FUNDS: + return "38"; + case TransactionType::ADD_CARD_FLASH_FUNDS: + return "209"; + case TransactionType::PUSH_MONEY_FLASH_FUNDS: + return "45"; + case TransactionType::DISBURSE_FUNDS: + return "02"; + case TransactionType::SPEND_BACK: + return "11"; + case TransactionType::REVERSE_SPLITPAY: + return "43"; + case TransactionType::SPLIT_FUNDS: + return "16"; + case TransactionType::GET_ACCOUNT_DETAILS: + return "13"; + case TransactionType::GET_ACCOUNT_BALANCE: + return "14"; + default: + throw new UnsupportedTransactionException(); + } + } + + public function mapResponse($builder, $rawResponse) + { + $root = $this->xml2object($rawResponse); + + $responseCode = !empty($root->status) ? $root->status : 'Invalid Status code'; + + if ($responseCode != '00') { + throw new GatewayException( + sprintf( + 'Unexpected Gateway Response: %s. ', + $responseCode + ) + ); + } + + $response = new Transaction(); + $response->payFacData = $this->populateProPayResponse($root); + $response->responseCode = (string) $root->status; + + return $response; + } + + /** + * Converts a XML string to a simple object for use, + * removing extra nodes that are not necessary for + * handling the response + * + * @param string $xml Response XML from the gateway + * + * @return SimpleXMLElement + */ + protected function xml2object($xml) + { + $envelope = simplexml_load_string( + $xml, + 'SimpleXMLElement' + ); + + return !empty($envelope->XMLTrans) ? $envelope->XMLTrans : null; + + throw new \Exception('XML from gateway could not be parsed'); + } + + + private function hydrateAccountDetails($xml, $xmlTrans, PayFacBuilder $builder) + { + if (!empty($builder->userPersonalData)) { + $this->hydrateUserPersonalData($xml, $xmlTrans, $builder->userPersonalData); + } + + if (!empty($builder->businessData)) { + $this->hydrateBusinessData($xml, $xmlTrans, $builder->businessData); + } + + if (!empty($builder->beneficialOwnerData)) { + $this->hydrateBeneficialOwnerData($xml, $xmlTrans, $builder->beneficialOwnerData); + } + + if (!empty($builder->grossBillingInformation)) { + $this->hydrateGrossBillingData($xml, $xmlTrans, $builder->grossBillingInformation); + } + + $this->hydrateBankDetails($xml, $xmlTrans, $builder); + $this->hydratOtherDetails($xml, $xmlTrans, $builder); + } + + private function hydrateAccountEditDetails($xml, $xmlTrans, PayFacBuilder $builder) + { + if (!empty($builder->password)) { + $xmlTrans->appendChild($xml->createElement('password', $builder->password)); + } elseif (!empty($builder->negativeLimit)) { + $xmlTrans->appendChild($xml->createElement('negativelimit', $builder->negativeLimit)); + } elseif (!empty($builder->userPersonalData)) { + $this->hydrateUserPersonalData($xml, $xmlTrans, $builder->userPersonalData); + } elseif (!empty($builder->accountPermissions)) { + $this->hydrateAccountPermissions($xml, $xmlTrans, $builder->accountPermissions); + } elseif (!empty($builder->businessData)) { + $this->hydrateBusinessData($xml, $xmlTrans, $builder->businessData); + } elseif (!empty($builder->grossBillingInformation)) { + $this->hydrateGrossBillingData($xml, $xmlTrans, $builder->grossBillingInformation); + } + //update bank details if any + $this->hydrateBankDetails($xml, $xmlTrans, $builder); + } + + private function hydrateAccountRenewDetails($xml, $xmlTrans, RenewAccountData $renewalAccountData) + { + $elementMap = [ + 'tier' => !empty($renewalAccountData->tier) ? $renewalAccountData->tier : '', + + 'CVV2' => !empty($renewalAccountData->creditCard->cvn) ? $renewalAccountData->creditCard->cvn : '', + 'ccNum' => !empty($renewalAccountData->creditCard->number) ? $renewalAccountData->creditCard->number : '', + 'expDate' => !empty($renewalAccountData->creditCard->expMonth) ? $renewalAccountData->creditCard->getShortExpiry() : '', + 'zip' => !empty($renewalAccountData->zipCode) ? $renewalAccountData->zipCode : '', + + 'PaymentBankAccountNumber' => !empty($renewalAccountData->paymentBankAccountNumber) ? $renewalAccountData->paymentBankAccountNumber : '', + 'PaymentBankRoutingNumber' => !empty($renewalAccountData->paymentBankRoutingNumber) ? $renewalAccountData->paymentBankRoutingNumber : '', + 'PaymentBankAccountType' => !empty($renewalAccountData->paymentBankAccountType) ? $renewalAccountData->paymentBankAccountType : '', + ]; + $this->createNewElements($xml, $xmlTrans, $elementMap); + } + + private function hydrateBeneficialOwnerData($xml, $xmLtransaction, $beneficialOwnerData) + { + $ownerDetails = $xml->createElement('BeneficialOwnerData'); + $ownerDetails->appendChild($xml->createElement('OwnerCount', $beneficialOwnerData->ownersCount)); + + if ($beneficialOwnerData->ownersCount > 0) { + $ownersList = $xml->createElement('Owners'); + + foreach ($beneficialOwnerData->ownersList as $ownerInfo) { + $newOwner = $xml->createElement('Owner'); + + $elements = [ + 'FirstName' => !empty($ownerInfo->firstName) ? $ownerInfo->firstName : '', + 'LastName' => !empty($ownerInfo->lastName) ? $ownerInfo->lastName : '', + 'Email' => !empty($ownerInfo->email) ? $ownerInfo->email : '', + 'SSN' => !empty($ownerInfo->ssn) ? $ownerInfo->ssn : '', + 'DateOfBirth' => !empty($ownerInfo->dateOfBirth) ? $ownerInfo->dateOfBirth : '', + 'Address' => !empty($ownerInfo->ownerAddress->streetAddress1) ? $ownerInfo->ownerAddress->streetAddress1 : '', + 'City' => !empty($ownerInfo->ownerAddress->city) ? $ownerInfo->ownerAddress->city : '', + 'State' => !empty($ownerInfo->ownerAddress->state) ? $ownerInfo->ownerAddress->state : '', + 'Zip' => !empty($ownerInfo->ownerAddress->postalCode) ? $ownerInfo->ownerAddress->postalCode : '', + 'Country' => !empty($ownerInfo->ownerAddress->country) ? $ownerInfo->ownerAddress->country : '', + 'Title' => !empty($ownerInfo->title) ? $ownerInfo->title : '', + 'Percentage' => !empty($ownerInfo->percentage) ? $ownerInfo->percentage : '' + ]; + + $this->createNewElements($xml, $newOwner, $elements); + $ownersList->appendChild($newOwner); + } + $ownerDetails->appendChild($ownersList); + } + + $xmLtransaction->appendChild($ownerDetails); + } + + private function hydrateBusinessData($xml, $transaction, BusinessData $businessData) + { + $propertyElementMap = [ + 'BusinessLegalName' => !empty($businessData->businessLegalName) ? $businessData->businessLegalName : '', + 'DoingBusinessAs' => !empty($businessData->doingBusinessAs) ? $businessData->doingBusinessAs : '', + 'EIN' => !empty($businessData->employerIdentificationNumber) ? $businessData->employerIdentificationNumber : '', + 'MCCCode' => !empty($businessData->merchantCategoryCode) ? $businessData->merchantCategoryCode : '', + 'WebsiteURL' => !empty($businessData->websiteURL) ? $businessData->websiteURL : '', + 'BusinessDesc' => !empty($businessData->businessDescription) ? $businessData->businessDescription : '', + 'MonthlyBankCardVolume' => !empty($businessData->monthlyBankCardVolume) ? $businessData->monthlyBankCardVolume : '', + 'AverageTicket' => !empty($businessData->averageTicket) ? $businessData->averageTicket : '', + 'HighestTicket' => !empty($businessData->highestTicket) ? $businessData->highestTicket : '', + 'BusinessAddress' => !empty($businessData->businessAddress->streetAddress1) ? $businessData->businessAddress->streetAddress1 : '', + 'BusinessAddress2' => !empty($businessData->businessAddress->streetAddress2) ? $businessData->businessAddress->streetAddress2 : '', + 'BusinessCity' => !empty($businessData->businessAddress->city) ? $businessData->businessAddress->city : '', + 'BusinessCountry' => !empty($businessData->businessAddress->country) ? $businessData->businessAddress->country : '', + 'BusinessState' => !empty($businessData->businessAddress->state) ? $businessData->businessAddress->state : '', + 'BusinessZip' => !empty($businessData->businessAddress->postalCode) ? $businessData->businessAddress->postalCode : '' + ]; + + $this->createNewElements($xml, $transaction, $propertyElementMap); + } + + private function hydrateUserPersonalData($xml, $transaction, UserPersonalData $userPersonalData) + { + $merchantAddress = $userPersonalData->userAddress; + $mailingAddress = $userPersonalData->mailingAddress; + + $elementMap = [ + 'firstName' => !empty($userPersonalData->firstName) ? $userPersonalData->firstName : '', + 'mInitial' => !empty($userPersonalData->mInitial) ? $userPersonalData->mInitial : '', + 'lastName' => !empty($userPersonalData->lastName) ? $userPersonalData->lastName : '', + 'dob' => !empty($userPersonalData->dateOfBirth) ? $userPersonalData->dateOfBirth : '', + 'ssn' => !empty($userPersonalData->ssn) ? $userPersonalData->ssn : '', + 'sourceEmail' => !empty($userPersonalData->sourceEmail) ? $userPersonalData->sourceEmail : '', + 'dayPhone' => !empty($userPersonalData->dayPhone) ? $userPersonalData->dayPhone : '', + 'evenPhone' => !empty($userPersonalData->eveningPhone) ? $userPersonalData->eveningPhone : '', + 'NotificationEmail' => !empty($userPersonalData->notificationEmail) ? $userPersonalData->notificationEmail : '', + 'currencyCode' => !empty($userPersonalData->currencyCode) ? $userPersonalData->currencyCode : '', + 'tier' => !empty($userPersonalData->tier) ? $userPersonalData->tier : '', + 'externalId' => !empty($userPersonalData->externalId) ? $userPersonalData->externalId : '', + + 'addr' => !empty($merchantAddress->streetAddress1) ? $merchantAddress->streetAddress1 : '', + 'aptNum' => !empty($merchantAddress->streetAddress2) ? $merchantAddress->streetAddress2 : '', + 'addr3' => !empty($merchantAddress->streetAddress3) ? $merchantAddress->streetAddress3 : '', + 'city' => !empty($merchantAddress->city) ? $merchantAddress->city : '', + 'state' => !empty($merchantAddress->state) ? $merchantAddress->state : '', + 'zip' => !empty($merchantAddress->postalCode) ? $merchantAddress->postalCode : '', + 'country' => !empty($merchantAddress->country) ? $merchantAddress->country : '', + + 'mailAddr' => !empty($mailingAddress->streetAddress1) ? $mailingAddress->streetAddress1 : '', + 'mailApt' => !empty($mailingAddress->streetAddress2) ? $mailingAddress->streetAddress2: '', + 'mailAddr3' => !empty($mailingAddress->streetAddress3) ? $mailingAddress->streetAddress3 : '', + 'mailCity' => !empty($mailingAddress->city) ? $mailingAddress->city : '', + 'mailCountry' => !empty($mailingAddress->country) ? $mailingAddress->country : '', + 'mailState' => !empty($mailingAddress->state) ? $mailingAddress->state : '' , + 'mailZip' => !empty($mailingAddress->postalCode) ? $mailingAddress->postalCode : '', + ]; + + $this->createNewElements($xml, $transaction, $elementMap); + } + + private function hydrateBankDetails($xml, $xmlTrans, $builder) + { + $elementMap = []; + + if (!empty($builder->creditCardInformation)) { + $elementMap = [ + 'NameOnCard' => !empty($builder->creditCardInformation->cardHolderName) ? $builder->creditCardInformation->cardHolderName : '', + 'ccNum' => !empty($builder->creditCardInformation->number) ? $builder->creditCardInformation->number : '', + 'expDate' => !empty($builder->creditCardInformation->number) ? $builder->creditCardInformation->getShortExpiry() : '', + ]; + } + + if (!empty($builder->achInformation)) { + $achInformation = [ + 'PaymentBankAccountNumber' => !empty($builder->achInformation->accountNumber) ? $builder->achInformation->accountNumber : '', + 'PaymentBankRoutingNumber' => !empty($builder->achInformation->routingNumber) ? $builder->achInformation->routingNumber : '', + 'PaymentBankAccountType' => !empty($builder->achInformation->accountType) ? $builder->achInformation->accountType : '', + ]; + + $elementMap = array_merge($elementMap, $achInformation); + } + + if (!empty($builder->bankAccountData)) { + $bankAccountData = [ + 'AccountCountryCode' => !empty($builder->bankAccountData->accountCountryCode) ? $builder->bankAccountData->accountCountryCode : '', + 'accountName' => !empty($builder->bankAccountData->accountName) ? $builder->bankAccountData->accountName : '', + 'AccountNumber' => !empty($builder->bankAccountData->accountNumber) ? $builder->bankAccountData->accountNumber : '', + 'AccountOwnershipType' => !empty($builder->bankAccountData->accountOwnershipType) ? $builder->bankAccountData->accountOwnershipType : '', + 'accountType' => !empty($builder->bankAccountData->accountType) ? $builder->bankAccountData->accountType : '', + 'BankName' => !empty($builder->bankAccountData->bankName) ? $builder->bankAccountData->bankName : '', + 'RoutingNumber' => !empty($builder->bankAccountData->routingNumber) ? $builder->bankAccountData->routingNumber : '', + ]; + + $elementMap = array_merge($elementMap, $bankAccountData); + } + + if (!empty($builder->secondaryBankInformation)) { + $secondaryBankInformation = [ + 'SecondaryAccountCountryCode' => !empty($builder->secondaryBankInformation->accountCountryCode) ? $builder->secondaryBankInformation->accountCountryCode : '', + 'SecondaryAccountName' => !empty($builder->secondaryBankInformation->accountName) ? $builder->secondaryBankInformation->accountName : '', + 'SecondaryAccountNumber' => !empty($builder->secondaryBankInformation->accountNumber) ? $builder->secondaryBankInformation->accountNumber : '', + 'SecondaryAccountOwnershipType' => !empty($builder->secondaryBankInformation->accountOwnershipType) ? $builder->secondaryBankInformation->accountOwnershipType : '', + 'SecondaryAccountType' => !empty($builder->secondaryBankInformation->accountType) ? $builder->secondaryBankInformation->accountType : '', + 'SecondaryBankName' => !empty($builder->secondaryBankInformation->bankName) ? $builder->secondaryBankInformation->bankName : '', + 'SecondaryRoutingNumber' => !empty($builder->secondaryBankInformation->routingNumber) ? $builder->secondaryBankInformation->routingNumber : '' + ]; + + $elementMap = array_merge($elementMap, $secondaryBankInformation); + } + + $this->createNewElements($xml, $xmlTrans, $elementMap); + } + + private function hydratOtherDetails($xml, $xmlTrans, $builder) + { + //threatRiskData, significantOwnerData + $significantData = $builder->significantOwnerData; + $details = [ + 'MerchantSourceip' => !empty($builder->threatRiskData->merchantSourceIp) ? $builder->threatRiskData->merchantSourceIp : '', + 'ThreatMetrixPolicy' => !empty($builder->threatRiskData->threatMetrixPolicy) ? $builder->threatRiskData->threatMetrixPolicy : '', + 'ThreatMetrixSessionid' => !empty($builder->threatRiskData->threatMetrixSessionId) ? $builder->threatRiskData->threatMetrixSessionId : '', + 'AuthorizedSignerFirstName' => !empty($significantData->authorizedSignerFirstName) ? $significantData->authorizedSignerFirstName : '', + 'AuthorizedSignerLastName' => !empty($significantData->authorizedSignerLastName) ? $significantData->authorizedSignerLastName : '', + 'AuthorizedSignerTitle' => !empty($significantData->authorizedSignerTitle) ? $significantData->authorizedSignerTitle : '', + ]; + + if (!empty($significantData->significantOwnerData)) { + $significantOwnerData = $significantData->significantOwnerData; + $details = array_merge($details, [ + 'SignificantOwnerFirstName' => !empty($significantOwnerData->firstName) ? $significantOwnerData->firstName : '', + 'SignificantOwnerLastName' => !empty($significantOwnerData->lastName) ? $significantOwnerData->lastName : '', + 'SignificantOwnerSSN' => !empty($significantOwnerData->ssn) ? $significantOwnerData->ssn : '', + 'SignificantOwnerDateOfBirth' => !empty($significantOwnerData->dateOfBirth) ? $significantOwnerData->dateOfBirth : '', + 'SignificantOwnerStreetAddress' => !empty($significantOwnerData->ownerAddress->streetAddress1) ? $significantOwnerData->ownerAddress->streetAddress1 : '', + 'SignificantOwnerCityName' => !empty($significantOwnerData->ownerAddress->city) ? $significantOwnerData->ownerAddress->city : '', + 'SignificantOwnerRegionCode' => !empty($significantOwnerData->ownerAddress->state) ? $significantOwnerData->ownerAddress->state : '', + 'SignificantOwnerPostalCode' => !empty($significantOwnerData->ownerAddress->postalCode) ? $significantOwnerData->ownerAddress->postalCode : '', + 'SignificantOwnerCountryCode' => !empty($significantOwnerData->ownerAddress->country) ? $significantOwnerData->ownerAddress->country : '', + 'SignificantOwnerTitle' => !empty($significantOwnerData->title) ? $significantOwnerData->title : '', + 'SignificantOwnerPercentage' => !empty($significantOwnerData->percentage) ? $significantOwnerData->percentage : '', + ]); + } + + $this->createNewElements($xml, $xmlTrans, $details); + } + + private function hydrateGrossBillingData($xml, $transaction, $grossBilling) + { + $propertyElementMap = [ + 'GrossSettleAddress' => !empty($grossBilling->grossSettleAddress->streetAddress1) ? $grossBilling->grossSettleAddress->streetAddress1 : '', + 'GrossSettleCity' => !empty($grossBilling->grossSettleAddress->city) ? $grossBilling->grossSettleAddress->city : '', + 'GrossSettleState' => !empty($grossBilling->grossSettleAddress->state) ? $grossBilling->grossSettleAddress->state : '', + 'GrossSettleZipCode' => !empty($grossBilling->grossSettleAddress->postalCode) ? $grossBilling->grossSettleAddress->postalCode : '', + 'GrossSettleCountry' => !empty($grossBilling->grossSettleAddress->country) ? $grossBilling->grossSettleAddress->country : '', + + 'GrossSettleCreditCardNumber' => !empty($grossBilling->grossSettleCreditCardData->number) ? $grossBilling->grossSettleCreditCardData->number : '', + 'GrossSettleNameOnCard' => !empty($grossBilling->grossSettleCreditCardData->cardHolderName) ? $grossBilling->grossSettleCreditCardData->cardHolderName : '', + 'GrossSettleCreditCardExpDate' => $grossBilling->grossSettleCreditCardData->getShortExpiry(), + + 'GrossSettleAccountCountryCode' => !empty($grossBilling->grossSettleBankData->accountCountryCode) ? $grossBilling->grossSettleBankData->accountCountryCode : '', + 'GrossSettleAccountHolderName' => !empty($grossBilling->grossSettleBankData->accountName) ? $grossBilling->grossSettleBankData->accountName : '', + 'GrossSettleAccountNumber' => !empty($grossBilling->grossSettleBankData->accountNumber) ? $grossBilling->grossSettleBankData->accountNumber : '', + 'GrossSettleAccountType' => !empty($grossBilling->grossSettleBankData->accountType) ? $grossBilling->grossSettleBankData->accountType : '', + 'GrossSettleRoutingNumber' => !empty($grossBilling->grossSettleBankData->routingNumber) ? $grossBilling->grossSettleBankData->routingNumber : '' + ]; + + $this->createNewElements($xml, $transaction, $propertyElementMap); + } + + private function hydrateAccountPermissions($xml, $xmlTrans, AccountPermissions $accountPermissions) + { + $propertyElementMap = [ + 'ACHIn' => !empty($accountPermissions->achIn) ? $accountPermissions->achIn : '', + 'ACHOut' => !empty($accountPermissions->achOut) ? $accountPermissions->achOut : '', + 'CCProcessing' => !empty($accountPermissions->ccProcessing) ? $accountPermissions->ccProcessing : '', + 'ProPayIn' => !empty($accountPermissions->proPayIn) ? $accountPermissions->proPayIn : '', + 'ProPayOut' => !empty($accountPermissions->proPayOut) ? $accountPermissions->proPayOut : '', + 'CreditCardMonthLimit' => !empty($accountPermissions->creditCardMonthLimit) ? $accountPermissions->creditCardMonthLimit : '', + 'CreditCardTransactionLimit' => !empty($accountPermissions->creditCardTransactionLimit) ? $accountPermissions->creditCardTransactionLimit : '', + 'MerchantOverallStatus' => !empty($accountPermissions->merchantOverallStatus) ? $accountPermissions->merchantOverallStatus : '', + 'SoftLimitEnabled' => !empty($accountPermissions->softLimitEnabled) ? $accountPermissions->softLimitEnabled : '', + 'AchPaymentSoftLimitEnabled' => !empty($accountPermissions->achPaymentSoftLimitEnabled) ? $accountPermissions->achPaymentSoftLimitEnabled : '', + 'SoftLimitAchOffPercent' => !empty($accountPermissions->softLimitAchOffPercent) ? $accountPermissions->softLimitAchOffPercent : '', + 'AchPaymentAchOffPercent' => !empty($accountPermissions->achPaymentAchOffPercent) ? $accountPermissions->achPaymentAchOffPercent : '', + ]; + + $this->createNewElements($xml, $xmlTrans, $propertyElementMap); + } + + private function createNewElements($xml, $transaction, $mapping) + { + foreach ($mapping as $tagName => $value) { + if (!is_null($value) && $value !== '') { + $transaction->appendChild($xml->createElement($tagName, $value)); + } + } + } + + private function setx509Certificate($certX509File) + { + try { + $cert = file_get_contents($certX509File); + return base64_encode($cert); + } catch (\Exception $e) { + throw new GatewayException( + 'X509 certificate error: ', + $e->getCode(), + $e->getMessage(), + $e + ); + } + } + + private function updateGatewaySettings($builder) + { + $certTransactions = [ + TransactionType::EDIT, + TransactionType::OBTAIN_SSO_KEY, + TransactionType::UPDATE_BANK_ACCOUNT_OWNERSHIP, + TransactionType::ADD_FUNDS, + TransactionType::ADD_CARD_FLASH_FUNDS, + ]; + + if (in_array($builder->transactionType, $certTransactions)) { + $this->headers['X509Certificate'] = $this->setx509Certificate($this->selfSignedCert); + } + } + + private function hydrateUploadDocument($xml, $xmlTrans, UploadDocumentData $uploadDocumentData) + { + $fileType = pathinfo($uploadDocumentData->documentLocation, PATHINFO_EXTENSION); + $elementMap = [ + 'DocumentName' => !empty($uploadDocumentData->documentName) ? $uploadDocumentData->documentName : '', + 'TransactionReference' => !empty($uploadDocumentData->transactionReference) ? $uploadDocumentData->transactionReference : '', + 'DocType' => $fileType, + 'Document' => base64_encode(file_get_contents($uploadDocumentData->documentLocation)), + 'DocCategory' => !empty($uploadDocumentData->documentCategory) ? $uploadDocumentData->documentCategory : '', + ]; + $this->createNewElements($xml, $xmlTrans, $elementMap); + } + + private function hydrateSingleSignOnData($xml, $xmlTrans, SingleSignOnData $singleSignOnData) + { + $elementMap = [ + 'ReferrerUrl' => !empty($singleSignOnData->referrerUrl) ? $singleSignOnData->referrerUrl : '', + 'IpAddress' => !empty($singleSignOnData->ipAddress) ? $singleSignOnData->ipAddress : '', + 'IpSubnetMask' => !empty($singleSignOnData->ipSubnetMask) ? $singleSignOnData->ipSubnetMask : '', + ]; + $this->createNewElements($xml, $xmlTrans, $elementMap); + } + + private function updateBankAccountOwnershipInfo($xml, $xmLtransaction, $beneficialOwnerData) + { + $ownerDetails = $xml->createElement('BankAccountOwnerData'); + + if (!empty($beneficialOwnerData->ownersList)) { + foreach ($beneficialOwnerData->ownersList as $key => $ownerInfo) { + $ownerType = ($key === 0) ? 'PrimaryBankAccountOwner' : 'SecondaryBankAccountOwner'; + $newOwner = $xml->createElement($ownerType); + + $elements = [ + 'FirstName' => !empty($ownerInfo->firstName) ? $ownerInfo->firstName : '', + 'LastName' => !empty($ownerInfo->lastName) ? $ownerInfo->lastName : '', + 'Address1' => !empty($ownerInfo->ownerAddress->streetAddress1) ? $ownerInfo->ownerAddress->streetAddress1 : '', + 'Address2' => !empty($ownerInfo->ownerAddress->streetAddress2) ? $ownerInfo->ownerAddress->streetAddress2 : '', + 'Address3' => !empty($ownerInfo->ownerAddress->streetAddress3) ? $ownerInfo->ownerAddress->streetAddress3 : '', + 'City' => !empty($ownerInfo->ownerAddress->city) ? $ownerInfo->ownerAddress->city : '', + 'StateProvince' => !empty($ownerInfo->ownerAddress->state) ? $ownerInfo->ownerAddress->state : '', + 'PostalCode' => !empty($ownerInfo->ownerAddress->postalCode) ? $ownerInfo->ownerAddress->postalCode : '', + 'Country' => !empty($ownerInfo->ownerAddress->country) ? $ownerInfo->ownerAddress->country : '', + 'Phone' => !empty($ownerInfo->phone) ? $ownerInfo->phone : '', + ]; + + $this->createNewElements($xml, $newOwner, $elements); + $ownerDetails->appendChild($newOwner); + } + } + + $xmLtransaction->appendChild($ownerDetails); + } + + private function hydrateCommonFields($xml, $xmlTrans, $builder) + { + $elementMap = [ + 'accountNum' => !empty($builder->accountNumber) ? $builder->accountNumber : '', + 'amount' => !empty($builder->amount) ? $builder->amount : '', + 'recAccntNum' => !empty($builder->receivingAccountNumber) ? $builder->receivingAccountNumber : '', + 'allowPending' => !empty($builder->allowPending) ? 'Y' : '', + 'ccAmount' => !empty($builder->ccAmount) ? $builder->ccAmount : '', + 'requireCCRefund' => !empty($builder->requireCCRefund) ? 'Y' : 'N', + 'transNum' => !empty($builder->transNum) ? $builder->transNum : '' + ]; + $this->createNewElements($xml, $xmlTrans, $elementMap); + } + + private function hydrateFlashFundsData($xml, $xmlTrans, FlashFundsPaymentCardData $flashFundsData) + { + $elementMap = [ + 'ccNum' => !empty($flashFundsData->creditCard->number) ? $flashFundsData->creditCard->number : '', + 'expDate' => !empty($flashFundsData->creditCard->expMonth) ? $flashFundsData->creditCard->getShortExpiry() : '', + 'CVV2' => !empty($flashFundsData->creditCard->cvn) ? $flashFundsData->creditCard->cvn : '', + 'cardholderName' => !empty($flashFundsData->creditCard->cardHolderName) ? $flashFundsData->creditCard->cardHolderName : '', + 'addr' => !empty($flashFundsData->cardholderAddress->streetAddress1) ? $flashFundsData->cardholderAddress->streetAddress1 : '', + 'city' => !empty($flashFundsData->cardholderAddress->city) ? $flashFundsData->cardholderAddress->city : '', + 'state' => !empty($flashFundsData->cardholderAddress->state) ? $flashFundsData->cardholderAddress->state : '', + 'zip' => !empty($flashFundsData->cardholderAddress->postalCode) ? $flashFundsData->cardholderAddress->postalCode : '', + ]; + $this->createNewElements($xml, $xmlTrans, $elementMap); + } + + private function populateProPayResponse($root) + { + $propayResponse = new PayFacResponseData(); + $propayResponse->password = (!empty($root->password)) ? (string) $root->password : ''; + $propayResponse->sourceEmail = (!empty($root->sourceEmail)) ? (string) $root->sourceEmail : ''; + $propayResponse->authToken = (!empty($root->AuthToken)) ? (string) $root->AuthToken : ''; + $propayResponse->recAccountNum = !empty($root->recAccntNum) ? (string) $root->recAccntNum : ''; + $propayResponse->amount = !empty($root->amount) ? (string) $root->amount : ''; + $propayResponse->transNum = !empty($root->transNum) ? (string) $root->transNum : ''; + $propayResponse->pending = !empty($root->pending) ? (string) $root->pending : ''; + $propayResponse->secondaryAmount = !empty($root->secondaryAmount) ? (string) $root->secondaryAmount : ''; + $propayResponse->secondaryTransNum = !empty($root->secondaryTransNum) ? (string) $root->secondaryTransNum : ''; + $propayResponse->accountStatus = !empty($root->accntStatus) ? (string) $root->accntStatus : ''; + $propayResponse->affiliation = !empty($root->affiliation) ? (string) $root->affiliation : ''; + $propayResponse->aPIReady = !empty($root->apiReady) ? (string) $root->apiReady : ''; + $propayResponse->currencyCode = !empty($root->currencyCode) ? (string) $root->currencyCode : ''; + $propayResponse->expiration = !empty($root->expiration) ? (string) $root->expiration : ''; + $propayResponse->signupDate = !empty($root->signupDate) ? (string) $root->signupDate : ''; + $propayResponse->visaCheckoutMerchantID = !empty($root->visaCheckoutMerchantId) ? (string) $root->visaCheckoutMerchantId : ''; + $propayResponse->creditCardTransactionLimit = !empty($root->CreditCardTransactionLimit) ? (string) $root->CreditCardTransactionLimit : ''; + $propayResponse->creditCardMonthLimit = !empty($root->CreditCardMonthLimit) ? (string) $root->CreditCardMonthLimit : ''; + $propayResponse->aCHPaymentPerTranLimit = !empty($root->ACHPaymentPerTranLimit) ? (string) $root->ACHPaymentPerTranLimit : ''; + $propayResponse->aCHPaymentMonthLimit = !empty($root->ACHPaymentMonthLimit) ? (string) $root->ACHPaymentMonthLimit : ''; + $propayResponse->creditCardMonthlyVolume = !empty($root->CreditCardMonthlyVolume) ? (string) $root->CreditCardMonthlyVolume : ''; + $propayResponse->aCHPaymentMonthlyVolume = !empty($root->ACHPaymentMonthlyVolume) ? (string) $root->ACHPaymentMonthlyVolume : ''; + $propayResponse->reserveBalance = !empty($root->ReserveBalance) ? (string) $root->ReserveBalance : ''; + $propayResponse->masterPassCheckoutMerchantID = !empty($root->MasterPassCheckoutMerchantId) ? (string) $root->MasterPassCheckoutMerchantId : ''; + $propayResponse->pendingAmount = !empty($root->pendingAmount) ? (string) $root->pendingAmount : ''; + $propayResponse->reserveAmount = !empty($root->reserveAmount) ? (string) $root->reserveAmount : ''; + + $propayResponse->physicalAddress->streetAddress1 = !empty($root->addr) ? (string) $root->addr : ''; + $propayResponse->physicalAddress->city = !empty($root->city) ? (string) $root->city : ''; + $propayResponse->physicalAddress->state = !empty($root->state) ? (string) $root->state : ''; + $propayResponse->physicalAddress->postalCode = !empty($root->zip) ? (string) $root->zip : ''; + + if (!empty($root->accntNum)) { + $propayResponse->accountNumber = (string) $root->accntNum; + } elseif (!empty($root->accountNum)) { + $propayResponse->accountNumber = (string) $root->accountNum; + } + + if (!empty($root->achOut)) { + $propayResponse->aCHOut->enabled = !empty($root->achOut->enabled) ? (string) $root->achOut->enabled : ''; + $propayResponse->aCHOut->limitRemaining = !empty($root->achOut->limitRemaining) ? (string) $root->achOut->limitRemaining : ''; + $propayResponse->aCHOut->transferFee = !empty($root->achOut->transferFee) ? (string) $root->achOut->transferFee : ''; + $propayResponse->aCHOut->feeType = !empty($root->achOut->feeType) ? (string) $root->achOut->feeType : ''; + $propayResponse->aCHOut->accountLastFour = !empty($root->achOut->accountLastFour) ? (string) $root->achOut->accountLastFour : ''; + } + + if (!empty($root->flashFunds)) { + $propayResponse->flashFunds->enabled = !empty($root->flashFunds->enabled) ? (string) $root->flashFunds->enabled : ''; + $propayResponse->flashFunds->limitRemaining = !empty($root->flashFunds->limitRemaining) ? (string) $root->flashFunds->limitRemaining : ''; + $propayResponse->flashFunds->transferFee = !empty($root->flashFunds->transferFee) ? (string) $root->flashFunds->transferFee : ''; + $propayResponse->flashFunds->feeType = !empty($root->flashFunds->feeType) ? (string) $root->flashFunds->feeType : ''; + $propayResponse->flashFunds->accountLastFour = !empty($root->flashFunds->accountLastFour) ? (string) $root->flashFunds->accountLastFour : ''; + } + + if (!empty($root->beneficialOwnerDataResult->Owner)) { + foreach ($root->beneficialOwnerDataResult->Owner as $owner) { + $ownerDetails = new OwnerDetailsResponseData(); + $ownerDetails->firstName = (string) $owner->FirstName; + $ownerDetails->lastName = (string) $owner->LastName; + $ownerDetails->validationStatus = (string) $owner->Status; + $propayResponse->beneficialOwnerDataResult[] = $ownerDetails; + } + } + + return $propayResponse; + } +} diff --git a/src/PaymentMethods/GiftCard.php b/src/PaymentMethods/GiftCard.php index bf12f0c1..0d9773c7 100644 --- a/src/PaymentMethods/GiftCard.php +++ b/src/PaymentMethods/GiftCard.php @@ -252,5 +252,5 @@ public function __set($name, $value) $this->valueType = 'TrackData'; return; } - } + } } diff --git a/src/PaymentMethods/RecurringPaymentMethod.php b/src/PaymentMethods/RecurringPaymentMethod.php index b0e22856..4591c538 100644 --- a/src/PaymentMethods/RecurringPaymentMethod.php +++ b/src/PaymentMethods/RecurringPaymentMethod.php @@ -104,6 +104,13 @@ class RecurringPaymentMethod extends RecurringEntity implements */ public $status; + /** + * eCheck Sec Code value + * + * @var string + */ + public $secCode; + /** * The payment method's tax type * diff --git a/src/ServiceConfigs/AcceptorConfig.php b/src/ServiceConfigs/AcceptorConfig.php index f8416900..45bee646 100644 --- a/src/ServiceConfigs/AcceptorConfig.php +++ b/src/ServiceConfigs/AcceptorConfig.php @@ -96,7 +96,8 @@ public function __construct( $this->terminalOutputCapability = $terminalOutputCapability; } - public function validate() { + public function validate() + { // for use in future gateway integrations } } diff --git a/src/ServiceConfigs/Configuration.php b/src/ServiceConfigs/Configuration.php index 050ddf90..e29d2fcc 100644 --- a/src/ServiceConfigs/Configuration.php +++ b/src/ServiceConfigs/Configuration.php @@ -30,7 +30,8 @@ abstract public function configureContainer(ConfiguredServices $services); /** @var bool */ public $forceGatewayTimeout; - public function validate() { + public function validate() + { $this->validated = true; } } diff --git a/src/ServiceConfigs/Gateways/PorticoConfig.php b/src/ServiceConfigs/Gateways/PorticoConfig.php index 219b79b8..40462f51 100644 --- a/src/ServiceConfigs/Gateways/PorticoConfig.php +++ b/src/ServiceConfigs/Gateways/PorticoConfig.php @@ -9,6 +9,7 @@ use GlobalPayments\Api\Entities\Enums\ServiceEndpoints; use GlobalPayments\Api\Gateways\PayPlanConnector; use GlobalPayments\Api\Gateways\PorticoConnector; +use GlobalPayments\Api\Gateways\ProPayConnector; class PorticoConfig extends GatewayConfig { @@ -25,6 +26,11 @@ class PorticoConfig extends GatewayConfig public $versionNumber; public $secretApiKey; public $uniqueDeviceId; + + //ProPay + public $certificationStr; + public $selfSignedCertLocation; + public $proPayUS = true; public function getPayPlanEndpoint() { @@ -89,6 +95,24 @@ public function configureContainer(ConfiguredServices $services) $payplan->serviceUrl = $this->serviceUrl . $this->getPayPlanEndpoint(); $services->recurringConnector = $payplan; + + //propay connector + if (!empty($this->certificationStr)) { + if ($this->environment === Environment::TEST) { + $this->serviceUrl = ($this->proPayUS) ? ServiceEndpoints::PROPAY_TEST : ServiceEndpoints::PROPAY_TEST_CANADIAN; + } else { + $this->serviceUrl = ($this->proPayUS) ? ServiceEndpoints::PROPAY_PRODUCTION : ServiceEndpoints::PROPAY_PRODUCTION_CANADIAN; + } + + $payFac = new ProPayConnector(); + $payFac->certStr = $this->certificationStr; + $payFac->termId = $this->terminalId; + $payFac->timeout = $this->timeout; + $payFac->serviceUrl = $this->serviceUrl; + $payFac->selfSignedCert = $this->selfSignedCertLocation; + + $services->setPayFacProvider($payFac); + } } public function validate() diff --git a/src/Services/PayFacService.php b/src/Services/PayFacService.php new file mode 100644 index 00000000..8933a11d --- /dev/null +++ b/src/Services/PayFacService.php @@ -0,0 +1,146 @@ +getPayFacProvider(); + if ($provider != null) { + return $provider; + } + throw new ConfigurationException('payFacProvider is not configured'); + } } diff --git a/test/Integration/Gateways/ProPay/ProPayAccountTests.php b/test/Integration/Gateways/ProPay/ProPayAccountTests.php new file mode 100644 index 00000000..e82c17de --- /dev/null +++ b/test/Integration/Gateways/ProPay/ProPayAccountTests.php @@ -0,0 +1,290 @@ +getConfig()); + } + + protected function getConfig() + { + $config = new PorticoConfig(); + $config->certificationStr = '5dbacb0fc504dd7bdc2eadeb7039dd'; + $config->terminalId = '7039dd'; + $config->environment = Environment::TEST; + $config->selfSignedCertLocation = __DIR__ . '/TestData/selfSignedCertificate.crt'; + return $config; + } + + public function testCreateAccount() + { + $bankAccountInformation = TestAccountData::getBankAccountData(); + $userBusinessInformation = TestAccountData::getBusinessData(); + $accountPersonalInformation = TestAccountData::getUserPersonalData(); + $threatRiskData = TestAccountData::getThreatRiskData(); + $significantOwnerData = TestAccountData::getSignificantOwnerData(); + $ownersInformation = TestAccountData::getBeneficialOwnerData(); + $creditCardInformation = TestAccountData::getCreditCardData(); + $achInformation = TestAccountData::getACHData(); + $secondaryBankInformation = TestAccountData::getSecondaryBankAccountData(); + + $response = PayFacService::createAccount() + ->withBankAccountData($bankAccountInformation) + ->withBusinessData($userBusinessInformation) + ->withUserPersonalData($accountPersonalInformation) + ->withThreatRiskData($threatRiskData) + ->withSignificantOwnerData($significantOwnerData) + ->withBeneficialOwnerData($ownersInformation) + ->withCreditCardData($creditCardInformation) + ->withACHData($achInformation) + ->withSecondaryBankAccountData($secondaryBankInformation) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('00', $response->responseCode); + $this->assertNotNull($response->payFacData->accountNumber); + $this->assertNotNull($response->payFacData->password); + $this->assertNotNull($response->payFacData->sourceEmail); + } + + public function testEditAccountInformation() + { + $response = PayFacService::editAccount() + ->withAccountNumber(718138433) + ->withUserPersonalData(TestAccountData::editUserPersonalData()) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('00', $response->responseCode); + } + + public function testEditPassword() + { + $response = PayFacService::editAccount() + ->withAccountNumber(718138433) + ->withPassword('testPwd_'.rand(1, 100)) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('00', $response->responseCode); + } + + public function testEditAddress() + { + $response = PayFacService::editAccount() + ->withAccountNumber(718138433) + ->withUserPersonalData(TestAccountData::editAddressData()) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('00', $response->responseCode); + } + + public function testEditAccountPermissions() + { + $response = PayFacService::editAccount() + ->withAccountNumber(718136530) + ->withAccountPermissions(TestAccountData::editAccountPermissions()) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('00', $response->responseCode); + } + + public function testEditPrimaryBankAccount() + { + $response = PayFacService::editAccount() + ->withAccountNumber(718150930) + ->withBankAccountData(TestAccountData::editBankData()) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('00', $response->responseCode); + } + + public function testEditSecondaryBankAccount() + { + $response = PayFacService::editAccount() + ->withAccountNumber(718150930) + ->withSecondaryBankAccountData(TestAccountData::editBankData()) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('00', $response->responseCode); + } + + public function testEditBusinessData() + { + $response = PayFacService::editAccount() + ->withAccountNumber(718150930) + ->withBusinessData(TestAccountData::getBusinessData()) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('00', $response->responseCode); + } + + public function testEditCreditCard() + { + $response = PayFacService::editAccount() + ->withAccountNumber(718138433) + ->withCreditCardData(TestAccountData::getCreditCardData()) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('00', $response->responseCode); + } + + public function testEditRenewalInformation() + { + $response = PayFacService::editAccount() + ->withAccountNumber(718138433) + ->withACHData(TestAccountData::editACHData()) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('00', $response->responseCode); + } + + public function testEditNegativeLimit() + { + $response = PayFacService::editAccount() + ->withAccountNumber(718136530) + ->withNegativeLimit(1) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('00', $response->responseCode); + } + + public function testResetPassword() + { + $response = PayFacService::resetPassword() + ->withAccountNumber(718150930) + ->withNegativeLimit(1) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('00', $response->responseCode); + $this->assertNotNull($response->payFacData->password); + } + + public function testRenewAccount() + { + $response = PayFacService::renewAccount() + ->withAccountNumber(718151055) + ->withRenewalAccountData(TestAccountData::getRenewAccountDetails()) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('00', $response->responseCode); + } + + public function testUpdateBeneficialOwnerData() + { + //Owners count shoud not be excedded 6 + $response = PayFacService::updateBeneficialOwnershipInfo() + ->withAccountNumber(718151188) + ->withBeneficialOwnerData(TestAccountData::getBeneficialOwnerData()) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('00', $response->responseCode); + $this->assertNotNull($response->payFacData->beneficialOwnerDataResult); + } + + public function testDisownAccount() + { + //Enter active account number + $response = PayFacService::disownAccount() + ->withAccountNumber(718150922) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('00', $response->responseCode); + } + + public function testUploadChargebackDocument() + { + $documentDetails = new UploadDocumentData(); + $documentDetails->transactionReference = '123456789'; + $documentDetails->documentName = 'ChargebackDispute'; + $documentDetails->documentLocation = __DIR__ . '/TestData/ChargebackDispute.jpg'; + + $response = PayFacService::uploadDocumentChargeback() + ->withAccountNumber(718134349) + ->withUploadDocumentData($documentDetails) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('00', $response->responseCode); + } + + public function testUnderwriteDocument() + { + $documentDetails = new UploadDocumentData(); + $documentDetails->documentCategory = 'Verification'; + $documentDetails->documentName = 'ChargebackDispute'; + $documentDetails->documentLocation = __DIR__ . '/TestData/ChargebackDispute.jpg'; + + $response = PayFacService::uploadDocument() + ->withAccountNumber(718150930) + ->withUploadDocumentData($documentDetails) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('00', $response->responseCode); + } + + public function testObtainSSOKey() + { + $singleSignOnData = new SingleSignOnData(); + $singleSignOnData->referrerUrl = 'https://www.globalpaymentsinc.com/'; + $singleSignOnData->ipAddress = '40.81.11.219'; + $singleSignOnData->ipSubnetMask = '255.255.255.0'; + + $response = PayFacService::obtainSSOKey() + ->withAccountNumber(718150930) + ->withSingleSignOnData($singleSignOnData) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('00', $response->responseCode); + $this->assertNotNull($response->payFacData->authToken); + } + + public function testUpdateBankAccountOwnershipInfo() + { + $response = PayFacService::updateBankAccountOwnershipInfo() + ->withAccountNumber(718136530) + ->withBeneficialOwnerData(TestAccountData::getBeneficialOwnerData()) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('00', $response->responseCode); + } + + public function testUpdateGrossBillingInfo() + { + $response = PayFacService::editAccount() + ->withAccountNumber(718151524) + ->withGrossBillingSettleData(TestAccountData::getGrossBillingSettleData()) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('00', $response->responseCode); + } +} diff --git a/test/Integration/Gateways/ProPay/ProPayFundsTests.php b/test/Integration/Gateways/ProPay/ProPayFundsTests.php new file mode 100644 index 00000000..e467dd9a --- /dev/null +++ b/test/Integration/Gateways/ProPay/ProPayFundsTests.php @@ -0,0 +1,74 @@ +getConfig()); + } + + protected function getConfig() + { + $config = new PorticoConfig(); + $config->certificationStr = '5dbacb0fc504dd7bdc2eadeb7039dd'; + $config->terminalId = '7039dd'; + $config->environment = Environment::TEST; + $config->selfSignedCertLocation = __DIR__ . '/TestData/selfSignedCertificate.crt'; + return $config; + } + + public function testAddFunds() + { + $response = PayFacService::addFunds() + ->withAccountNumber("718136438") + ->withAmount("300") + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("00", $response->responseCode); + } + + + public function testSweepFunds() + { + $response = PayFacService::sweepFunds() + ->withAccountNumber("718136438") + ->withAmount("10") + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("00", $response->responseCode); + } + + public function testAddFlashFundsPaymentCard() + { + $response = PayFacService::addCardFlashFunds() + ->withAccountNumber("718136438") + ->withFlashFundsPaymentCardData(TestFundsData::getFlashFundsData()) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("00", $response->responseCode); + } + + public function testPushMoneyToFlashFundsCard() + { + $response = PayFacService::pushMoneyToFlashFundsCard() + ->withAccountNumber("718136438") + ->withAmount("100") + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("00", $response->responseCode); + } +} diff --git a/test/Integration/Gateways/ProPay/ProPayGetInformationTests.php b/test/Integration/Gateways/ProPay/ProPayGetInformationTests.php new file mode 100644 index 00000000..0d14ea3e --- /dev/null +++ b/test/Integration/Gateways/ProPay/ProPayGetInformationTests.php @@ -0,0 +1,73 @@ +getConfig()); + } + + protected function getConfig() + { + $config = new PorticoConfig(); + $config->certificationStr = '5dbacb0fc504dd7bdc2eadeb7039dd'; + $config->terminalId = '7039dd'; + $config->environment = Environment::TEST; + $config->selfSignedCertLocation = __DIR__ . '/TestData/selfSignedCertificate.crt'; + return $config; + } + + public function testGetAccountInfo() + { + $response = PayFacService::getAccountDetails() + ->withAccountNumber("718136438") + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("00", $response->responseCode); + } + + + public function testGetAccountBalance() + { + $response = PayFacService::getAccountBalance() + ->withAccountNumber("718136438") + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("00", $response->responseCode); + $this->assertNotNull($response->payFacData->flashFunds); + $this->assertNotNull($response->payFacData->aCHOut); + } + + public function testGetAccountInfoExternalId() + { + $response = PayFacService::getAccountDetails() + ->withExternalId("1") + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("00", $response->responseCode); + } + + + public function testGetAccountInfoSourceEmail() + { + $response = PayFacService::getAccountDetails() + ->withSourceEmail("user4804@user.com") + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("00", $response->responseCode); + } + +} diff --git a/test/Integration/Gateways/ProPay/ProPayNetworkTests.php b/test/Integration/Gateways/ProPay/ProPayNetworkTests.php new file mode 100644 index 00000000..5f1a663b --- /dev/null +++ b/test/Integration/Gateways/ProPay/ProPayNetworkTests.php @@ -0,0 +1,82 @@ +getConfig()); + } + + protected function getConfig() + { + $config = new PorticoConfig(); + $config->certificationStr = '5dbacb0fc504dd7bdc2eadeb7039dd'; + $config->terminalId = '7039dd'; + $config->environment = Environment::TEST; + $config->selfSignedCertLocation = __DIR__ . '/TestData/selfSignedCertificate.crt'; + return $config; + } + + public function testDisburseFunds() + { + // This method in the ProPay API requires a different, special CertificationStr value from a disbursement account + $response = PayFacService::disburseFunds() + ->withReceivingAccountNumber("718136438") + ->withAmount("100") + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("00", $response->responseCode); + } + public function testSpendBackTransaction() + { + $response = PayFacService::spendBack() + ->withAccountNumber("718037672") + ->withReceivingAccountNumber("718136438") + ->withAmount("100") + ->withAllowPending(false) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("00", $response->responseCode); + } + + public function testReverseSplitPay() + { + $response = PayFacService::reverseSplitPay() + ->withAccountNumber("718136438") + ->withAmount("3") + ->withCCAmount("1") + ->withRequireCCRefund(false) + ->withTransNum("35") + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("00", $response->responseCode); + $this->assertNotNull($response->payFacData->amount); + $this->assertNotNull($response->payFacData->recAccountNum); + $this->assertNotNull($response->payFacData->transNum); + } + + public function testSplitFunds() + { + $response = PayFacService::splitFunds() + ->withAccountNumber("718136438") + ->withReceivingAccountNumber("718134204") + ->withAmount("3") + ->withTransNum("35") + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("00", $response->responseCode); + } +} diff --git a/test/Integration/Gateways/ProPay/TestData/ChargebackDispute.jpg b/test/Integration/Gateways/ProPay/TestData/ChargebackDispute.jpg new file mode 100644 index 0000000000000000000000000000000000000000..03c7e47041f3664b902ab2e37bce447609a65dda GIT binary patch literal 51094 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

wZ z%~qYc%01+G4DZ}tY?-|EhOVws#k9UxLys+;i*TiTs(ul!YB};_|7qFNKcqopr)xAX zi=&_Q&*P9rF1@h^%4S-rE%SoOP5N!ac2!*>c1EvDx8eO`Nu6yN%;bx-_{ZE$w-EH- zSkdPrX{_$)E9s>UD`mIF-W}eAFRaAm@zo?2qBj|mZ&wCSRF===dUm{xF&t*%e1CZq zm+Z>$QH?XauR1)cxOJcztI|_?y$4KB#*nzc(u$hH z;ZmgKoU7iO^-I$+S!;f~le}_evzCFP#nEKV<_0(0O;EE2zqdcEB{AGZ6^(43Wm+9D zlyddRs_{@W9Tk3>tlf!ezk8yi|7@HzlD3IB80Vo%DSSq(l`B2NQiKAzHYgXd>#pi! zwG}k+rc(|dsD=P_o>*qtlWZJ4w|>M1R@$)ysV=5#Gt6Q5-6)%<XPBPT0I4^nHb zaOhE&a=fNrP~?@BSMutl%}reP@ZQV;-J#2M1>PyU&J2qP9xd|dcKfo!bfxR=brKlf z{Mn>^N5gXV)6J1V#>l%PY2p}!gDO=Z(*j;|XvM7AY$>&PVwiHWT8OMM+4lh^!_kl4 zOTRIQV~sq!cPXLhN4Yic>)jWtNh(_Nk<+_RpHw)ZvaGQN!cjv7Wb6uyrV}x`N6Aq$>;Otr$u5cb-4| zceAeUj=GNP<~r7m*OY!gxP%cx3N8#=YvNKvSAZjc`=o`z8<(WZ_<_tHLX8-)dL#W|(82d(4{8b=0LjSS8-e z2qCT&{}etkq^4G`TS;$F=lY_X>#gjifH+n%IHR_De0jBPJsgRCbF*ro;|TU4qq)ws zenhKFYv;yKFCmFHXjIrJ7oIk|Yl-om(JfV)h<$qXuU!4SjUPLMUlcDy48(lsuc;9oGGI^%6 zb;?b}e-ECsB3t;I=F0xB_m=dzxg-#BlRJLD^;6vh??FZ+2=x$`DcuHHOYkB*4&Z=T z4`|d9CQArO5c!&b{1$i@au752)eg#JoHG7;p6j1LLj<6Xf}~Z8C@AKZef#`xw~%g0 z%K%w`LHQ>j@$?fv=(hscpM?G&Y_in=&H;c3bsxtCFZ-DOanZ$d9wyOppGH%^Z{>d` zA;4-}9~7=`&U7(;;^UxQ-Qk?`@8$2_Dh5L%zj5WFQw`!A4TpnHN3d1k`%J5B_wMzv zJH*zPi(&6Hgn|;iEc7Hp2t!y4;!`OJrNpmXr1dE5(zl1kmqaPfo`|lUt~xlYJ4jn! zU_h}lR_MBbDH?PMZm6nJv=)D75TkEZ*tPWPG!3idc`mupjt2*_%_tjhX69&{x@p&+ z;Xyg`cMZ0S;&PFjufi-xZR28$kSagzbw|xBmrh&F)+x^pOV89@ z>XO7&UlO}s_;o?Ljrabam`^p7Ir|5cLy`tIUR+&Ph>L5Lt`o@b8~j-#W2@P?Q2MJ` zFO$!&?)qgNM)P`@cCT#$e@9K4R59hyVqi%ws?Ladd7DMnZd=&H!Kttk{=B+Hq6#G7 zx$Ap=hCa+$&YAjYvV^oyGa9uYGIH)K%^kEty)1n#ydCrE$EC5IL6?`9Dg$^rGQ3sR z2~kj7Id=p*kSv#4N-Z;~eQs=ALvJ8L;!w4+pGn7FHlH-)VszkTf0ZiQxvSyK*g^H$ zz`EO3tu;Pbqlv+@>dH>K-T|9-*g<+pJ_>1HzOj;)EYJKg)opQO<>H#WEp3{$ZDycF zx#AJ*0(PUMvw8Kw=+b0zd2Y`$oDH~nhXJKH;Iqe{2;WuoQFgEuSJ{2DMVB^3{`@cm zZ{HCfSd|2BOUUd4Ucn&?SB_r^kwhzrhF-}(iU%HgR3ZLsq$STPz)$U@xT{_Bwz0^= z*_j)!d^RyBiSYe&sD9OC8JW6QkoyJ{%B$Idn{uLVFRrUM9;^Ce$g+5^{!yJdY``x@ zKd|?Py7Oh_-M!0&o;5?eS6_8X{;t<5Ll293zcqh*Uzj`yo~r?9wrOHGXmljy3Q_U4q9CT|3@RG&0VifO6PK~@t`-5baLXRO{>{h95((+jrYAxjc zu9Q;9Xc@J4v)a3C7&ScZ;ng*THMn?C7!p;%?kX(P_#saHP!K$c4*hlJap+PlE@mnw z&UCp%t4ccVm?Wim)$<5PSDf^>X>wJ5(sK&LXMPzJ5A{FlDi!Rr>Z$d3Br~*#J{XX? zUYu1nv3YQ+$2DNQJSVnmX>fdCn|4Y(XU!<}Q^TpT$k*P~x&~;026Ye5Vw=YMRtOWV zpQU_nq?nZJlG7`_%B$`7=FESL|29&&7IgTKc!3)=hYiKFf%C;&U_uYZzIFK1oZG5T zp3c^y5~Z3GI_CG3inW{XDkafsQlF~_O~aGqgJiu8ca`GxNOZ0PUWHFBV;ApNl$KTF zax3zs)fBnbKI|QMC?Cjqi!5~=Xc$pk{T;noVZ1QkzmudQ4ye6e{|n_VpLGL}reM|wUV!FGjxxOtWD9l_Eq(1C+_V<#KEd}(mZb@KXp zT7y&g5p3k|OQ}p;8Tt;Vris&SNUm>Oq@#b4Irs7H0@QPh!19TJnA5UB9sjhU%6XOP za!#795I7td%?MFbMG!OwET0R&2@uJq4@#jx;RXTs{&yG=m=aKKe3c_tHK{XBo5<;@sPy>l6F$chaP#nXEldAh_9b+#6~{kw#zrl43k)X%riIL9lN5 z2=?Cj2$t9H{Y2ZY5S-SG%)4dU=6xjh;2VhvoCQG&PkM80#` zGpn~{yTMo$xIXMWIVZ+EWJuyMpeHEMf1af=#cEaeu)}D7G2V6Zfq>hhPfR+#j^fw$ z`)fAH?MsmwFWa+yBk%<}wVajO8;N)uH8l$v=dGn=rh;l~_+u8~rGf|d2K0-g%MZKa z@aa_L>+A}(c-;^lgT^@l8#>%*19{cFxa0ZPwZ{6qd`viWw7#ZlCjR2k_gQPy*4xX) zi)dZ6OSz-D<6R2b6FbAJXO>;6X+5j?441m23u~LNWVfwMb(&1E9Kno~8tdvske}1+ zd%l^-Z8Tpwg5i_^;Rxy?pyDYx7kvbqwm|0`!G4B04DG$7nm~U*Ahy+Bz(q)O5ax8G zpEt(IX1X_uiaw?jH|BRnuDsrN@irk5){a&SZfw$BRe#k{pz#UiqwaXnHeM&D>g~v@ zeIlN{e$HviDZ04XxN6Y)XLxeT2w$V=fgIJa`T4^e= z$EX}m&RjcOzAu_ObsCMcYvR8s@;)#I+I+o#ZT^YW6W!=CTi4y#1RYl#Dmr<_2TyF-pr0Dc7fjXeAa&^GG^#mPXI z9V9mdrBvA;uuwL9d*4CR6cRk`a?2Xugsrv`r&FlLA|y3O#`@`%xy^fHWEHK5B}>Wc zhOF0gJ|H+nsCbrF!{%G8Dz=OYYdV6Tj6YVZW*Ubbg2L*t^4*XG4_x`w5p3Q5(TMu~S%$BWkHr3uq1@K*rMZgoChaXo-a?N)%4`FxK(Ygk$aTELKjmu%* zEvhRb+Z~D$I}^GvP48$9FPPr@Bho2(cg*EedFb66+bY8SN&7l!Y%()>25&?J)IHK}LItMn(u?KiU02l2Z2$J5x&6h2$tciT)Y?U$2ue!L3$ zX0%XbWL_Mqygai1r+d;ag}lyjT_Aa)C$)ZYoK0Tfz28atb7bfUdqqXYigJ~Jw*AC`-Y~WymWRyHo$2$$ zGlEh>EDRHH2GgvKP&vT)O$>ZI5jkoNW!0 zEEma3pIqC>Z945S-Jhi;Aw69_#vk>faqbVojiWrur7y4K9x%pBlpeyn&n70P4zCTr zy!+=5K22>Wm}L!oV{h6BR5TKYVl(ID*C1Q2AU_*rhfo{smwh_M_!Jj$%&pl~iL96XHVJL#I7KpU3r{l`)zIBWSWl!2A=c)4>^E!7lFyen_8EDER0tk) zx(_W^+VC{b{*a$%ZR2nEb5Li!E@PnDV1>|eY!BYlG(3V0IgLp)&TBMA4Xfq8TX*Aa zkU?Y0nK8W>I+u8psMSkN{Ctj&8_S=aygE}o*PPw&&D<o_eRTi*w+E^|>Fy!g zXBFOc-EZ)pdXg$u>}vSSeA{wzTophzuhkE}b@AiHX@VKM#M5o}<} z?Jh4yxoQ#}&NpQCc*y!{VO&LAJv@1|;jLNXVeGfsVevx?tV{0qAB%BZnsut`WO)Gk&qMiHi{BJ`uUs734%tn}*CUiP%>IOT$7_?yrMx?wU!koLK_ zzJ1LU0L|5PTc$m>m|phS>q_V!!A5mZ^!lPHVSPK?MPxp)Y3NDP{ge(bL%zh|MQz$p zt{U+N&5qqF)mB0gh`5RSFDO=05kTC@Q)ycu?X(u}AkdCarkd2-Ek#b|B=aKDexG8@I>>br9CB29B)tmw$P$p{a|60 zq^&GGYL>rU+KO;vw0>2f3vGD02DQT%#jwm%uCaG@c%1KII!k(7w`~;=&f0PqyAjh` zdA5JulqsY|b9Ub$bW@lmc{b8&7)2IbSR^-TiqA;M!)d#;mz~~ z`y-f|(Aa##+TPN@vvY7sqVpmu@=={56A0_+59AsC97G>p=yf`|7fSK*4C&5X z`!VsXb-1b6`m#QG`mR2oC#puJ?|gp;v01cKnvT56l?~p=Ei(hEjihS-#h|Az~`ntV0M;W~EE_Eg7%Fl@Nj#`^>E&R7p zw$sTl2eB8DHe5R8diiZ@CiPr&&iMkDm1_)gn+ofP=7l%zq*Lu-oW>$ z@pQLeb1ks1* zS#RHpXuq-_g{-5>``HOsonsDomET`DQe0kRDe--*#&AA16m31ENA}`ewQ@oW1ycb% z#VM|$VQidD7B5%)+1%H2g6{Z==hc4xTw$MV^0=PvF2Z|& z$!Mb(&)1<}H|CRCg;<6kjPQn3-gP)wmdRS$Cf{d{Ud7%&K!G0>+=pE`Zx6m@qn^5J zixtc>b=>)GmyclY+=P!{os)-g%J-|)e)D^wYL~_>8$MW!0(M#zlWIVXhsKt0CQilf zo&2bKi)X`@8{63-ikmf^v=7}ee62{ll|o2>Sf@e!ybz1<;1Xi)cX--&v@Y-P@Yn$E zPPO6Cf(4Usa0iLj(rbzWeae?7c6zWQ8`=eB1|s8oRmIWU1;a)KrD(HKyL`CU$@7>? zEp8XfUc@Dhva~1Q+qK6uk6=CZ-`2~ejD1>stac;SHbsKx3dj}+x#3`l62}O-Y#b-T z8~j1`+W1fQBlqNgvd6(BNl=~{H0gwTc^>Diok0Rz1+@FTcaou(HA9?EQVFJ6nlH_Y z0{ym0Q!G6PeWl15IAEef!P2b%`s;}iU`yjbLFvhJ`!|8(j3}t+f-l*L?kH)tBG73O zMhBXYlPub31NM(*;%^? z%j}Be+O{v6MuzN`ZIoZ#;xh*|%)2%1@ZZ_Ht*ve)G!0a0eJpS8&qh8X6YXUs0{y_R zN3e=N+2tV8YRZEhv|*=+Y{w(t?b9fGk#8*{KP6G?etfnM_F#DSjQ0n}X(xGs+pp^@ zWLQ~*_No?R&wtpplDwHa?NCJbi+#iJ;3N3DQu!=_C(FeketY?kg2Wh$V^^G(2!4BM zn{08dxNS79ct_0CcxtxoOmUQkc zg1%nd3qrJ}D#_)QNl~rrbn9k#uq-LF${ugtGIZ>dbP{`Z}W zcV`iLcK);~9qBK2nwzJ%WweI+V_N#G=|y-kC;{BwF2nk>b60euUWb2i z<@JpJedgxKAS;alXsAi#24(NB>^uQ5B$D&GH(-8#PSX)5fGraS{rNPX{NKCp0Fszs zLlt2T;P0mjo(%g-vkF8VT$Foui!2WY9CX=_oIq>!-VETM%ddb^y}{8Sq1hlSX9_Zg zG?2&cc*I_oG_8ZC?x`g6Mz(B_QsnEUR;1L;lzB_9GY|}eS``rTi85!7|1RDj>mR{T z2_=-l1jN99_!!3XAiqbpU--twYwQJ|x0>eaFVEeNI7sK~=;m%P7;T8s@(#3X%}dMn zxZT`v_?EN8Ae_`?ckk4sxQ*k;jP;!*-$@$bHD!@O3!fYnI3`+!>E#wGK)JYFT|!mi z##=2HKeA`fIzaA{$XZj&pQFn5@l91}0n~=-Gv7hppo_pYnGO5SCG{j2rt?PA5=wx} zoFF7{BZ=}s2TUzjydDy_b+EW?rxUvF&Bmb^(P892YL^_{C!S;gFZCccV*93!TG72YF7FHR@Aj=W)&~~2=Zn(& z3{&jB{t;08j4xOZzg$0K{d@dnyVt=Jfc-Zf@^Bm1HQ>Q&_FC%pqhrybB4W=dLdd3R zCxyR$DjW7#Xv}}PO$q0jJF(66q_a!(Vv@O=?$f-AX=#hAdu&`FZLdfKR?ilYKaJzv-y zSy3=b&j{VFLh!sFeT!lh`4L(h)w!uNIj^CIFzvrrFH!un&!(`Ow@cwVXh^T=+nYcR z?5U(G0>+V#A=l-fciI1bYM`60>8oU|$#6;oy6LR+m_3dQAlJ`9LQ%LNM+6JJJ17I} zgMcy~7-j@Ps>C3ZA#hMif+m9Zn}HWm?iuhH%EE3#%?AJFSY(X+@)$S=fgRBaN7aoM z?ivDp%jQ5o^W8F~M0#oDc{WmMmWzEhRVh!M3)teF!f#~u;&k{Im_^PEO5RHVd2J`l z37Cl%U>E(hBLdd^4dRRhh==rY7W9#a-QUT8fr2zpr4s)Yl)s!lzC2Dr=<3AsK`k03 z-594A8i*l~u6L=6JA#$tj$kdbC^--rm^gw3?QGj0)Q|2fPr9CQ%>wBDKYSL|Mn5+a z|FpG7XEX8qT?=EyG_W*2G`PW0crwiX!mJp~#LzN$8Wi8eTx3omSUI6q@L&k&@9x0y zm|3h=BVn58;_SO)i>hw8DztB{xRJHPF?7SMEn?lz^iS5@6y9~W!|Ta@!D0LQWo?i~ z??>nEgIL6$?E27>{d%=hx5O0Aki9K0l;A*ZX3%i{Uh-ws$I{-7K2&}j71c@kg&RLp+c$OpeBPi^3niy(H z|4pU|Y$E8UK9_U_cCOK%wZ|d;%(W{QN#9<`ycIc!MWr@S{z%;#FSe}LX}>h*lkltl zL(tbD?}?4YYwN?MOox&rXZ7F~7Hj$j5;*4bnv*!!4i7gqp04rSN|xBQX9Cq5hv5s6 zdKZ)W&a$3@0iQ$Mk3PsP{Udz4ew*p}i_>GD^@-@c6sQYx zxOLzg;)WDYy}h$iO*;EV^M>H`W#+r0VorN*XP;qlUAWMy15B`#*^tgh-KL`X^L`v= z(Z*5-vv;0F4g2vt?p{SZG2U7Q?^}=7fXBHEpPQ03lcUW$;2QUY^Srk8^QuLgSK;L zSWDtw1dUn~UHWRh?b z{ljEY@-BTNsoA#>y_T-vK#Ci^qzo1|c$+K+8~3^e&Y4}m>+_6Fx5zS75)xlNLrI{@ zx41M%V=yag2G_WXCvc164(e_mbtjFyvACgr+c9*OeSb(Cw|)x0AH6xXn6<>yvhE>E z=b`7wO`a_~ZxeE*!U2Q0!QmRFmY?{0HsH|)PMqIG+GY()_=YuMiOeHd$+FLn%H`Bj z#4-bhH_Py0#hzk^XM|%AedOl50*YGNZ5@QkfRWv(sGi`w;GTiYj%^KE6mwBh7uSdl z)r!+%&wQIEE6ArqZ*jhJXVd6CS~3amUMFYorJi1^SDe|NTR8bDVRj}Hl`%BgJHe9O zKOT#GIm12m<#)Z;r*Er=EGuXJhMK6u!PAFc!y6^J!cxMd}q{EwW?OykiH>_2}6 zPm6e!uMFqf*`fkHYMt@s4XdSw1u0Xb=ezU5cXA!EH;2 z@w7H2+UTKo8)=s(vN*ZyTtyRk+$3s7=IZW0;wJa-Do|%J3*vFaS!v0}Kc~&TSc@|L zvd)#stsLl*f^_G3YdlHSCIeP7pW)?LXrA)iNI-}iQ4s9h+3cWm zmgW4mH6A6}T#v)JqHmYtcCn>nlk&c^y-VPk9oYsl&(<=ifkF4^{2x1ul!(@tO$>qbJkU^ zq`w%qgMT-%uqphrX}NmP8IwASmQP}_sWg|Dm0b{u3eQ*Yr4dtzFsPR(Q1YL&((88{ za-_rQ77lyxZ0I_nO3;|HEq`2zRT;N+k!*)fAYR<}Br6q-Exj>ZkC|)9&DcP1`0Ce0 zJ@3^h^dORPY)adRDd({dKr+^HROJc;Qa8p`hmxj7&9W3$s$OufVP_a!{1p?-^dIS1)aaK`kWS zoeY$JDq0mP6u0Rfw2je8jCLL{aNbN><|TVIX;5HeJgkSzIk|KvL#6Z@CryZXz~+m^ z=n2=sk9Fb_?X{^>Ib)T}>L%JATf1t*2t0Fpt&Nb@He=r|?UW0`2HyQnQ+aePAWIdk+tOdIsJ``=^)fb^|wH67DW~!ce z_~1^h_RBFlkIL`6ZoNM=%RypCkV5wj**h#D8u<9NhqS{g`YsI4)4L@uEq44wD zIPa*fa>vn%IFlsoy5soC_c=rxe3O=?cN1?vt;TS5cnfm}xAW`oT;E8oQ?qo1qpOtF z3wpn4RaAk78uaFI>LI61*jM$qwmLbvy=)5AtqX41j=ShMy4WE*J6c@gmnH`FQSc61 z-IO4NIj=063fo-NPbVY0;i`B|NrUg@jV4;z{K2s{z^@L0I^)?IqHO& z@0pI=Pv~hc{CUrz6zL#qs%S3uS=IPD5wAkyxo3(XcO`EE<*rH}nLefc^InEiu8}&D zU47Z#=Zo&y1Cb3gSA6$$5kB`?<)Pzp-JF2IiS&xajXgMB@wZX-oyR20#Ug4JMpvu0 zbrsZ;a7AIb--0Zzm1GmicD>)?-WTiNzT{47!qUc-j}=xdYo|NYK)07NXHl43f?Umw znexypNUfh1)_-Ts-NkvAnTOSz+-S5m)S6)$YYsmMy?cJ#a>ea1#R^}d&rbV(hCJX$ z7j;bdTF_I}tYmTi;l9+h!qzdqMJw#;%S0o7!OTIRu{ZmzHg$_03hvoFuJit7d5@@- ztDjlC1gU2o*WI~|HY;9C;V{5^po@R^;}|5oc1QX{=_vIY7B3)G-0IUv7IA+_G^$$8Bp8tHkkH}_`YX>=gGl|p zs|#LaqeLlfmdAgFDvoLy$joA#*NNoFPPl-Gxu|zA=kvWEJZas5v(~n1{w2ZnPDV9m zyY3!iQ{S8KYc4ZQYz?AoiVXb6-qJ3$#}rdDVu)PO@TB+vHJ2^?c&(rqB|^2_qH6ei zy6=x`u1mPYE_tU!P7RJIrN&kx(VE%un({iW><*WRE*{4u}0BtB$2z6@I3M z(GT0n0=bbL_5LNC^UzDrrLYMs<+>Mwew29VEvcXPJfOwsu-#OPN@6Mz&f&~6o;^4* z1Q&J2G1=qzls;^Qo2el-MM_c~20Zbvu374}(ved06(GAzRmc2vlN4ql2kiA4})psNJ+3dCr_8SI~iMtMQPIQsqFSh)_HK^y67h@*+ zrgU$nN`6GYc-HVKw!-s11|>tLcM(lMs)w!~?J*#?0|fBf)88__zd ztIoL&OT7MZ9dIbCX$Mh z{J1#~R#cEYw-NB&YWUYzlSMV1`Z>04^qw6&-mG`NGMh;y#2C|&duyXdd#4a_=dRo6 zTeSUlRDfn-eft{5C2i6CE_buqL}cl?o=T)=wci(cJnzYZ!J%(6@rMdFLyJ~s>)?m^ zyxByhh%;KaLBq5X&ESFHNqhX7BJc+<0E|bD2IJ!|+u8pJV^=nA;Hj#ony&q5fqgrd z7wDkh*EXGFqYZaN(iq_G4{&(u3||?=$hAMh!sD+^;Zjxc{=4-HoT{?i zRthIy`>jO801uH893>YH63uUC7KFqpSJT9+%K1mPI{TdmQaLB#8pzvw@?yrUzdE`o z7DM~2%4Sgoq1x#Ro(r2|tG^LN9=ZK~9;0<7gYzzTyvz=ogqNSDz&%m7_|MW{)8wV1 zYV59Az?)qV7%w{~x%s^?4~=@XSMi|f$IO!6&G^uvaX8k!U8B&#c-r(X2sUSTTcem- z*B|!G+eu+5C9rXU%5gP3Ia$^T}KtCq0v2 z-Cs2*klvfdogD~+krk0|XQ9s-C*ioB}ddxOYiRZgCe#4hJDS!e@?T> z$EVq=!y1+M)$1*{$$c;V!5V~q_L(raeYTJFfGev(wYU?mfIq!6&Tv_XYFztigH;L5 z4a3D{_jk%_6?!zGc|VNmc+cmZ3y-+Xv7x_g<>GezNA;chBbd{Ck3C8%r?N}C*?*b7 zH_}0_RUikvx}w3`4p=j!K?~}4`~tLJ#b|F*gb-uS$#BZY$jiPpNhSqHTN>=DG-;^i zyTbR)yr)=wH>cmhOdI<${iY{ws7pU2WDOHV9|WHV)kXdh(pS4VK*`&K;FHlWbL5El zL3MdBvFV@b>q5M{J}XoKz^QORZ&1Iw%jG@aYG;&!T7K0rX;UwVPm9~nBNr*^h;HLQ z;jpK-hqSZzN51OHl1R06Ap$Xh&Yhvbt+=Oi7gALgy<26A@FLIIdeS#tdxx+l zHa$Cae#Ic%Vx`~~CNY2bN0^>x+j2Yn>bErEwztXd7&pV|o{6E!)P5e#Ox8ILAH^G& zeiHXg4ViW4l}^l|5n16cFs6M|-~DHd!$E>t0X2!;>i%tr|Ew1_;LyBXN0wV&%eUhG z5Ifx-lh@Z%>fw{m;JwsCAHn{jtJmA<^=qF#GsMW6i;Gsbn4y|ZA!c>6Vq4+5w}#4c zYT4lw`VNZWW#Xi7DEh@k{#{2JR;pJ9@y}87xc1x{^vl&%#^S+LlWrSS;92^2Dc@8! zN>VEN#oJ`EJS3O@o;!=nL5P0KYjT%y*zyRrh@V`QVqW$^prwL5a9_PW)SFo*Hs}b~ zs7zPYeMsFWDOL==?^mlvd~VnWc6FL>?gqI7U)w5*TkRWrY3aNko6H{G=Etg$%sa93J!n&ty9%^J zeG{F0b5Y8Dp+4@BSN)_&QGX4evR*#Qo5cdjZrie7ow7odA;He9oG>bsSZ=LXKRc|s z;h-ND__FVJW3GYn0 zb$4W~uh28!v$!F_sNRYX#P%XYcQCJD#BvEtC(|YTbRp_%X6x4 z5)H2{xam zs>du`r=T!KKHOUAwCK)Ki1Pqt8;(ZhOQs2oPBNhzY#G|wm2*p-6x`8G*pZI( zgwvgL?|RJU0ak8NEGV`eKqwB2U+G4E|y1+Nl( zh{~bzrybi>&}}BN@(9NA71PjEC+A^5I5D^_8L#c~1|wgELHmoEr}naS?LQcL*0N@8 zSGS5{^A-;cv$Y0ocZ+F9hJ!8}9$3#{LmbL2&5=&Z?&knxT`z*ji(JP9MY&bXi>_@Z z&qnGcHSKW4r*udZ_hC@ulcFSR8(S7P+5=iMPc}MWQko_{)N74(m3Y}z$;)#( z*@5{!U!yll>W$t3Vn`oUTYIorh7Zq}d4XTd zxr8uTF!_k* zrJsD%>y_?v00iv5&rU(XQo}*I+o6KcnAG0k_P+ARU-de@%a>g-qQftCGetyY(J;TA zA7y{at%vSbnfM?i?<)j8SZ?%M++uHg;ng*&iZEqZRQHniox9tacPn9D$%{*8jPhCs z=-j&rI`?iSQ-){^v=4alt*`O(oBnzcrrIhaS=id~_!KE}+LzdR{t+|CGhQHV4HW#8 z!TDqd;8xPLpq^dQZYz&qDh4+hPexyrJH==t_u%H>aTYRy$n|3WXCk)`>x#rBq34L2 zDin!}H2$500-2~kAVF!JtTm5LZ5(rT4gIdeB$+u_t(%ZCb$YgfLBKDSO--j*w$`VsP5J%azr zH1mZI`o#@ocXbS^af^CjAMa=P&NgrgxomC1adbtwuSQV02%aT;Q|28nmq=>*wtJk9 zeJ#iRVo$S0G27(yTYp}3UZmBgD^U=1+6xu7<8+IsS$ujJ(On$pRXVcAq|)yGwPd`+ zm)-VKVw`8GWpvbCC9du86|_sdkeeaC)(iLAo1c3R-{-o?ZKOsnz@+tYt3cgN!(FFj zGNo8QUQ7{*F9>V*8Xm`a>P6=_8-eN-qjh6aB(e%JXy zxTdXHGm~dB&sz7rMzT(B_*-uT`nYv+pF#XWz3tOD8z!nj?`Qaw;~ghgTb;lxzD-7} zFmyRC=lgfr*s+ZRAEJVY|7)_ydgHEorFxRLG%o)TfG-~);!!+luNXmICX(Iz4GzOc z+3U`hQ}a>Po_lT_R+l48<%yAXB(r6V3(hSJWA1!YGBhb;yFz!`11F7_X6)n0sL9-# zKX@JTvSxH{eog^L>f!p4`ZXX) zLoKnd@axJO#*k=W@CkNfb@5 z{S8S`t)>0=Qj+Po#qcac*bA?{95_)PO(;kZFp!(ZZ}Jrc4Zw&vcwdc}o7}jNpf7k$ zntENkqC>M`Zp5PW<X!T@#9O()Kr6t+=2Y6tinw$=_U9&Tp!=7v8FUV zMpj|qz}QK^OUJTUF<{DIA2cnC9M>}ozSsRus+H>m)QkFhS5~i|%a0b;FVz1JIGC&Gbz3T-QTOZuD+@ zkj6o~J32Joc3OU{>Oi%_%7bi^VS}~C?@j9N6u6mhPNTUQh0h~NYa%jzpDJ6^#5xjs zh3i^VqH}dJ_~pZIn6ZRD$~hO%c^p>|H?n5aMAZW;TM!98R>Ioad`HBnE@PptE=0dVmN#TarZ>?z zaToJ-u@jHsGfYD)bTY^5d|XIF(mx-pt+BvIk74@!8w-^xqcs3uq2%&(7%qQ^Pg@=> ze@QmVuuRdj?~&sb;S0>~n4fshs1suee*LM(&r0N0v?lQjx(But=-U*ok} zIH$e6c+U>zJ>ui@yPvfOIE$^+V|=T-HO%zb3wF3koA8#y7SGs_vLVa;1Utu-UCN-b z*K)h)Ifjxi?ST$@quoqykNA1VmQB<26F0LX%q!{xL(h~MCYc5wnE5wWehC&K5OF1^ z`0WN)&%WcdU&?m1!mLW)bUm(B>Q#R7e{=lOjzuj!MjmsRp%g)XrL)hwf$OuSGYd`f zTgY7|0E=j3&WdxDKRb@KCm0sl6-J}J?#KnNfFy6scEcUQ*&JL1Qf$U%S{`=0S#npO z{033aD)k2Rrt$U8+qkO|OjgLA=I+*$7}~G`oxQTDko?h4V!8|O?<1=C3(RbP9c2YR z{WUojP(Mpht5w>im#D>+R@h9;nKqXa(4=#uTj;fo)fVT@g9w!c&!z5dz8a>DS(iiQ zT>h(>7vmU)a$;sS3tON%L9^c9bK zE823~it5))T>y5An7HVRw&C4Zjhd9hh{;%`j=dag)AMV@li`zND-Yph?(400Ttd4Q zrK}*d?Nu-IspHrO@b#{n)tE_6Nyf#VL3PFusltp9so0xsfu6#sON+(B7R?Mg*}j6K z>j>8PxA8_U!)ML={ViT*N}|Uq>QvMf^V{#RJ-dTR=%*_;b)1)NN3K>^qQU<`4i|DbQpEq7~dlKxMJ-K-_gO z(TV?45}8Pj2FUZtR6J}*(VkThN1;jH^Mbi#ngVPdxa=;HQsFYlBy$KHG;nBBK2Ex) z?*H0DqW_MYqNCe_0r<*nA&c!B`hvDeeDy>0Zm55%zwQ&sW4Ky|1!>>fxFNvV=^Ey3 zFbV(pq{bNHDEc)1p;)@q?PV4W-fX0{1pRB=+Er1#ckQ0OPH{;Hs@Y;>eFyKE`8+KC zMsOs3QlP5ci@|SNB}s41cH(wFTZ>ZrRbpqM%{KBEZ0LuBKvNA0-XhbS-_}3;vZFDR5<|5 z1HcABnYf4ppiyATPesWB1toV~1YNV)Vk0S48)3j?oX$86;KhH8?6IV~obgGSu2Z}< zl?qxD^?;hI=}x9H=-L|>W3E^rBv;-N{gs8tyyV&Qz|A;D4yUmO-oo7S&)$)Wq>JnU ze&S*;(kS)hbahe)w9!$TGToPj7K=~QfPpweOg@>)K%B0tv6T2~QZ-T0P$QC+W4Sn8 zQ-+t0HAW|`VEAaG^visC&|1w=Ief3E)Dlzau^VDGT1*f@VFI{=p5I`OdMpW>3pJZJ zojm+7*LczxX1i57w3)utS#DM*?Cv;O7t+@<_C%Muw|-eJPFMPw?`7^m*PSebI?gij zIZyd}+1?hL*hrP;;Ypq(0Eb=NjNsfE7yfbLh~aYjvIyM@aXarUP{MGvvqc zL}RNSo4gTAH{0&SwOu*a8V?Jp2Ar!RA-v(D_r7eyZhCJq0rM`t*yzm}886!FJ&CbS zGrOF{FTJ#OySz7oLwH-UMJuu8?;T~8(=KPzaY-5A11+Ofi4h-y=a^=g}e&l=M? z0{Dz#0HCAG7TL%2{}$>zMA||0y&Ysh3|hl@{V#eYU8eUAOGc-xSvHFEd2C;EVy;-m z2(d$AXg)K_ipT&cp=~YXsP=iF4Lj8<1dQI~--~;0E*f0=Oj`H5=51i1OSwT$#n~9B z0gwmBDG5sZ560t0%4v);-&0~!F9dXrgYL|er=Oo$6boG`WP%APd6x-lwtM__ioq9X zgMf4_M7bGx=q}u6Ie+^ZltpybOdGgOUId^w#cXMUm`#~nlsrVEk+UE2X&|vC|1M+{ zpv!yGF!3cKPGLGi@%T2{>grPY>dtwd(%+yZT;Ay6_DKo>XLeOmtd@uqi_q*KUCjij znGUZ@2qF)Nr1cZK-nw+NO)IK*4lQ;->T7#y)9{Tc4Fr{sVjs4v@jl2X&@fNmO3@8Ba7Pm)1}s#w0W(F(ehitx9r5 z_XLKr8b39QXv>#at7vCRem=+O{PMF>gAIpGhyHuqLYZj&V3onMw0G)jJyhxDWHyM_XZ~i=&};_s=H$I4u99 zfN_8MvC++sFMBFuldPJ6bvmiuC@dUqCpf24Mi2i{R%7vxRT}1#Ejrc|m_pSV7kM6!R zm#Wt1E5$k_>UKg5aC$n8cMl+lx1W^VmR+6orsN6u4T2zDvn+7JQy$qi>GPIecl<|f z77#pr%OTD4Rc+|4&FW!aL;Mt~k65+m+pzKsd;a4`TjUny=!++hkJ}mo9^eFR`+Lw$ zh1@U0-K8<4P;AMxa~dvUm7#mr=cvAt0smushaZ1y$zyeg3xmEFrcuyP;AP^*>3NhL zBi#9%n!!x$#e}%I+l7)n%Mq^(thZqWZ$6P6PQw&!# zH_WVxUZn12Tr{k5YT5Ws_Vl-tDI#sUS=7mi5!}n^e!OHi-*zy-u@JAp+e)Zo=;em*YNvMDphdi0kqT`!~qCe%HaMdTjDm zsHwzn`!~B|mn_K~Wv(~^^`5myf|^IGdN+ljY|a~}Tih%|U?2SS%|Pc9Yi&v1$+3-} zKdfR7(qw-A(0wwY8jdd|@wM!d_?{D!>xGrAqMmmL_&`#XsfIm%Zr}{;14=3-5A~F> zOI=RycPbh$_ctX4;A;X}x=Rk#!u$DJ&6Nqr`Ul$%!h(p8+>7Ty96*$jTq>gJs5t?@ zD3#aIUozs1L6Q6=3NNXNT*MtJdX19I_xbpqO^&7+1wUX^D41y#zFni<~l_1%}2Ns}8GJO5)RA}2?ndJBNNAdkNr zS~aYkO5f=(VR~Zy04khylmDHM6<@9bPnDHt)i!$_`4vw)@7O})deI`bkaFDn7L`(f!(yMUBhe#x+yHa zQ^*6?@uu|ftqfW#Y-jKtEc5z5@K!Y};xO=T*IzdPyb@v`_Kq1Nr)L`{qe=b~M?D#^ zD>W>-f4J6N#(SCV)DN%DUy-pNS*m9YKcpF*% zz%b}RENzgpZ9r^oanVSy@Mp-AoX+cc5ZsK`N60AUHE9Q6BZeaN^JRp1mox!t-JfjD zl}H-Mcxs;VL!`39ACsg6SjJD7G6M!yXQCE2rcQ(A34K_KM5eB=QA;8z>^^}YRWROa zItqtrQBhh^Htv|3#-Id+<&vYzM#K+~Xr2q~X4p;UgtzSn4*d%1yHgu@Xl6C-(JLRE zx#pj-%hJBvMMzO|NLyjZfaxumha!vpv?ew?s{HusO(V2M-N z2q``_2`jW3LzVZDlldFKFi$LTpVfaPG8Dci?&_NMGdtX3hh58%;}t${aX?^jPvV+> zKF00hU=dmnv`B-Qw!4EK^(+Zw-sT|(5@!5g6*;;4D<014mF6V%j@ac?807Y_^zNHe z)h#xX95EV-ii>Gj!j=_0b={oG?FV;8M8ptJ?%Mo;k4-q~!2K7af$LH4YmFz$d&Rk1 zcLk2yW||tp`%di1IL%>z<&|;R*>DK>l4gx(fE(cu1|d`Dy2BP+4zC_0HTH4VTD515 zlAOkawK%Qr6;X0p8(v5aD4Aeh~u5H*J z@I=>#)@Pa#=4he%rP5y{-mlhLmF%U(4JB@s;}y+|_U>i#e1EmKh;c^~J&7FX$-3}C zSM4JjHBD>XF!i660k&@oYFo2<&|({i%$h?uz^`s@_zl{`71d)=Nk7tqBA(~y?jDpK z34D$p$L$8c3aqH!fHNb$kU}%V_a*9+r*+HHrxDh5fpY5}de8YZ1{22%>*V!h=bc8~ zOh#5OTuw4vzyDQ(H9@Z}uw)mts^p$wwuW#LnDldVzM*z?Yv;>lP;otWI??>QXbki8MGH zsGn^82HE4US_b}jSRG<`tf~U+Ke+IdD4*uHB1ifq5l1<{L4~z-$Ju~e>|DR=>nW)f zDZo$0ArM4+99`gbG;osW?mA_+VzqaCc5Ki0*LYa&4O#f~P=YORrJn112#PpzFX3ZQ zhf?o%>xviwJN5K^xZbUDT*=eJ27p5E70mPNxWGKW%Fhy8f)Uf2g&>9XAAD4a<7xBbK(qZrTTpWavm>LS&kLZR7hnOUfSsTi9IyqWZ$6g=1FQs5>?=sKifDE( zHVRaNF$EANCQ5G8Y1c;qqkci-t(f^kb4fj_TC^W#MpJ-!1l5;5TelzuI{AN5W^jER>O#&s98gej?^ zebQqDJ>K0FH!s^Tmt+u->9()l_foZc)q&NsC-}WSwAWL;-J6e9wn>42X(Ay z;i*T#qwcor;eU;g0{KicR)}4P-Q5Ja3cxH?uzz*5;|IViKRsXZq6ZJMRl?5rl5QQF zb9O8MI%jO`pYC>i8bGv;h^DwA?70(mhTot}%)StYn0JJk)=dJ~%C8Q~JH;)>m?d=I zaGv#Bl6k#;|0F)^OXj(7;mnKTp75TRL58R|+p z>U8Hy8e{H~5!DZ*=4PMp2uZXacHCX73>oOt3&B@CxN&${iU=^?H!r>Um_Au@R;tqm zBZ-JYq#UJP+$o0-TY6Oml1v}9ykQlo3B3W;;CI=S6{ZcEm* z`NRz{#CS;5RC9A$Lu3vE!|{lP zGIbb>+M*)moO%Bqpv13ouet5lC(FRTE590gsdZXK^;h2n!EaB{Il%0Blpt>!h0sS| zaco!z5AIf2Sv;>1KE<-QdinDW=b9-#Ye}*SHhqy#t$^M*=P{`BdM5bD7Kp-Bt|-~u zdpoYrD?~4Sti0~3TlwK(_i>WPvExiv><&qBXJgel*QxpN7jxTQ)MG*;($FaJn?N64 z%x)65j{9)5mr2Y&i9B@g>Arvj zA6%y4#Dg-;w&of8p~&T_QaPE{Re9jB`fgC8%2*xNUT+%4db=`+eBgzT^~+TsR^>1V zf4Fz)y?O{i@~|p6pmM#?4TzgV*szFyyr7A$kK0dhM3q%M#o@h*NuHBCfkLCzEu+&l z*)98=KI9aPa}Z7}ag!MQNZTk!SGgc*g)K?-yEfR9m63#D`a{{wNz~WC)Cx2v2a6Ru$mC)nZrInB=aAx;`x*oSPB$ z80WD3I5TPU8@MMZ*vICQ75ZpD6#x3smaUv`eL3NZ)eqF|29>Lr< zHEgcA;d||hJ;F0X!4^cPEn&3TC~?iql5Dl;H13M$f2~@1QaF9Bo3yuu@#Oo&XFD6R zu-aDAs$pqV?Zf~UYzpu+Qd4dmuQxt&A z`SJ(Z@r9j4vG$Ob$oV()9sd1JHag=IOXK_w!JZaUZAIwr5$mG9KIZLv+xL~`ish2L znm-M!)JjhUhCCe+PusIG;L^J+mFlq|{qbaOEg)>JTm0aWwI20~vs9DE{!B#Am-j)H z`VXg%dq_lvJh{MjjENv9;loWq+Va9n-;}6oMmB?_D;;-pgT__^)D8q{8_{q0Nt+cz zgb-i5{9*U)H7P51;{)^j9}p&fW6H>maq^VMD@ioIbR4m1vWX$x%dsT2th?m;2Y=PW z;M<9{foJ_gqBqluI4WTM;zgFSXOJoP7_#pqF~aM}Y*z~z_O{;R6!=lG)|G_@SL?&( z@gX>`giAB!2UAJ8v9Yc|~@) zas1(n48Ml8u=b5!;WV+}ssK~L(Kufjp-0cY_=|<4JsO&5UR{w3@R%widM2hj+7O8< ziF1ULVWlIK`r9-^d)D*Vw2OzUKGxxj_3B1O7`{cJ)i&wU8s?$+=m*>E+OXlU%=1QX>gAzf^URSr-CoFh z9)wNe{%GU$>Jo55vd0L=p*)G7vu94`Td%0RYRBY!FPj=PDIC44dmZk2IayZ-8R>vmOQhFAvM z!m3x5jeFg9r}5g5G(0zvSJF-1WN=N}b~i3xv#>)v^PRGf4LLV>cmZugH1Cy-9`VSE zlZ^9Rx9TeB^(7kNc?z55Bn7JE5=b6z)$$&%#zVoGzHJ$CGeA&2*)olORUjTz$r}1B z5E6$lUiWpCHh~ke`g;y>Uf#^g&2Z7MR7do~+NlbNCOE|_52@7(1uFo%% zx``d-4|cv?9+$9X17C|gyv740=GtdzjygZh2TyaMI^~{h T^Y65X3N>9|MpLkUa zN$85$7x}&$ubrOX3p*5?9S=>_D-QoW zxjhvU$7Y&oA3F(h)TNy9Vn#MFuX&5kj%|C+pwMkjwsv*va@px^{^P1!zKd%TclN2P zwRPs}wY2G&;j0;gX)*-$83WdFTah(+dgsyaYgf5`KiGWAGKblXBT?3cal+d=ez__YW?&Sbj#x zzU9?S$tP@J-|$>14{Rwz2kmqfO$YQ~mL7@QIQj+0R@T4nD40>~Bo4AlNM;Sx(7$8O zS(1?f+#H|W6j7dy@nt3Cse*U-jVaaIpTKKi@Ul9U^?dB`Cp51Qj9L-)XR{ule4+xQ z?gch$khCA@5wKlfr+j)DBp^qb_}AmMkv}=Ga7{i_QHV5*R|a(bK9YqG~joVBRO9 zP>R1IDW9Io0$PX`Usv*D;=LM61BwM~=Unta11R!(J_}_G(DsyRQYpvezr!~}2xj1w z%aRD|R&l?TO0azT(7}iIYi}zM!p05Voj>wm3I72I9urnV=nKc%m5#f?-F5>RNIF9d z-Kk%aLFa?060+qdB?GM&YeYDBe5O!!T6!N-be6)u{nP!nCcscVRroIpV2H^uAr(N0 zQ>TQj3l#91Ac1v-2`NT$fG>Pzh63LJ*x#n|SQ^ID;axjb8+v1pJ7{Eh2|l5M4{?TuuIRNscw;!qY#i=B#j>v|0^ic@QNlR^)Yl; z6TH4Zpb46bq#T4$=hFz~Fu{WJkh_`?iht!m@~&r;(ww`?1p6Z@7>c|>BfNGhjEV98 z=74-OAwYLP9YZEfsk==4#ZZb!nlsU-k|Bc-mK&#Xz@;=$HYWaOP*zwZ?WJOXc%okh!v19@Zv|A4j6tw`hMWfHqnh~QQ>%0y9WUSseQ(jPcOBE8!{8ZJPZu^6=dztT#1l)a$YSfByu zAWtMwR7+_t`ag1j-A-xlKSThhP(biMGS>b+tAf-97=hEPGz|DW?L;Y$=ASD6ty|tT zKq)ZWT~McqE=;tOiVsxq7WgwKKm|~$##ma!S|D-6MQ8DGmBTbU&E}Zt02TuNz gqUhAr1Ns3uh!#NE96;4zJuNyF5Emf!-0#W%0gsOFc>n+a literal 0 HcmV?d00001 diff --git a/test/Integration/Gateways/ProPay/TestData/TestAccountData.php b/test/Integration/Gateways/ProPay/TestData/TestAccountData.php new file mode 100644 index 00000000..2ec1fcdf --- /dev/null +++ b/test/Integration/Gateways/ProPay/TestData/TestAccountData.php @@ -0,0 +1,304 @@ +accountCountryCode = 'USA'; + $bankAccountInformation->accountName = 'MyBankAccount'; + $bankAccountInformation->accountNumber = '123456789'; + $bankAccountInformation->accountOwnershipType = 'Personal'; + $bankAccountInformation->accountType = 'C'; + $bankAccountInformation->routingNumber = '102000076'; + + return $bankAccountInformation; + } + public static function getBusinessData() + { + $userBusinessInformation = new BusinessData(); + $userBusinessInformation->businessLegalName = 'Twain Enterprises'; + $userBusinessInformation->doingBusinessAs = 'Twain Enterprises'; + $userBusinessInformation->employerIdentificationNumber = 987654321;//mt_rand(100000000, 999999999); + $userBusinessInformation->businessDescription = 'Accounting Services'; + $userBusinessInformation->websiteURL = 'https://www.Propay.com'; + $userBusinessInformation->merchantCategoryCode = '5399'; + $userBusinessInformation->monthlyBankCardVolume = 50000; + $userBusinessInformation->averageTicket = 100; + $userBusinessInformation->highestTicket = 300; + $userBusinessInformation->businessAddress->streetAddress1 = '3400 Ashton Blvd'; + $userBusinessInformation->businessAddress->city = 'Lehi'; + $userBusinessInformation->businessAddress->state = 'UT'; + $userBusinessInformation->businessAddress->postalCode = '84045'; + $userBusinessInformation->businessAddress->country = 'USA'; + + return $userBusinessInformation; + } + public static function getUserPersonalData() + { + $accountPersonalInformation = new UserPersonalData(); + $accountPersonalInformation->dayPhone = 4464464464; + $accountPersonalInformation->eveningPhone = 4464464464; + $accountPersonalInformation->externalId = uniqid(); + $accountPersonalInformation->firstName = 'David'; + $accountPersonalInformation->lastName = 'Tennant'; + $accountPersonalInformation->phonePin = 1234; + $accountPersonalInformation->sourceEmail = sprintf("user%s@user.com", mt_rand(1, 10000)); + $accountPersonalInformation->notificationEmail = sprintf("user%s@user.com", mt_rand(1, 10000)); + $accountPersonalInformation->ssn = 123456789; + $accountPersonalInformation->dateOfBirth = '01-01-1981'; + $accountPersonalInformation->tier = 'TestEIN'; + + $accountPersonalInformation->userAddress->streetAddress1 = '123 Main St.'; + $accountPersonalInformation->userAddress->city = 'Downtown'; + $accountPersonalInformation->userAddress->state = 'NJ'; + $accountPersonalInformation->userAddress->postalCode = '12345'; + $accountPersonalInformation->userAddress->country = 'USA'; + + $accountPersonalInformation->mailingAddress->streetAddress1 = '123 Main St.'; + $accountPersonalInformation->mailingAddress->city = 'Downtown'; + $accountPersonalInformation->mailingAddress->state = 'NJ'; + $accountPersonalInformation->mailingAddress->postalCode = '12345'; + $accountPersonalInformation->mailingAddress->country = 'USA'; + + return $accountPersonalInformation; + } + public static function getThreatRiskData() + { + $threatRiskData = new ThreatRiskData(); + $threatRiskData->merchantSourceIp = '8.8.8.8'; + $threatRiskData->threatMetrixPolicy = 'Default'; + $threatRiskData->threatMetrixSessionId = 'dad889c1-1ca4-4fq71-8f6f-807eb4408bc7'; + + return $threatRiskData; + } + + public static function getSignificantOwnerData() + { + $significantOwnerData = new SignificantOwnerData(); + $significantOwnerData->authorizedSignerFirstName = 'John'; + $significantOwnerData->authorizedSignerLastName = 'Doe'; + $significantOwnerData->authorizedSignerTitle = 'Director'; + + $significantOwnerData->significantOwnerData->firstName = 'John'; + + return $significantOwnerData; + } + + public static function getBeneficialOwnerData() + { + $ownersInformation = new BeneficialOwnerData(); + $firstOwnerInformation = new OwnersData(); + $firstOwnerInformation->firstName = 'Scott'; + $firstOwnerInformation->lastName = 'Sterling'; + $firstOwnerInformation->title = 'USA'; + $firstOwnerInformation->email = 'TwainEnterprises@Twain.com'; + $firstOwnerInformation->dateOfBirth = '11-11-1988'; + $firstOwnerInformation->ssn = 123456789; + $firstOwnerInformation->percentage = 100; + $firstOwnerInformation->ownerAddress->streetAddress1 = '123 Address'; + $firstOwnerInformation->ownerAddress->streetAddress2 = 'Second'; + $firstOwnerInformation->ownerAddress->streetAddress3 = 'Floor'; + $firstOwnerInformation->ownerAddress->city = 'Lehi'; + $firstOwnerInformation->ownerAddress->state = 'UT'; + $firstOwnerInformation->ownerAddress->postalCode = '84045'; + $firstOwnerInformation->ownerAddress->country = 'USA'; + $firstOwnerInformation->phone = '12233445'; + + $secondOwnerInformation = new OwnersData(); + $secondOwnerInformation->firstName = 'First4'; + $secondOwnerInformation->lastName = 'Last4'; + $secondOwnerInformation->title = 'Director'; + $secondOwnerInformation->email = 'abc1@qamail.com'; + $secondOwnerInformation->dateOfBirth = '11-11-1989'; + $secondOwnerInformation->ssn = 123545677; + $secondOwnerInformation->ownerAddress->streetAddress1 = '125 Main St.'; + $secondOwnerInformation->ownerAddress->streetAddress2 = 'Second'; + $secondOwnerInformation->ownerAddress->streetAddress3 = 'Floor'; + $secondOwnerInformation->ownerAddress->city = 'Downtown'; + $secondOwnerInformation->ownerAddress->state = 'NJ'; + $secondOwnerInformation->ownerAddress->postalCode = '12345'; + $secondOwnerInformation->ownerAddress->country = 'USA'; + $secondOwnerInformation->phone = '12233445'; + + $ownersInformation->ownersCount = 5; + $ownersInformation->ownersList = [$firstOwnerInformation, $secondOwnerInformation]; + + return $ownersInformation; + } + + public static function getCreditCardData() + { + $card = new CreditCardData(); + $card->number = '4111111111111111'; + $card->expMonth = 12; + $card->expYear = 2025; + $card->cvn = '123'; + $card->cardHolderName = 'Joe Smith'; + + return $card; + } + + public static function getACHData() + { + $bankAccountInformation = new BankAccountData(); + $bankAccountInformation->accountNumber = '123456789'; + $bankAccountInformation->accountType = 'C'; + $bankAccountInformation->routingNumber = '102000076'; + + return $bankAccountInformation; + } + + public static function getSecondaryBankAccountData() + { + $bankAccountInformation = new BankAccountData(); + $bankAccountInformation->accountCountryCode = 'USA'; + $bankAccountInformation->accountName = 'MyBankAccount'; + $bankAccountInformation->accountNumber = '123456788'; + $bankAccountInformation->accountOwnershipType = 'Personal'; + $bankAccountInformation->accountType = 'C'; + $bankAccountInformation->routingNumber = '102000076'; + + return $bankAccountInformation; + } + + public static function getGrossBillingSettleData() + { + $grossBillingInformation = new GrossBillingInformation(); + + $grossBillingInformation->grossSettleBankData->accountCountryCode = 'USA'; + $grossBillingInformation->grossSettleBankData->accountName = 'Scott Sterling'; + $grossBillingInformation->grossSettleBankData->accountNumber = '111222333'; + $grossBillingInformation->grossSettleBankData->accountOwnershipType = 'Personal'; + $grossBillingInformation->grossSettleBankData->accountType = 'C'; + $grossBillingInformation->grossSettleBankData->routingNumber = '124002971'; + $grossBillingInformation->grossSettleBankData->accountHolderName = 'Scott Sterling'; + + $grossBillingInformation->grossSettleAddress->streetAddress1 = '123 Main St.'; + $grossBillingInformation->grossSettleAddress->city = 'Downtown'; + $grossBillingInformation->grossSettleAddress->state = 'NJ'; + $grossBillingInformation->grossSettleAddress->postalCode = '12345'; + $grossBillingInformation->grossSettleAddress->country = 'USA'; + + $grossBillingInformation->grossSettleCreditCardData->number = '4111111111111111'; + $grossBillingInformation->grossSettleCreditCardData->expMonth = 12; + $grossBillingInformation->grossSettleCreditCardData->expYear = 2025; + $grossBillingInformation->grossSettleCreditCardData->cvn = '123'; + $grossBillingInformation->grossSettleCreditCardData->cardHolderName = 'Joe Smith'; + + + return $grossBillingInformation; + } + + public static function editAccountPermissions() + { + $accountPermissions = new AccountPermissions(); + $accountPermissions->achIn = 'Y'; + $accountPermissions->achOut = 'N'; + $accountPermissions->ccProcessing = 'Y'; + $accountPermissions->proPayIn = 'Y'; + $accountPermissions->proPayOut = 'N'; + $accountPermissions->creditCardMonthLimit = '10000'; + $accountPermissions->creditCardTransactionLimit = '10000'; + $accountPermissions->merchantOverallStatus = ProPayAccountStatus::READY_TO_PROCESS; + $accountPermissions->softLimitEnabled = 'Y'; + $accountPermissions->achPaymentSoftLimitEnabled = 'N'; + $accountPermissions->softLimitAchOffPercent = '100'; //0-499 + $accountPermissions->achPaymentAchOffPercent = '100'; //0-499 + + return $accountPermissions; + } + + public static function editUserPersonalData() + { + $accountPersonalInformation = new UserPersonalData(); + $accountPersonalInformation->dayPhone = 4464464464; + $accountPersonalInformation->eveningPhone = 4464464464; + $accountPersonalInformation->externalId = uniqid(); + $accountPersonalInformation->firstName = 'John'; + $accountPersonalInformation->lastName = 'Doe'; + $accountPersonalInformation->phonePin = 1234; + $accountPersonalInformation->sourceEmail = sprintf("user%s@user.com", mt_rand(1, 10000)); + $accountPersonalInformation->notificationEmail = sprintf("user%s@user.com", mt_rand(1, 10000)); + $accountPersonalInformation->ssn = 123456789; + $accountPersonalInformation->dateOfBirth = '01-01-1981'; + $accountPersonalInformation->tier = 'TestEIN'; + + return $accountPersonalInformation; + } + + public static function editAddressData() + { + $accountPersonalInformation = new UserPersonalData(); + $accountPersonalInformation->userAddress->streetAddress1 = '124 Main St.'; + $accountPersonalInformation->userAddress->city = 'Downtown'; + $accountPersonalInformation->userAddress->state = 'NJ'; + $accountPersonalInformation->userAddress->postalCode = '12345'; + $accountPersonalInformation->userAddress->country = 'USA'; + + $accountPersonalInformation->mailingAddress->streetAddress1 = '125 Main St.'; + $accountPersonalInformation->mailingAddress->city = 'Downtown'; + $accountPersonalInformation->mailingAddress->state = 'NJ'; + $accountPersonalInformation->mailingAddress->postalCode = '12345'; + $accountPersonalInformation->mailingAddress->country = 'USA'; + + return $accountPersonalInformation; + } + + public static function editBankData() + { + $bankAccountInformation = new BankAccountData(); + $bankAccountInformation->accountCountryCode = 'USA'; + $bankAccountInformation->accountName = 'Sterling'; + $bankAccountInformation->accountNumber = '111111111'; + $bankAccountInformation->accountOwnershipType = 'Business'; + //Valid values are: Checking, Savings, and GeneralLedger + $bankAccountInformation->accountType = 'Checking'; + $bankAccountInformation->routingNumber = '91000019'; + $bankAccountInformation->bankName = 'Bank Name'; + + return $bankAccountInformation; + } + + public static function editACHData() + { + $bankAccountInformation = new BankAccountData(); + $bankAccountInformation->accountNumber = '123456789'; + //Valid values are: Checking, Savings, and GeneralLedger + $bankAccountInformation->accountType = 'Savings'; + $bankAccountInformation->routingNumber = '102000076'; + + return $bankAccountInformation; + } + + public static function getRenewAccountDetails() + { + $renewAccountData = new RenewAccountData(); + $renewAccountData->tier = 'TestEIN'; + $renewAccountData->zipCode = '12345'; + $renewAccountData->creditCard->number = '4111111111111111'; + $renewAccountData->creditCard->expMonth = 12; + $renewAccountData->creditCard->expYear = 2025; + $renewAccountData->creditCard->cvn = 123; + $renewAccountData->paymentBankAccountNumber = '123456789'; + $renewAccountData->paymentBankRoutingNumber = '102000076'; + $renewAccountData->paymentBankAccountType = 'Checking'; + + return $renewAccountData; + } +} diff --git a/test/Integration/Gateways/ProPay/TestData/TestFundsData.php b/test/Integration/Gateways/ProPay/TestData/TestFundsData.php new file mode 100644 index 00000000..997c43fd --- /dev/null +++ b/test/Integration/Gateways/ProPay/TestData/TestFundsData.php @@ -0,0 +1,27 @@ +creditCard->number = '4895142232120006'; + $flashFundsData->creditCard->expMonth = 10; + $flashFundsData->creditCard->expYear = 2025; + $flashFundsData->creditCard->cvn = '022'; + $flashFundsData->creditCard->cardHolderName = 'Clint Eastwood'; + + $flashFundsData->cardholderAddress->streetAddress1 = '900 Metro Center Blv'; + $flashFundsData->cardholderAddress->city = 'San Fransisco'; + $flashFundsData->cardholderAddress->state = 'CA'; + $flashFundsData->cardholderAddress->postalCode = '94404'; + $flashFundsData->cardholderAddress->country = 'USA'; + $flashFundsData->cardholderAddress->phone = '12233445'; + + return $flashFundsData; + } +} diff --git a/test/Integration/Gateways/ProPay/TestData/selfSignedCertificate.crt b/test/Integration/Gateways/ProPay/TestData/selfSignedCertificate.crt new file mode 100644 index 00000000..4e5c4d9b --- /dev/null +++ b/test/Integration/Gateways/ProPay/TestData/selfSignedCertificate.crt @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIICpDCCAYygAwIBAgIIS7Y5fijJytIwDQYJKoZIhvcNAQENBQAwETEPMA0GA1UE +AwwGUFJPUEFZMB4XDTE5MDkxOTAwMDAwMFoXDTI5MDkxOTAwMDAwMFowEzERMA8G +A1UEAwwIMTI3LjAuMDEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCC +wvq2ho43oeeGX3L9+2aD7bna7qjdLwWumeIpwhPZLa44MeQ5100wy4W2hKk3pOb5 +yaHqyhzoHDriveQnq/EpZJk9m7sizXsxZtBHtt+wghSZjdNhnon3R54SH5J7oEPy +bRSAKXSEzHjN+kCu7W3TmXSLve6YuODnjUpbOcAsHG2wE+zpCoEbe8toH5Tt7g8H +zEc5mJYkkILTq6j9pwDE50r2NVbV3SXwmQ1ifxf54Z9EFB5bQv5cI3+GL/VwlQeJ +diKMGj1rs8zTR8TjbAjVlJbz6bBkFItUsqexgwAHIJZAaU7an8ZamGRlPjf6dp3m +OEu4B47igNj5KOSgCNdRAgMBAAEwDQYJKoZIhvcNAQENBQADggEBAF88u367yrdu +qd3PfEIo2ClaI2QPRIIWKKACMcZDl3z1BzVzNFOZNG2vLcSuKnGRH89tJPCjyxdJ +a0RyDTkXMSLqb5FgUseEjmj3ULAvFqLZNW35PY9mmlmCY+S3CC/bQR4iyPLo8lsR +q0Nl6hlvB440+9zS8UQjtc2957QgcXfD427UJb698gXzsfQcNeaQWy8pNm7FzDfH +TJbo/t6FOpmfR+RMZky9FrlWabInkrkf3w2XJL0uUAYU9jGQa+l/vnZD2KNzs1mO +1EqkS6yB/fsn85mkgGe4Vfbo9GQ/S+KmDujewFA0ma7O03fy1W5v6Amn/nAcFTCd +dVL3BDNEtOM= +-----END CERTIFICATE----- +