diff --git a/CHANGELOG.md b/CHANGELOG.md index eac41d07..08037a49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,12 @@ ## Latest version #### Enhancements: +- GPI Transactions : added support for credit, ach & reporting transactions +- GP-API: add to generateXGPSignature to GenerationUtils +- Portico Gateway: Fix incorrect date handling in schedule response + +## v6.0.5 (01/12/2023) +#### Enhancements: - GP-API: add exemption status on "/transaction" endpoint - Add enum classes: HostedPaymentMethods, IntervalToExpire - Portico: added support for SDKNameVersion field diff --git a/metadata.xml b/metadata.xml index 571500b0..d5b0e1f9 100644 --- a/metadata.xml +++ b/metadata.xml @@ -1,3 +1,3 @@ - 6.0.5 + 6.0.6 \ No newline at end of file diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 44c49830..6fa6f240 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -38,6 +38,9 @@ ./test/Integration/Gateways/GpApiConnector/ + + ./test/Integration/Gateways/TransactionApiConnector/ + diff --git a/src/Builders/AuthorizationBuilder.php b/src/Builders/AuthorizationBuilder.php index 4f77b2c5..eb1dfacb 100644 --- a/src/Builders/AuthorizationBuilder.php +++ b/src/Builders/AuthorizationBuilder.php @@ -2,39 +2,45 @@ namespace GlobalPayments\Api\Builders; -use GlobalPayments\Api\Entities\Address; -use GlobalPayments\Api\Entities\AutoSubstantiation; -use GlobalPayments\Api\Entities\EcommerceInfo; -use GlobalPayments\Api\Entities\Enums\BNPLShippingMethod; -use GlobalPayments\Api\Entities\Enums\EmvFallbackCondition; -use GlobalPayments\Api\Entities\Enums\EmvLastChipRead; -use GlobalPayments\Api\Entities\Enums\FraudFilterMode; -use GlobalPayments\Api\Entities\Enums\PaymentMethodUsageMode; -use GlobalPayments\Api\Entities\Enums\PhoneNumberType; -use GlobalPayments\Api\Entities\Enums\RemittanceReferenceType; -use GlobalPayments\Api\Entities\Exceptions\ArgumentException; -use GlobalPayments\Api\Entities\FraudRuleCollection; -use GlobalPayments\Api\Entities\HostedPaymentData; -use GlobalPayments\Api\Entities\Enums\AddressType; -use GlobalPayments\Api\Entities\Enums\AliasAction; -use GlobalPayments\Api\Entities\Enums\InquiryType; -use GlobalPayments\Api\Entities\Enums\RecurringSequence; -use GlobalPayments\Api\Entities\Enums\RecurringType; -use GlobalPayments\Api\Entities\Enums\TransactionModifier; -use GlobalPayments\Api\Entities\Enums\TransactionType; -use GlobalPayments\Api\Entities\PhoneNumber; -use GlobalPayments\Api\Entities\StoredCredential; -use GlobalPayments\Api\Entities\Transaction; -use GlobalPayments\Api\PaymentMethods\BNPL; -use GlobalPayments\Api\PaymentMethods\EBTCardData; -use GlobalPayments\Api\PaymentMethods\GiftCard; -use GlobalPayments\Api\PaymentMethods\Interfaces\IPaymentMethod; -use GlobalPayments\Api\PaymentMethods\TransactionReference; use GlobalPayments\Api\ServicesContainer; -use GlobalPayments\Api\Entities\DccRateData; -use GlobalPayments\Api\Entities\Customer; -use GlobalPayments\Api\Entities\DecisionManager; -use GlobalPayments\Api\Entities\OrderDetails; +use GlobalPayments\Api\Entities\{ + Address, + Customer, + AutoSubstantiation, + EcommerceInfo, + FraudRuleCollection, + HostedPaymentData, + PhoneNumber, + StoredCredential, + Transaction +}; +use GlobalPayments\Api\Entities\Enums\{ + AddressType, + AliasAction, + BNPLShippingMethod, + DccRateData, + DecisionManager, + EmvFallbackCondition, + EmvLastChipRead, + InquiryType, + FraudFilterMode, + OrderDetails, + PaymentMethodUsageMode, + PhoneNumberType, + RemittanceReferenceType, + RecurringSequence, + RecurringType, + TransactionModifier, + TransactionType +}; +use GlobalPayments\Api\PaymentMethods\{ + BNPL, + EBTCardData, + GiftCard, + TransactionReference +}; +use GlobalPayments\Api\PaymentMethods\Interfaces\IPaymentMethod; +use GlobalPayments\Api\Entities\Exceptions\ArgumentException; class AuthorizationBuilder extends TransactionBuilder { @@ -511,6 +517,9 @@ class AuthorizationBuilder extends TransactionBuilder /** @var BNPLShippingMethod */ public $bnplShippingMethod; + /** @var boolean */ + public $maskedDataResponse; + /** * {@inheritdoc} * @@ -534,7 +543,7 @@ public function __construct($type, IPaymentMethod $paymentMethod = null) public function execute($configName = 'default') { parent::execute($configName); - + $client = ServicesContainer::instance()->getClient($configName); return $client->processAuthorization($this); } @@ -567,9 +576,9 @@ protected function setupValidations() { $this->validations->of( TransactionType::AUTH | - TransactionType::SALE | - TransactionType::REFUND | - TransactionType::ADD_VALUE + TransactionType::SALE | + TransactionType::REFUND | + TransactionType::ADD_VALUE ) ->with(TransactionModifier::NONE) ->check('amount')->isNotNull() @@ -578,7 +587,7 @@ protected function setupValidations() $this->validations->of( TransactionType::AUTH | - TransactionType::SALE + TransactionType::SALE ) ->with(TransactionModifier::HOSTEDREQUEST) ->check('amount')->isNotNull() @@ -586,7 +595,7 @@ protected function setupValidations() $this->validations->of( TransactionType::AUTH | - TransactionType::SALE + TransactionType::SALE ) ->with(TransactionModifier::OFFLINE) ->check('amount')->isNotNull() @@ -605,7 +614,7 @@ protected function setupValidations() $this->validations->of( TransactionType::AUTH | - TransactionType::SALE + TransactionType::SALE ) ->with(TransactionModifier::ENCRYPTED_MOBILE) ->check('paymentMethod')->isNotNull() @@ -620,7 +629,7 @@ protected function setupValidations() $this->validations->of( TransactionType::AUTH | - TransactionType::SALE + TransactionType::SALE ) ->with(TransactionModifier::ALTERNATIVE_PAYMENT_METHOD) ->check('amount')->isNotNull() @@ -795,6 +804,13 @@ public function withCashBack($cashBackAmount) return $this; } + /** + * Set the Client Transaction Id + * + * @param string $clientTransactionId + * + * @return AuthorizationBuilder + */ public function withClientTransactionId($clientTransactionId) { if ($this->transactionType !== TransactionType::REVERSAL) { @@ -1134,7 +1150,7 @@ public function withDccRateData($value) /** * Set the request Convenience amount * - * @param string|float $convenienceAmt Request Convenience amount + * @param string|float $convenienceAmount Request Convenience amount * * @return AuthorizationBuilder */ @@ -1258,9 +1274,9 @@ public function withScheduleId($scheduleId) } /** - * Set the associated schedule ID + * Set the Discount Details * - * @param string $scheduleId + * @param string $discountDetails * * @return AuthorizationBuilder */ @@ -1302,7 +1318,7 @@ public function withCardBrandStorage($transactionInitiator, $value = '') * Set lastRegisteredDate - DD/MM/YYYY * Used w/TransIT gateway * - * @param bool $isRegistered + * @param string $date * * @return AuthorizationBuilder */ @@ -1312,6 +1328,13 @@ public function withLastRegisteredDate($date) return $this; } + /** + * Set the Multi Capture. + * + * @param boolean $multiCapture + * + * @return $this + */ public function withMultiCapture($multiCapture = false) { $this->multiCapture = $multiCapture; @@ -1319,7 +1342,25 @@ public function withMultiCapture($multiCapture = false) } /** - * @param $value + * Set shippingDate - YYYY/MM/DD + * Used w/TransactionApi gateway + * + * @param string $date + * + * @return AuthorizationBuilder + */ + public function withShippingDate($date) + { + $this->shippingDate = $date; + return $this; + } + + /** + * Set the Tag Data + * + * @param string $value + * + * @return $this */ public function withTagData($value) { @@ -1328,6 +1369,13 @@ public function withTagData($value) return $this; } + /** + * Sets the Idempotency Key. + * + * @param string $value + * + * @return $this + */ public function withIdempotencyKey($value) { $this->idempotencyKey = $value; @@ -1362,6 +1410,19 @@ public function withChipCondition($value) return $this; } + /** + * Set the request clerkId + * + * @param string|integer $clerkId Request clerkId + * + * @return AuthorizationBuilder + */ + public function withClerkId($clerkId) + { + $this->clerkId = $clerkId; + return $this; + } + /** * @param float $value * @@ -1393,7 +1454,7 @@ public function withPaymentMethodUsageMode($value) * @param string $number * @param string $type * - * @return $this + * @return AuthorizationBuilder */ public function withPhoneNumber($phoneCountryCode, $number, $type) { @@ -1414,6 +1475,14 @@ public function withPhoneNumber($phoneCountryCode, $number, $type) return $this; } + /** + * Set Remittance Reference + * + * @param string $remittanceReferenceType + * @param string $remittanceReferenceValue + * + * @return AuthorizationBuilder + */ public function withRemittanceReference($remittanceReferenceType, $remittanceReferenceValue) { $this->remittanceReferenceType = $remittanceReferenceType; @@ -1436,4 +1505,18 @@ public function withBNPLShippingMethod($bnpShippingMethod) $this->bnplShippingMethod = $bnpShippingMethod; return $this; } + + /** + * Indicates whether some date will be masked in the response. + * Ex: Personally Identifiable Information (PII) etc. + * + * @param boolean $value + * @return $this + */ + public function withMaskedDataResponse($value) + { + $this->maskedDataResponse = $value; + + return $this; + } } diff --git a/src/Builders/ManagementBuilder.php b/src/Builders/ManagementBuilder.php index df3d60de..0ffe1434 100644 --- a/src/Builders/ManagementBuilder.php +++ b/src/Builders/ManagementBuilder.php @@ -2,23 +2,30 @@ namespace GlobalPayments\Api\Builders; -use GlobalPayments\Api\Entities\DccRateData; -use GlobalPayments\Api\Entities\Enums\CommercialIndicator; -use GlobalPayments\Api\Entities\Enums\PaymentMethodUsageMode; -use GlobalPayments\Api\Entities\Enums\TaxType; -use GlobalPayments\Api\Entities\Enums\TransactionModifier; -use GlobalPayments\Api\Entities\Enums\TransactionType; -use GlobalPayments\Api\Entities\LodgingData; -use GlobalPayments\Api\Entities\Transaction; -use GlobalPayments\Api\PaymentMethods\CreditCardData; -use GlobalPayments\Api\PaymentMethods\ECheck; -use GlobalPayments\Api\PaymentMethods\TransactionReference; -use GlobalPayments\Api\PaymentMethods\Interfaces\IPaymentMethod; -use GlobalPayments\Api\PaymentMethods\Interfaces\ITokenizable; +use GlobalPayments\Api\Entities\{ + DccRateData, + LodgingData, + Transaction +}; +use GlobalPayments\Api\Entities\Enums\{ + CommercialIndicator, + PaymentMethodUsageMode, + TaxType, + TransactionModifier, + TransactionType +}; +use GlobalPayments\Api\Entities\TransactionApi\TransactionApiData; +use GlobalPayments\Api\PaymentMethods\{ + CreditCardData, + ECheck, + TransactionReference +}; +use GlobalPayments\Api\PaymentMethods\Interfaces\{IPaymentMethod, ITokenizable}; use GlobalPayments\Api\ServicesContainer; /** * @property string $transactionId + * @property string $clientTransactionId */ class ManagementBuilder extends TransactionBuilder { @@ -47,13 +54,7 @@ class ManagementBuilder extends TransactionBuilder public $cardType; /** - * @internal - * @var string - */ - public $clientTransactionId; - - /** - * + * * @var CommercialData */ public $commercialData; @@ -96,6 +97,14 @@ class ManagementBuilder extends TransactionBuilder */ public $invoiceNumber; + /** + * Original Transaction Type + * + * @internal + * @var TransactionType + */ + public $originalTransactionType; + /** * Request purchase order number * @@ -133,7 +142,7 @@ class ManagementBuilder extends TransactionBuilder * @var IPaymentMethod */ public $paymentMethod; - + /** * Previous request's transaction reference * @@ -193,6 +202,9 @@ class ManagementBuilder extends TransactionBuilder /** @var string */ public $tagData; + /** @var TransactionApiData */ + public $transactionData; + /** @var PaymentMethodUsageMode */ public $paymentMethodUsageMode; @@ -235,6 +247,11 @@ public function __get($name) return $this->paymentMethod->authCode; } return null; + case 'clientTransactionId': + if ($this->paymentMethod instanceof TransactionReference) { + return $this->paymentMethod->clientTransactionId; + } + return null; } } @@ -244,6 +261,7 @@ public function __isset($name) 'transactionId', 'orderId', 'authorizationId', + 'clientTransactionId', ]) || isset($this->{$name}); } @@ -269,13 +287,17 @@ protected function setupValidations() { $this->validations->of( TransactionType::CAPTURE | - TransactionType::EDIT | - TransactionType::HOLD | - TransactionType::RELEASE | - TransactionType::REAUTH + TransactionType::EDIT | + TransactionType::HOLD | + TransactionType::RELEASE | + TransactionType::REAUTH ) ->check('transactionId')->isNotNull(); + $this->validations->of(TransactionType::EDIT) + ->with(TransactionModifier::ADDITIONAL) + ->check('clientTransactionId')->isNotNull(); + $this->validations->of(TransactionType::EDIT) ->with(TransactionModifier::LEVEL_II) ->check('taxType')->isNotNull(); @@ -344,7 +366,7 @@ public function withCommercialData($commercialData) if ($commercialData->commercialIndicator === CommercialIndicator::LEVEL_III) { $this->transactionModifier = TransactionModifier::LEVEL_III; } - + return $this; } @@ -434,6 +456,16 @@ public function withIssuerData(CardIssuerEntryTag $tag, String $value) return $this; } + /** + * @param TransactionType|int + * @return ManagementBuilder + */ + public function withOriginalTransactionType($value): ManagementBuilder + { + $this->originalTransactionType = $value; + return $this; + } + /** * Previous request's transaction reference * @@ -442,7 +474,7 @@ public function withIssuerData(CardIssuerEntryTag $tag, String $value) * * @return ManagementBuilder */ - public function withPaymentMethod(IPaymentMethod $paymentMethod) + public function withPaymentMethod(IPaymentMethod $paymentMethod): ManagementBuilder { $this->paymentMethod = $paymentMethod; return $this; @@ -455,7 +487,7 @@ public function withPaymentMethod(IPaymentMethod $paymentMethod) * * @return ManagementBuilder */ - public function withPoNumber($poNumber) + public function withPoNumber($poNumber): ManagementBuilder { $this->poNumber = $poNumber; return $this; @@ -468,7 +500,7 @@ public function withPoNumber($poNumber) * * @return ManagementBuilder */ - public function withReasonCode($value) + public function withReasonCode($value): ManagementBuilder { $this->reasonCode = $value; return $this; @@ -483,7 +515,7 @@ public function withReasonCode($value) * * @return ManagementBuilder */ - public function withTaxAmount($taxAmount) + public function withTaxAmount($taxAmount): ManagementBuilder { $this->taxAmount = $taxAmount; return $this; @@ -498,7 +530,7 @@ public function withTaxAmount($taxAmount) * * @return ManagementBuilder */ - public function withMultiCapture($sequence = 1, $paymentCount = 1) + public function withMultiCapture($sequence = 1, $paymentCount = 1): ManagementBuilder { $this->multiCapture = true; $this->multiCaptureSequence = $sequence; @@ -516,36 +548,71 @@ public function withMultiCapture($sequence = 1, $paymentCount = 1) * * @return ManagementBuilder */ - public function withTaxType($taxType) + public function withTaxType($taxType): ManagementBuilder { $this->taxType = $taxType; return $this; } - + + /** + * Sets the Alternative Payment Type. + * + * @param string $alternativePaymentType + * + * @return $this + */ public function withAlternativePaymentType($alternativePaymentType) { $this->alternativePaymentType = $alternativePaymentType; return $this; } + /** + * Sets the Payer Authentication Response. + * + * @param string $payerAuthenticationResponse + * + * @return $this + */ public function withPayerAuthenticationResponse($payerAuthenticationResponse) { $this->payerAuthenticationResponse = $payerAuthenticationResponse; return $this; } + /** + * Sets the Dispute Id. + * + * @param string $value + * + * @return $this + */ public function withDisputeId($value) { $this->disputeId = $value; return $this; } + /** + * Sets the Dispute Documents. + * + * @param string $value + * + * @return $this + */ public function withDisputeDocuments($value) { $this->disputeDocuments = $value; return $this; } + /** + * Sets the Idempotency Key. + * + * @param string $value + * + * @return $this + */ public function withIdempotencyKey($value) { $this->idempotencyKey = $value; @@ -553,6 +620,13 @@ public function withIdempotencyKey($value) return $this; } + /** + * Sets the Batch Reference. + * + * @param string $value + * + * @return $this + */ public function withBatchReference($value) { $this->batchReference = $value; @@ -587,12 +661,19 @@ public function withBankTransferData($eCheck) return $this; } + /** + * Set the Tag Data + * + * @param string $value + * + * @return $this + */ public function withTagData($value) { $this->tagData = $value; return $this; } - + /** * Set the request dccRateData * diff --git a/src/Builders/RequestBuilder/GpApi/GpApiAuthorizationRequestBuilder.php b/src/Builders/RequestBuilder/GpApi/GpApiAuthorizationRequestBuilder.php index 78dd28ca..751a52d3 100644 --- a/src/Builders/RequestBuilder/GpApi/GpApiAuthorizationRequestBuilder.php +++ b/src/Builders/RequestBuilder/GpApi/GpApiAuthorizationRequestBuilder.php @@ -9,6 +9,7 @@ use GlobalPayments\Api\Entities\Enums\CardType; use GlobalPayments\Api\Entities\Enums\Channel; use GlobalPayments\Api\Entities\Enums\DigitalWalletTokenFormat; +use GlobalPayments\Api\Entities\Enums\EncyptedMobileType; use GlobalPayments\Api\Entities\Enums\EntryMethod; use GlobalPayments\Api\Entities\Enums\GatewayProvider; use GlobalPayments\Api\Entities\Enums\ManualEntryMethod; @@ -191,6 +192,9 @@ private function createFromAuthorizationBuilder($builder, GpApiConfig $config) $requestBody['currency'] = $builder->currency; $requestBody['reference'] = !empty($builder->clientTransactionId) ? $builder->clientTransactionId : GenerationUtils::getGuid(); + if ($builder->paymentMethod->mobileType == EncyptedMobileType::CLICK_TO_PAY) { + $requestBody['masked'] = $builder->maskedDataResponse === true ? 'YES' : 'NO'; + } $requestBody['description'] = $builder->description; $requestBody['order'] = ['reference' => $builder->orderId]; $requestBody['gratuity_amount'] = StringUtils::toNumeric($builder->gratuity); @@ -255,15 +259,15 @@ private function setPayerInformation($builder) case AlternativePaymentMethod::class: $payer['home_phone'] = [ 'country_code' => !empty($builder->homePhone) ? - StringUtils::validateToNumber($builder->homePhone->countryCode): null, + StringUtils::validateToNumber($builder->homePhone->countryCode) : null, 'subscriber_number' => !empty($builder->homePhone) ? - StringUtils::validateToNumber($builder->homePhone->number): null + StringUtils::validateToNumber($builder->homePhone->number) : null ]; $payer['work_phone'] = [ 'country_code' => !empty($builder->workPhone) ? - StringUtils::validateToNumber($builder->workPhone->countryCode): null, + StringUtils::validateToNumber($builder->workPhone->countryCode) : null, 'subscriber_number' => !empty($builder->workPhone) ? - StringUtils::validateToNumber($builder->workPhone->number): null, + StringUtils::validateToNumber($builder->workPhone->number) : null, ]; break; case ECheck::class: @@ -305,9 +309,9 @@ private function setPayerInformation($builder) if (isset($builder->customerData->phone)) { $payer['contact_phone'] = [ 'country_code' => !empty($builder->customerData->phone->countryCode) ? - StringUtils::validateToNumber($builder->customerData->phone->countryCode): null, + StringUtils::validateToNumber($builder->customerData->phone->countryCode) : null, 'subscriber_number' => !empty($builder->customerData->phone->number) ? - StringUtils::validateToNumber($builder->customerData->phone->number): null, + StringUtils::validateToNumber($builder->customerData->phone->number) : null, ]; } if (!empty($builder->customerData->documents)) { @@ -380,7 +384,7 @@ private function createPaymentMethodParam($builder, $config) $builder->customerData->deviceFingerPrint : null); $secureEcom = $paymentMethodContainer->threeDSecure; if (!empty($secureEcom)) { - $paymentMethod->authentication = + $paymentMethod->authentication = [ 'id' => $secureEcom->serverTransactionId, 'three_ds' => [ @@ -404,15 +408,15 @@ private function createPaymentMethodParam($builder, $config) 'code' => $paymentMethodContainer->routingNumber, 'name' => $paymentMethodContainer->bankName, 'address' => - [ - 'line_1' => $paymentMethodContainer->bankAddress->streetAddress1, - 'line_2' => $paymentMethodContainer->bankAddress->streetAddress2, - 'line_3' => $paymentMethodContainer->bankAddress->streetAddress3, - 'city' => $paymentMethodContainer->bankAddress->city, - 'postal_code' => $paymentMethodContainer->bankAddress->postalCode, - 'state' => $paymentMethodContainer->bankAddress->state, - 'country' => $paymentMethodContainer->bankAddress->countryCode - ] + [ + 'line_1' => $paymentMethodContainer->bankAddress->streetAddress1, + 'line_2' => $paymentMethodContainer->bankAddress->streetAddress2, + 'line_3' => $paymentMethodContainer->bankAddress->streetAddress3, + 'city' => $paymentMethodContainer->bankAddress->city, + 'postal_code' => $paymentMethodContainer->bankAddress->postalCode, + 'state' => $paymentMethodContainer->bankAddress->state, + 'country' => $paymentMethodContainer->bankAddress->countryCode + ] ] ]; @@ -474,8 +478,16 @@ private function createPaymentMethodParam($builder, $config) /* digital wallet */ switch ($builder->transactionModifier) { case TransactionModifier::ENCRYPTED_MOBILE: - $digitalWallet['payment_token'] = !empty($paymentMethodContainer->token) ? - json_decode(preg_replace('/(\\\)(\w)/', '${1}${1}${2}', $paymentMethodContainer->token)) : null; + $paymentToken = null; + switch ($paymentMethodContainer->mobileType){ + case EncyptedMobileType::CLICK_TO_PAY: + $paymentToken = ['data' => $paymentMethodContainer->token]; + break; + default: + $paymentToken = !empty($paymentMethodContainer->token) ? + json_decode(preg_replace('/(\\\)(\w)/', '${1}${1}${2}', $paymentMethodContainer->token)) : null; + } + $digitalWallet['payment_token'] = $paymentToken; break; case TransactionModifier::DECRYPTED_MOBILE: $digitalWallet['token'] = !empty($paymentMethodContainer->token) ? @@ -521,8 +533,7 @@ private function getEciCode($paymentMethod) return $paymentMethod->eci; } $eciCode = null; - switch (CardUtils::getBaseCardType($paymentMethod->getCardType())) - { + switch (CardUtils::getBaseCardType($paymentMethod->getCardType())) { case CardType::VISA: case CardType::AMEX: $eciCode = '05'; @@ -571,7 +582,7 @@ private function getEntryMode(AuthorizationBuilder $builder, $channel) if ($builder->paymentMethod->readerPresent === true) { return PaymentEntryMode::ECOM; } - if( + if ( $builder->paymentMethod->readerPresent === false && !is_null($builder->paymentMethod->entryMethod) ) { @@ -738,7 +749,7 @@ public function mapFraudManagement() if (!empty($this->builder->fraudRules)) { foreach ($this->builder->fraudRules as $fraudRule) { $rules[] = [ - 'reference'=> $fraudRule->key, + 'reference' => $fraudRule->key, 'mode' => $fraudRule->mode ]; } @@ -749,4 +760,4 @@ public function mapFraudManagement() 'rules' => $rules ?? null ]; } -} \ No newline at end of file +} diff --git a/src/Builders/RequestBuilder/RequestBuilderFactory.php b/src/Builders/RequestBuilder/RequestBuilderFactory.php index 5b384a94..d132cf86 100644 --- a/src/Builders/RequestBuilder/RequestBuilderFactory.php +++ b/src/Builders/RequestBuilder/RequestBuilderFactory.php @@ -3,15 +3,23 @@ namespace GlobalPayments\Api\Builders\RequestBuilder; use GlobalPayments\Api\Builders\BaseBuilder; -use GlobalPayments\Api\Builders\RequestBuilder\GpApi\GpApiAuthorizationRequestBuilder; -use GlobalPayments\Api\Builders\RequestBuilder\GpApi\GpApiManagementRequestBuilder; -use GlobalPayments\Api\Builders\RequestBuilder\GpApi\GpApiPayFacRequestBuilder; -use GlobalPayments\Api\Builders\RequestBuilder\GpApi\GpApiReportRequestBuilder; -use GlobalPayments\Api\Builders\RequestBuilder\GpApi\GpApiSecure3DRequestBuilder; -use GlobalPayments\Api\Builders\RequestBuilder\GpEcom\GpEcomAuthorizationRequestBuilder; -use GlobalPayments\Api\Builders\RequestBuilder\GpEcom\GpEcomManagementRequestBuilder; -use GlobalPayments\Api\Builders\RequestBuilder\GpEcom\GpEcomRecurringRequestBuilder; -use GlobalPayments\Api\Builders\RequestBuilder\GpEcom\GpEcomReportRequestBuilder; +use GlobalPayments\Api\Builders\RequestBuilder\GpApi\{ + GpApiAuthorizationRequestBuilder, + GpApiManagementRequestBuilder, + GpApiPayFacRequestBuilder, + GpApiReportRequestBuilder, + GpApiSecure3DRequestBuilder}; +use GlobalPayments\Api\Builders\RequestBuilder\GpEcom\{ + GpEcomAuthorizationRequestBuilder, + GpEcomManagementRequestBuilder, + GpEcomRecurringRequestBuilder, + GpEcomReportRequestBuilder +}; +use GlobalPayments\Api\Builders\RequestBuilder\TransactionApi\{ + TransactionApiReportRequestBuilder, + TransactionApiManagementRequestBuilder, + TransactionApiAuthorizationRequestBuilder +}; use GlobalPayments\Api\Entities\Enums\GatewayProvider; class RequestBuilderFactory @@ -29,6 +37,11 @@ class RequestBuilderFactory GpApiReportRequestBuilder::class, GpApiSecure3DRequestBuilder::class, GpApiPayFacRequestBuilder::class + ], + GatewayProvider::TRANSACTION_API => [ + TransactionApiReportRequestBuilder::class, + TransactionApiManagementRequestBuilder::class, + TransactionApiAuthorizationRequestBuilder::class ] ]; @@ -45,4 +58,4 @@ public function getRequestBuilder(BaseBuilder $builder, $gatewayProvider) return null; } -} \ No newline at end of file +} diff --git a/src/Builders/RequestBuilder/TransactionApi/TransactionApiAuthorizationRequestBuilder.php b/src/Builders/RequestBuilder/TransactionApi/TransactionApiAuthorizationRequestBuilder.php new file mode 100644 index 00000000..2609af24 --- /dev/null +++ b/src/Builders/RequestBuilder/TransactionApi/TransactionApiAuthorizationRequestBuilder.php @@ -0,0 +1,392 @@ +transactionType) { + case TransactionType::SALE: + $verb = 'POST'; + if (isset($builder->paymentMethod) && $builder->paymentMethod->paymentMethodType == PaymentMethodType::ACH) { + $endpoint = TransactionApiRequest::CHECKSALES; + } else { + $endpoint = TransactionApiRequest::CREDITSALE; + } + + $requestData = $this->createFromAuthorizationBuilder($builder, $config); + break; + case TransactionType::AUTH: + $endpoint = TransactionApiRequest::CREDITAUTH; + $verb = 'POST'; + $requestData = $this->createFromAuthorizationBuilder($builder, $config); + break; + case TransactionType::VERIFY: + $endpoint = TransactionApiRequest::CREDITAUTH; + $verb = 'POST'; + $requestData = $this->createFromAuthorizationBuilder($builder, $config); + break; + case TransactionType::REFUND: + if (isset($builder->paymentMethod) && $builder->paymentMethod->paymentMethodType == PaymentMethodType::ACH) { + $endpoint = TransactionApiRequest::CHECKREFUND; + } + if (isset($builder->paymentMethod) && $builder->paymentMethod->paymentMethodType == PaymentMethodType::CREDIT) { + $endpoint = TransactionApiRequest::CREDITREFUND; + } + $verb = 'POST'; + $requestData = $this->createFromAuthorizationBuilder($builder, $config, $additionalSlug); + break; + default: + return ''; + } + return new TransactionApiRequest($endpoint, $verb, $requestData); + } + + /** + * @param BaseBuilder $builder + * @param TransactionApiConfig $config + * @param String $additionalSlug + * + * @return array + */ + private function createFromAuthorizationBuilder(BaseBuilder $builder, TransactionApiConfig $config = null, String $additionalSlug = "") + { + $requestBody = []; + if (empty($additionalSlug)) { + $requestBody['reference_id'] = 'REF' . str_shuffle('abcdefg123212'); + } + + if (isset($builder->paymentMethod)) { + if (isset($builder->paymentMethod) && $builder->paymentMethod->paymentMethodType == PaymentMethodType::ACH) { + if ($config->country == Region::CA) { + if (!empty($builder->paymentMethod->token)) { + $requestBody["check"] = [ + "account_type" => $builder->paymentMethod->accountType, + "token" => $builder->paymentMethod->token, + ]; + } else { + $requestBody["check"] = [ + "account_type" => $builder->paymentMethod->accountType, + "account_number" => $builder->paymentMethod->accountNumber, + "branch_transit_number" => $builder->paymentMethod->branchTransitNumber, + "financial_institution_number" => $builder->paymentMethod->financialInstitutionNumber, + "check_number" => $builder->paymentMethod->checkNumber, + ]; + } + } else if ($config->country == Region::US) { + if (!empty($builder->paymentMethod->token)) { + $requestBody["check"] = [ + "account_type" => $builder->paymentMethod->accountType, + "token" => $builder->paymentMethod->token, + ]; + } else { + $requestBody["check"] = [ + "account_type" => $builder->paymentMethod->accountType, + "account_number" => $builder->paymentMethod->accountNumber, + "routing_number" => $builder->paymentMethod->routingNumber, + "check_number" => $builder->paymentMethod->checkNumber, + ]; + } + } + } else if (empty($additionalSlug)) { + if (!empty($builder->paymentMethod->token)) { + if ($builder->paymentMethodUsageMode === PaymentMethodUsageMode::SINGLE) { + $requestBody["card"] = [ + "temporary_token" => $builder->paymentMethod->token + ]; + } else { + $requestBody["card"] = [ + "token" => $builder->paymentMethod->token, + "card_security_code" => !empty($builder->paymentMethod->cvn) ? $builder->paymentMethod->cvn : "", + "cardholder_name" => !empty($builder->paymentMethod->cardHolderName) ? $builder->paymentMethod->cardHolderName : "", + ]; + } + } else { + $requestBody["card"] = [ + "card_number" => !empty($builder->paymentMethod->number) ? $builder->paymentMethod->number : "", + "card_security_code" => !empty($builder->paymentMethod->cvn) ? $builder->paymentMethod->cvn : "", + "cardholder_name" => !empty($builder->paymentMethod->cardHolderName) ? $builder->paymentMethod->cardHolderName : "", + "expiry_month" => !empty($builder->paymentMethod->expMonth) ? $builder->paymentMethod->expMonth : "", + "expiry_year" => !empty($builder->paymentMethod->expYear) ? $builder->paymentMethod->expYear : "", + ]; + } + } + } + + if (isset($builder->billingAddress)) { + $billingAddress = [ + 'line1' => $builder->billingAddress->streetAddress1, + 'line2' => !empty($builder->billingAddress->streetAddress2) ? $builder->billingAddress->streetAddress2 : "test", + 'city' => isset($builder->billingAddress->city) ? $builder->billingAddress->city : "", + 'postal_code' => isset($builder->billingAddress->postalCode) ? $builder->billingAddress->postalCode : "", + 'state' => isset($builder->billingAddress->state) ? $builder->billingAddress->state : "", + 'country' => isset($builder->billingAddress->countryCode) ? $builder->billingAddress->countryCode : "" + ]; + } + + if (isset($builder->shippingAddress)) { + $shippingAddress = [ + 'line1' => isset($builder->shippingAddress->streetAddress1) ? $builder->shippingAddress->streetAddress1 : "", + 'line2' => !empty($builder->shippingAddress->streetAddress2) ? $builder->shippingAddress->streetAddress2 : "", + 'city' => isset($builder->shippingAddress->city) ? $builder->shippingAddress->city : "", + 'postal_code' => isset($builder->shippingAddress->postalCode) ? $builder->shippingAddress->postalCode : "", + 'state' => isset($builder->shippingAddress->state) ? $builder->shippingAddress->state : "", + 'country' => isset($builder->shippingAddress->countryCode) ? $builder->shippingAddress->countryCode : "" + ]; + } + + list($phoneNumber, $phoneCountryCode) = $this->getPhoneNumber($builder, PhoneNumberType::MOBILE); + + $requestBody["customer"] = [ + "id" => isset($builder->customerData->id) ? $builder->customerData->id : "", + "title" => isset($builder->customerData->title) ? $builder->customerData->title : "", + "first_name" => isset($builder->customerData->firstName) ? $builder->customerData->firstName : "", + "middle_name" => isset($builder->customerData->middleName) ? $builder->customerData->middleName : "", + "last_name" => isset($builder->customerData->lastName) ? $builder->customerData->lastName : "", + // "business_name" => $builder->customerData->businessName, + "email" => isset($builder->customerData->email) ? $builder->customerData->email : "", + "phone" => $phoneCountryCode . $phoneNumber, + "billing_address" => isset($billingAddress) ? $billingAddress : "" + ]; + + $requestBody["payment"] = [ + "amount" => isset($builder->amount) ? (string)AmountUtils::transitFormat($builder->amount) : "0.00", + "invoice_number" => isset($builder->invoiceNumber) ? $builder->invoiceNumber : "" + ]; + + if (empty($additionalSlug)) { + $requestBody["payment"]["currency_code"] = isset($builder->currency) ? + CountryUtils::getNumericCodeByCountry($builder->currency) : ""; + } + + if (isset($builder->shippingDate)) { + $requestBody["shipping"] = [ + "date" => isset($builder->shippingDate) ? $builder->shippingDate : "", + "address" => isset($shippingAddress) ? $shippingAddress : "" + ]; + } + + $requestBody["transaction"] = $this->buildTransactionData($builder, $config, $additionalSlug); + + if ( + $builder->transactionType == TransactionType::AUTH + && !empty($builder->clerkId) + ) { + $requestBody["receipt"] = [ + "clerk_id" => $builder->clerkId + ]; + } + + return $requestBody; + } + + /** + * @param BaseBuilder $builder + * @param TransactionApiConfig $config + * @param String $additionalSlug + * + * @return array + */ + private function buildTransactionData(BaseBuilder $builder, TransactionApiConfig $config, String $additionalSlug) + { + if ($builder->paymentMethod->paymentMethodType == PaymentMethodType::ACH) { + return $this->buildAchTransactionData($builder, $config, $additionalSlug); + } + + if ($builder->paymentMethod->paymentMethodType == PaymentMethodType::CREDIT) { + return $this->buildCreditCardTransactionData($builder, $config, $additionalSlug); + } + + return []; + } + + /** + * @param BaseBuilder $builder + * @param TransactionApiConfig $config + * @param String $additionalSlug + * + * @return array + */ + private function buildAchTransactionData(BaseBuilder $builder, TransactionApiConfig $config, String $additionalSlug) + { + if (isset($builder->transactionData)) { + + $transactionData = $builder->transactionData; + if (empty($additionalSlug)) { + $transactionObjectCountry = [ + "country_code" => !empty($config->country) ? CountryUtils::getNumericCodeByCountry($config->country) : "" + ]; + } + + $transactionObject = [ + "ecommerce_indicator" => isset($transactionData->ecommerceIndicator) ? $transactionData->ecommerceIndicator : "", + "language" => isset($transactionData->language) ? $transactionData->language : "", + "soft_descriptor" => isset($transactionData->softDescriptor) ? $transactionData->softDescriptor : "" + ]; + + if (!empty($transactionObjectCountry)) { + $transactionObject = array_merge($transactionObjectCountry, $transactionObject); + } + + if (isset($builder->paymentMethod) && $builder->paymentMethod->paymentMethodType == PaymentMethodType::ACH) { + if ($config->country == Region::CA) { + $transactionObject["payment_purpose_code"] = isset($builder->paymentPurposeCode) + ? $builder->paymentPurposeCode : ""; + } else if ($config->country == Region::US) { + $transactionObject["entry_class"] = isset($builder->entryClass) + ? $builder->entryClass : ""; + } else { + $transactionObject["processing_indicators"] = [ + "address_verification_service" => isset($transactionData->addressVerificationService) + ? $transactionData->addressVerificationService : false, + "create_token" => isset($builder->requestMultiUseToken) + ? $builder->requestMultiUseToken : false, + "generate_receipt" => isset($builder->transactionData) + ? $builder->transactionData->generateReceipt : null, + "partial_approval" => isset($builder->allowPartialAuth) + ? $builder->allowPartialAuth : false + + ]; + } + + if (isset($builder->requestMultiUseToken)) { + $transactionObject["processing_indicators"] = [ + "create_token" => isset($builder->requestMultiUseToken) + ? $builder->requestMultiUseToken : false, + ]; + } + } + } + + return $transactionObject; + } + + /** + * @param BaseBuilder $builder + * @param TransactionApiConfig $config + * @param String $additionalSlug + * + * @return array + */ + private function buildCreditCardTransactionData(BaseBuilder $builder, TransactionApiConfig $config, String $additionalSlug) + { + $transactionData = []; + if (isset($builder->transactionData)) { + $transactionData = $builder->transactionData; + } + + if (empty($additionalSlug)) { + $transactionObjectCountry = [ + "country_code" => !empty($config->country) ? CountryUtils::getNumericCodeByCountry($config->country) : "" + ]; + } + + $transactionObject = [ + "ecommerce_indicator" => null, + "language" => isset($transactionData->language) ? $transactionData->language : "", + "soft_descriptor" => isset($transactionData->softDescriptor) ? $transactionData->softDescriptor : "" + ]; + + if (!empty($transactionObjectCountry)) { + $transactionObject = array_merge($transactionObjectCountry, $transactionObject); + } + + if ( + $builder->transactionType == TransactionType::AUTH + || $builder->transactionType == TransactionType::VERIFY + ) { + $transactionObject["processing_indicators"] = [ + "address_verification_service" => isset($transactionData->addressVerificationService) + ? $transactionData->addressVerificationService : false, + "create_token" => isset($builder->requestMultiUseToken) + ? $builder->requestMultiUseToken : false, + "partial_approval" => isset($builder->allowPartialAuth) + ? $builder->allowPartialAuth : false + ]; + } else if ($builder->transactionType == TransactionType::SALE) { + $transactionObject["processing_indicators"] = [ + "partial_approval" => isset($builder->allowPartialAuth) + ? $builder->allowPartialAuth : false, + "create_token" => isset($builder->requestMultiUseToken) + ? $builder->requestMultiUseToken : false + ]; + } + + if (isset($builder->allowDuplicates) && $builder->allowDuplicates == TRUE) { + $transactionObject["processing_indicators"]["allow_duplicate"] = true; + } + + if ( + isset($builder->transactionData) + && isset($builder->transactionData->generateReceipt) + && $builder->transactionData->generateReceipt == TRUE + ) { + $transactionObject["processing_indicators"]["generate_receipt"] = true; + } + + return $transactionObject; + } + + /** + * You can have the phone number set on customerData or directly to the builder + * + * @param AuthorizationBuilder $builder + * @param string $type + * + * @return array + */ + private function getPhoneNumber(AuthorizationBuilder $builder, String $type) + { + $phoneKey = strtolower($type) . 'Phone'; + $phoneCountryCode = $phoneNumber = ''; + if ( + isset($builder->customerData) && + isset($builder->customerData->{$phoneKey}) && + $builder->customerData->{$phoneKey} instanceof PhoneNumber + ) { + $phoneCountryCode = $builder->customerData->{$phoneKey}->countryCode; + $phoneNumber = $builder->customerData->{$phoneKey}->number; + } + if (empty($phoneNumber) && isset($builder->{$phoneKey}) && $builder->{$phoneKey} instanceof PhoneNumber) { + $phoneCountryCode = $builder->{$phoneKey}->countryCode; + $phoneNumber = $builder->{$phoneKey}->number; + } + + return [StringUtils::validateToNumber($phoneNumber), StringUtils::validateToNumber($phoneCountryCode)]; + } +} diff --git a/src/Builders/RequestBuilder/TransactionApi/TransactionApiManagementRequestBuilder.php b/src/Builders/RequestBuilder/TransactionApi/TransactionApiManagementRequestBuilder.php new file mode 100644 index 00000000..e1166c06 --- /dev/null +++ b/src/Builders/RequestBuilder/TransactionApi/TransactionApiManagementRequestBuilder.php @@ -0,0 +1,154 @@ +transactionType) { + case TransactionType::REFUND: + if (isset($builder->paymentMethod) && $builder->paymentMethod->paymentMethodType == PaymentMethodType::ACH) { + $verb = 'POST'; + $payload["check"] = [ + "account_type" => isset($builder->bankTransferDetails->accountType) ? $builder->bankTransferDetails->accountType : "0.00", + "check_number" => isset($builder->bankTransferDetails->checkNumber) ? $builder->bankTransferDetails->checkNumber : null + ]; + $payload["payment"] = [ + "amount" => isset($builder->amount) ? (string)AmountUtils::transitFormat($builder->amount) : "0.00", + ]; + if ($config->country == Region::CA) { + $payload["transaction"] = [ + "payment_purpose_code" => isset($builder->paymentPurposeCode) ? $builder->paymentPurposeCode : null, + ]; + } else if ($config->country == Region::US) { + $payload["transaction"] = [ + "entry_class" => isset($builder->entryClass) ? $builder->entryClass : null, + ]; + } + + if (isset($builder->paymentMethod->transactionId)) { + $endpoint = TransactionApiRequest::CHECKSALES . '/' . + $builder->paymentMethod->transactionId . '/' . TransactionApiRequest::CHECKREFUND; + } else if (isset($builder->paymentMethod->clientTransactionId)) { + $endpoint = TransactionApiRequest::CHECKSALESREF . '/' + . $builder->paymentMethod->clientTransactionId . '/' . TransactionApiRequest::CHECKREFUND; + } else { + throw new ApiException("Previous transaction ID must be supplied"); + } + } + if (isset($builder->paymentMethod) && $builder->paymentMethod->paymentMethodType == PaymentMethodType::CREDIT) { + $verb = 'POST'; + if (isset($builder->paymentMethod->clientTransactionId)) { + $endpoint = TransactionApiRequest::CREDITSALEREF . '/' + . $builder->paymentMethod->clientTransactionId . '/' + . TransactionApiRequest::CREDITREFUND; + } else if (isset($builder->paymentMethod->transactionId)) { + $endpoint = TransactionApiRequest::CREDITSALE . '/' + . $builder->paymentMethod->transactionId . '/' + . TransactionApiRequest::CREDITREFUND; + } else { + throw new ApiException("Previous transaction ID must be supplied"); + } + $payload = [ + 'payment' => [ + 'amount' => isset($builder->amount) ? (string)AmountUtils::transitFormat($builder->amount) : "0.00", + "invoice_number" => isset($builder->invoiceNumber) ? $builder->invoiceNumber : null + ], + 'transaction' => [ + "generate_receipt" => isset($builder->transactionData->generateReceipt) + ? $builder->transactionData->generateReceipt : null, + "allow_duplicate" => isset($builder->allowDuplicates) ? $builder->allowDuplicates : null + ] + ]; + } + break; + case TransactionType::EDIT: + $verb = 'GET'; + if ($builder->transactionData) { + $verb = 'PATCH'; + $payload["payment"] = [ + "amount" => isset($builder->amount) ? (string)AmountUtils::transitFormat($builder->amount) : "0.00", + "gratuity_amount" => isset($builder->gratuity) ? $builder->gratuity : null, + "invoice_number" => isset($builder->invoiceNumber) ? $builder->invoiceNumber : null + ]; + $payload["transaction"]["processing_indicators"] = [ + "generate_receipt" => isset($builder->transactionData->generateReceipt) + ? $builder->transactionData->generateReceipt : null, + "allow_duplicate" => isset($builder->allowDuplicates) ? $builder->allowDuplicates : null + ]; + } + + if (isset($builder->paymentMethod) && isset($builder->paymentMethod->transactionId)) { + $endpoint = TransactionApiRequest::CREDITSALE . '/' . $builder->paymentMethod->transactionId; + } else if (isset($builder->paymentMethod) && isset($builder->paymentMethod->clientTransactionId)) { + $endpoint = TransactionApiRequest::CREDITSALEREF . '/' . $builder->paymentMethod->clientTransactionId; + } else { + throw new ApiException("Previous transaction ID must be supplied"); + } + + break; + case TransactionType::VOID: + $verb = 'PUT'; + $payload["payment"]["amount"] = isset($builder->amount) ? (string)AmountUtils::transitFormat($builder->amount) : "0.00"; + $payload["transaction"]["processing_indicators"]["generate_receipt"] = null; + if (isset($builder->originalTransactionType) && $builder->originalTransactionType === TransactionType::SALE) { + if (isset($builder->paymentMethod->transactionId)) { + $endpoint = TransactionApiRequest::CREDITSALE . '/' . $builder->paymentMethod->transactionId . "/" . TransactionApiRequest::CREDITSALEVOID; + } else if (isset($builder->paymentMethod->clientTransactionId)) { + $endpoint = TransactionApiRequest::CREDITSALEREF . '/' . $builder->paymentMethod->clientTransactionId . "/" . TransactionApiRequest::CREDITSALEVOID; + } else { + throw new ApiException("Previous transaction ID must be supplied"); + } + } else if (isset($builder->originalTransactionType) && $builder->originalTransactionType === TransactionType::REFUND) { + if (isset($builder->paymentMethod->transactionId)) { + $endpoint = TransactionApiRequest::CREDITREFUND . '/' . $builder->paymentMethod->transactionId . "/" . TransactionApiRequest::CREDITSALEVOID; + } else if (isset($builder->paymentMethod->clientTransactionId)) { + $endpoint = TransactionApiRequest::CREDITREFUNDREF . '/' . $builder->paymentMethod->clientTransactionId . "/" . TransactionApiRequest::CREDITSALEVOID; + } else { + throw new ApiException("Previous transaction ID must be supplied"); + } + } else { + throw new ApiException("Must be either a sale or refund transaction type"); + } + + break; + default: + return null; + } + + return new TransactionApiRequest($endpoint, $verb, $payload); + } +} diff --git a/src/Builders/RequestBuilder/TransactionApi/TransactionApiReportRequestBuilder.php b/src/Builders/RequestBuilder/TransactionApi/TransactionApiReportRequestBuilder.php new file mode 100644 index 00000000..00742e01 --- /dev/null +++ b/src/Builders/RequestBuilder/TransactionApi/TransactionApiReportRequestBuilder.php @@ -0,0 +1,74 @@ +reportType) { + case ReportType::TRANSACTION_DETAIL || ReportType::FIND_TRANSACTIONS: + if (is_object($builder->transactionId)) { + $transData = $builder->transactionId; + if ($transData->paymentMethodType == PaymentMethodType::CREDIT) { + if (isset($transData->transactionReference->transactionId)) { + $endpoint = TransactionApiRequest::CREDITREFUND . '/' . $transData->transactionReference->transactionId; + } + if (isset($transData->transactionReference->clientTransactionId)) { + $endpoint = TransactionApiRequest::CREDITREFUNDREF . '/' . $transData->transactionReference->clientTransactionId; + } + } + if ($transData->paymentMethodType == PaymentMethodType::ACH) { + if ($transData->originalTransactionType == "REFUND") { + if (isset($transData->transactionReference->transactionId)) { + $endpoint = TransactionApiRequest::CHECKREFUND . '/' . $transData->transactionReference->transactionId; + } + if (isset($transData->transactionReference->clientTransactionId)) { + $endpoint = TransactionApiRequest::CHECKREFUNDREF . '/' . $transData->transactionReference->clientTransactionId; + } + } else { + if (isset($transData->transactionReference->transactionId)) { + $endpoint = TransactionApiRequest::CHECKSALES . '/' . $transData->transactionReference->transactionId; + } + if (isset($transData->transactionReference->clientTransactionId)) { + $endpoint = TransactionApiRequest::CHECKSALESREF . '/' . $transData->transactionReference->clientTransactionId; + } + } + } + } else { + if (isset($builder->transactionId)) { + $endpoint = TransactionApiRequest::CREDITSALE . '/' . $builder->transactionId; + } + if (isset($builder->searchBuilder->clientTransactionId)) { + $endpoint = TransactionApiRequest::CREDITSALEREF . '/' . $builder->searchBuilder->clientTransactionId; + } + } + + $verb = 'GET'; + break; + default: + return null; + } + return new TransactionApiRequest($endpoint, $verb, $payload, $queryParams); + } +} diff --git a/src/Builders/TransactionBuilder.php b/src/Builders/TransactionBuilder.php index ad031db6..6c2bea18 100644 --- a/src/Builders/TransactionBuilder.php +++ b/src/Builders/TransactionBuilder.php @@ -85,6 +85,21 @@ abstract class TransactionBuilder extends BaseBuilder */ public $paymentLinkId; + /** + * @var string $transactionData + */ + public $transactionData; + + /** + * @var string $entryClass + */ + public $entryClass; + + /** + * @var string $paymentPurposeCode + */ + public $paymentPurposeCode; + /** * Instantiates a new builder * @@ -178,4 +193,45 @@ public function withPaymentLinkId($paymentLinkId) $this->paymentLinkId = $paymentLinkId; return $this; } + + /** + * Set the request transactionData + * + * @param array $data Request transactionData + * + * @return $this + */ + public function withTransactionData($data) + { + $this->transactionData = $data; + return $this; + } + + /** + * Three digit code used by a payment originator to identify a Canada check payment. + * + * @param string $paymentPurposeCode + * + * @return $this + */ + public function withPaymentPurposeCode(string $paymentPurposeCode) + { + $this->paymentPurposeCode = $paymentPurposeCode; + + return $this; + } + + /** + * Standard entry class to designate how the transaction was authorized by the originator for check refunds. + * + * @param string $entryClass + * + * @return $this + */ + public function withEntryClass(string $entryClass) + { + $this->entryClass = $entryClass; + + return $this; + } } diff --git a/src/Builders/TransactionReportBuilder.php b/src/Builders/TransactionReportBuilder.php index 3e1d566d..9717f4f8 100644 --- a/src/Builders/TransactionReportBuilder.php +++ b/src/Builders/TransactionReportBuilder.php @@ -34,12 +34,24 @@ class TransactionReportBuilder extends ReportBuilder */ public $startDate; + /** + * @internal + * @var string + */ + public $clientTransactionId; + /** * @internal * @var string */ public $transactionId; + /** + * @internal + * @var string + */ + public $paymentType; + /** * @var TransactionSortProperty */ @@ -107,6 +119,19 @@ public function __construct($activity) $this->searchBuilder = new SearchCriteriaBuilder($this); } + /** + * Sets the client transaction ID as criteria for the report. + * + * @param string $value The client transaction ID + * + * @return TransactionReportBuilder + */ + public function withClientTransactionId($value) + { + $this->clientTransactionId = $value; + return $this; + } + /** * Sets the gateway deposit id as criteria for the report. * @param $depositId @@ -157,15 +182,15 @@ public function withEndDate($value) } /** - * Sets the start date as criteria for the report. + * Sets the payment type. * - * @param \DateTime $value The start date + * @param string $value The payemtn type * * @return TransactionReportBuilder */ - public function withStartDate($value) + public function withPaymentType($value) { - $this->searchBuilder->startDate = $value; + $this->paymentType = $value; return $this; } @@ -264,7 +289,7 @@ public function orderBy($sortProperty, $sortDirection = SortDirection::DESC) case ReportType::FIND_DEPOSITS_PAGED: $this->depositOrderBy = $sortProperty; $this->order = $sortDirection; - break; + break; case ReportType::FIND_DISPUTES: case ReportType::FIND_DISPUTES_PAGED: case ReportType::FIND_SETTLEMENT_DISPUTES: diff --git a/src/Entities/Customer.php b/src/Entities/Customer.php index 7c7b6bdb..3a16fce7 100644 --- a/src/Entities/Customer.php +++ b/src/Entities/Customer.php @@ -40,6 +40,13 @@ class Customer extends RecurringEntity */ public $company; + /** + * Business Name + * + * @var string + */ + public $businessName; + /** * Customer's password * diff --git a/src/Entities/Enums/EcommerceIndicator.php b/src/Entities/Enums/EcommerceIndicator.php new file mode 100644 index 00000000..848455fe --- /dev/null +++ b/src/Entities/Enums/EcommerceIndicator.php @@ -0,0 +1,18 @@ + self::FUNDED, self::REJECTED => self::REJECTED, ]; -} \ No newline at end of file +} diff --git a/src/Entities/Enums/TransactionType.php b/src/Entities/Enums/TransactionType.php index ed7422cd..75492b3b 100644 --- a/src/Entities/Enums/TransactionType.php +++ b/src/Entities/Enums/TransactionType.php @@ -47,16 +47,16 @@ class TransactionType extends Enum const UPLOAD_DOCUMENT = 549755813888; // 1 << 39; const OBTAIN_SSO_KEY = 1099511627776; // 1 << 40; const UPDATE_BANK_ACCOUNT_OWNERSHIP = 2199023255552; // 1 << 41; - const ADD_FUNDS = 4398046511104;//1 << 42; - const SWEEP_FUNDS = 8796093022208;//1 << 43; - const ADD_CARD_FLASH_FUNDS = 17592186044416;//1 << 44; - const PUSH_MONEY_FLASH_FUNDS = 35184372088832;//1 << 45; - const DISBURSE_FUNDS = 70368744177664;//1 << 46; - const SPEND_BACK = 140737488355328;//1 << 47; - const REVERSE_SPLITPAY = 281474976710656;//1 << 48; - const SPLIT_FUNDS = 562949953421312;//1 << 49; - const GET_ACCOUNT_DETAILS = 1125899906842624;//1 << 50; - const GET_ACCOUNT_BALANCE = 2251799813685248;//1 << 51; + const ADD_FUNDS = 4398046511104; //1 << 42; + const SWEEP_FUNDS = 8796093022208; //1 << 43; + const ADD_CARD_FLASH_FUNDS = 17592186044416; //1 << 44; + const PUSH_MONEY_FLASH_FUNDS = 35184372088832; //1 << 45; + const DISBURSE_FUNDS = 70368744177664; //1 << 46; + const SPEND_BACK = 140737488355328; //1 << 47; + const REVERSE_SPLITPAY = 281474976710656; //1 << 48; + const SPLIT_FUNDS = 562949953421312; //1 << 49; + const GET_ACCOUNT_DETAILS = 1125899906842624; //1 << 50; + const GET_ACCOUNT_BALANCE = 2251799813685248; //1 << 51; const DETOKENIZE = 4503599627370496; //1 << 52 const DISPUTE_ACCEPTANCE = 9007199254740992; // 1 << 53 const DISPUTE_CHALLENGE = 18014398509481984; // 1 << 54 diff --git a/src/Entities/IRequestBuilder.php b/src/Entities/IRequestBuilder.php index 54b7b0f9..f0c242cb 100644 --- a/src/Entities/IRequestBuilder.php +++ b/src/Entities/IRequestBuilder.php @@ -10,4 +10,4 @@ interface IRequestBuilder public function buildRequest(BaseBuilder $builder, $config); public static function canProcess($builder); -} \ No newline at end of file +} diff --git a/src/Entities/Reporting/CheckData.php b/src/Entities/Reporting/CheckData.php index 6105b431..8062d0fc 100644 --- a/src/Entities/Reporting/CheckData.php +++ b/src/Entities/Reporting/CheckData.php @@ -1,4 +1,5 @@ withPaymentMethod($this->transactionReference) ->withAmount($amount); - + if ($this->multiCapture) { $builder->withMultiCapture($this->multiCaptureSequence, $this->multiCapturePaymentCount); } - + return $builder; } @@ -519,6 +539,16 @@ public function __get($name) return $this->transactionReference->clientTransactionId; } return null; + case 'checkRefundId': + if ($this->transactionReference !== null) { + return $this->transactionReference->checkRefundId; + } + return null; + case 'checkSaleId': + if ($this->transactionReference !== null) { + return $this->transactionReference->checkSaleId; + } + return null; case 'orderId': if ($this->transactionReference !== null) { return $this->transactionReference->orderId; @@ -563,6 +593,8 @@ public function __isset($name) 'authorizationId', 'paymentMethodType', 'clientTransactionId', + 'checkRefundId', + 'checkSaleId', 'alternativePaymentResponse', 'bnplResponse' ]) || isset($this->{$name}); @@ -583,6 +615,18 @@ public function __set($name, $value) } $this->transactionReference->clientTransactionId = $value; return; + case 'checkRefundId': + if (!$this->transactionReference instanceof TransactionReference) { + $this->transactionReference = new TransactionReference(); + } + $this->transactionReference->checkRefundId = $value; + return; + case 'checkSaleId': + if (!$this->transactionReference instanceof TransactionReference) { + $this->transactionReference = new TransactionReference(); + } + $this->transactionReference->checkSaleId = $value; + return; case 'orderId': if (!$this->transactionReference instanceof TransactionReference) { $this->transactionReference = new TransactionReference(); diff --git a/src/Entities/TransactionApi/TransactionApiData.php b/src/Entities/TransactionApi/TransactionApiData.php new file mode 100644 index 00000000..e76484b2 --- /dev/null +++ b/src/Entities/TransactionApi/TransactionApiData.php @@ -0,0 +1,25 @@ +endpoint = $endpoint; + $this->httpVerb = $httpVerb; + $this->requestBody = $requestBody; + $this->queryParams = $queryParams; + } +} diff --git a/src/Gateways/Gateway.php b/src/Gateways/Gateway.php index 400aa859..fc603c93 100644 --- a/src/Gateways/Gateway.php +++ b/src/Gateways/Gateway.php @@ -88,15 +88,7 @@ protected function sendRequest( $queryString = $this->buildQueryString($queryStringParams); $request = curl_init($this->serviceUrl . $endpoint . $queryString); - $this->headers = array_merge($this->dynamicHeaders, $this->headers, [ - 'Content-Type' => sprintf('%s; charset=UTF-8', $this->contentType), - 'Content-Length' => empty($data) ? 0 : strlen($data), - ]); - - $headers = []; - foreach ($this->headers as $key => $value) { - $headers[] = $key . ': ' . $value; - } + $headers = $this->prepareHeaders($data); if (isset($this->requestLogger)) { $this->requestLogger->requestSent($verb, $this->serviceUrl . $endpoint . $queryString, $headers, null, $data); @@ -160,6 +152,25 @@ protected function sendRequest( } } + private function prepareHeaders($data) + { + $mandatoryHeaders = [ + 'Content-Type' => sprintf('%s', $this->contentType), + 'Content-Length' => empty($data) ? 0 : strlen($data), + ]; + + $this->headers = array_merge($this->dynamicHeaders, $this->headers, $mandatoryHeaders); + + foreach ($this->headers as $key => $value) { + if (is_array($value)) { + $value = implode('; ', $value); + } + $headers[] = $key . ': ' . $value; + } + + return $headers ?? []; + } + /** * @param array|null $queryStringParams * diff --git a/src/Gateways/GpApiConnector.php b/src/Gateways/GpApiConnector.php index 91853ca8..18ed3178 100644 --- a/src/Gateways/GpApiConnector.php +++ b/src/Gateways/GpApiConnector.php @@ -48,6 +48,7 @@ public function __construct(GpApiConfig $gpApiConfig) $this->headers['Accept'] = 'application/json'; $this->headers['Accept-Encoding'] = 'gzip'; $this->headers['x-gp-sdk'] = 'php;version=' . $this->getReleaseVersion(); + $this->headers['Content-Type'] = 'charset=UTF-8'; } /** @@ -147,7 +148,7 @@ public function processReport(ReportBuilder $builder) * @throws ApiException * @throws \GlobalPayments\Api\Entities\Exceptions\UnsupportedTransactionException */ - public function processBoardingUser(PayFacBuilder $builder) : User + public function processBoardingUser(PayFacBuilder $builder): User { if (empty($this->accessToken)) { $this->signIn(); @@ -321,4 +322,4 @@ public function getAccessToken() return new GpApiTokenResponse($response); } -} \ No newline at end of file +} diff --git a/src/Gateways/PayPlanConnector.php b/src/Gateways/PayPlanConnector.php index b8c5958f..fca8e28c 100644 --- a/src/Gateways/PayPlanConnector.php +++ b/src/Gateways/PayPlanConnector.php @@ -644,7 +644,7 @@ protected function hydrateSchedule($response) $schedule->description = isset($response->Description) ? $response->Description : null; // statusSetDate $schedule->nextProcessingDate = isset($response->nextProcessingDate) - ? \DateTime::createFromFormat('dmY', $response->nextProcessingDate) + ? \DateTime::createFromFormat('mdY', $response->nextProcessingDate) : null; // previousProcessingDate // approvedTransactionCount diff --git a/src/Gateways/RestGateway.php b/src/Gateways/RestGateway.php index 1a68c077..7529ebc3 100644 --- a/src/Gateways/RestGateway.php +++ b/src/Gateways/RestGateway.php @@ -27,25 +27,37 @@ protected function doTransaction( $data = null, array $queryStringParams = null ) { - if ($this->isGpApi()) { + if ($this->isGpApi() || $this->isTransactionApi()) { if (!empty($data)) { $data = (array) $data; $data = ArrayUtils::array_remove_empty($data); $data = json_encode($data, JSON_UNESCAPED_SLASHES); } - if (!empty($queryStringParams)){ + if (!empty($queryStringParams)) { $queryStringParams = ArrayUtils::array_remove_empty($queryStringParams); } } - $response = $this->sendRequest($verb, $endpoint, $data, $queryStringParams); + $response = $this->sendRequest( + $verb, + $endpoint, + $data, + $queryStringParams + ); - if ($this->isGpApi()) { + if ($this->isGpApi() || $this->isTransactionApi()) { if (strpos($response->header, ': gzip') !== false) { $response->rawResponse = gzdecode($response->rawResponse); } } - if (!in_array($response->statusCode, [200, 204, 201])) { + + $statusCodes = [200, 204, 201]; + + if ($this->isTransactionApi()) { + $statusCodes = [200, 204, 201, 473, 471, 470]; + } + + if (!in_array($response->statusCode, $statusCodes)) { $parsed = json_decode($response->rawResponse); $error = isset($parsed->error) ? $parsed->error : $parsed; if (empty($error)) { @@ -58,8 +70,7 @@ protected function doTransaction( 'Status Code: %s - %s', $error->error_code, isset($error->detailed_error_description) ? - $error->detailed_error_description : - (isset($error->detailed_error_code) ? $error->detailed_error_code : (string)$error) + $error->detailed_error_description : (isset($error->detailed_error_code) ? $error->detailed_error_code : (string)$error) ), (!empty($error->detailed_error_code) ? $error->detailed_error_code : null) ); @@ -67,8 +78,24 @@ protected function doTransaction( $this->requestLogger->responseError($gatewayException, $response->header); } throw $gatewayException; + } else if ($this->isTransactionApi()) { + if (isset($error) && isset($error->detail)) { + $gatewayException = new GatewayException( + sprintf( + 'Status Code: %s - %s', + $error->code, + isset($error->detail) && isset($error->detail[0]->description) ? + $error->detail[0]->description : (isset($error->message) ? $error->message : (string)$error) + ), + (!empty($error->code) ? $error->code : null) + ); + if ($this->requestLogger) { + $this->requestLogger->responseError($gatewayException); + } + throw $gatewayException; + } } else { - $errMsgProperty = ['error_description', 'error_detail', 'message' , 'eos_reason']; + $errMsgProperty = ['error_description', 'error_detail', 'message', 'eos_reason']; $errorMessage = ''; foreach ($errMsgProperty as $propertyName) { if (property_exists($error, $propertyName)) { @@ -94,4 +121,9 @@ private function isGpApi() { return $this instanceof GpApiConnector; } + + private function isTransactionApi() + { + return $this instanceof TransactionApiConnector; + } } diff --git a/src/Gateways/TransactionApiConnector.php b/src/Gateways/TransactionApiConnector.php new file mode 100644 index 00000000..4c0f1b77 --- /dev/null +++ b/src/Gateways/TransactionApiConnector.php @@ -0,0 +1,240 @@ +transactionApiConfig = $transactionApiConfig; + } + + /** + * Serializes and executes authorization transactions + * + * @param AuthorizationBuilder $builder The transaction's builder + * + * @return Transaction + */ + public function processAuthorization(AuthorizationBuilder $builder) + { + if (empty($this->accessToken)) { + $this->signIn(); + } + + $response = $this->executeProcess($builder); + return TransactionApiMapping::mapResponse($response); + } + + /** + * Serializes and executes follow up transactions + * + * @param ManagementBuilder $builder The transaction's builder + * + * @return Transaction + */ + public function manageTransaction(ManagementBuilder $builder) + { + if (empty($this->accessToken)) { + $this->signIn(); + } + $response = $this->executeProcess($builder); + return TransactionApiMapping::mapResponse($response); + } + + /** + * Executes the reports + * + * @param ReportBuilder $builder + * + * @return DepositSummary|DisputeSummary|TransactionSummary + * @throws ApiException + * @throws GatewayException + */ + public function processReport(ReportBuilder $builder) + { + if (empty($this->accessToken)) { + $this->signIn(); + } + $response = $this->executeProcess($builder); + + return TransactionApiMapping::mapReportResponse($response, $builder->reportType); + } + + private function executeProcess($builder) + { + $processFactory = new RequestBuilderFactory(); + /** + * @var IRequestBuilder $requestBuilder + */ + $requestBuilder = $processFactory->getRequestBuilder($builder, $this->transactionApiConfig->gatewayProvider); + if (empty($requestBuilder)) { + throw new ApiException("Request builder not found!"); + } + /** + * @var TransactionApiRequest $request + */ + $request = $requestBuilder->buildRequest($builder, $this->transactionApiConfig); + + if (empty($request)) { + throw new ApiException("Request was not generated!"); + } + + return $this->doTransaction( + $request->httpVerb, + $request->endpoint, + $request->requestBody, + $request->queryParams + ); + } + + public function serializeRequest(AuthorizationBuilder $builder) + { + // TODO: Implement serializeRequest() method. + } + + /** + * @param string $verb + * @param string $endpoint + * @param null $data + * @param array|null $queryStringParams + * + * @return object + * + * @throws GatewayException + */ + public function doTransaction( + $verb, + $endpoint, + $data = null, + array $queryStringParams = null + ) { + if (empty($this->accessToken)) { + $this->signIn(); + } + + //weird bug where if you populate the contentType header on this endpoint it throws a 502 bad gateway error + //if you don't send it the error is even weirder, you just have to send it empty + if ( + strpos($endpoint, 'settlement') !== false || + (strpos($endpoint, 'disputes') !== false && strpos($endpoint, 'challenge') == false) + ) { + $this->contentType = ''; + } + + try { + $response = parent::doTransaction( + $verb, + $endpoint, + $data, + $queryStringParams + ); + } catch (GatewayException $exception) { + if ( + strpos($exception->getMessage(), 'NOT_AUTHENTICATED') !== false + && !empty($this->transactionApiConfig->appKey) + ) { + $this->accessToken = null; + $this->signIn(); + return parent::doTransaction( + $verb, + $endpoint, + $data, + $queryStringParams + ); + } + + throw $exception; + } + $this->accessToken = null; + return json_decode($response); + } + + /** + * + * Transaction API token generation + */ + public function signIn() + { + // Transaction API get config credentials + $accountCredential = $this->transactionApiConfig->accountCredential; + $apiSecret = $this->transactionApiConfig->apiSecret; + $region = $this->transactionApiConfig->country; + $apiKey = $this->transactionApiConfig->apiKey; + $apiVersion = $this->transactionApiConfig->apiVersion; + $apiPartnerName = $this->transactionApiConfig->apiPartnerName; + + if (!empty($this->accessToken)) { + $this->headers['Authorization'] = sprintf('AuthToken %s', $this->accessToken); + return; + } + + // token generation + $this->accessToken = $this->generateAuthToken($accountCredential, $apiSecret, $region); + $this->headers['Authorization'] = sprintf('AuthToken %s', $this->accessToken); + $this->headers['X-GP-Api-Key'] = $apiKey; + $this->headers['X-GP-Version'] = $apiVersion; + $this->headers['X-GP-Partner-App-Name'] = $apiPartnerName; + } + + /** + * @return encodedData + * + * Transaction API base64 encoding + */ + private function base64url_encode($data) + { + return strtr(base64_encode($data), '+/', '-_'); + } + + /** + * @param string $accountCredential + * @param string $apiSecret + * @param string $region + * + * @return string $authToken + * + */ + public function generateAuthToken($accountCredential, $apiSecret, $region) + { + $headerObj = new \stdClass(); + $headerObj->alg = 'HS256'; + $headerObj->typ = 'JWT'; + $headerJSON = $this->base64url_encode(json_encode($headerObj)); + $microseconds = floor(microtime(true) * 1000); + $jwtPayloadObj = new \stdClass(); + $jwtPayloadObj->account_credential = $accountCredential; + $jwtPayloadObj->region = $region; + $jwtPayloadObj->type = 'AuthTokenV2'; + $jwtPayloadObj->ts = $microseconds; + $payloadJSON = $this->base64url_encode(json_encode($jwtPayloadObj)); + + $signature = $this->base64url_encode(hash_hmac('sha256', sprintf('%s.%s', $headerJSON, $payloadJSON), $apiSecret, true)); + $authToken = sprintf('%s.%s.%s', $headerJSON, $payloadJSON, $signature); + return $authToken; + } +} diff --git a/src/Mapping/TransactionApiMapping.php b/src/Mapping/TransactionApiMapping.php new file mode 100644 index 00000000..26665c86 --- /dev/null +++ b/src/Mapping/TransactionApiMapping.php @@ -0,0 +1,169 @@ +clientTransactionId = !empty($response->creditauth_id) + ? $response->creditauth_id : null; + $transaction->checkSaleId = !empty($response->checksale_id) + ? $response->checksale_id : null; + $transaction->checkRefundId = !empty($response->checkrefund_id) + ? $response->checkrefund_id : null; + if (!empty($response->creditsale_id)) + $transaction->transactionId = $response->creditsale_id; + if (!empty($response->creditreturn_id)) + $transaction->transactionId = $response->creditreturn_id; + + $transaction->responseMessage = !empty($response->processor_response) + ? $response->processor_response : null; + $transaction->responseCode = !empty($response->status) + ? $response->status : null; + $transaction->authorizationCode = !empty($response->approval_code) + ? $response->approval_code : null; + $transaction->avsResponseCode = !empty($response->avs_response) + ? $response->avs_response : null; + $transaction->avsResponseMessage = !empty($response->avs_response_description) + ? $response->avs_response_description : null; + $transaction->cardSecurityResponse = !empty($response->cardsecurity_response) + ? $response->cardsecurity_response : null; + + if (!empty($response->card)) { + $card = $response->card; + $transaction->maskedCardNumber = !empty($card->masked_card_number) ? $card->masked_card_number : ""; + $transaction->cardholderName = !empty($card->cardholder_name) ? $card->cardholder_name : ""; + $transaction->cardExpMonth = !empty($card->expiry_month) ? $card->expiry_month : ''; + $transaction->cardExpYear = !empty($card->expiry_year) ? $card->expiry_year : ''; + $transaction->token = !empty($card->token) ? $card->token : ''; + $transaction->cardType = !empty($card->type) ? $card->type : ''; + } + + if (!empty($response->check)) { + $check = $response->check; + $transaction->token = !empty($check->token) ? $check->token : ''; + } + + $transaction->referenceNumber = !empty($response->reference_id) + ? $response->reference_id : null; + $transaction->balanceAmount = !empty($response->amount) + ? StringUtils::toAmount($response->amount) : null; + + return $transaction; + } + + /** + * @param Object $response + * @param string $reportType + */ + public static function mapReportResponse($response, $reportType) + { + switch ($reportType) { + case ReportType::TRANSACTION_DETAIL || ReportType::FIND_TRANSACTIONS: + $report = self::mapTransactionSummary($response); + break; + default: + throw new ApiException("Report type not supported!"); + } + + return $report; + } + + /** + * @param Object $response + * @return TransactionSummary + * @throws \Exception + */ + public static function mapTransactionSummary($response) + { + $summary = new TransactionSummary(); + + if (!empty($response->creditreturn_id)) { + $summary->transactionId = $response->creditreturn_id; + } + if (!empty($response->creditsale_id)) { + $summary->transactionId = $response->creditsale_id; + } + if (!empty($response->checksale_id)) { + $summary->transactionId = $response->checksale_id; + } + if (!empty($response->checkrefund_id)) { + $summary->transactionId = $response->checkrefund_id; + } + + $summary->transactionStatus = isset($response->status) ? $response->status : null; + $summary->authCode = isset($response->approval_code) + ? $response->approval_code : null; + $summary->issuerResponseMessage = !empty($response->cardsecurity_response) + ? $response->cardsecurity_response : null; + + if (isset($response->check)) { + $checkSummary = new CheckData(); + $checkSummary->accountInfo = isset($response->check->account_type) + ? $response->check->account_type : null; + $checkSummary->accountNumber = isset($response->check->account_number) + ? $response->check->account_number : null; + $checkSummary->bankNumber = isset($response->check->bank_number) + ? $response->check->bank_number : null; + $checkSummary->branchTransitNumber = isset($response->check->branch_transit_number) + ? $response->check->branch_transit_number : null; + $checkSummary->bsbNumber = isset($response->check->bsb_number) + ? $response->check->bsb_number : null; + $checkSummary->maskedCardNumber = isset($response->check->masked_card_number) + ? $response->check->masked_card_number : null; + $checkSummary->financialInstitutionNumber = isset($response->check->financial_institution_number) + ? $response->check->financial_institution_number : null; + $checkSummary->checkNumber = isset($response->check->check_number) + ? $response->check->check_number : null; + $checkSummary->routingNumber = isset($response->check->routing_number) + ? $response->check->routing_number : null; + + $summary->checkData = $checkSummary; + } + + if (isset($response->check)) { + $summary->maskedCardNumber = isset($response->card->masked_card_number) + ? $response->card->masked_card_number : null; + $summary->cardType = isset($response->card->type) ? $response->card->type : null; + } + + if (isset($response->payment)) { + $summary->amount = isset($response->payment->amount) + ? $response->payment->amount : null; + $summary->invoiceNumber = isset($response->payment->invoice_number) + ? $response->payment->invoice_number : null; + $summary->paymentType = isset($response->payment->type) + ? $response->payment->type : null; + } + + if (isset($response->transaction)) { + $summary->batchSequenceNumber = isset($response->transaction->batch_number) + ? $response->transaction->batch_number : null; + $summary->paymentPurposeCode = isset($response->transaction->payment_purpose_code) + ? $response->transaction->payment_purpose_code : null; + } + + $summary->referenceNumber = isset($response->reference_id) ? $response->reference_id : null; + + return $summary; + } +} diff --git a/src/PaymentMethods/ECheck.php b/src/PaymentMethods/ECheck.php index 6fa4cd41..8762517c 100644 --- a/src/PaymentMethods/ECheck.php +++ b/src/PaymentMethods/ECheck.php @@ -3,8 +3,7 @@ namespace GlobalPayments\Api\PaymentMethods; use GlobalPayments\Api\Builders\AuthorizationBuilder; -use GlobalPayments\Api\Builders\ManagementBuilder; -use GlobalPayments\Api\Entities\Address; +use GlobalPayments\Api\Entities\{Address, Customer}; use GlobalPayments\Api\Entities\Enums\PaymentMethodType; use GlobalPayments\Api\Entities\Enums\TransactionType; use GlobalPayments\Api\PaymentMethods\Interfaces\IChargable; @@ -18,6 +17,7 @@ class ECheck implements public $accountType; public $achVerify; public $birthYear; + public $branchTransitNumber; public $checkHolderName; public $checkNumber; public $checkType; @@ -25,6 +25,7 @@ class ECheck implements public $driversLicenseNumber; public $driversLicenseState; public $entryMode; + public $financialInstitutionNumber; public $micrNumber; public $paymentMethodType = PaymentMethodType::ACH; public $phoneNumber; @@ -40,6 +41,11 @@ class ECheck implements */ public $bankAddress; + /** + * @var Customer + */ + public $customer; + /** * Authorizes the payment method and captures the entire authorized amount * diff --git a/src/PaymentMethods/TransactionReference.php b/src/PaymentMethods/TransactionReference.php index d32aedec..766958aa 100644 --- a/src/PaymentMethods/TransactionReference.php +++ b/src/PaymentMethods/TransactionReference.php @@ -39,6 +39,13 @@ class TransactionReference implements IPaymentMethod */ public $clientTransactionId; + /** + * Previous authorization's creditsale ID + * + * @var string + */ + public $creditsaleId; + public $orderId; /** @var AlternativePaymentResponse $alternativePaymentResponse */ diff --git a/src/ServiceConfigs/Gateways/TransactionApiConfig.php b/src/ServiceConfigs/Gateways/TransactionApiConfig.php new file mode 100644 index 00000000..22ee482c --- /dev/null +++ b/src/ServiceConfigs/Gateways/TransactionApiConfig.php @@ -0,0 +1,119 @@ +gatewayProvider = GatewayProvider::TRANSACTION_API; + } + + public function configureContainer(ConfiguredServices $services) + { + if (empty($this->serviceUrl)) { + $this->serviceUrl = ($this->environment == Environment::PRODUCTION) ? + ServiceEndpoints::TRANSACTION_API_PROD : ServiceEndpoints::TRANSACTION_API_TEST; + } + $gateway = new TransactionApiConnector($this); + $gateway->serviceUrl = $this->serviceUrl; + $gateway->requestLogger = $this->requestLogger; + $gateway->webProxy = $this->webProxy; + $gateway->dynamicHeaders = $this->dynamicHeaders; + + $services->gatewayConnector = $gateway; + $services->reportingService = $gateway; + } + + public function validate() + { + parent::validate(); + if ((empty($this->apiKey) || empty($this->apiSecret)) && empty($this->accountCredential)) { + throw new ConfigurationException('ApiKey or ApiSecret and AccountCredential cannot be null'); + } + } +} diff --git a/src/Services/ReportingService.php b/src/Services/ReportingService.php index b8a7b79c..82e0bb7f 100644 --- a/src/Services/ReportingService.php +++ b/src/Services/ReportingService.php @@ -35,6 +35,12 @@ public static function activity() public static function transactionDetail($transactionId) { + if (isset($transactionId->paymentMethodType)) { + return (new TransactionReportBuilder(ReportType::TRANSACTION_DETAIL)) + ->withTransactionId($transactionId) + ->withPaymentType($transactionId->paymentMethodType); + } + return (new TransactionReportBuilder(ReportType::TRANSACTION_DETAIL)) ->withTransactionId($transactionId); } @@ -147,4 +153,4 @@ public static function findMerchants($page, $pageSize) ->withModifier(TransactionModifier::MERCHANT) ->withPaging($page, $pageSize); } -} \ No newline at end of file +} diff --git a/src/Terminals/Builders/TerminalAuthBuilder.php b/src/Terminals/Builders/TerminalAuthBuilder.php index a51238ec..19813b48 100644 --- a/src/Terminals/Builders/TerminalAuthBuilder.php +++ b/src/Terminals/Builders/TerminalAuthBuilder.php @@ -168,7 +168,7 @@ public function withTaxAmount($taxAmount) public function withToken($value) { - if ($this->paymentMethod == null || ! ($this->paymentMethod instanceof CreditCardData)) { + if ($this->paymentMethod == null || !($this->paymentMethod instanceof CreditCardData)) { $this->paymentMethod = new CreditCardData(); $this->paymentMethod->token = $value; } @@ -185,7 +185,7 @@ public function withToken($value) */ public function withTransactionId($transactionId) { - if ($this->paymentMethod == null || ! $this->paymentMethod instanceof TransactionReference) { + if ($this->paymentMethod == null || !$this->paymentMethod instanceof TransactionReference) { $this->paymentMethod = new TransactionReference(); $this->paymentMethod->transactionId = $transactionId; } diff --git a/src/Terminals/Builders/TerminalBuilder.php b/src/Terminals/Builders/TerminalBuilder.php index 45ea5b4c..9e8c5925 100644 --- a/src/Terminals/Builders/TerminalBuilder.php +++ b/src/Terminals/Builders/TerminalBuilder.php @@ -6,7 +6,7 @@ abstract class TerminalBuilder extends TransactionBuilder { - + /** * Request transaction type * @@ -23,7 +23,7 @@ abstract class TerminalBuilder extends TransactionBuilder * @var int */ public $requestId; - + /* * ID of the clerk if in retail mode, and ID of the server if in restaurant mode * @@ -50,13 +50,13 @@ public function __construct($type, $paymentMethodType) $this->paymentMethodType = $paymentMethodType; parent::__construct($type); } - + public function withRequestId($requestId) { $this->requestId = $requestId; return $this; } - + public function withClerkId($clerkId) { $this->clerkId = $clerkId; @@ -69,7 +69,7 @@ public function withCardOnFileIndicator($cardOnFileIndicator) return $this; } - public function withCardBrandTransId ($cardBrandTransId) + public function withCardBrandTransId($cardBrandTransId) { $this->cardBrandTransId = $cardBrandTransId; return $this; diff --git a/src/Utils/AmountUtils.php b/src/Utils/AmountUtils.php index 3ce62e8a..7194ac90 100644 --- a/src/Utils/AmountUtils.php +++ b/src/Utils/AmountUtils.php @@ -12,7 +12,7 @@ class AmountUtils * * @return float */ - public static function transitFormat($amount) + public static function transitFormat(float $amount) { return number_format($amount, 2, '.', ''); } diff --git a/src/Utils/GenerationUtils.php b/src/Utils/GenerationUtils.php index f47a21cd..b5bff1e2 100644 --- a/src/Utils/GenerationUtils.php +++ b/src/Utils/GenerationUtils.php @@ -196,4 +196,20 @@ public static function generateScheduleId() 20 )); } + + /** + * Generate HASH to validate the X-GP-Signature + * + * @param string $toHash + * @param string $appKey + * + * @return string + */ + public static function generateXGPSignature(string $toHash, string $appKey) : string + { + $stringToHash = $toHash . $appKey; + + return hash(ShaHashType::SHA512, $stringToHash); + } + } diff --git a/test/Integration/Gateways/GpApiConnector/GpApiDigitalWalletTest.php b/test/Integration/Gateways/GpApiConnector/GpApiDigitalWalletTest.php index c0484b00..a1c11151 100644 --- a/test/Integration/Gateways/GpApiConnector/GpApiDigitalWalletTest.php +++ b/test/Integration/Gateways/GpApiConnector/GpApiDigitalWalletTest.php @@ -26,9 +26,9 @@ public function setup() : void $this->card->expYear = date('Y', strtotime('+1 year')); $this->card->cardHolderName = "James Mason"; $this->googlePayToken = '{ - "signature": "MEYCIQCmqtWzjV/HvFoTCbydIeFcuKvkLe2JqUOkqqLFxw98agIhAN1fo4hBVyPOfMz+hivwbtCUfsBJX3n5w2Z4V9c0/7gY", + "signature": "MEYCIQChBRI9LwVnpkueFTULQBJbAHodFE6HnWX1iPFVdvfQ5wIhAMxZR232GGIa/yIROdEcIbh3x9qqILLUJ8K/KvqzncET", "protocolVersion": "ECv1", - "signedMessage": "{\"encryptedMessage\":\"QeiCtyFoWkjtYZl9aXOwh1KofQp0T8NurwZKJnpsPObWXWTkOTceXbTSqv1MvorX9I1qtDO6rrEbEfwzD3VJAl0LP2NePp5O4jTw4rh7qjXIQdskwx1+dEwOJSVFGtq4KU9DGRtnhtENezet08mlNGvOdT9Ufy+rX+pKHA5msMmlsdAREr+Fp2NppQE+IhiQDHVi7oiNMnPQLB9z+hr4f8pEg0gUD9qOUdtCalDBb7jwACXW4MvxtNz0Qin7nLQm/4AcRS8xM07uUeys6Z86v3It3WmOqgPNUERx37DIcUaZ2CcF7Oy7uvxpHCshjvpR/Gc0puRPPi1cDGSnqfMuXfyv15hMP3huYe8IHXPFJ855qhnIIeqKnVf+IcsLSYaX+bUc2niDC+VFmOb8RgGYwXrSNCFF8UXvAdNMxCQ1BulIRDxIseh89iwZKKBX3eNj2yxr\",\"ephemeralPublicKey\":\"BOwa6fGQkkFxxF3VnkZoMGmIebvsJ7KGSYtSE6V3nFcTv7UfQF1Txx/vfuSWPUoSQmVPshJ0S8EHIp4Kyf49ozU\\u003d\",\"tag\":\"zB2Bb1L6rOMKV3AiTrMzS4ZgBoKqDZSpf1jYV/8BDm4\\u003d\"}" + "signedMessage": "{\"encryptedMessage\":\"lUzJWAt/5VVerPaDLHctV0x7CHbAijOonczp2JtgVe9GS1fCiTwUuq6wCN6CWKe5mC+lRjpsgfTXuPFTgOGCCoTSYxAmb4hbtvjD7vlK+lHy/3UDtLGt0BxgPruT2IzyAzR5cNwf4fvmWwucTdf1nbywkAs5hIrVeQvxC1UkvBcsSz/pIMiBYkWRXk0NGH+g0AvyyYYUFZLZyZ/cfVXbUSRD012Ky8dvbt9Cu1VncBLhSuQ/0p8ifB/sWznp1ZZ3OTv5eMwHIW4oj18k22JJXhbbI5D8KEnkwg6zO5CBo+Ka29lTLbRd5Ok0MWSApeGfvQGqfSuPJJck/+HbJVshBYwuf6VEE0JLqXTIauEsYMY1rwb5St/57y8fDoHcNb5XYiE8/qN4G8YB0a8gGyEaMSLM5B9esgy8UQDWBc7nEOd7C13EDSe6O4joIdH0EFlICDYN\",\"ephemeralPublicKey\":\"BPp6cBv4ogIfYGfqtGPr2gwhNE3gLxco7Ka7laO1U7Jdijz2AHnodW1HgztnuBfuSXUKCVYOhblYYXt+pJE/zLI\\u003d\",\"tag\":\"dTBKFQag7foGF/MYBUJBsI8bFVQ766kEUb04jLk5hcA\\u003d\"}" }'; } @@ -44,13 +44,14 @@ public function setUpConfig() public function testClickToPayEncrypted() { - $this->markTestSkipped('You need a valid ApplePay token that it is valid only for 60 sec'); - $this->card->token = '{"data":"9113329269393758302"}' ; + $this->markTestSkipped('Special setup configuration needed from GP-API team on the appId/appKey'); + $this->card->token = "9113329269393758302" ; $this->card->mobileType = EncyptedMobileType::CLICK_TO_PAY; $response = $this->card->charge($this->amount) ->withCurrency($this->currency) ->withModifier(TransactionModifier::ENCRYPTED_MOBILE) + ->withMaskedDataResponse(true) ->execute(); $this->assertTransactionResponse($response, TransactionStatus::CAPTURED); diff --git a/test/Integration/Gateways/PorticoConnector/Certifications/RecurringTest.php b/test/Integration/Gateways/PorticoConnector/Certifications/RecurringTest.php index a0d0b355..071168e2 100644 --- a/test/Integration/Gateways/PorticoConnector/Certifications/RecurringTest.php +++ b/test/Integration/Gateways/PorticoConnector/Certifications/RecurringTest.php @@ -2,24 +2,18 @@ namespace GlobalPayments\Api\Tests\Integration\Gateways\PorticoConnector\Certifications; -use GlobalPayments\Api\Tests\Data\TestCards; -use PHPUnit\Framework\TestCase; -use DateTime; use DateInterval; +use DateTime; +use GlobalPayments\Api\Entities\{Address, Customer, Schedule}; +use GlobalPayments\Api\Entities\Enums\{ + AccountType, CheckType, SecCode, ScheduleFrequency, StoredCredentialInitiator +}; +use GlobalPayments\Api\PaymentMethods\{CreditCardData, ECheck, RecurringPaymentMethod}; +use GlobalPayments\Api\ServiceConfigs\Gateways\PorticoConfig; use GlobalPayments\Api\ServicesContainer; -use GlobalPayments\Api\Entities\Address; -use GlobalPayments\Api\Entities\Customer; -use GlobalPayments\Api\Entities\Schedule; -use GlobalPayments\Api\Entities\Enums\AccountType; -use GlobalPayments\Api\Entities\Enums\CheckType; -use GlobalPayments\Api\Entities\Enums\SecCode; -use GlobalPayments\Api\Entities\Enums\ScheduleFrequency; -use GlobalPayments\Api\PaymentMethods\CreditCardData; -use GlobalPayments\Api\PaymentMethods\ECheck; -use GlobalPayments\Api\PaymentMethods\RecurringPaymentMethod; +use GlobalPayments\Api\Tests\Data\TestCards; use GlobalPayments\Api\Utils\GenerationUtils; -use GlobalPayments\Api\Entities\Enums\StoredCredentialInitiator; -use GlobalPayments\Api\ServiceConfigs\Gateways\PorticoConfig; +use PHPUnit\Framework\TestCase; final class RecurringTest extends TestCase { @@ -81,12 +75,12 @@ private function config() $config = new PorticoConfig(); $config->secretApiKey = 'skapi_cert_MTyMAQBiHVEAewvIzXVFcmUd2UcyBge_eCpaASUp0A'; $config->serviceUrl = ($this->enableCryptoUrl) ? - 'https://cert.api2-c.heartlandportico.com/': - 'https://cert.api2.heartlandportico.com'; + 'https://cert.api2-c.heartlandportico.com/' : + 'https://cert.api2.heartlandportico.com'; return $config; } - public function setup() : void + public function setup(): void { ServicesContainer::configureService($this->config()); @@ -98,7 +92,11 @@ public function setup() : void ); } - public function test000CleanUp() + /** + * @doesNotPerformAssertions + * @return void + */ + public function test000CleanUp() : void { try { $results = Schedule::findAll(); @@ -326,13 +324,15 @@ public function test008AddScheduleCreditVisa() static::$scheduleVisaID = $this->getIdentifier('CreditV'); + $startDate = \DateTime::createFromFormat('Y-m-d', '2027-02-01'); + $schedule = static::$paymentMethodVisa->addSchedule( static::$scheduleVisaID ) ->withStatus('Active') ->withAmount(30.02) ->withCurrency('USD') - ->withStartDate(\DateTime::createFromFormat('Y-m-d', '2027-02-01')) + ->withStartDate($startDate) ->withFrequency(ScheduleFrequency::WEEKLY) ->withEndDate(\DateTime::createFromFormat('Y-m-d', '2027-04-01')) ->withReprocessingCount(2) @@ -340,6 +340,9 @@ public function test008AddScheduleCreditVisa() $this->assertNotNull($schedule); $this->assertNotNull($schedule->key); + $this->assertTrue( + $startDate->format('Y-m-d') == $schedule->nextProcessingDate->format('Y-m-d') + ); static::$scheduleVisa = $schedule; } @@ -594,7 +597,7 @@ public function test023RecurringBillingCheckPPDDecline() $this->assertNotNull($response); $this->assertEquals('1', $response->responseCode); } - + public function test024RecurringBillingVisaWithCOF() { if (static::$paymentMethodVisa == null || static::$scheduleVisa == null) { @@ -608,7 +611,7 @@ public function test024RecurringBillingVisaWithCOF() ->withAllowDuplicates(true) ->withCardBrandStorage(StoredCredentialInitiator::CARDHOLDER) ->execute(); - + $this->assertNotNull($response); $this->assertEquals('00', $response->responseCode); $this->assertNotNull($response->cardBrandTransactionId); @@ -655,14 +658,14 @@ public function generateSUT(string $cardNo, string $cvv, string $expYear, string CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'POST', - CURLOPT_POSTFIELDS =>'{ + CURLOPT_POSTFIELDS => '{ "object": "token", "token_type": "supt", "card": { - "number": '.$cardNo.', - "cvc": '.$cvv.', - "exp_month": '.$expMonth.', - "exp_year": '.$expYear.' + "number": ' . $cardNo . ', + "cvc": ' . $cvv . ', + "exp_month": ' . $expMonth . ', + "exp_year": ' . $expYear . ' } }', CURLOPT_HTTPHEADER => array( diff --git a/test/Integration/Gateways/TransactionApiConnector/TransactionApiAchTest.php b/test/Integration/Gateways/TransactionApiConnector/TransactionApiAchTest.php new file mode 100644 index 00000000..8cfa6a0e --- /dev/null +++ b/test/Integration/Gateways/TransactionApiConnector/TransactionApiAchTest.php @@ -0,0 +1,484 @@ +eCheck = new ECheck(); + $this->eCheck->accountNumber = '12121'; + $this->eCheck->accountType = "Checking"; + $this->eCheck->checkHolderName = 'Jane Doe'; + + $this->customer = new Customer(); + $this->customer->title = "Mr."; + $this->customer->firstName = "Joe"; + $this->customer->middle_name = "Henry"; + $this->customer->lastName = "Doe"; + $this->eCheck->customer = $this->customer; + } + + public function setUpConfigCA() + { + $config = new TransactionApiConfig(); + $config->accountCredential = '800000052925:80039996:58xcGM3pbTtzcidVPY65XBqbB1EzWoD3'; + $config->apiSecret = 'lucQKkwz3W3RGzABkSWUVZj1Mb0Yx3E9chAA8ESUVAv'; + $config->apiKey = 'qeG6EWZOiAwk4jsiHzsh2BN8VkN2rdAs'; + $config->apiVersion = '2021-04-08'; + $config->apiPartnerName = 'mobile_sdk'; + $config->country = 'CA'; + $config->requestLogger = new SampleRequestLogger(new Logger("logs")); + + return $config; + } + + public function setUpConfigUS() + { + $config = new TransactionApiConfig(); + $config->accountCredential = '800000052925:80039990:n7j9rGFUml1Du7rcRs7XGYdJdVMmZKzh'; + $config->apiSecret = 'lucQKkwz3W3RGzABkSWUVZj1Mb0Yx3E9chAA8ESUVAv'; + $config->apiKey = 'qeG6EWZOiAwk4jsiHzsh2BN8VkN2rdAs'; + $config->apiVersion = '2021-04-08'; + $config->apiPartnerName = 'php_mobile_sdk'; + $config->country = 'US'; + $config->requestLogger = new SampleRequestLogger(new Logger("logs")); + + return $config; + } + + public function testGetNumericCodeExact() + { + $result = CountryUtils::getNumericCodeByCountry('US'); + + $this->assertNotNull($result); + $this->assertEquals('840', $result); + } + + public function test001USCheckSale() + { + ServicesContainer::configureService($this->setUpConfigUS()); + + $this->transData = $this->getTransactionData( + 'US', + TransactionLanguage::EN_US, + CountryUtils::getNumericCodeByCountry('US') + ); + + $this->eCheck->checkNumber = (string)rand(); + $this->eCheck->routingNumber = '112000066'; + + $response = $this->eCheck->charge(11) + ->withCurrency('840') + ->withTransactionData($this->transData) + ->withEntryClass("PPD") + ->withCustomerData($this->customer) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('check_submitted', $response->responseCode); + } + + public function test002USCheckRefund() + { + ServicesContainer::configureService($this->setUpConfigUS()); + + $this->transData = $this->getTransactionData( + 'US', + TransactionLanguage::EN_US, + CountryUtils::getNumericCodeByCountry('US') + ); + + $this->eCheck->checkNumber = (string)rand(); + $this->eCheck->routingNumber = '112000066'; + + $response = $this->eCheck->refund(11) + ->withCurrency('840') + ->withTransactionData($this->transData) + ->withEntryClass("PPD") + ->withCustomerData($this->customer) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('check_submitted', $response->responseCode); + } + + public function test003USByCheckRefundId() + { + ServicesContainer::configureService($this->setUpConfigUS()); + + $this->transData = $this->getTransactionData( + 'US', + TransactionLanguage::EN_US, + CountryUtils::getNumericCodeByCountry('US') + ); + + $this->eCheck->checkNumber = (string)rand(); + $this->eCheck->routingNumber = '112000066'; + + $response = $this->eCheck->charge(11) + ->withCurrency('840') + ->withEntryClass("PPD") + ->withTransactionData($this->transData) + ->withCustomerData($this->customer) + ->execute(); + + $checkSaleId = $response->checkSaleId; + $transaction = Transaction::fromId($checkSaleId, null, PaymentMethodType::ACH); + + $this->eCheck->account_type = "Checking"; + + $response = $transaction->refund(5) + ->withCurrency('840') + ->withBankTransferData($this->eCheck) + ->withEntryClass("PPD") + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('check_submitted', $response->responseCode); + } + + public function test004USByReferenceIdCheckRefund() + { + ServicesContainer::configureService($this->setUpConfigUS()); + + $this->transData = $this->getTransactionData( + 'US', + TransactionLanguage::EN_US, + CountryUtils::getNumericCodeByCountry('US') + ); + + $this->eCheck->checkNumber = (string)rand(); + $this->eCheck->routingNumber = '112000066'; + + $response = $this->eCheck->charge(11) + ->withCurrency('840') + ->withTransactionData($this->transData) + ->withEntryClass("PPD") + ->withCustomerData($this->customer) + ->execute(); + + $referenceID = $response->referenceNumber; + $transaction = Transaction::fromClientTransactionId($referenceID, null, PaymentMethodType::ACH); + + $response = $transaction->refund(5) + ->withCurrency('840') + ->withBankTransferData($this->eCheck) + ->withEntryClass("PPD") + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('check_submitted', $response->responseCode); + $this->assertEquals($referenceID, $response->referenceNumber); + } + + public function test005CACheckSale() + { + ServicesContainer::configureService($this->setUpConfigCA()); + + $this->transData = $this->getTransactionData( + 'CA', + TransactionLanguage::EN_CA, + CountryUtils::getNumericCodeByCountry('CA') + ); + + $this->eCheck->checkNumber = (string)rand(); + $this->eCheck->branchTransitNumber = "12345"; + $this->eCheck->financialInstitutionNumber = "999"; + + $response = $this->eCheck->charge(11) + ->withCurrency('124') + ->withTransactionData($this->transData) + ->withPaymentPurposeCode("150") + ->withCustomerData($this->customer) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('check_submitted', $response->responseCode); + } + + public function test006CACheckRefund() + { + ServicesContainer::configureService($this->setUpConfigCA()); + + $this->transData = $this->getTransactionData( + 'CA', + TransactionLanguage::EN_CA, + CountryUtils::getNumericCodeByCountry('CA') + ); + + $this->eCheck->checkNumber = (string)rand(); + $this->eCheck->branchTransitNumber = "12345"; + $this->eCheck->financialInstitutionNumber = "999"; + + $response = $this->eCheck->refund(11) + ->withCurrency('124') + ->withTransactionData($this->transData) + ->withPaymentPurposeCode("150") + ->withCustomerData($this->customer) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('check_submitted', $response->responseCode); + } + + public function test007CAByCheckRefundId() + { + ServicesContainer::configureService($this->setUpConfigCA()); + + $this->transData = $this->getTransactionData( + 'CA', + TransactionLanguage::EN_CA, + CountryUtils::getNumericCodeByCountry('CA') + ); + + $this->eCheck->checkNumber = (string)rand(); + $this->eCheck->branchTransitNumber = "12345"; + $this->eCheck->financialInstitutionNumber = "999"; + + $response = $this->eCheck->charge(15) + ->withCurrency('124') + ->withPaymentPurposeCode("150") + ->withTransactionData($this->transData) + ->withCustomerData($this->customer) + ->execute(); + + $checkSaleId = $response->transactionReference->checkSaleId; + + $transaction = Transaction::fromId($checkSaleId, null, PaymentMethodType::ACH); + $this->eCheck->checkNumber = (string)rand(); + + $response = $transaction->refund(6) + ->withCurrency('124') + ->withPaymentPurposeCode("150") + ->withBankTransferData($this->eCheck) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('check_submitted', $response->responseCode); + } + + public function test008CAByReferenceIdCheckRefund() + { + ServicesContainer::configureService($this->setUpConfigCA()); + + $this->transData = $this->getTransactionData( + 'CA', + TransactionLanguage::EN_CA, + CountryUtils::getNumericCodeByCountry('CA') + ); + + $this->eCheck->checkNumber = (string)rand(); + $this->eCheck->branchTransitNumber = "12345"; + $this->eCheck->financialInstitutionNumber = "999"; + + $response = $this->eCheck->charge(15) + ->withCurrency('124') + ->withPaymentPurposeCode("150") + ->withTransactionData($this->transData) + ->withCustomerData($this->customer) + ->execute(); + + ServicesContainer::configureService($this->setUpConfigCA()); + $referenceID = $response->referenceNumber; + + $transaction = Transaction::fromClientTransactionId($referenceID, null, PaymentMethodType::ACH); + + $this->eCheck->checkNumber = (string)rand(); + + $response = $transaction->refund(8) + ->withCurrency('124') + ->withPaymentPurposeCode("150") + ->withBankTransferData($this->eCheck) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('check_submitted', $response->responseCode); + $this->assertEquals($referenceID, $response->referenceNumber); + } + + # with token + public function test009WithTokenUSCheckSale() + { + ServicesContainer::configureService($this->setUpConfigUS()); + + $this->transData = $this->getTransactionData( + 'US', + TransactionLanguage::EN_US, + CountryUtils::getNumericCodeByCountry('US') + ); + + $this->eCheck->checkNumber = (string)rand(); + $this->eCheck->routingNumber = '112000066'; + + $response = $this->eCheck->charge(11) + ->withCurrency('840') + ->withTransactionData($this->transData) + ->withEntryClass("PPD") + ->withRequestMultiUseToken(true) + ->withCustomerData($this->customer) + ->execute(); + + $this->assertNotNull($response); + $this->assertNotNull($response->token); + + $this->eCheck->checkNumber = (string)rand(); + $this->eCheck->token = $response->token; + + $response = $this->eCheck->charge(11) + ->withCurrency('840') + ->withTransactionData($this->transData) + ->withEntryClass("PPD") + ->withCustomerData($this->customer) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('check_submitted', $response->responseCode); + } + + public function test010WithTokenCACheckSale() + { + ServicesContainer::configureService($this->setUpConfigCA()); + + $this->transData = $this->getTransactionData( + 'CA', + TransactionLanguage::EN_CA, + CountryUtils::getNumericCodeByCountry('CA') + ); + + $this->eCheck->checkNumber = (string)rand(); + $this->eCheck->branchTransitNumber = "12345"; + $this->eCheck->financialInstitutionNumber = "999"; + + $response = $this->eCheck->charge(11) + ->withCurrency('124') + ->withRequestMultiUseToken(true) + ->withPaymentPurposeCode("150") + ->withTransactionData($this->transData) + ->withCustomerData($this->customer) + ->execute(); + + $this->assertNotNull($response); + $this->assertNotNull($response->token); + + $this->eCheck->checkNumber = (string)rand(); + $this->eCheck->token = $response->token; + + $response = $this->eCheck->charge(11) + ->withCurrency('124') + ->withTransactionData($this->transData) + ->withPaymentPurposeCode("150") + ->withCustomerData($this->customer) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('check_submitted', $response->responseCode); + } + + public function test011USWithTokenCheckRefund() + { + ServicesContainer::configureService($this->setUpConfigUS()); + + $this->transData = $this->getTransactionData( + 'US', + TransactionLanguage::EN_US, + CountryUtils::getNumericCodeByCountry('US') + ); + + $this->eCheck->checkNumber = (string)rand(); + $this->eCheck->routingNumber = '112000066'; + + $response = $this->eCheck->charge(15) + ->withCurrency('840') + ->withTransactionData($this->transData) + ->withEntryClass("PPD") + ->withRequestMultiUseToken(true) + ->withCustomerData($this->customer) + ->execute(); + + $this->assertNotNull($response); + $this->assertNotNull($response->token); + + $this->eCheck->checkNumber = (string)rand(); + $this->eCheck->token = $response->token; + + $response = $this->eCheck->refund(15) + ->withCurrency('840') + ->withTransactionData($this->transData) + ->withEntryClass("PPD") + ->withCustomerData($this->customer) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('check_submitted', $response->responseCode); + } + + public function test012CAWithTokenCheckRefund() + { + ServicesContainer::configureService($this->setUpConfigCA()); + + $this->transData = $this->getTransactionData( + 'CA', + TransactionLanguage::EN_CA, + CountryUtils::getNumericCodeByCountry('CA') + ); + + $this->eCheck->checkNumber = (string)rand(); + $this->eCheck->branchTransitNumber = "12345"; + $this->eCheck->financialInstitutionNumber = "999"; + + $response = $this->eCheck->charge(11) + ->withCurrency('124') + ->withRequestMultiUseToken(true) + ->withPaymentPurposeCode("150") + ->withTransactionData($this->transData) + ->withCustomerData($this->customer) + ->execute(); + + $this->assertNotNull($response); + $this->assertNotNull($response->token); + + $this->eCheck->checkNumber = (string)rand(); + $this->eCheck->token = $response->token; + + $response = $this->eCheck->refund(15) + ->withCurrency('124') + ->withPaymentPurposeCode("150") + ->withTransactionData($this->transData) + ->withEntryClass("PPD") + ->withCustomerData($this->customer) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals('check_submitted', $response->responseCode); + } + + # end with token + + private function getTransactionData($region, $language, $countryCode) + { + $this->transData = new TransactionApiData(); + $this->transData->countryCode = $countryCode; + $this->transData->language = $language; + $this->transData->region = $region; + $this->transData->checkVerify = false; + + return $this->transData; + } +} diff --git a/test/Integration/Gateways/TransactionApiConnector/TransactionApiCAReportingTest.php b/test/Integration/Gateways/TransactionApiConnector/TransactionApiCAReportingTest.php new file mode 100644 index 00000000..6b20c495 --- /dev/null +++ b/test/Integration/Gateways/TransactionApiConnector/TransactionApiCAReportingTest.php @@ -0,0 +1,388 @@ +setUpConfig()); + + $this->card = new CreditCardData(); + $this->card->number = "4263970000005262"; + $this->card->cvn = "131"; + $this->card->expMonth = date('m'); + $this->card->expYear = substr(date('Y', strtotime('+1 year')), -2); + $this->card->cardHolderName = "James Mason"; + + $this->addressCa = new Address(); + $this->addressCa->streetAddress1 = "Suite 101-290"; + $this->addressCa->streetAddress2 = "Suite 109"; + $this->addressCa->city = "Diamond Bar"; + $this->addressCa->state = "CA"; + $this->addressCa->country = "Canada"; + $this->addressCa->postalCode = "91765"; + + $this->customer = new Customer(); + $this->customer->id = "2e39a948-2a9e-4b4a-9c59-0b96765343b7"; + $this->customer->title = "Mr."; + $this->customer->firstName = "Joe"; + $this->customer->middleName = "Henry"; + $this->customer->lastName = "Doe"; + $this->customer->businessName = "ABC Company LLC"; + $this->customer->email = "joe.doe@gmail.com"; + $this->customer->dateOfBirth = "1980-01-01"; + $this->customer->mobilePhone = new PhoneNumber('+35', '312345678', PhoneNumberType::MOBILE); + $this->customer->homePhone = new PhoneNumber('+1', '12345899', PhoneNumberType::HOME); + + + $this->eCheck = new ECheck(); + $this->eCheck->accountNumber = '12121'; + $this->eCheck->accountType = "Checking"; + $this->eCheck->checkHolderName = 'Jane Doe'; + + $this->customer = new Customer(); + $this->customer->title = "Mr."; + $this->customer->firstName = "Joe"; + $this->customer->middle_name = "Henry"; + $this->customer->lastName = "Doe"; + $this->eCheck->customer = $this->customer; + } + public function setUpConfigACH() + { + $this->config = new TransactionApiConfig(); + $this->config->accountCredential = '800000052925:80039996:58xcGM3pbTtzcidVPY65XBqbB1EzWoD3'; + $this->config->apiSecret = 'lucQKkwz3W3RGzABkSWUVZj1Mb0Yx3E9chAA8ESUVAv'; + $this->config->apiKey = 'qeG6EWZOiAwk4jsiHzsh2BN8VkN2rdAs'; + $this->config->apiVersion = '2021-04-08'; + $this->config->apiPartnerName = 'mobile_sdk'; + $this->config->country = 'CA'; + $this->config->requestLogger = new SampleRequestLogger(new Logger("logs")); + + return $this->config; + } + + public function setUpConfig() + { + $this->config = new TransactionApiConfig(); + $this->config->accountCredential = '800000052925:80039923:eWcWNJhfxiJ7QyEHSHndWk4VHKbSmSue'; + $this->config->apiSecret = 'lucQKkwz3W3RGzABkSWUVZj1Mb0Yx3E9chAA8ESUVAv'; + $this->config->apiKey = 'qeG6EWZOiAwk4jsiHzsh2BN8VkN2rdAs'; + $this->config->apiVersion = '2021-04-08'; + $this->config->apiPartnerName = 'mobile_sdk'; + $this->config->country = 'CA'; + $this->config->requestLogger = new SampleRequestLogger(new Logger("logs")); + + return $this->config; + } + + public function test001CreditSaleByCreditSaleId() + { + $transData = $this->getTransactionData('CA'); + + $response = $this->card->charge('12.80') + ->withCurrency('124') + ->withInvoiceNumber('167892') + ->withAddress($this->addressCa, AddressType::BILLING) + ->withAddress($this->addressCa, AddressType::SHIPPING) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($response->transactionId); + + $creditSaleId = $response->transactionId; + + $response = ReportingService::transactionDetail($creditSaleId) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("approved", $response->transactionStatus); + $this->assertEquals($creditSaleId, $response->transactionId); + } + + public function test002CreditSaleByReferenceId() + { + $transData = $this->getTransactionData('CA'); + + $response = $this->card->charge('15.80') + ->withCurrency('124') + ->withInvoiceNumber('167892') + ->withAddress($this->addressCa, AddressType::BILLING) + ->withAddress($this->addressCa, AddressType::SHIPPING) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($response->transactionId); + + $referenceID = $response->referenceNumber; + + $response = ReportingService::findTransactions() + ->where(SearchCriteria::CLIENT_TRANSACTION_ID, $referenceID) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("approved", $response->transactionStatus); + $this->assertEquals($referenceID, $response->referenceNumber); + } + + public function test003CreditReturnByCreditSaleId() + { + ServicesContainer::configureService($this->setUpConfig()); + + $transData = $this->getTransactionData( + 'CA', + CountryUtils::getNumericCodeByCountry('CA'), + TransactionLanguage::EN_CA + ); + + $response = $this->card->refund('2.00') + ->withCurrency('124') + ->withInvoiceNumber('123456') + ->withAddress($this->addressCa, AddressType::BILLING) + ->withTransactionData($transData) + ->withAllowDuplicates(true) + ->execute(); + + $this->assertNotNull($response->transactionId); + + $creditReturnId = $response->transactionId; + + $transaction = Transaction::fromId($creditReturnId, null, PaymentMethodType::CREDIT); + + $response = ReportingService::transactionDetail($transaction) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("approved", $response->transactionStatus); + $this->assertEquals($creditReturnId, $response->transactionId); + } + + public function test004CreditReturnByCreditReferenceId() + { + ServicesContainer::configureService($this->setUpConfig()); + + $transData = $this->getTransactionData( + 'CA', + CountryUtils::getNumericCodeByCountry('CA'), + TransactionLanguage::EN_CA + ); + + $response = $this->card->refund('6.00') + ->withCurrency('124') + ->withInvoiceNumber('123456') + ->withAddress($this->addressCa, AddressType::BILLING) + ->withTransactionData($transData) + ->withAllowDuplicates(true) + ->execute(); + + $this->assertNotNull($response->referenceNumber); + + $creditReferenceId = $response->referenceNumber; + + $transaction = Transaction::fromClientTransactionId($creditReferenceId); + + $response = ReportingService::transactionDetail($transaction) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("approved", $response->transactionStatus); + $this->assertEquals($creditReferenceId, $response->referenceNumber); + } + + public function test005CheckSaleById() + { + ServicesContainer::configureService($this->setUpConfigACH()); + + $this->transData = $this->getTransactionAchData( + 'CA', + TransactionLanguage::EN_CA, + CountryUtils::getNumericCodeByCountry('CA') + ); + + $this->eCheck->checkNumber = (string)rand(); + $this->eCheck->branchTransitNumber = "12345"; + $this->eCheck->financialInstitutionNumber = "999"; + + $response = $this->eCheck->charge(11) + ->withCurrency('124') + ->withPaymentPurposeCode("150") + ->withTransactionData($this->transData) + ->withCustomerData($this->customer) + ->execute(); + + $this->assertNotNull($response->transactionReference->checkSaleId); + + $checkSaleId = $response->transactionReference->checkSaleId; + + $transaction = Transaction::fromId($checkSaleId, null, PaymentMethodType::ACH); + + $response = ReportingService::transactionDetail($transaction) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("check_submitted", $response->transactionStatus); + $this->assertEquals($checkSaleId, $response->transactionId); + } + + public function test006CheckSaleByRefId() + { + ServicesContainer::configureService($this->setUpConfigACH()); + + $this->transData = $this->getTransactionAchData( + 'CA', + TransactionLanguage::EN_CA, + CountryUtils::getNumericCodeByCountry('CA') + ); + + $this->eCheck->checkNumber = (string)rand(); + $this->eCheck->branchTransitNumber = "12345"; + $this->eCheck->financialInstitutionNumber = "999"; + + $response = $this->eCheck->charge(11) + ->withCurrency('124') + ->withPaymentPurposeCode("150") + ->withTransactionData($this->transData) + ->withCustomerData($this->customer) + ->execute(); + + $this->assertNotNull($response->referenceNumber); + + $checkRefId = $response->referenceNumber; + + $transaction = Transaction::fromClientTransactionId( + $checkRefId, + null, + PaymentMethodType::ACH + ); + + $response = ReportingService::transactionDetail($transaction) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("check_submitted", $response->transactionStatus); + $this->assertEquals($checkRefId, $response->referenceNumber); + } + + public function test007CheckRefundById() + { + ServicesContainer::configureService($this->setUpConfigACH()); + + $this->transData = $this->getTransactionAchData( + 'CA', + TransactionLanguage::EN_CA, + CountryUtils::getNumericCodeByCountry('CA') + ); + + $this->eCheck->checkNumber = (string)rand(); + $this->eCheck->branchTransitNumber = "12345"; + $this->eCheck->financialInstitutionNumber = "999"; + + $response = $this->eCheck->refund(11) + ->withCurrency('124') + ->withPaymentPurposeCode("150") + ->withTransactionData($this->transData) + ->withCustomerData($this->customer) + ->execute(); + + $this->assertNotNull($response->transactionReference->checkRefundId); + + $checkRefundId = $response->transactionReference->checkRefundId; + + $transaction = Transaction::fromId($checkRefundId, null, PaymentMethodType::ACH); + $transaction->originalTransactionType = "REFUND"; + + $response = ReportingService::transactionDetail($transaction) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("check_submitted", $response->transactionStatus); + $this->assertEquals($checkRefundId, $response->transactionId); + } + + public function test008CheckRefundByRefId() + { + ServicesContainer::configureService($this->setUpConfigACH()); + + $this->transData = $this->getTransactionAchData( + 'CA', + TransactionLanguage::EN_CA, + CountryUtils::getNumericCodeByCountry('CA') + ); + + $this->eCheck->checkNumber = (string)rand(); + $this->eCheck->branchTransitNumber = "12345"; + $this->eCheck->financialInstitutionNumber = "999"; + + $this->transData->paymentPurposeCode = "150"; + $this->transData->entryClass = "PPD"; + + $response = $this->eCheck->refund(18) + ->withCurrency('124') + ->withPaymentPurposeCode("150") + ->withTransactionData($this->transData) + ->withCustomerData($this->customer) + ->execute(); + + $this->assertNotNull($response->referenceNumber); + + $checkRefId = $response->referenceNumber; + + $transaction = Transaction::fromClientTransactionId( + $checkRefId, + null, + PaymentMethodType::ACH + ); + $transaction->originalTransactionType = "REFUND"; + + $response = ReportingService::transactionDetail($transaction) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("check_submitted", $response->transactionStatus); + $this->assertEquals($checkRefId, $response->referenceNumber); + } + + private function getTransactionData($region, $countryCode = null, $lang = null) + { + $transData = new TransactionApiData(); + $transData->countryCode = isset($countryCode) ? $countryCode : CountryUtils::getNumericCodeByCountry('CA'); + $transData->ecommerceIndicator = EcommerceIndicator::ECOMMERCE_INDICATOR_2; + $transData->language = isset($lang) ? $lang : TransactionLanguage::EN_CA; + $transData->softDescriptor = "soft"; + $transData->region = $region; + return $transData; + } + + private function getTransactionAchData($region, $language, $countryCode) + { + $this->transData = new TransactionApiData(); + $this->transData->countryCode = $countryCode; + $this->transData->language = $language; + $this->transData->region = $region; + $this->transData->checkVerify = false; + + return $this->transData; + } +} diff --git a/test/Integration/Gateways/TransactionApiConnector/TransactionApiCreditReturnTest.php b/test/Integration/Gateways/TransactionApiConnector/TransactionApiCreditReturnTest.php new file mode 100644 index 00000000..2b7b52c5 --- /dev/null +++ b/test/Integration/Gateways/TransactionApiConnector/TransactionApiCreditReturnTest.php @@ -0,0 +1,325 @@ +setUpConfig()); + $this->card = new CreditCardData(); + $this->card->number = "4263970000005262"; + $this->card->cvn = "131"; + $this->card->expMonth = date('m'); + $this->card->expYear = substr(date('Y', strtotime('+1 year')), -2); + $this->card->cardHolderName = "James Mason"; + + $this->address = new Address(); + $this->address->streetAddress1 = "2600 NW"; + $this->address->streetAddress2 = "23th Street"; + $this->address->city = "Lindon"; + $this->address->state = "Utah"; + $this->address->country = "USA"; + $this->address->postalCode = "84042"; + + $this->addressCa = new Address(); + $this->addressCa->streetAddress1 = "Suite 101-290"; + $this->addressCa->streetAddress2 = "Suite 109"; + $this->addressCa->city = "Diamond Bar"; + $this->addressCa->state = "CA"; + $this->addressCa->country = "Canada"; + $this->addressCa->postalCode = "91765"; + + $this->customer = new Customer(); + $this->customer->id = "2e39a948-2a9e-4b4a-9c59-0b96765343b7"; + $this->customer->title = "Mr."; + $this->customer->firstName = "Joe"; + $this->customer->middleName = "Henry"; + $this->customer->lastName = "Doe"; + $this->customer->businessName = "ABC Company LLC"; + $this->customer->email = "joe.doe@gmail.com"; + $this->customer->dateOfBirth = "1980-01-01"; + $this->customer->mobilePhone = new PhoneNumber('+35', '312345678', PhoneNumberType::MOBILE); + $this->customer->homePhone = new PhoneNumber('+1', '12345899', PhoneNumberType::HOME); + } + + public function setUpConfig($country = "US") + { + $this->config = new TransactionApiConfig(); + $this->config->accountCredential = '800000052925:80039923:eWcWNJhfxiJ7QyEHSHndWk4VHKbSmSue'; + $this->config->apiSecret = 'lucQKkwz3W3RGzABkSWUVZj1Mb0Yx3E9chAA8ESUVAv'; + $this->config->apiKey = 'qeG6EWZOiAwk4jsiHzsh2BN8VkN2rdAs'; + $this->config->apiVersion = '2021-04-08'; + $this->config->apiPartnerName = 'mobile_sdk'; + $this->config->country = $country; + $this->config->requestLogger = new SampleRequestLogger(new Logger("logs")); + + return $this->config; + } + + public function test01USCreditReturn() + { + $transData = $this->getTransactionData('US'); + + $response = $this->card->refund('23.00') + ->withCurrency('840') + ->withInvoiceNumber('239087') + ->withAddress($this->address, AddressType::BILLING) + ->withTransactionData($transData) + ->withAllowDuplicates(true) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("approved", $response->responseCode); + } + + public function test02CACreditReturn() + { + ServicesContainer::configureService($this->setUpConfig('CA')); + + $transData = $this->getTransactionData( + 'CA', + CountryUtils::getNumericCodeByCountry('CA'), + TransactionLanguage::EN_CA + ); + + $response = $this->card->refund('2.00') + ->withCurrency('124') + ->withInvoiceNumber('123456') + ->withAddress($this->addressCa, AddressType::BILLING) + ->withTransactionData($transData) + ->withAllowDuplicates(true) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("approved", $response->responseCode); + } + + public function test03CACreditSaleCreditReturn() + { + ServicesContainer::configureService($this->setUpConfig('CA')); + + $transData = $this->getTransactionData( + 'CA', + CountryUtils::getNumericCodeByCountry('CA'), + TransactionLanguage::EN_CA + ); + + $response = $this->card->charge('8.00') + ->withCurrency('124') + ->withInvoiceNumber('239087') + ->withAddress($this->address, AddressType::BILLING) + ->withAddress($this->address, AddressType::SHIPPING) + ->withTransactionData($transData) + ->execute(); + + $creditSaleId = $response->transactionId; + + $this->config->country = 'US'; + + $transaction = Transaction::fromId( + $creditSaleId, + null, + PaymentMethodType::CREDIT + ); + + $response = $transaction->refund('3.00') + ->withCurrency('840') + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("approved", $response->responseCode); + } + + public function test04USCreditSaleCreditReturn() + { + ServicesContainer::configureService($this->setUpConfig('US')); + $transData = $this->getTransactionData('US'); + + $response = $this->card->charge('15.00') + ->withCurrency('840') + ->withInvoiceNumber('123456') + ->withAddress($this->address, AddressType::BILLING) + ->withAddress($this->address, AddressType::SHIPPING) + ->withTransactionData($transData) + ->execute(); + + $creditSaleId = $response->transactionId; + + $transaction = Transaction::fromId( + $creditSaleId, + null, + PaymentMethodType::CREDIT + ); + + $response = $transaction->refund('10.00') + ->withCurrency('840') + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("approved", $response->responseCode); + } + + public function test05USReferenceIdCreditSaleCreditReturn() + { + ServicesContainer::configureService($this->setUpConfig('US')); + + $transData = $this->getTransactionData('US'); + + $response = $this->card->charge('13.00') + ->withCurrency('840') + ->withInvoiceNumber('2256667') + ->withAddress($this->address, AddressType::BILLING) + ->withAddress($this->address, AddressType::SHIPPING) + ->withTransactionData($transData) + ->execute(); + + $referenceId = $response->referenceNumber; + + $transaction = Transaction::fromClientTransactionId($referenceId); + + $response = $transaction->refund('13.00') + ->withCurrency('840') + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("approved", $response->responseCode); + $this->assertEquals($referenceId, $response->referenceNumber); + } + + public function test06CAReferenceIdCreditSaleCreditReturn() + { + ServicesContainer::configureService($this->setUpConfig('CA')); + + $transData = $this->getTransactionData( + 'CA', + CountryUtils::getNumericCodeByCountry('CA'), + TransactionLanguage::EN_CA + ); + + $response = $this->card->charge('17.00') + ->withCurrency('124') + ->withInvoiceNumber('123456') + ->withAddress($this->address, AddressType::BILLING) + ->withAddress($this->address, AddressType::SHIPPING) + ->withTransactionData($transData) + ->execute(); + + $referenceId = $response->referenceNumber; + + $transaction = Transaction::fromClientTransactionId($referenceId); + + $response = $transaction->refund('17.00') + ->withCurrency('124') + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("approved", $response->responseCode); + $this->assertEquals($referenceId, $response->referenceNumber); + } + + public function test07CAWithTokenCreditReturn() + { + ServicesContainer::configureService($this->setUpConfig('CA')); + + $transData = $this->getTransactionData( + 'CA', + CountryUtils::getNumericCodeByCountry('CA'), + TransactionLanguage::EN_CA + ); + + $transaction = $this->card->authorize('0.0') + ->withCurrency('124') + ->withRequestMultiUseToken(true) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($transaction); + $this->assertNotNull($transaction->token); + + $this->card->token = $transaction->token; + + $transData = $this->getTransactionData( + 'CA', + CountryUtils::getNumericCodeByCountry('CA'), + TransactionLanguage::EN_CA + ); + + $response = $this->card->refund('2.00') + ->withCurrency('124') + ->withInvoiceNumber('123456') + ->withAddress($this->addressCa, AddressType::BILLING) + ->withTransactionData($transData) + ->withAllowDuplicates(true) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("approved", $response->responseCode); + } + + public function test08USWithTokenCreditReturn() + { + ServicesContainer::configureService($this->setUpConfig('US')); + $transData = $this->getTransactionData('US'); + $transData->addressVerificationService = false; + $transData->generateReceipt = false; + $transData->partialApproval = false; + + $transaction = $this->card->authorize('0.0') + ->withCurrency('840') + ->withRequestMultiUseToken(true) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($transaction->token); + + $this->card->token = $transaction->token; + + $transData = $this->getTransactionData('US'); + + $response = $this->card->refund('7.00') + ->withCurrency('840') + ->withInvoiceNumber('239087') + ->withAddress($this->address, AddressType::BILLING) + ->withTransactionData($transData) + ->withAllowDuplicates(true) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("approved", $response->responseCode); + } + + private function getTransactionData($region, $countryCode = null, $lang = null) + { + $transData = new TransactionApiData(); + $transData->countryCode = isset($countryCode) ? $countryCode : CountryUtils::getNumericCodeByCountry('US'); + $transData->ecommerceIndicator = EcommerceIndicator::ECOMMERCE_INDICATOR_2; + $transData->language = isset($lang) ? $lang : TransactionLanguage::EN_US; + $transData->softDescriptor = "soft"; + $transData->region = $region; + return $transData; + } +} diff --git a/test/Integration/Gateways/TransactionApiConnector/TransactionApiCreditTest.php b/test/Integration/Gateways/TransactionApiConnector/TransactionApiCreditTest.php new file mode 100644 index 00000000..0e0649eb --- /dev/null +++ b/test/Integration/Gateways/TransactionApiConnector/TransactionApiCreditTest.php @@ -0,0 +1,941 @@ +setUpConfig()); + $this->card = new CreditCardData(); + $this->card->number = "4263970000005262"; + $this->card->cvn = "131"; + $this->card->expMonth = date('m'); + $this->card->expYear = substr(date('Y', strtotime('+1 year')), -2); + $this->card->cardHolderName = "James Mason"; + + $this->address = new Address(); + $this->address->streetAddress1 = "2600 NW"; + $this->address->streetAddress2 = "23th Street"; + $this->address->city = "Lindon"; + $this->address->state = "Utah"; + $this->address->country = "USA"; + $this->address->postalCode = "84042"; + + $this->addressCa = new Address(); + $this->addressCa->streetAddress1 = "Suite 101-290"; + $this->addressCa->streetAddress2 = "Suite 109"; + $this->addressCa->city = "Diamond Bar"; + $this->addressCa->state = "CA"; + $this->addressCa->country = "Canada"; + $this->addressCa->postalCode = "91765"; + + $this->customer = new Customer(); + $this->customer->id = "2e39a948-2a9e-4b4a-9c59-0b96765343b7"; + $this->customer->title = "Mr."; + $this->customer->firstName = "Joe"; + $this->customer->middleName = "Henry"; + $this->customer->lastName = "Doe"; + $this->customer->businessName = "ABC Company LLC"; + $this->customer->email = "joe.doe@gmail.com"; + $this->customer->dateOfBirth = "1980-01-01"; + $this->customer->mobilePhone = new PhoneNumber('+35', '312345678', PhoneNumberType::MOBILE); + $this->customer->homePhone = new PhoneNumber('+1', '12345899', PhoneNumberType::HOME); + } + + public function setUpConfig($country = "US") + { + $config = new TransactionApiConfig(); + $config->accountCredential = '800000052925:80039923:eWcWNJhfxiJ7QyEHSHndWk4VHKbSmSue'; + $config->apiSecret = 'lucQKkwz3W3RGzABkSWUVZj1Mb0Yx3E9chAA8ESUVAv'; + $config->apiKey = 'qeG6EWZOiAwk4jsiHzsh2BN8VkN2rdAs'; + $config->apiVersion = '2021-04-08'; + $config->apiPartnerName = 'mobile_sdk'; + $config->country = $country; + $config->requestLogger = new SampleRequestLogger(new Logger("logs")); + + return $config; + } + + # credit verify | auth + public function test001CreditAuthorization() + { + $transData = $this->getTransactionData('US'); + $transData->addressVerificationService = true; + $transData->generateReceipt = true; + + $transaction = $this->card->authorize('0.0') + ->withCurrency('840') + ->withAllowPartialAuth(true) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($transaction); + $this->assertEquals("approved", $transaction->responseCode); + } + + public function test099CreditAuthorizationWithTokenUS() + { + $transData = $this->getTransactionData('US'); + $transData->addressVerificationService = true; + $transData->generateReceipt = true; + + $transaction = $this->card->authorize('0.0') + ->withCurrency('840') + ->withRequestMultiUseToken(true) + ->withPaymentMethodUsageMode(PaymentMethodUsageMode::MULTIPLE) + ->withAllowPartialAuth(true) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($transaction); + $this->assertNotNull($transaction->token); + $this->assertEquals("approved", $transaction->responseCode); + } + + public function test100CreditAuthorizationWithSingleTokenUS() + { + $this->markTestSkipped('To run this test you need to generate single use token'); + + $transData = $this->getTransactionData('US'); + $transData->addressVerificationService = true; + $transData->generateReceipt = true; + + // temporary token + $this->card = new CreditCardData(); + $this->card->token = "abaac872-4ae0-4f46-ab89-61cdb9ccf11b"; + + $transaction = $this->card->authorize('0.0') + ->withCurrency('840') + ->withRequestMultiUseToken(false) + ->withPaymentMethodUsageMode(PaymentMethodUsageMode::SINGLE) + ->withAllowPartialAuth(true) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($transaction); + $this->assertNotNull($transaction->token); + $this->assertEquals("approved", $transaction->responseCode); + } + + + public function test002CACreditAuthorization() + { + ServicesContainer::configureService($this->setUpConfig('CA')); + + $transData = $this->getTransactionData( + 'CA', + CountryUtils::getNumericCodeByCountry('CA'), + TransactionLanguage::EN_CA + ); + + $transaction = $this->card->authorize('0.0') + ->withCurrency('124') + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($transaction); + $this->assertEquals("approved", $transaction->responseCode); + } + + public function test098CreditAuthorizationWithTokenCA() + { + ServicesContainer::configureService($this->setUpConfig('CA')); + + $transData = $this->getTransactionData( + 'CA', + CountryUtils::getNumericCodeByCountry('CA'), + TransactionLanguage::EN_CA + ); + + $transaction = $this->card->authorize('0.0') + ->withCurrency('124') + ->withRequestMultiUseToken(true) + ->withPaymentMethodUsageMode(PaymentMethodUsageMode::MULTIPLE) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($transaction); + $this->assertNotNull($transaction->token); + $this->assertEquals("approved", $transaction->responseCode); + } + + public function test101CreditAuthorizationWithSingleTokenCA() + { + $this->markTestSkipped('To run this test you need to generate single use token'); + + $transData = $this->getTransactionData('CA'); + $transData->addressVerificationService = true; + $transData->generateReceipt = true; + + $transData = $this->getTransactionData( + 'CA', + CountryUtils::getNumericCodeByCountry('CA') + ); + + // temporary token + $this->card = new CreditCardData(); + $this->card->token = "0f6c4011-016d-4cce-bca4-87e63bc8187e"; + + $transaction = $this->card->authorize('0.0') + ->withCurrency('840') + ->withRequestMultiUseToken(false) + ->withPaymentMethodUsageMode(PaymentMethodUsageMode::SINGLE) + ->withAllowPartialAuth(true) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($transaction); + $this->assertNotNull($transaction->token); + $this->assertEquals("approved", $transaction->responseCode); + } + + public function test003USCreditVerify() + { + $transData = $this->getTransactionData('US'); + $transData->addressVerificationService = true; + $transData->generateReceipt = true; + + $transaction = $this->card->verify('0.0') + ->withCurrency('840') + ->withAllowPartialAuth(true) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($transaction); + $this->assertEquals("approved", $transaction->responseCode); + } + + public function test110CreditVerifyWithTokenUS() + { + $transData = $this->getTransactionData('US'); + $transData->addressVerificationService = true; + $transData->generateReceipt = true; + + $transaction = $this->card->verify('0.0') + ->withCurrency('840') + ->withRequestMultiUseToken(true) + ->withPaymentMethodUsageMode(PaymentMethodUsageMode::MULTIPLE) + ->withAllowPartialAuth(true) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($transaction); + $this->assertNotNull($transaction->token); + $this->assertEquals("approved", $transaction->responseCode); + } + + public function test108CACreditVerify() + { + $transData = $this->getTransactionData('CA'); + $transData->addressVerificationService = true; + $transData->generateReceipt = true; + + $transaction = $this->card->verify('0.0') + ->withCurrency('840') + ->withAllowPartialAuth(true) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($transaction); + $this->assertEquals("approved", $transaction->responseCode); + } + + public function test112CreditVerifyWithTokenCA() + { + ServicesContainer::configureService($this->setUpConfig('CA')); + + $transData = $this->getTransactionData( + 'CA', + CountryUtils::getNumericCodeByCountry('CA'), + TransactionLanguage::EN_CA + ); + + $transaction = $this->card->verify('0.0') + ->withCurrency('124') + ->withRequestMultiUseToken(true) + ->withPaymentMethodUsageMode(PaymentMethodUsageMode::MULTIPLE) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($transaction); + $this->assertNotNull($transaction->token); + $this->assertEquals("approved", $transaction->responseCode); + } + + # end credit verify | auth + + # credit sale + + public function test004WithTokenUSCreditSale() + { + $transData = $this->getTransactionData('US'); + $transData->addressVerificationService = false; + $transData->generateReceipt = false; + + $transaction = $this->card->authorize('0.0') + ->withCurrency('840') + ->withAllowPartialAuth(false) + ->withRequestMultiUseToken(true) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($transaction->token); + + $transData = $this->getTransactionData('US'); + $this->card->token = $transaction->token; + $response = $this->card->charge('5.00') + ->withCurrency('840') + ->withInvoiceNumber('178988') + ->withAddress($this->address, AddressType::BILLING) + ->withAddress($this->address, AddressType::SHIPPING) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("approved", $response->responseCode); + } + + public function test004USCreditSale() + { + $transData = $this->getTransactionData('US'); + + $response = $this->card->charge('23.70') + ->withCurrency('840') + ->withInvoiceNumber('178988') + ->withAddress($this->address, AddressType::BILLING) + ->withAddress($this->address, AddressType::SHIPPING) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("approved", $response->responseCode); + } + + public function test200USCreditSaleWithReferenceId() + { + $transData = $this->getTransactionData('US'); + + $response = $this->card->charge('8.70') + ->withCurrency('840') + ->withInvoiceNumber('178988') + ->withClientTransactionId(str_shuffle('abcdefg123212')) + ->withAddress($this->address, AddressType::BILLING) + ->withAddress($this->address, AddressType::SHIPPING) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("approved", $response->responseCode); + } + + public function test005WithTokenCACreditSale() + { + ServicesContainer::configureService($this->setUpConfig('CA')); + + $transData = $this->getTransactionData( + 'CA', + CountryUtils::getNumericCodeByCountry('CA'), + TransactionLanguage::EN_CA + ); + + $transaction = $this->card->authorize('0.0') + ->withCurrency('124') + ->withRequestMultiUseToken(true) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($transaction); + $this->assertNotNull($transaction->token); + + $response = $this->card->charge('19.80') + ->withCurrency('124') + ->withInvoiceNumber('167892') + ->withAddress($this->address, AddressType::BILLING) + ->withAddress($this->address, AddressType::SHIPPING) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("approved", $response->responseCode); + } + + public function test005CARegionCreditSale() + { + ServicesContainer::configureService($this->setUpConfig('CA')); + + $transData = $this->getTransactionData('CA'); + $transData->language = TransactionLanguage::EN_CA; + + $response = $this->card->charge('16.80') + ->withCurrency('124') + ->withInvoiceNumber('167892') + ->withAddress($this->address, AddressType::BILLING) + ->withAddress($this->address, AddressType::SHIPPING) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("approved", $response->responseCode); + } + + # end credit sale + + # credit void + + public function test006USVoidCreditSale() + { + ServicesContainer::configureService($this->setUpConfig('US')); + + $transData = $this->getTransactionData('US'); + + $response = $this->card->charge('15.50') + ->withCurrency('840') + ->withInvoiceNumber('123456') + ->withAddress($this->address, AddressType::BILLING) + ->withAddress($this->address, AddressType::SHIPPING) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($response->transactionId); + + $creditReturnId = $response->transactionId; + + ServicesContainer::configureService($this->setUpConfig()); + + $transaction = Transaction::fromId($creditReturnId); + $transaction->originalTransactionType = "REFUND"; + + $response = $transaction->void() + ->withCurrency('840') + ->withOriginalTransactionType(TransactionType::SALE) + ->withAmount("15.50") + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("voided", $response->responseCode); + } + + public function test006CAVoidCreditSale() + { + ServicesContainer::configureService($this->setUpConfig('CA')); + + $transData = $this->getTransactionData('CA'); + $transData->language = TransactionLanguage::EN_CA; + + $response = $this->card->charge('8.80') + ->withCurrency('124') + ->withInvoiceNumber('1211200') + ->withAddress($this->address, AddressType::BILLING) + ->withAddress($this->address, AddressType::SHIPPING) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($response->transactionId); + + $creditReturnId = $response->transactionId; + + ServicesContainer::configureService($this->setUpConfig()); + + $transaction = Transaction::fromId($creditReturnId); + $transaction->originalTransactionType = "REFUND"; + + $response = $transaction->void() + ->withCurrency('840') + ->withOriginalTransactionType(TransactionType::SALE) + ->withAmount("8.80") + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("voided", $response->responseCode); + } + + public function test007USReferenceVoidCreditSale() + { + ServicesContainer::configureService($this->setUpConfig('US')); + + $transData = $this->getTransactionData('US'); + + $response = $this->card->charge('3.00') + ->withCurrency('840') + ->withInvoiceNumber(str_shuffle('123456789')) + ->withAddress($this->address, AddressType::BILLING) + ->withAddress($this->address, AddressType::SHIPPING) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($response->referenceNumber); + + $referenceNumber = $response->referenceNumber; + + ServicesContainer::configureService($this->setUpConfig()); + + $transaction = Transaction::fromClientTransactionId($referenceNumber); + + $response = $transaction->void() + ->withCurrency('840') + ->withOriginalTransactionType(TransactionType::SALE) + ->withAmount("3.00") + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("voided", $response->responseCode); + } + + public function test008CAReferenceVoidCreditSale() + { + ServicesContainer::configureService($this->setUpConfig('CA')); + + $transData = $this->getTransactionData('CA'); + $transData->language = TransactionLanguage::EN_CA; + + $response = $this->card->charge('3.00') + ->withCurrency('124') + ->withInvoiceNumber('877762652') + ->withAddress($this->address, AddressType::BILLING) + ->withAddress($this->address, AddressType::SHIPPING) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($response->referenceNumber); + + $referenceNumber = $response->referenceNumber; + + ServicesContainer::configureService($this->setUpConfig()); + + $transaction = Transaction::fromClientTransactionId($referenceNumber); + + $response = $transaction->void() + ->withCurrency('124') + ->withOriginalTransactionType(TransactionType::SALE) + ->withAmount("3.00") + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("voided", $response->responseCode); + } + + public function test009USVoidCreditReturn() + { + ServicesContainer::configureService($this->setUpConfig('US')); + + $transData = $this->getTransactionData( + 'US', + CountryUtils::getNumericCodeByCountry('US'), + TransactionLanguage::EN_US + ); + + $response = $this->card->refund('2.00') + ->withCurrency('840') + ->withInvoiceNumber('239087') + ->withAddress($this->addressCa, AddressType::BILLING) + ->withTransactionData($transData) + ->withAllowDuplicates(true) + ->execute(); + + $this->assertNotNull($response->transactionId); + + $creditReturnId = $response->transactionId; + + $transaction = Transaction::fromId($creditReturnId, null, PaymentMethodType::CREDIT); + $response = $transaction->void() + ->withCurrency('840') + ->withOriginalTransactionType(TransactionType::REFUND) + ->withAmount("2.00") + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("voided", $response->responseCode); + } + + public function test010CAVoidCreditReturn() + { + ServicesContainer::configureService($this->setUpConfig('CA')); + + $transData = $this->getTransactionData('CA'); + $transData->language = TransactionLanguage::EN_CA; + + $response = $this->card->refund('2.00') + ->withCurrency('124') + ->withInvoiceNumber('239087') + ->withAddress($this->addressCa, AddressType::BILLING) + ->withTransactionData($transData) + ->withAllowDuplicates(true) + ->execute(); + + $this->assertNotNull($response->transactionId); + + $creditReturnId = $response->transactionId; + + $transaction = Transaction::fromId($creditReturnId); + $response = $transaction->void() + ->withCurrency('124') + ->withOriginalTransactionType(TransactionType::REFUND) + ->withAmount("2.00") + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("voided", $response->responseCode); + } + + public function test011USReferenceVoidCreditReturn() + { + ServicesContainer::configureService($this->setUpConfig('US')); + + $transData = $this->getTransactionData('US'); + + $response = $this->card->charge('6.00') + ->withCurrency('840') + ->withInvoiceNumber('1445444') + ->withAddress($this->address, AddressType::BILLING) + ->withAddress($this->address, AddressType::SHIPPING) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($response->referenceNumber); + + $referenceNumber = $response->referenceNumber; + + ServicesContainer::configureService($this->setUpConfig()); + + $transaction = Transaction::fromClientTransactionId($referenceNumber); + + $response = $transaction->void() + ->withCurrency('840') + ->withOriginalTransactionType(TransactionType::REFUND) + ->withAmount("6.00") + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("voided", $response->responseCode); + } + + public function test012CAReferenceVoidCreditReturn() + { + ServicesContainer::configureService($this->setUpConfig('CA')); + + $transData = $this->getTransactionData('CA'); + $transData->language = TransactionLanguage::EN_CA; + + $response = $this->card->refund('12.00') + ->withCurrency('124') + ->withInvoiceNumber('239087') + ->withAddress($this->addressCa, AddressType::BILLING) + ->withTransactionData($transData) + ->withAllowDuplicates(true) + ->execute(); + + $this->assertNotNull($response->referenceNumber); + + $referenceNumber = $response->referenceNumber; + + $transaction = Transaction::fromClientTransactionId($referenceNumber); + + $response = $transaction->void() + ->withCurrency('124') + ->withOriginalTransactionType(TransactionType::REFUND) + ->withAmount("12.00") + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("voided", $response->responseCode); + } + + # end credit void + + # credit edit + + public function test012USByCreditSaleId() + { + ServicesContainer::configureService($this->setUpConfig('US')); + + $transData = $this->getTransactionData('US'); + + $response = $this->card->charge('11.50') + ->withCurrency('840') + ->withInvoiceNumber('239087') + ->withAddress($this->address, AddressType::BILLING) + ->withAddress($this->address, AddressType::SHIPPING) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($response->transactionId); + + $creditSaleId = $response->transactionId; + + $transData = new TransactionApiData(); + $transData->generateReceipt = true; + + $transaction = Transaction::fromId($creditSaleId); + + $response = $transaction->edit() + ->withAmount("9.50") + ->withInvoiceNumber("239087") + ->withAllowDuplicates(true) + ->withGratuity("5.00") + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals($creditSaleId, $response->transactionId); + $this->assertEquals("approved", $response->responseCode); + } + + public function test013CAByCreditSaleId() + { + ServicesContainer::configureService($this->setUpConfig('CA')); + + $transData = $this->getTransactionData('CA'); + $transData->language = TransactionLanguage::EN_CA; + + $response = $this->card->charge('15.00') + ->withCurrency('124') + ->withInvoiceNumber('178988') + ->withAddress($this->address, AddressType::BILLING) + ->withAddress($this->address, AddressType::SHIPPING) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($response->transactionId); + + $creditSaleId = $response->transactionId; + $transaction = Transaction::fromId($creditSaleId, null, PaymentMethodType::CREDIT); + $transData = new TransactionApiData(); + $transData->generateReceipt = true; + $transaction->transactionId = $creditSaleId; + + $response = $transaction->edit() + ->withAmount("15.00") + ->withInvoiceNumber("178988") + ->withAllowDuplicates(true) + ->withGratuity("10.00") + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals($creditSaleId, $response->transactionId); + $this->assertEquals("approved", $response->responseCode); + } + + public function test014USByCreditSaleReferenceId() + { + $transData = $this->getTransactionData('US'); + + $response = $this->card->charge('17.90') + ->withCurrency('840') + ->withInvoiceNumber('1255552') + ->withAddress($this->address, AddressType::BILLING) + ->withAddress($this->address, AddressType::SHIPPING) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($response->referenceNumber); + + $creditRefId = $response->referenceNumber; + $transaction = Transaction::fromClientTransactionId($creditRefId); + $transData = new TransactionApiData(); + $transData->generateReceipt = true; + + $response = $transaction->edit() + ->withModifier(TransactionModifier::ADDITIONAL) + ->withAmount("10.00") + ->withInvoiceNumber("1255552") + ->withAllowDuplicates(true) + ->withGratuity("10.00") + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals($creditRefId, $response->referenceNumber); + $this->assertEquals("approved", $response->responseCode); + } + + public function test015CAByCreditSaleReferenceId() + { + ServicesContainer::configureService($this->setUpConfig('CA')); + + $transData = $this->getTransactionData('CA'); + $transData->language = TransactionLanguage::EN_CA; + + $response = $this->card->charge('11.00') + ->withCurrency('124') + ->withInvoiceNumber('178988') + ->withAddress($this->address, AddressType::BILLING) + ->withAddress($this->address, AddressType::SHIPPING) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($response->referenceNumber); + $creditSaleId = $response->transactionId; + + $creditRefId = $response->referenceNumber; + $transaction = Transaction::fromClientTransactionId($creditRefId); + $transData = new TransactionApiData(); + $transData->generateReceipt = true; + + $response = $transaction->edit() + ->withModifier(TransactionModifier::ADDITIONAL) + ->withAmount("9.00") + ->withInvoiceNumber("178988") + ->withAllowDuplicates(true) + ->withGratuity("5.00") + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals($creditRefId, $response->referenceNumber); + $this->assertEquals("approved", $response->responseCode); + } + + # end credit edit + + # partially approved + + public function test016USPartiallyApprovedCreditSale() + { + $transData = $this->getTransactionData('US'); + + $response = $this->card->charge('13.17') + ->withCurrency('840') + ->withInvoiceNumber('178988') + ->withAllowPartialAuth(true) + ->withAddress($this->address, AddressType::BILLING) + ->withAddress($this->address, AddressType::SHIPPING) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("partially_approved", $response->responseCode); + } + + public function test016USVoidedPartiallyApprovedCreditSale() + { + $transData = $this->getTransactionData('US'); + + $response = $this->card->charge('13.17') + ->withCurrency('840') + ->withInvoiceNumber('178988') + ->withAllowPartialAuth(true) + ->withAddress($this->address, AddressType::BILLING) + ->withAddress($this->address, AddressType::SHIPPING) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("partially_approved", $response->responseCode); + + $referenceNumber = $response->referenceNumber; + + ServicesContainer::configureService($this->setUpConfig()); + + $transaction = Transaction::fromClientTransactionId($referenceNumber); + + $response = $transaction->void() + ->withCurrency('840') + ->withOriginalTransactionType(TransactionType::SALE) + ->withAmount("5.32") + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("voided", $response->responseCode); + } + + public function test017CAPartiallyApprovedCreditSale() + { + ServicesContainer::configureService($this->setUpConfig('CA')); + + $transData = $this->getTransactionData( + 'CA', + CountryUtils::getNumericCodeByCountry('CA'), + TransactionLanguage::EN_CA + ); + + $response = $this->card->charge('13.17') + ->withCurrency('124') + ->withInvoiceNumber('167892') + ->withAllowPartialAuth(true) + ->withAddress($this->address, AddressType::BILLING) + ->withAddress($this->address, AddressType::SHIPPING) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("partially_approved", $response->responseCode); + } + + public function test017VoidedCAPartiallyApprovedCreditSale() + { + ServicesContainer::configureService($this->setUpConfig('CA')); + + $transData = $this->getTransactionData( + 'CA', + CountryUtils::getNumericCodeByCountry('CA'), + TransactionLanguage::EN_CA + ); + + $response = $this->card->charge('13.17') + ->withCurrency('124') + ->withInvoiceNumber('167892') + ->withAllowPartialAuth(true) + ->withAddress($this->address, AddressType::BILLING) + ->withAddress($this->address, AddressType::SHIPPING) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("partially_approved", $response->responseCode); + + $referenceNumber = $response->referenceNumber; + + ServicesContainer::configureService($this->setUpConfig()); + + $transaction = Transaction::fromClientTransactionId($referenceNumber); + + $response = $transaction->void() + ->withCurrency('124') + ->withOriginalTransactionType(TransactionType::SALE) + ->withAmount("5.32") + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("voided", $response->responseCode); + } + + # end partially approved + + private function getTransactionData($region, $countryCode = null, $lang = null) + { + $transData = new TransactionApiData(); + $transData->countryCode = isset($countryCode) ? $countryCode : CountryUtils::getNumericCodeByCountry('US'); + $transData->ecommerceIndicator = EcommerceIndicator::ECOMMERCE_INDICATOR_2; + $transData->language = isset($lang) ? $lang : TransactionLanguage::EN_US; + $transData->softDescriptor = "soft"; + $transData->region = $region; + return $transData; + } +} diff --git a/test/Integration/Gateways/TransactionApiConnector/TransactionApiReportingTest.php b/test/Integration/Gateways/TransactionApiConnector/TransactionApiReportingTest.php new file mode 100644 index 00000000..f0fc1b2c --- /dev/null +++ b/test/Integration/Gateways/TransactionApiConnector/TransactionApiReportingTest.php @@ -0,0 +1,364 @@ +setUpConfig()); + + $this->eCheck = new ECheck(); + $this->eCheck->accountNumber = '12121'; + $this->eCheck->accountType = "Checking"; + $this->eCheck->checkHolderName = 'Jane Doe'; + + $this->card = new CreditCardData(); + $this->card->number = "4263970000005262"; + $this->card->cvn = "131"; + $this->card->expMonth = date('m'); + $this->card->expYear = substr(date('Y', strtotime('+1 year')), -2); + $this->card->cardHolderName = "James Mason"; + + $this->address = new Address(); + $this->address->streetAddress1 = "2600 NW"; + $this->address->streetAddress2 = "23th Street"; + $this->address->city = "Lindon"; + $this->address->state = "Utah"; + $this->address->country = "USA"; + $this->address->postalCode = "84042"; + + $this->customer = new Customer(); + $this->customer->id = "2e39a948-2a9e-4b4a-9c59-0b96765343b7"; + $this->customer->title = "Mr."; + $this->customer->firstName = "Joe"; + $this->customer->middleName = "Henry"; + $this->customer->lastName = "Doe"; + $this->customer->businessName = "ABC Company LLC"; + $this->customer->email = "joe.doe@gmail.com"; + $this->customer->dateOfBirth = "1980-01-01"; + $this->customer->mobilePhone = new PhoneNumber('+35', '312345678', PhoneNumberType::MOBILE); + $this->customer->homePhone = new PhoneNumber('+1', '12345899', PhoneNumberType::HOME); + } + + public function setUpConfig() + { + $this->config = new TransactionApiConfig(); + $this->config->accountCredential = '800000052925:80039923:eWcWNJhfxiJ7QyEHSHndWk4VHKbSmSue'; + $this->config->apiSecret = 'lucQKkwz3W3RGzABkSWUVZj1Mb0Yx3E9chAA8ESUVAv'; + $this->config->apiKey = 'qeG6EWZOiAwk4jsiHzsh2BN8VkN2rdAs'; + $this->config->apiVersion = '2021-04-08'; + $this->config->apiPartnerName = 'mobile_sdk'; + $this->config->country = 'US'; + $this->config->requestLogger = new SampleRequestLogger(new Logger("logs")); + + return $this->config; + } + + public function test001CreditSaleByCreditSaleId() + { + $transData = $this->getTransactionData('US'); + + $response = $this->card->charge('31.70') + ->withCurrency('840') + ->withInvoiceNumber('178988') + ->withAddress($this->address, AddressType::BILLING) + ->withAddress($this->address, AddressType::SHIPPING) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($response->transactionId); + + $creditSaleId = $response->transactionId; + + $response = ReportingService::transactionDetail($creditSaleId) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("approved", $response->transactionStatus); + $this->assertEquals($creditSaleId, $response->transactionId); + } + + public function test002CreditSaleByReferenceId() + { + $transData = $this->getTransactionData('US'); + + $response = $this->card->charge('32.70') + ->withCurrency('840') + ->withInvoiceNumber('178988') + ->withAddress($this->address, AddressType::BILLING) + ->withAddress($this->address, AddressType::SHIPPING) + ->withTransactionData($transData) + ->execute(); + + $this->assertNotNull($response->referenceNumber); + + $referenceID = $response->referenceNumber; + + $response = ReportingService::findTransactions() + ->where(SearchCriteria::CLIENT_TRANSACTION_ID, $referenceID) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("approved", $response->transactionStatus); + $this->assertEquals($referenceID, $response->referenceNumber); + } + + public function test003CreditReturnByCreditReturnId() + { + $transData = $this->getTransactionData('US'); + + $response = $this->card->refund('33.70') + ->withCurrency('840') + ->withInvoiceNumber('239087') + ->withAddress($this->address, AddressType::BILLING) + ->withTransactionData($transData) + ->withAllowDuplicates(true) + ->execute(); + + $this->assertNotNull($response->transactionId); + + $creditReturnId = $response->transactionId; + + $transaction = Transaction::fromId($creditReturnId, null, PaymentMethodType::CREDIT); + + $response = ReportingService::transactionDetail($transaction) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("approved", $response->transactionStatus); + $this->assertEquals($creditReturnId, $response->transactionId); + } + + public function test004CreditReturnByCreditReferenceId() + { + $transData = $this->getTransactionData('US'); + + $response = $this->card->refund('34.70') + ->withCurrency('840') + ->withInvoiceNumber('239087') + ->withAddress($this->address, AddressType::BILLING) + ->withTransactionData($transData) + ->withAllowDuplicates(true) + ->execute(); + + $this->assertNotNull($response->referenceNumber); + $creditReferenceId = $response->referenceNumber; + + $transaction = Transaction::fromClientTransactionId($creditReferenceId); + + $response = ReportingService::transactionDetail($transaction) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("approved", $response->transactionStatus); + $this->assertEquals($creditReferenceId, $response->referenceNumber); + } + + public function test005CheckSaleById() + { + ServicesContainer::configureService($this->setUpConfig()); + $this->config->accountCredential = "800000052925:80039990:n7j9rGFUml1Du7rcRs7XGYdJdVMmZKzh"; + + $this->transData = $this->getTransactionDataAch( + 'US', + TransactionLanguage::EN_US, + CountryUtils::getNumericCodeByCountry('US') + ); + + $this->eCheck->checkNumber = (string)rand(); + $this->eCheck->routingNumber = '112000066'; + + $this->customer->id = null; + $this->customer->email = null; + $this->customer->mobilePhone = null; + + $response = $this->eCheck->charge(11) + ->withCurrency('840') + ->withEntryClass("PPD") + ->withTransactionData($this->transData) + ->withCustomerData($this->customer) + ->execute(); + + $this->assertNotNull($response->transactionReference->checkSaleId); + + $checkSaleId = $response->transactionReference->checkSaleId; + + $transaction = Transaction::fromId($checkSaleId, null, PaymentMethodType::ACH); + + $response = ReportingService::transactionDetail($transaction) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("check_submitted", $response->transactionStatus); + $this->assertEquals($checkSaleId, $response->transactionId); + } + + public function test006CheckSaleByRefId() + { + ServicesContainer::configureService($this->setUpConfig()); + $this->config->accountCredential = "800000052925:80039990:n7j9rGFUml1Du7rcRs7XGYdJdVMmZKzh"; + + $this->transData = $this->getTransactionDataAch( + 'US', + TransactionLanguage::EN_US, + CountryUtils::getNumericCodeByCountry('US') + ); + + $this->eCheck->checkNumber = (string)rand(); + $this->eCheck->routingNumber = '112000066'; + + $this->customer->id = null; + $this->customer->email = null; + $this->customer->mobilePhone = null; + + $response = $this->eCheck->charge(11) + ->withCurrency('840') + ->withEntryClass("PPD") + ->withTransactionData($this->transData) + ->withCustomerData($this->customer) + ->execute(); + + $this->assertNotNull($response->referenceNumber); + $checkRefId = $response->referenceNumber; + + $transaction = Transaction::fromClientTransactionId( + $checkRefId, + null, + PaymentMethodType::ACH + ); + + $response = ReportingService::transactionDetail($transaction) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("check_submitted", $response->transactionStatus); + $this->assertEquals($checkRefId, $response->referenceNumber); + } + + public function test007CheckRefundById() + { + ServicesContainer::configureService($this->setUpConfig()); + $this->config->accountCredential = "800000052925:80039990:n7j9rGFUml1Du7rcRs7XGYdJdVMmZKzh"; + + $this->transData = $this->getTransactionDataAch( + 'US', + TransactionLanguage::EN_US, + CountryUtils::getNumericCodeByCountry('US') + ); + + $this->eCheck->checkNumber = (string)rand(); + $this->eCheck->routingNumber = '112000066'; + + $this->customer->id = null; + $this->customer->email = null; + $this->customer->mobilePhone = null; + + $response = $this->eCheck->refund(13) + ->withCurrency('840') + ->withEntryClass("PPD") + ->withTransactionData($this->transData) + ->withCustomerData($this->customer) + ->execute(); + + $checkRefundId = $response->checkRefundId; + + $transaction = Transaction::fromId($checkRefundId, null, PaymentMethodType::ACH); + $transaction->originalTransactionType = "REFUND"; + + $response = ReportingService::transactionDetail($transaction) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("check_submitted", $response->transactionStatus); + $this->assertEquals($checkRefundId, $response->transactionId); + } + + public function test008CheckRefundByRefId() + { + ServicesContainer::configureService($this->setUpConfig()); + $this->config->accountCredential = "800000052925:80039990:n7j9rGFUml1Du7rcRs7XGYdJdVMmZKzh"; + + $this->transData = $this->getTransactionDataAch( + 'US', + TransactionLanguage::EN_US, + CountryUtils::getNumericCodeByCountry('US') + ); + + $this->eCheck->checkNumber = (string)rand(); + $this->eCheck->routingNumber = '112000066'; + + $this->customer->id = null; + $this->customer->email = null; + $this->customer->mobilePhone = null; + + $response = $this->eCheck->refund(15) + ->withCurrency('840') + ->withEntryClass("PPD") + ->withTransactionData($this->transData) + ->withCustomerData($this->customer) + ->execute(); + + $checkRefId = $response->referenceNumber; + + $transaction = Transaction::fromClientTransactionId( + $checkRefId, + null, + PaymentMethodType::ACH + ); + $transaction->originalTransactionType = "REFUND"; + + $response = ReportingService::transactionDetail($transaction) + ->execute(); + + $this->assertNotNull($response); + $this->assertEquals("check_submitted", $response->transactionStatus); + $this->assertEquals($checkRefId, $response->referenceNumber); + } + + private function getTransactionData($region, $countryCode = null, $lang = null) + { + $transData = new TransactionApiData(); + $transData->countryCode = isset($countryCode) ? $countryCode : CountryUtils::getNumericCodeByCountry('US'); + $transData->ecommerceIndicator = EcommerceIndicator::ECOMMERCE_INDICATOR_2; + $transData->language = isset($lang) ? $lang : TransactionLanguage::EN_US; + $transData->softDescriptor = "soft"; + $transData->region = $region; + return $transData; + } + + private function getTransactionDataAch($region, $language, $countryCode) + { + $this->transData = new TransactionApiData(); + $this->transData->countryCode = $countryCode; + $this->transData->language = $language; + $this->transData->region = $region; + $this->transData->checkVerify = false; + + return $this->transData; + } +}