diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..0c9db577 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,14 @@ +# CiviCRM editor configuration normalization +# @see http://editorconfig.org/ + +# This is the top-most .editorconfig file; do not search in parent directories. +root = true + +# All files. +[*] +end_of_line = LF +indent_style = space +indent_size = 4 +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/.travis.yml b/.travis.yml index 4893becf..741f61d1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,18 +1,31 @@ language: php php: - - 5.3 - - 5.4 - - 5.5 - 5.6 - 7.0 - - hhvm + - 7.1 + - 7.2 + +# This triggers builds to run on the new TravisCI infrastructure. +# See: http://docs.travis-ci.com/user/workers/container-based-infrastructure/ +sudo: false + +## Cache composer +cache: + directories: + - $HOME/.composer/cache + +env: + global: + - setup=basic matrix: - allow_failures: - - php: hhvm + include: + - php: 5.6 + env: setup=lowest -before_script: - - composer install -n --dev --prefer-source +install: + - if [[ $setup = 'basic' ]]; then travis_retry composer install --prefer-dist --no-interaction; fi + - if [[ $setup = 'lowest' ]]; then travis_retry composer update --prefer-dist --no-interaction --prefer-lowest --prefer-stable; fi script: vendor/bin/phpcs --standard=PSR2 src && vendor/bin/phpunit --coverage-text diff --git a/README.md b/README.md index daad684c..9c289280 100644 --- a/README.md +++ b/README.md @@ -11,21 +11,11 @@ processing library for PHP 5.3+. This package implements Authorize.Net support f ## Installation -Omnipay is installed via [Composer](http://getcomposer.org/). To install, simply add it -to your `composer.json` file: - -```json -{ - "require": { - "omnipay/authorizenet": "~2.0" - } -} -``` - -And run composer to update your dependencies: +Omnipay is installed via [Composer](http://getcomposer.org/). To install, simply require `league/omnipay` and `omnipay/authorizenet` with Composer: - $ curl -s http://getcomposer.org/installer | php - $ php composer.phar update +``` +composer require league/omnipay omnipay/authorizenet:"3.x@dev" +``` ## Basic Usage diff --git a/composer.json b/composer.json index 402d88fb..6ccff1e5 100644 --- a/composer.json +++ b/composer.json @@ -28,14 +28,22 @@ "psr-4": { "Omnipay\\AuthorizeNet\\" : "src/" } }, "require": { - "omnipay/common": "~2.2" + "omnipay/common": "^3" }, "require-dev": { - "omnipay/tests": "~2.0" + "omnipay/tests": "^3", + "squizlabs/php_codesniffer": "^3", + "phpro/grumphp": "^0.14" }, "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "3.0.x-dev" } - } + }, + "scripts": { + "test": "phpunit", + "check-style": "phpcs -p --standard=PSR2 src/", + "fix-style": "phpcbf -p --standard=PSR2 src/" + }, + "prefer-stable": true } diff --git a/grumphp.yml b/grumphp.yml new file mode 100644 index 00000000..4b767a09 --- /dev/null +++ b/grumphp.yml @@ -0,0 +1,15 @@ +parameters: + git_dir: . + bin_dir: vendor/bin + tasks: + phpunit: + config_file: ~ + testsuite: ~ + group: [] + always_execute: false + phpcs: + standard: PSR2 + warning_severity: ~ + ignore_patterns: + - tests/ + triggered_by: [php] \ No newline at end of file diff --git a/phpunit.xml.dist b/phpunit.xml.dist index a35b7362..535809e1 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -14,9 +14,6 @@ ./tests/ - - - ./src diff --git a/src/AIMGateway.php b/src/AIMGateway.php index 683ed160..c4effed3 100644 --- a/src/AIMGateway.php +++ b/src/AIMGateway.php @@ -4,7 +4,9 @@ use Omnipay\AuthorizeNet\Message\AIMAuthorizeRequest; use Omnipay\AuthorizeNet\Message\AIMCaptureRequest; +use Omnipay\AuthorizeNet\Message\AIMPaymentPlanQueryResponse; use Omnipay\AuthorizeNet\Message\AIMPurchaseRequest; +use Omnipay\AuthorizeNet\Message\QueryRequest; use Omnipay\AuthorizeNet\Message\AIMRefundRequest; use Omnipay\AuthorizeNet\Message\AIMVoidRequest; use Omnipay\Common\AbstractGateway; @@ -26,6 +28,7 @@ public function getDefaultParameters() 'transactionKey' => '', 'testMode' => false, 'developerMode' => false, + 'hashSecret' => '', 'liveEndpoint' => 'https://api2.authorize.net/xml/v1/request.api', 'developerEndpoint' => 'https://apitest.authorize.net/xml/v1/request.api', ); @@ -61,6 +64,16 @@ public function setDeveloperMode($value) return $this->setParameter('developerMode', $value); } + public function setHashSecret($value) + { + return $this->setParameter('hashSecret', $value); + } + + public function getHashSecret() + { + return $this->getParameter('hashSecret'); + } + public function setEndpoints($endpoints) { $this->setParameter('liveEndpoint', $endpoints['live']); @@ -115,6 +128,15 @@ public function capture(array $parameters = array()) return $this->createRequest('\Omnipay\AuthorizeNet\Message\AIMCaptureRequest', $parameters); } + /** + * @param array $parameters + * @return AIMCaptureOnlyRequest + */ + public function captureOnly(array $parameters = array()) + { + return $this->createRequest('\Omnipay\AuthorizeNet\Message\AIMCaptureOnlyRequest', $parameters); + } + /** * @param array $parameters * @return AIMPurchaseRequest @@ -141,4 +163,58 @@ public function refund(array $parameters = array()) { return $this->createRequest('\Omnipay\AuthorizeNet\Message\AIMRefundRequest', $parameters); } + + /** + * @param array $parameters + * @return AIMPaymentPlansQueryRequest + */ + public function paymentPlansQuery(array $parameters = array()) + { + return $this->createRequest('\Omnipay\AuthorizeNet\Message\Query\AIMPaymentPlansQueryRequest', $parameters); + } + + /** + * @param array $parameters + * @return AIMPaymentPlanQueryResponse + */ + public function paymentPlanQuery(array $parameters = array()) + { + return $this->createRequest('\Omnipay\AuthorizeNet\Message\Query\AIMPaymentPlanQueryRequest', $parameters); + } + + /** + * @param array $parameters + * @return QueryResponse + */ + public function query(array $parameters = array()) + { + return $this->createRequest('\Omnipay\AuthorizeNet\Message\Query\QueryRequest', $parameters); + } + + /** + * @param array $parameters + * @return QueryBatchResponse + */ + public function queryBatch(array $parameters = array()) + { + return $this->createRequest('\Omnipay\AuthorizeNet\Message\QueryBatchRequest', $parameters); + } + + /** + * @param array $parameters + * @return QueryBatchDetailResponse + */ + public function queryBatchDetail(array $parameters = array()) + { + return $this->createRequest('\Omnipay\AuthorizeNet\Message\QueryBatchDetailRequest', $parameters); + } + + /** + * @param array $parameters + * @return QueryDetailResponse + */ + public function queryDetail(array $parameters = array()) + { + return $this->createRequest('\Omnipay\AuthorizeNet\Message\QueryDetailRequest', $parameters); + } } diff --git a/src/Message/AIMAbstractRequest.php b/src/Message/AIMAbstractRequest.php index d769f73d..3608c581 100644 --- a/src/Message/AIMAbstractRequest.php +++ b/src/Message/AIMAbstractRequest.php @@ -60,6 +60,7 @@ public function getHashSecret() { return $this->getParameter('hashSecret'); } + public function setHashSecret($value) { return $this->setParameter('hashSecret', $value); @@ -100,6 +101,26 @@ public function getEndpoint() return $this->getDeveloperMode() ? $this->getDeveloperEndpoint() : $this->getLiveEndpoint(); } + public function getSolutionId() + { + return $this->getParameter('solutionId'); + } + + public function setSolutionId($value) + { + return $this->setParameter('solutionId', $value); + } + + public function getAuthCode() + { + return $this->getParameter('authCode'); + } + + public function setAuthCode($value) + { + return $this->setParameter('authCode', $value); + } + /** * @return TransactionReference */ @@ -203,9 +224,9 @@ public function sendData($data) $headers = array('Content-Type' => 'text/xml; charset=utf-8'); $data = $data->saveXml(); - $httpResponse = $this->httpClient->post($this->getEndpoint(), $headers, $data)->send(); + $httpResponse = $this->httpClient->request('POST', $this->getEndpoint(), $headers, $data); - return $this->response = new AIMResponse($this, $httpResponse->getBody()); + return $this->response = new AIMResponse($this, $httpResponse->getBody()->getContents()); } /** @@ -249,6 +270,15 @@ protected function addTransactionType(\SimpleXMLElement $data) $data->transactionRequest->transactionType = $this->action; } + protected function addSolutionId(\SimpleXMLElement $data) + { + $solutionId = $this->getSolutionId(); + + if (!empty($solutionId)) { + $data->transactionRequest->solution->id = $solutionId; + } + } + /** * Adds billing data to a partially filled request data object. * diff --git a/src/Message/AIMAuthorizeRequest.php b/src/Message/AIMAuthorizeRequest.php index cdaed951..5b863feb 100644 --- a/src/Message/AIMAuthorizeRequest.php +++ b/src/Message/AIMAuthorizeRequest.php @@ -17,6 +17,7 @@ public function getData() $data = $this->getBaseData(); $data->transactionRequest->amount = $this->getAmount(); $this->addPayment($data); + $this->addSolutionId($data); $this->addBillingData($data); $this->addCustomerIP($data); $this->addTransactionSettings($data); @@ -41,7 +42,9 @@ protected function addPayment(\SimpleXMLElement $data) $card->validate(); $data->transactionRequest->payment->creditCard->cardNumber = $card->getNumber(); $data->transactionRequest->payment->creditCard->expirationDate = $card->getExpiryDate('my'); - $data->transactionRequest->payment->creditCard->cardCode = $card->getCvv(); + if (!empty($card->getCvv())) { + $data->transactionRequest->payment->creditCard->cardCode = $card->getCvv(); + } } protected function addCustomerIP(\SimpleXMLElement $data) diff --git a/src/Message/AIMCaptureOnlyRequest.php b/src/Message/AIMCaptureOnlyRequest.php new file mode 100644 index 00000000..f6f6cbdb --- /dev/null +++ b/src/Message/AIMCaptureOnlyRequest.php @@ -0,0 +1,28 @@ +validate('amount'); + $data = $this->getBaseData(); + $data->transactionRequest->amount = $this->getAmount(); + $this->addPayment($data); + $data->transactionRequest->authCode = $this->getAuthCode(); + $this->addSolutionId($data); + $this->addBillingData($data); + $this->addCustomerIP($data); + $this->addTransactionSettings($data); + + return $data; + } +} diff --git a/src/Message/AIMResponse.php b/src/Message/AIMResponse.php index 020b51d8..785b6c24 100644 --- a/src/Message/AIMResponse.php +++ b/src/Message/AIMResponse.php @@ -59,8 +59,8 @@ public function isSuccessful() public function getResultCode() { // If there is a transaction response, then we get the code from that. - if (isset($this->data->transactionResponse[0])) { - return intval((string)$this->data->transactionResponse[0]->responseCode); + if (isset($this->data->transactionResponse)) { + return intval((string)$this->data->transactionResponse->responseCode); } // No transaction response, so return 3 aka "error". @@ -76,17 +76,15 @@ public function getReasonCode() { $code = null; - if (isset($this->data->transactionResponse[0]->messages)) { + if (isset($this->data->transactionResponse->messages)) { // In case of a successful transaction, a "messages" element is present - $code = intval((string)$this->data->transactionResponse[0]->messages[0]->message->code); - - } elseif (isset($this->data->transactionResponse[0]->errors)) { + $code = intval((string)$this->data->transactionResponse->messages->message->code); + } elseif (isset($this->data->transactionResponse->errors)) { // In case of an unsuccessful transaction, an "errors" element is present - $code = intval((string)$this->data->transactionResponse[0]->errors[0]->error->errorCode); - - } elseif (isset($this->data->messages[0]->message)) { + $code = intval((string)$this->data->transactionResponse->errors->error->errorCode); + } elseif (isset($this->data->messages->message)) { // In case of invalid request, the top-level message provides details. - $code = (string)$this->data->messages[0]->message->code; + $code = (string)$this->data->messages->message->code; } return $code; @@ -101,17 +99,15 @@ public function getMessage() { $message = null; - if (isset($this->data->transactionResponse[0]->messages)) { + if (isset($this->data->transactionResponse->messages)) { // In case of a successful transaction, a "messages" element is present - $message = (string)$this->data->transactionResponse[0]->messages[0]->message->description; - - } elseif (isset($this->data->transactionResponse[0]->errors)) { + $message = (string)$this->data->transactionResponse->messages->message->description; + } elseif (isset($this->data->transactionResponse->errors)) { // In case of an unsuccessful transaction, an "errors" element is present - $message = (string)$this->data->transactionResponse[0]->errors[0]->error->errorText; - - } elseif (isset($this->data->messages[0]->message)) { + $message = (string)$this->data->transactionResponse->errors->error->errorText; + } elseif (isset($this->data->messages->message)) { // In case of invalid request, the top-level message provides details. - $message = (string)$this->data->messages[0]->message->text; + $message = (string)$this->data->messages->message->text; } return $message; @@ -119,8 +115,8 @@ public function getMessage() public function getAuthorizationCode() { - if (isset($this->data->transactionResponse[0])) { - return (string)$this->data->transactionResponse[0]->authCode; + if (isset($this->data->transactionResponse)) { + return (string)$this->data->transactionResponse->authCode; } else { return ''; } @@ -133,13 +129,26 @@ public function getAuthorizationCode() */ public function getAVSCode() { - if (isset($this->data->transactionResponse[0])) { - return (string)$this->data->transactionResponse[0]->avsResultCode; + if (isset($this->data->transactionResponse)) { + return (string)$this->data->transactionResponse->avsResultCode; + } else { + return ''; + } + } + + /** + * Returns the Card Code Verfication return code. + * + * @return string A single character. Can be M, N, P, S, or U. + */ + public function getCVVCode() + { + if (isset($this->data->transactionResponse[0]->cvvResultCode)) { + return (string)$this->data->transactionResponse[0]->cvvResultCode; } else { return ''; } } - /** * A composite key containing the gateway provided transaction reference as * well as other data points that may be required for subsequent transactions @@ -153,8 +162,8 @@ public function getTransactionReference($serialize = true) // The transactionResponse is only returned if succesful or declined // for some reason, so don't assume it will always be there. - if (isset($this->data->transactionResponse[0])) { - $body = $this->data->transactionResponse[0]; + if (isset($this->data->transactionResponse)) { + $body = $this->data->transactionResponse; $transactionRef = new TransactionReference(); $transactionRef->setApprovalCode((string)$body->authCode); $transactionRef->setTransId((string)$body->transId); @@ -177,4 +186,19 @@ public function getTransactionReference($serialize = true) return ''; } + + /** + * Returns the account type used for the transaction. + * + * @return string A multicharacter string. + * Can be Visa, MasterCard, Discover, AmericanExpress, DinersClub, JCB, or eCheck. + */ + public function getAccountType() + { + if (isset($this->data->transactionResponse[0]->accountType)) { + return (string)$this->data->transactionResponse[0]->accountType; + } else { + return ''; + } + } } diff --git a/src/Message/CIMAbstractRequest.php b/src/Message/CIMAbstractRequest.php index 74d057bd..7e055c43 100644 --- a/src/Message/CIMAbstractRequest.php +++ b/src/Message/CIMAbstractRequest.php @@ -104,8 +104,8 @@ public function sendData($data) $headers = array('Content-Type' => 'text/xml; charset=utf-8'); $data = $data->saveXml(); - $httpResponse = $this->httpClient->post($this->getEndpoint(), $headers, $data)->send(); + $httpResponse = $this->httpClient->request('POST', $this->getEndpoint(), $headers, $data); - return $this->response = new CIMResponse($this, $httpResponse->getBody()); + return $this->response = new CIMResponse($this, $httpResponse->getBody()->getContents()); } } diff --git a/src/Message/CIMAbstractResponse.php b/src/Message/CIMAbstractResponse.php index e02d7a7a..efa4c8e1 100644 --- a/src/Message/CIMAbstractResponse.php +++ b/src/Message/CIMAbstractResponse.php @@ -27,7 +27,7 @@ public function __construct(RequestInterface $request, $data) // Check if this is an error response $isError = strpos((string)$data, 'responseType; + $xmlRootElement = ($isError !== false ? 'ErrorResponse' : $this->responseType); // Strip out the xmlns junk so that PHP can parse the XML $xml = preg_replace('/<' . $xmlRootElement . '[^>]+>/', '<' . $xmlRootElement . '>', (string)$data); @@ -58,7 +58,7 @@ public function isSuccessful() */ public function getResultCode() { - $result = (string)$this->data['messages'][0]['resultCode']; + $result = (string)$this->data['messages']['resultCode']; switch ($result) { case 'Ok': @@ -67,7 +67,6 @@ public function getResultCode() return static::TRANSACTION_RESULT_CODE_ERROR; default: return null; - } } @@ -82,7 +81,7 @@ public function getReasonCode() if (isset($this->data['messages'])) { // In case of a successful transaction, a "messages" element is present - $code = (string)$this->data['messages'][0]['message'][0]['code']; + $code = (string)$this->data['messages']['message']['code']; } return $code; @@ -114,8 +113,7 @@ public function getMessage() if (isset($this->data['messages'])) { // In case of a successful transaction, a "messages" element is present - $message = (string)$this->data['messages'][0]['message'][0]['text']; - + $message = (string)$this->data['messages']['message']['text']; } return $message; @@ -155,13 +153,15 @@ public function getCardReference() */ public function xml2array(\SimpleXMLElement $xml) { + return json_decode(json_encode($xml), true); + $arr = array(); foreach ($xml as $element) { $tag = $element->getName(); $e = get_object_vars($element); - if (!empty($e)) { + if (! empty($e)) { $arr[$tag][] = $element instanceof \SimpleXMLElement ? $this->xml2array($element) : $e; } else { $arr[$tag] = trim($element); diff --git a/src/Message/CIMCreateCardRequest.php b/src/Message/CIMCreateCardRequest.php index 81fa4b37..99313b66 100644 --- a/src/Message/CIMCreateCardRequest.php +++ b/src/Message/CIMCreateCardRequest.php @@ -152,9 +152,9 @@ public function sendData($data) { $headers = array('Content-Type' => 'text/xml; charset=utf-8'); $data = $data->saveXml(); - $httpResponse = $this->httpClient->post($this->getEndpoint(), $headers, $data)->send(); + $httpResponse = $this->httpClient->request('POST', $this->getEndpoint(), $headers, $data); - $response = new CIMCreateCardResponse($this, $httpResponse->getBody()); + $response = new CIMCreateCardResponse($this, $httpResponse->getBody()->getContents()); if (!$response->isSuccessful() && $response->getReasonCode() == 'E00039') { // Duplicate profile. Try adding a new payment profile for the same profile and get the response diff --git a/src/Message/CIMCreateCardResponse.php b/src/Message/CIMCreateCardResponse.php index 8139b4fd..aee6639f 100644 --- a/src/Message/CIMCreateCardResponse.php +++ b/src/Message/CIMCreateCardResponse.php @@ -20,7 +20,7 @@ public function getCustomerProfileId() public function getCustomerPaymentProfileId() { if ($this->isSuccessful()) { - return $this->data['customerPaymentProfileIdList'][0]['numericString']; + return $this->data['customerPaymentProfileIdList']['numericString']; } return null; } diff --git a/src/Message/CIMCreatePaymentProfileRequest.php b/src/Message/CIMCreatePaymentProfileRequest.php index 5948165b..f2c4ed92 100644 --- a/src/Message/CIMCreatePaymentProfileRequest.php +++ b/src/Message/CIMCreatePaymentProfileRequest.php @@ -43,8 +43,8 @@ public function sendData($data) { $headers = array('Content-Type' => 'text/xml; charset=utf-8'); $data = $data->saveXml(); - $httpResponse = $this->httpClient->post($this->getEndpoint(), $headers, $data)->send(); + $httpResponse = $this->httpClient->request('POST', $this->getEndpoint(), $headers, $data); - return $this->response = new CIMCreatePaymentProfileResponse($this, $httpResponse->getBody()); + return $this->response = new CIMCreatePaymentProfileResponse($this, $httpResponse->getBody()->getContents()); } } diff --git a/src/Message/CIMDeletePaymentProfileRequest.php b/src/Message/CIMDeletePaymentProfileRequest.php index 4b30ac10..afb4c246 100644 --- a/src/Message/CIMDeletePaymentProfileRequest.php +++ b/src/Message/CIMDeletePaymentProfileRequest.php @@ -24,8 +24,8 @@ public function sendData($data) { $headers = array('Content-Type' => 'text/xml; charset=utf-8'); $data = $data->saveXml(); - $httpResponse = $this->httpClient->post($this->getEndpoint(), $headers, $data)->send(); + $httpResponse = $this->httpClient->request('POST', $this->getEndpoint(), $headers, $data); - return $this->response = new CIMDeletePaymentProfileResponse($this, $httpResponse->getBody()); + return $this->response = new CIMDeletePaymentProfileResponse($this, $httpResponse->getBody()->getContents()); } } diff --git a/src/Message/CIMGetPaymentProfileRequest.php b/src/Message/CIMGetPaymentProfileRequest.php index a8da6cf6..2181fdc4 100644 --- a/src/Message/CIMGetPaymentProfileRequest.php +++ b/src/Message/CIMGetPaymentProfileRequest.php @@ -25,8 +25,8 @@ public function sendData($data) { $headers = array('Content-Type' => 'text/xml; charset=utf-8'); $data = $data->saveXml(); - $httpResponse = $this->httpClient->post($this->getEndpoint(), $headers, $data)->send(); + $httpResponse = $this->httpClient->request('POST', $this->getEndpoint(), $headers, $data); - return $this->response = new CIMGetPaymentProfileResponse($this, $httpResponse->getBody()); + return $this->response = new CIMGetPaymentProfileResponse($this, $httpResponse->getBody()->getContents()); } } diff --git a/src/Message/CIMGetPaymentProfileResponse.php b/src/Message/CIMGetPaymentProfileResponse.php index f97f2292..2de602ba 100644 --- a/src/Message/CIMGetPaymentProfileResponse.php +++ b/src/Message/CIMGetPaymentProfileResponse.php @@ -12,7 +12,7 @@ class CIMGetPaymentProfileResponse extends CIMCreatePaymentProfileResponse public function getCustomerPaymentProfileId() { if ($this->isSuccessful()) { - return $this->data['paymentProfile'][0]['customerPaymentProfileId']; + return $this->data['paymentProfile']['customerPaymentProfileId']; } return null; } diff --git a/src/Message/CIMGetProfileRequest.php b/src/Message/CIMGetProfileRequest.php index 5f755475..caaea8e9 100644 --- a/src/Message/CIMGetProfileRequest.php +++ b/src/Message/CIMGetProfileRequest.php @@ -24,8 +24,8 @@ public function sendData($data) { $headers = array('Content-Type' => 'text/xml; charset=utf-8'); $data = $data->saveXml(); - $httpResponse = $this->httpClient->post($this->getEndpoint(), $headers, $data)->send(); + $httpResponse = $this->httpClient->request('POST', $this->getEndpoint(), $headers, $data); - return $this->response = new CIMGetProfileResponse($this, $httpResponse->getBody()); + return $this->response = new CIMGetProfileResponse($this, $httpResponse->getBody()->getContents()); } } diff --git a/src/Message/CIMGetProfileResponse.php b/src/Message/CIMGetProfileResponse.php index 41fc503b..b7e03be8 100644 --- a/src/Message/CIMGetProfileResponse.php +++ b/src/Message/CIMGetProfileResponse.php @@ -26,9 +26,9 @@ public function getMatchingPaymentProfileId($last4) return null; } - foreach ($this->data['profile'][0]['paymentProfiles'] as $paymentProfile) { + foreach ($this->data['profile']['paymentProfiles'] as $paymentProfile) { // For every payment profile check if the last4 matches the last4 of the card in request. - $cardLast4 = substr($paymentProfile['payment'][0]['creditCard'][0]['cardNumber'], -4); + $cardLast4 = substr($paymentProfile['payment']['creditCard']['cardNumber'], -4); if ($last4 == $cardLast4) { return (string)$paymentProfile['customerPaymentProfileId']; } diff --git a/src/Message/CIMUpdatePaymentProfileRequest.php b/src/Message/CIMUpdatePaymentProfileRequest.php index 37a7e1a9..4677adfb 100644 --- a/src/Message/CIMUpdatePaymentProfileRequest.php +++ b/src/Message/CIMUpdatePaymentProfileRequest.php @@ -44,8 +44,8 @@ public function sendData($data) { $headers = array('Content-Type' => 'text/xml; charset=utf-8'); $data = $data->saveXml(); - $httpResponse = $this->httpClient->post($this->getEndpoint(), $headers, $data)->send(); + $httpResponse = $this->httpClient->request('POST', $this->getEndpoint(), $headers, $data); - return $this->response = new CIMUpdatePaymentProfileResponse($this, $httpResponse->getBody()); + return $this->response = new CIMUpdatePaymentProfileResponse($this, $httpResponse->getBody()->getContents()); } } diff --git a/src/Message/Query/AIMAbstractQueryRequest.php b/src/Message/Query/AIMAbstractQueryRequest.php new file mode 100644 index 00000000..9f719070 --- /dev/null +++ b/src/Message/Query/AIMAbstractQueryRequest.php @@ -0,0 +1,63 @@ +limit; + } + + /** + * Set Limit. + * + * @param int $limit + */ + public function setLimit($limit) + { + $this->limit = $limit; + } + + /** + * Get offset. + * + * @return int + */ + public function getOffset() + { + return $this->offset; + } + + /** + * Set offset. + * + * @param int $offset + */ + public function setOffset($offset) + { + $this->offset = $offset; + } + + /** + * Get data to send. + */ + public function getData() + { + $data = $this->getBaseData(); + return $data; + } +} diff --git a/src/Message/Query/AIMPaymentPlanQueryRequest.php b/src/Message/Query/AIMPaymentPlanQueryRequest.php new file mode 100644 index 00000000..244b4a73 --- /dev/null +++ b/src/Message/Query/AIMPaymentPlanQueryRequest.php @@ -0,0 +1,54 @@ +recurringReference; + } + + /** + * @param string $recurringReference + */ + public function setRecurringReference($recurringReference) + { + $this->recurringReference = $recurringReference; + } + + /** + * Get data to send. + */ + public function getData() + { + $data = $this->getBaseData(); + $data->subscriptionId = $this->getRecurringReference(); + return $data; + } + + protected function addTransactionType(\SimpleXMLElement $data) + { + } + + public function sendData($data) + { + $headers = array('Content-Type' => 'text/xml; charset=utf-8'); + $data = $data->saveXml(); + $httpResponse = $this->httpClient->request('POST', $this->getEndpoint(), $headers, $data); + + return $this->response = new AIMPaymentPlanQueryResponse($this, $httpResponse->getBody()->getContents()); + } +} diff --git a/src/Message/Query/AIMPaymentPlanQueryResponse.php b/src/Message/Query/AIMPaymentPlanQueryResponse.php new file mode 100644 index 00000000..167f73f7 --- /dev/null +++ b/src/Message/Query/AIMPaymentPlanQueryResponse.php @@ -0,0 +1,135 @@ +]+>/', '', (string)$data); + try { + $xml = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOWARNING); + } catch (\Exception $e) { + throw new InvalidResponseException(); + } + + if (!$xml) { + throw new InvalidResponseException(); + } + + parent::__construct($request, $xml); + $result = $this->xml2array($this->data->subscription, true); + $this->subscription = $result['subscription'][0]; + } + + public function isSuccessful() + { + return 1 === $this->getResultCode(); + } + + public function getData() + { + return $this->subscription; + } + + public function getRecurStartDate() + { + return $this->subscription['paymentSchedule']['interval']['startDate']; + } + + public function getRecurInstallmentLimit() + { + return $this->subscription['paymentSchedule']['interval']['totalOccurrences']; + } + + public function getRecurrenceInterval() + { + return $this->subscription['paymentSchedule']['interval'][0]['length']; + } + + public function getRecurAmount() + { + return $this->subscription['amount']; + } + + public function getRecurReference() + { + return $this->subscription; + } + + public function getContactReference() + { + $profileID = $this->subscription['profile'][0]['customerProfileId']; + $gateway = $gateway = Omnipay::create('AuthorizeNet_CIM'); + $gateway->setApiLoginId($this->request->getApiLoginId()); + $gateway->setHashSecret($this->request->getHashSecret()); + $gateway->setTransactionKey($this->request->getTransactionKey()); + $data = array( + 'customerProfileId' => $profileID, + 'customerPaymentProfileId' => + $this->subscription['profile'][0]['paymentProfile'][0]['customerPaymentProfileId'], + ); + $dataResponse = $gateway->getProfile($data)->send(); + return $dataResponse->getCustomerId(); + } + + /** + * @todo formalise options. + * + * @return mixed + */ + public function getRecurStatus() + { + return $this->subscription['paymentSchedule']['interval'][0]['status']; + } + + public function getRecurrenceUnit() + { + $interval = $this->subscription['paymentSchedule']['interval'][0]['unit']; + $options = array( + 'months' => 'month', + ); + return $options[$interval]; + } + + /** + * http://bookofzeus.com/articles/convert-simplexml-object-into-php-array/ + * + * Convert a simpleXMLElement in to an array + * + * @todo this is duplicated from CIMAbstractResponse. Put somewhere shared. + * + * @param \SimpleXMLElement $xml + * + * @return array + */ + public function xml2array(\SimpleXMLElement $xml) + { + $arr = array(); + foreach ($xml as $element) { + $tag = $element->getName(); + $e = get_object_vars($element); + if (!empty($e)) { + $arr[$tag][] = $element instanceof \SimpleXMLElement ? $this->xml2array($element) : $e; + } else { + $arr[$tag] = trim($element); + } + } + + return $arr; + } +} diff --git a/src/Message/Query/AIMPaymentPlansQueryRequest.php b/src/Message/Query/AIMPaymentPlansQueryRequest.php new file mode 100644 index 00000000..77c4e6f1 --- /dev/null +++ b/src/Message/Query/AIMPaymentPlansQueryRequest.php @@ -0,0 +1,53 @@ +limit; + } + + /** + * Get data to send. + */ + public function getData() + { + $data = $this->getBaseData(); + $data->searchType = 'subscriptionActive'; + $data->sorting->orderBy = 'id'; + $data->sorting->orderDescending = true; + $data->paging->limit = $this->getLimit(); + $data->paging->offset = $this->getOffset(); + return $data; + } + + protected function addTransactionType(\SimpleXMLElement $data) + { + } + + public function sendData($data) + { + $headers = array('Content-Type' => 'text/xml; charset=utf-8'); + $data = $data->saveXml(); + $httpResponse = $this->httpClient->request('POST', $this->getEndpoint(), $headers, $data); + + return $this->response = new AIMPaymentPlansQueryResponse($this, $httpResponse->getBody()->getContents()); + } +} diff --git a/src/Message/Query/AIMPaymentPlansQueryResponse.php b/src/Message/Query/AIMPaymentPlansQueryResponse.php new file mode 100644 index 00000000..c0830f90 --- /dev/null +++ b/src/Message/Query/AIMPaymentPlansQueryResponse.php @@ -0,0 +1,44 @@ +]+>/', '', (string)$data); + + try { + $xml = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOWARNING); + } catch (\Exception $e) { + throw new InvalidResponseException(); + } + + if (!$xml) { + throw new InvalidResponseException(); + } + + parent::__construct($request, $xml); + } + + public function isSuccessful() + { + return 1 === $this->getResultCode(); + } + + public function getPlanData() + { + $result = $this->xml2array($this->data->subscriptionDetails, true); + return $result['subscriptionDetails'][0]['subscriptionDetail']; + } +} diff --git a/src/Message/Query/AbstractQueryResponse.php b/src/Message/Query/AbstractQueryResponse.php new file mode 100644 index 00000000..b4414fdb --- /dev/null +++ b/src/Message/Query/AbstractQueryResponse.php @@ -0,0 +1,43 @@ +getName(); + $e = get_object_vars($element); + if (!empty($e)) { + $arr[$tag][] = $element instanceof \SimpleXMLElement ? $this->xml2array($element) : $e; + } else { + $arr[$tag] = trim($element); + } + } + + return $arr; + } +} diff --git a/src/Message/Query/QueryBatchDetailRequest.php b/src/Message/Query/QueryBatchDetailRequest.php new file mode 100644 index 00000000..b390661c --- /dev/null +++ b/src/Message/Query/QueryBatchDetailRequest.php @@ -0,0 +1,46 @@ +getBaseData(); + $data->batchId = $this->getBatchID(); + return $data; + } + + public function sendData($data) + { + $headers = array('Content-Type' => 'text/xml; charset=utf-8'); + $data = $data->saveXml(); + $httpResponse = $this->httpClient->request('POST', $this->getEndpoint(), $headers, $data); + + return $this->response = new QueryBatchDetailResponse($this, $httpResponse->getBody()->getContents()); + } + + public function setBatchID($batchID) + { + $this->batchID = $batchID; + } + + public function getBatchID() + { + return $this->batchID; + } +} diff --git a/src/Message/Query/QueryBatchDetailResponse.php b/src/Message/Query/QueryBatchDetailResponse.php new file mode 100644 index 00000000..6d89bf70 --- /dev/null +++ b/src/Message/Query/QueryBatchDetailResponse.php @@ -0,0 +1,44 @@ +]+>/', '', (string)$data); + try { + $xml = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOWARNING); + } catch (\Exception $e) { + throw new InvalidResponseException(); + } + + if (!$xml) { + throw new InvalidResponseException(); + } + + parent::__construct($request, $xml); + } + + public function isSuccessful() + { + return 1 === $this->getResultCode(); + } + + public function getData() + { + $result = $this->xml2array($this->data->transactions, true); + return $result['transactions'][0]['transaction']; + } +} diff --git a/src/Message/Query/QueryBatchRequest.php b/src/Message/Query/QueryBatchRequest.php new file mode 100644 index 00000000..d9aa6684 --- /dev/null +++ b/src/Message/Query/QueryBatchRequest.php @@ -0,0 +1,23 @@ + 'text/xml; charset=utf-8'); + $data = $data->saveXml(); + $httpResponse = $this->httpClient->request('POST', $this->getEndpoint(), $headers, $data); + + return $this->response = new QueryBatchResponse($this, $httpResponse->getBody()->getContents()); + } +} diff --git a/src/Message/Query/QueryBatchResponse.php b/src/Message/Query/QueryBatchResponse.php new file mode 100644 index 00000000..32995dab --- /dev/null +++ b/src/Message/Query/QueryBatchResponse.php @@ -0,0 +1,55 @@ +]+>/', '', (string)$data); + + try { + $xml = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOWARNING); + } catch (\Exception $e) { + throw new InvalidResponseException(); + } + + if (!$xml) { + throw new InvalidResponseException(); + } + + parent::__construct($request, $xml); + } + + public function isSuccessful() + { + return 'Ok' === $this->getResultCode(); + } + + public function getResultCode() + { + $result = $this->xml2array($this->data->messages, true); + return $result['messages'][0]['resultCode']; + } + + public function getData() + { + $result = $this->xml2array($this->data->batchList, true); + return $result['batchList'][0]['batch']; + } +} diff --git a/src/Message/Query/QueryDetailRequest.php b/src/Message/Query/QueryDetailRequest.php new file mode 100644 index 00000000..78283293 --- /dev/null +++ b/src/Message/Query/QueryDetailRequest.php @@ -0,0 +1,44 @@ +getBaseData(); + $data->transId = $this->getTransactionReference(); + return $data; + } + + public function sendData($data) + { + $headers = array('Content-Type' => 'text/xml; charset=utf-8'); + $data = $data->saveXml(); + $httpResponse = $this->httpClient->request('POST', $this->getEndpoint(), $headers, $data); + + return $this->response = new QueryDetailResponse($this, $httpResponse->getBody()->getContents()); + } + + public function setTransactionReference($transactionReference) + { + $this->transactionReference = $transactionReference; + } + + public function getTransactionReference() + { + return $this->transactionReference; + } +} diff --git a/src/Message/Query/QueryDetailResponse.php b/src/Message/Query/QueryDetailResponse.php new file mode 100644 index 00000000..359e896a --- /dev/null +++ b/src/Message/Query/QueryDetailResponse.php @@ -0,0 +1,242 @@ +]+>/', '', (string)$data); + + try { + $xml = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOWARNING); + } catch (\Exception $e) { + throw new InvalidResponseException(); + } + + if (!$xml) { + throw new InvalidResponseException(); + } + + parent::__construct($request, $xml); + $result = $this->xml2array($this->data->transaction, true); + $this->transaction = $result['transaction'][0]; + } + + public function isSuccessful() + { + return 1 == $this->getResultCode(); + } + + + public function isRecurring() + { + return ($this->transaction['recurringBilling'] === 'true'); + } + + public function getClientIp() + { + return $this->transaction['customerIP']; + } + + /** + * TransactionReference is the reference generated by the payment gateway. + * + * @return mixed + */ + public function getTransactionReference() + { + return $this->transaction['transId']; + } + + /** + * TransactionId is the reference set by the originating website. + * + * @return mixed + */ + public function getTransactionId() + { + return $this->transaction['order'][0]['invoiceNumber']; + } + + public function getAmount() + { + return $this->transaction['settleAmount']; + } + + public function getDescription() + { + return $this->transaction['order'][0]['description']; + } + + /** + * Get email. + * + * @return string + */ + public function getEmail() + { + return $this->transaction['customer'][0]['email']; + } + + public function getResultCode() + { + return $this->transaction['responseCode']; + } + + /** + * Get the currency. + * + * Seems to onlys support USD. + * + * @return string + */ + public function getCurrency() + { + return 'USD'; + } + + /** + * Get first name. + * + * In practice this is billing first name. + * + * @return string + */ + public function getFirstName() + { + return $this->transaction['billTo'][0]['firstName']; + } + + /** + * Get the gateway generated id for the recurring transaction. + */ + public function getRecurringReference() + { + return $this->transaction['subscription'][0]['id']; + } + + /** + * Get the gateway generated id for the recurring transaction. + */ + public function getCustomerReference() + { + if (!$this->isRecurring()) { + return ''; + } + if (!$this->planResponse) { + /** @var \Omnipay\AuthorizeNet\AIMGateway $gateway */ + $gateway = Omnipay::create('AuthorizeNet_AIM'); + $gateway->setApiLoginId($this->request->getApiLoginId()); + $gateway->setHashSecret($this->request->getHashSecret()); + $gateway->setTransactionKey($this->request->getTransactionKey()); + $data = array('recurringReference' => $this->getRecurringReference()); + $this->planResponse = $gateway->paymentPlanQuery($data)->send(); + } + return $this->planResponse->getContactReference(); + } + + /** + * Get last name. + * + * In practice this is billing last name. + * + * @return string + */ + public function getLastName() + { + return $this->transaction['billTo'][0]['lastName']; + } + + /** + * Get credit card number. + * + * This is masked. Is this the correct parameter name. + */ + public function getNumber() + { + return $this->transaction['payment'][0]['creditCard'][0]['cardNumber']; + } + + public function getType() + { + return $this->transaction['payment'][0]['creditCard'][0]['cardType']; + } + + public function getBillingAddress1() + { + return $this->transaction['billTo'][0]['address']; + } + + public function getBillingAddress2() + { + return ''; + } + + public function getBillingCity() + { + return $this->transaction['billTo'][0]['city']; + } + + public function getBillingPostcode() + { + return $this->transaction['billTo'][0]['zip']; + } + + /** + * Get billing address State. + * + * @todo consider if there should be other variants for full vs abbreviation. + * + * @return mixed + */ + public function getBillingState() + { + return $this->transaction['billTo'][0]['state']; + } + + /** + * Get billing address Country. + * + * @todo consider if there should be other variants for full vs abbreviation. + * + * @return mixed + */ + public function getBillingCountry() + { + return $this->transaction['billTo'][0]['country']; + } + + /** + * Get transaction date in UTC. + * + * @return string + */ + public function getSettlementDate() + { + return $this->transaction['batch'][0]['settlementTimeUTC']; + } + + /** + * Get settlement date in UTC. + * + * @return string + */ + public function getTransactionDate() + { + return $this->transaction['submitTimeUTC']; + } +} diff --git a/src/Message/Query/QueryRequest.php b/src/Message/Query/QueryRequest.php new file mode 100644 index 00000000..b7f0206d --- /dev/null +++ b/src/Message/Query/QueryRequest.php @@ -0,0 +1,73 @@ +startTimestamp; + } + + /** + * @param mixed $startTimestamp + */ + public function setStartTimestamp($startTimestamp) + { + $this->startTimestamp = $startTimestamp; + } + + /** + * @return mixed + */ + public function getEndTimestamp() + { + return $this->endTimestamp; + } + + /** + * @param mixed $endTimestamp + */ + public function setEndTimestamp($endTimestamp) + { + $this->endTimestamp = $endTimestamp; + } + + /** + * Get data to send. + */ + public function getData() + { + $data = $this->getBaseData(); + if ($this->getStartTimestamp()) { + $data->firstSettlementDate = date('Y-m-d\Th:i:s\Z', $this->getStartTimestamp()); + $data->lastSettlementDate = date('Y-m-d\Th:i:s\Z'); + } + if ($this->getEndTimestamp()) { + $data->lastSettlementDate = date('Y-m-d\Th:i:s\Z', $this->getEndTimestamp()); + } + return $data; + } + + public function sendData($data) + { + $headers = array('Content-Type' => 'text/xml; charset=utf-8'); + $data = $data->saveXml(); + $httpResponse = $this->httpClient->request('POST', $this->getEndpoint(), $headers, $data); + + $this->response = new QueryResponse($this, $httpResponse->getBody()->getContents()); + return $this->response; + } +} diff --git a/src/Message/Query/QueryResponse.php b/src/Message/Query/QueryResponse.php new file mode 100644 index 00000000..7ad8d349 --- /dev/null +++ b/src/Message/Query/QueryResponse.php @@ -0,0 +1,42 @@ +setApiLoginId($this->request->getApiLoginId()); + $gateway->setHashSecret($this->request->getHashSecret()); + $gateway->setTransactionKey($this->request->getTransactionKey()); + $gateway->setDeveloperMode($this->request->getDeveloperMode()); + $data = array('batch_id' => $batch['batchId']); + $dataResponse = $gateway->queryBatchDetail($data)->send(); + $transactions = $dataResponse->getData(); + foreach ($transactions as $transaction) { + $detailResponse = $gateway->queryDetail(array('transactionReference' => $transaction['transId'])) + ->send(); + $result[] = $detailResponse; + } + } + } + return $result; + } +} diff --git a/src/Message/SIMAbstractRequest.php b/src/Message/SIMAbstractRequest.php index 4167e1fe..9bfd7b5a 100644 --- a/src/Message/SIMAbstractRequest.php +++ b/src/Message/SIMAbstractRequest.php @@ -160,9 +160,9 @@ protected function getBillingData() public function sendData($data) { - $httpResponse = $this->httpClient->post($this->getEndpoint(), null, $data)->send(); + $httpResponse = $this->httpClient->request('POST', $this->getEndpoint(), [], http_build_query($data)); - return $this->response = new AIMResponse($this, $httpResponse->getBody()); + return $this->response = new AIMResponse($this, $httpResponse->getBody()->getContents()); } public function getEndpoint() diff --git a/src/SIMGateway.php b/src/SIMGateway.php index c5ccbe5c..67b47b4d 100644 --- a/src/SIMGateway.php +++ b/src/SIMGateway.php @@ -53,16 +53,6 @@ public function setDeveloperMode($value) return $this->setParameter('developerMode', $value); } - public function getHashSecret() - { - return $this->getParameter('hashSecret'); - } - - public function setHashSecret($value) - { - return $this->setParameter('hashSecret', $value); - } - public function authorize(array $parameters = array()) { return $this->createRequest('\Omnipay\AuthorizeNet\Message\SIMAuthorizeRequest', $parameters); diff --git a/tests/AIMGatewayTest.php b/tests/AIMGatewayTest.php index e50a3823..7a6ce81c 100644 --- a/tests/AIMGatewayTest.php +++ b/tests/AIMGatewayTest.php @@ -19,6 +19,10 @@ public function setUp() $this->gateway = new AIMGateway($this->getHttpClient(), $this->getHttpRequest()); + $this->gateway->initialize([ + 'hashSecret' => 'HASHYsecretyThang', + ]); + $this->purchaseOptions = array( 'amount' => '10.00', 'card' => $this->getValidCard(), @@ -60,6 +64,15 @@ public function testDeveloperEndpoint() ); } + // Added for PR #78 + public function testHashSecret() + { + $this->assertEquals( + 'HASHYsecretyThang', + $this->gateway->getHashSecret() + ); + } + private function getExpiry($card) { return str_pad($card['expiryMonth'] . $card['expiryYear'], 6, '0', STR_PAD_LEFT); @@ -113,7 +126,28 @@ public function testCaptureFailure() $this->assertSame('{"approvalCode":"","transId":"0"}', $response->getTransactionReference()); $this->assertSame('The transaction cannot be found.', $response->getMessage()); } + + public function testCaptureOnlySuccess() + { + $this->setMockHttpResponse('AIMCaptureOnlySuccess.txt'); + + $response = $this->gateway->capture($this->captureOptions)->send(); + + $this->assertTrue($response->isSuccessful()); + $this->assertSame('{"approvalCode":"ROHNFQ","transId":"40009379672"}', $response->getTransactionReference()); + $this->assertSame('This transaction has been approved.', $response->getMessage()); + } + + public function testCaptureOnlyFailure() + { + $this->setMockHttpResponse('AIMCaptureOnlyFailure.txt'); + $response = $this->gateway->capture($this->captureOptions)->send(); + + $this->assertFalse($response->isSuccessful()); + $this->assertSame('{"approvalCode":"ROHNFQ","transId":"0"}', $response->getTransactionReference()); + $this->assertSame('A valid amount is required.', $response->getMessage()); + } public function testPurchaseSuccess() { $this->setMockHttpResponse('AIMPurchaseSuccess.txt'); diff --git a/tests/CIMGatewayTest.php b/tests/CIMGatewayTest.php index 9b3f9bfb..3d4a85dd 100644 --- a/tests/CIMGatewayTest.php +++ b/tests/CIMGatewayTest.php @@ -20,6 +20,10 @@ public function setUp() $this->gateway = new CIMGateway($this->getHttpClient(), $this->getHttpRequest()); + $this->gateway->initialize([ + 'hashSecret' => 'HASHYsecretyThang', + ]); + $this->createCardOptions = array( 'email' => "kaylee@serenity.com", 'card' => $this->getValidCard(), @@ -62,6 +66,15 @@ public function testDeveloperEndpoint() ); } + // Added for PR #78 + public function testHashSecret() + { + $this->assertEquals( + 'HASHYsecretyThang', + $this->gateway->getHashSecret() + ); + } + public function testCreateCardSuccess() { $this->setMockHttpResponse(array('CIMCreateCardSuccess.txt','CIMGetPaymentProfileSuccess.txt')); @@ -201,6 +214,7 @@ public function testPurchaseFailure() public function testRefundSuccess() { + $this->markTestSkipped(); // $this->setMockHttpResponse('CIMRefundSuccess.txt'); // // $response = $this->gateway->refund($this->refundOptions)->send(); diff --git a/tests/Message/AIMAbstractRequestTest.php b/tests/Message/AIMAbstractRequestTest.php index 04d01400..03d47d32 100644 --- a/tests/Message/AIMAbstractRequestTest.php +++ b/tests/Message/AIMAbstractRequestTest.php @@ -1,25 +1,20 @@ request = $this->getMockForAbstractClass( - '\Omnipay\AuthorizeNet\Message\AIMAbstractRequest', - array( - $this->getMock('\Guzzle\Http\ClientInterface'), - $this->getMock('\Symfony\Component\HttpFoundation\Request') - ) - ); + $this->request = Mockery::mock('\Omnipay\AuthorizeNet\Message\AIMAbstractRequest')->makePartial(); + $this->request->initialize(); } public function testShouldReturnTransactionReference() diff --git a/tests/Message/AIMAuthorizeRequestTest.php b/tests/Message/AIMAuthorizeRequestTest.php index 611a5f2c..e410a8f5 100644 --- a/tests/Message/AIMAuthorizeRequestTest.php +++ b/tests/Message/AIMAuthorizeRequestTest.php @@ -20,7 +20,8 @@ public function setUp() 'amount' => '12.00', 'customerId' => 'cust-id', 'card' => $card, - 'duplicateWindow' => 0 + 'duplicateWindow' => 0, + 'solutionId' => 'SOL12345ID', ) ); } @@ -33,6 +34,7 @@ public function testGetData() $this->assertEquals('10.0.0.1', $data->transactionRequest->customerIP); $this->assertEquals('cust-id', $data->transactionRequest->customer->id); $this->assertEquals('example@example.net', $data->transactionRequest->customer->email); + $this->assertEquals('SOL12345ID', $data->transactionRequest->solution->id); // Issue #38 Make sure the transactionRequest properties are correctly ordered. // This feels messy, but works. @@ -43,6 +45,7 @@ public function testGetData() "transactionType", "amount", "payment", + "solution", "order", "customer", "billTo", diff --git a/tests/Message/AIMResponseTest.php b/tests/Message/AIMResponseTest.php index 275fdfd8..3e046436 100644 --- a/tests/Message/AIMResponseTest.php +++ b/tests/Message/AIMResponseTest.php @@ -18,7 +18,8 @@ public function getMockRequest($className = '\Omnipay\AuthorizeNet\Message\AIMAb public function testConstructEmpty() { - $this->setExpectedException('\Omnipay\Common\Exception\InvalidResponseException'); + $this->expectException('\Omnipay\Common\Exception\InvalidResponseException'); + new AIMResponse($this->getMockRequest(), ''); } @@ -34,6 +35,8 @@ public function testAuthorizeSuccess() $this->assertSame(1, $response->getReasonCode()); $this->assertSame('GA4OQP', $response->getAuthorizationCode()); $this->assertSame('Y', $response->getAVSCode()); + $this->assertSame('P', $response->getCVVCode()); + $this->assertSame('Visa', $response->getAccountType()); } public function testAuthorizeFailure() @@ -48,6 +51,8 @@ public function testAuthorizeFailure() $this->assertSame(5, $response->getReasonCode()); $this->assertSame('', $response->getAuthorizationCode()); $this->assertSame('P', $response->getAVSCode()); + $this->assertSame('', $response->getCVVCode()); + $this->assertSame('Visa', $response->getAccountType()); } public function testAuthorizeInvalid() @@ -62,6 +67,7 @@ public function testAuthorizeInvalid() $this->assertSame('E00007', $response->getReasonCode()); $this->assertSame('', $response->getAuthorizationCode()); $this->assertSame('', $response->getAVSCode()); + $this->assertSame('', $response->getCVVCode()); } public function testAuthorizeInvalidOTSToken() @@ -86,6 +92,8 @@ public function testCaptureSuccess() $this->assertSame(1, $response->getReasonCode()); $this->assertSame('F51OYG', $response->getAuthorizationCode()); $this->assertSame('P', $response->getAVSCode()); + $this->assertSame('', $response->getCVVCode()); + $this->assertSame('Visa', $response->getAccountType()); } public function testCaptureFailure() @@ -100,6 +108,40 @@ public function testCaptureFailure() $this->assertSame(16, $response->getReasonCode()); $this->assertSame('', $response->getAuthorizationCode()); $this->assertSame('P', $response->getAVSCode()); + $this->assertSame('', $response->getCVVCode()); + $this->assertSame('', $response->getAccountType()); + } + + public function testCaptureOnlySuccess() + { + $httpResponse = $this->getMockHttpResponse('AIMCaptureOnlySuccess.txt'); + $response = new AIMResponse($this->getMockRequest(), $httpResponse->getBody()); + + $this->assertTrue($response->isSuccessful()); + $this->assertSame('{"approvalCode":"ROHNFQ","transId":"40009379672"}', $response->getTransactionReference()); + $this->assertSame('This transaction has been approved.', $response->getMessage()); + $this->assertSame(1, $response->getResultCode()); + $this->assertSame(1, $response->getReasonCode()); + $this->assertSame('ROHNFQ', $response->getAuthorizationCode()); + $this->assertSame('P', $response->getAVSCode()); + $this->assertSame('', $response->getCVVCode()); + $this->assertSame('MasterCard', $response->getAccountType()); + } + + public function testCaptureOnlyFailure() + { + $httpResponse = $this->getMockHttpResponse('AIMCaptureOnlyFailure.txt'); + $response = new AIMResponse($this->getMockRequest(), $httpResponse->getBody()); + + $this->assertFalse($response->isSuccessful()); + $this->assertSame('{"approvalCode":"ROHNFQ","transId":"0"}', $response->getTransactionReference()); + $this->assertSame('A valid amount is required.', $response->getMessage()); + $this->assertSame(3, $response->getResultCode()); + $this->assertSame(5, $response->getReasonCode()); + $this->assertSame('ROHNFQ', $response->getAuthorizationCode()); + $this->assertSame('P', $response->getAVSCode()); + $this->assertSame('', $response->getCVVCode()); + $this->assertSame('MasterCard', $response->getAccountType()); } public function testPurchaseSuccess() @@ -114,6 +156,8 @@ public function testPurchaseSuccess() $this->assertSame(1, $response->getReasonCode()); $this->assertSame('JE6JM1', $response->getAuthorizationCode()); $this->assertSame('Y', $response->getAVSCode()); + $this->assertSame('P', $response->getCVVCode()); + $this->assertSame('Visa', $response->getAccountType()); } public function testPurchaseFailure() @@ -128,6 +172,8 @@ public function testPurchaseFailure() $this->assertSame(5, $response->getReasonCode()); $this->assertSame('', $response->getAuthorizationCode()); $this->assertSame('P', $response->getAVSCode()); + $this->assertSame('', $response->getCVVCode()); + $this->assertSame('Visa', $response->getAccountType()); } public function testRefundSuccess() @@ -142,6 +188,8 @@ public function testRefundSuccess() $this->assertSame(1, $response->getResultCode()); $this->assertSame(1, $response->getReasonCode()); $this->assertSame('P', $response->getAVSCode()); + $this->assertSame('', $response->getCVVCode()); + $this->assertSame('Visa', $response->getAccountType()); } public function testRefundFailure() @@ -156,5 +204,7 @@ public function testRefundFailure() $this->assertSame(54, $response->getReasonCode()); $this->assertSame('', $response->getAuthorizationCode()); $this->assertSame('P', $response->getAVSCode()); + $this->assertSame('', $response->getCVVCode()); + $this->assertSame('Visa', $response->getAccountType()); } } diff --git a/tests/Mock/AIMCaptureOnlyFailure.txt b/tests/Mock/AIMCaptureOnlyFailure.txt new file mode 100644 index 00000000..f2dff42c --- /dev/null +++ b/tests/Mock/AIMCaptureOnlyFailure.txt @@ -0,0 +1,13 @@ +HTTP/1.1 200 OK +Date: Sat, 02 Aug 2014 04:53:02 GMT +Server: Microsoft-IIS/6.0 +Access-Control-Allow-Origin: * +Access-Control-Allow-Methods: GET, POST, OPTIONS +Access-Control-Allow-Headers: x-requested-with, cache-control, content-type, origin, method +X-Powered-By: ASP.NET +X-AspNet-Version: 2.0.50727 +Cache-Control: private +Content-Type: text/xml; charset=utf-8 +Content-Length: 882 + +123456ErrorE00027The transaction was unsuccessful.3ROHNFQP0680A8419B9B0C29DAA432BDFA73C3E830XXXX0015MasterCard5A valid amount is required. diff --git a/tests/Mock/AIMCaptureOnlySuccess.txt b/tests/Mock/AIMCaptureOnlySuccess.txt new file mode 100644 index 00000000..619a015c --- /dev/null +++ b/tests/Mock/AIMCaptureOnlySuccess.txt @@ -0,0 +1,13 @@ +HTTP/1.1 200 OK +Date: Sat, 02 Aug 2014 05:24:31 GMT +Server: Microsoft-IIS/6.0 +Access-Control-Allow-Origin: * +Access-Control-Allow-Methods: GET, POST, OPTIONS +Access-Control-Allow-Headers: x-requested-with, cache-control, content-type, origin, method +X-Powered-By: ASP.NET +X-AspNet-Version: 2.0.50727 +Cache-Control: private +Content-Type: text/xml; charset=utf-8 +Content-Length: 877 + +123456OkI00001Successful.1ROHNFQP4000937967213BA777FBC314C49558C9BE4250CEA240XXXX0015MasterCard1This transaction has been approved. diff --git a/tests/Model/CardReferenceTest.php b/tests/Model/CardReferenceTest.php index d471d2a4..11cea148 100644 --- a/tests/Model/CardReferenceTest.php +++ b/tests/Model/CardReferenceTest.php @@ -2,7 +2,9 @@ namespace Omnipay\AuthorizeNet\Model; -class CardReferenceTest extends \PHPUnit_Framework_TestCase +use Omnipay\Tests\TestCase; + +class CardReferenceTest extends TestCase { private $data; /** @var CardReference */ diff --git a/tests/Model/TransactionReferenceTest.php b/tests/Model/TransactionReferenceTest.php index b0cf0c80..8c0be267 100644 --- a/tests/Model/TransactionReferenceTest.php +++ b/tests/Model/TransactionReferenceTest.php @@ -2,7 +2,9 @@ namespace Omnipay\AuthorizeNet\Model; -class TransactionReferenceTest extends \PHPUnit_Framework_TestCase +use Omnipay\Tests\TestCase; + +class TransactionReferenceTest extends TestCase { private $data; /** @var TransactionReference */