├── .gitignore ├── .travis.yml ├── LICENSE.md ├── README.md ├── composer.json ├── phpunit.xml.dist ├── src ├── Gateway.php ├── Message │ ├── AbstractRequest.php │ ├── CompletePurchaseRequest.php │ ├── CompletePurchaseResponse.php │ ├── DetailSaleRequest.php │ ├── DetailSaleResponse.php │ ├── NotificationRequest.php │ ├── NotificationResponse.php │ ├── PurchaseRequest.php │ ├── PurchaseResponse.php │ ├── RefundRequest.php │ ├── RefundResponse.php │ ├── StopRecurringRequest.php │ ├── StopRecurringResponse.php │ ├── TokenPurchaseRequest.php │ └── TokenPurchaseResponse.php └── TokenGateway.php └── tests ├── GatewayTest.php ├── Message ├── NotificationRequestTest.php ├── NotificationResponseTest.php ├── PurchaseResponseTest.php ├── TokenPurchaseRequestTest.php └── TokenPurchaseResponseTest.php ├── Mock ├── DetailSaleFailure.txt ├── DetailSaleSuccess.txt ├── FraudChangeNotificationFail.txt ├── FraudChangeNotificationPass.txt ├── StopRecurringFailure.txt ├── TokenPurchaseFailure.txt └── TokenPurchaseSuccess.txt └── TokenGatewayTest.php /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/* 2 | composer.lock 3 | vendor 4 | build 5 | sandbox.php 6 | .phpstorm.meta.php 7 | complete.php 8 | sandboxToken.php 9 | custom-hosted.php 10 | test.php -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 5.3 5 | - 5.4 6 | - 5.5 7 | - 5.6 8 | - 7.0 9 | 10 | matrix: 11 | allow_failures: 12 | - php: 7.0 13 | 14 | before_script: 15 | - travis_retry composer self-update 16 | - travis_retry composer update ${COMPOSER_FLAGS} --no-interaction --prefer-source 17 | 18 | script: 19 | - phpunit --coverage-text --coverage-clover=coverage.clover 20 | - vendor/bin/phpcs --standard=PSR2 src && vendor/bin/phpunit --coverage-text 21 | 22 | after_script: 23 | - php vendor/bin/ocular code-coverage:upload --format=php-clover coverage.clover 24 | - vendor/bin/coveralls -v 25 | 26 | addons: 27 | code_climate: 28 | repo_token: a6822f9c6a59e02665b7b69aec43d9db13a9ca476d6460aa4bd8118d16bd6804 29 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Agbonghama Collins 4 | 5 | > Permission is hereby granted, free of charge, to any person obtaining a copy 6 | > of this software and associated documentation files (the "Software"), to deal 7 | > in the Software without restriction, including without limitation the rights 8 | > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | > copies of the Software, and to permit persons to whom the Software is 10 | > furnished to do so, subject to the following conditions: 11 | > 12 | > The above copyright notice and this permission notice shall be included in 13 | > all copies or substantial portions of the Software. 14 | > 15 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | > THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Omnipay: 2checkout 2 | 3 | **2checkout gateway for the Omnipay PHP payment processing library** 4 | 5 | [![Latest Version on Packagist](https://img.shields.io/packagist/v/collizo4sky/omnipay-2checkout.svg?style=flat-square)](https://packagist.org/packages/collizo4sky/omnipay-2checkout) 6 | [![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE.md) 7 | [![Build Status](https://img.shields.io/travis/collizo4sky/omnipay-2checkout/master.svg?style=flat-square)](https://travis-ci.org/collizo4sky/omnipay-2checkout) 8 | [![Coverage Status](https://coveralls.io/repos/collizo4sky/omnipay-2checkout/badge.svg?branch=master&service=github)](https://coveralls.io/github/collizo4sky/omnipay-2checkout?branch=master) 9 | [![Code Climate](https://codeclimate.com/github/collizo4sky/omnipay-2checkout/badges/gpa.svg)](https://codeclimate.com/github/collizo4sky/omnipay-2checkout) 10 | [![Dependency Status](https://www.versioneye.com/user/projects/56790f2210799700300013b8/badge.svg?style=flat)](https://www.versioneye.com/user/projects/56790f2210799700300013b8) 11 | [![Total Downloads](https://img.shields.io/packagist/dt/collizo4sky/omnipay-2checkout.svg?style=flat-square)](https://packagist.org/packages/collizo4sky/omnipay-2checkout) 12 | 13 | 14 | [Omnipay](https://github.com/thephpleague/omnipay) is a framework agnostic, multi-gateway payment 15 | processing library for PHP 5.3+. This package implements 2checkout support for Omnipay. 16 | 17 | ## Install 18 | 19 | Via Composer 20 | 21 | ``` bash 22 | $ composer require collizo4sky/omnipay-2checkout 23 | ``` 24 | 25 | ## Usage 26 | 27 | The following gateways are provided by this package: 28 | 29 | * TwoCheckoutPlus 30 | * TwoCheckoutPlus_Token 31 | 32 | ### TwoCheckoutPlus 33 | ``` php 34 | 35 | use Omnipay\Omnipay; 36 | 37 | $gateway = Omnipay::create('TwoCheckoutPlus'); 38 | $gateway->setAccountNumber($this->account_number); 39 | $gateway->setSecretWord($this->secret_word); 40 | $gateway->setTestMode($this->is_sandbox_test()); 41 | // activate test mode by passing demo parameter to checkout parameters. 42 | $gateway->setDemoMode($this->is_test_mode()); 43 | 44 | 45 | try { 46 | $formData = array( 47 | 'firstName' => $order->get_billing_first_name(), 48 | 'lastName' => $order->get_billing_last_name(), 49 | 'email' => $order->get_billing_email(), 50 | 'address1' => $order->get_billing_address_1(), 51 | 'address2' => $order->get_billing_address_2(), 52 | 'city' => $order->get_billing_city(), 53 | 'state' => $order->get_billing_state(), 54 | 'postcode' => $order->get_billing_postcode(), 55 | 'country' => $order->get_billing_country(), 56 | ); 57 | 58 | $order_cart = $order->get_items(); 59 | 60 | $cart = array(); 61 | 62 | $i = 0; 63 | foreach ($order_cart as $order_item_id => $product) { 64 | $product_id = $product['product_id']; 65 | $cart[$i]['name'] = $product['name']; 66 | $cart[$i]['quantity'] = $product['qty']; 67 | $cart[$i]['type'] = 'product'; 68 | $cart[$i]['price'] = round($product['line_subtotal'] / $product['qty'], 2); 69 | $cart[$i]['product_id'] = $product_id; 70 | 71 | $i++; 72 | } 73 | 74 | if (($shipping_total = $order->get_shipping_total()) > 0) { 75 | $cart[] = array( 76 | 'name' => 'Shipping Fee', 77 | 'quantity' => 1, 78 | 'type' => 'shipping', 79 | 'price' => round($shipping_total, 2), 80 | ); 81 | } 82 | 83 | if (($discount_total = $order->get_total_discount()) > 0) { 84 | $cart[] = array( 85 | 'name' => 'Discount', 86 | 'quantity' => 1, 87 | 'type' => 'coupon', 88 | 'price' => round($discount_total, 2), 89 | ); 90 | } 91 | 92 | if (($tax_total = $order->get_total_tax()) > 0) { 93 | $cart[] = array( 94 | 'name' => 'Tax Fee', 95 | 'type' => 'tax', 96 | 'quantity' => 1, 97 | 'price' => round($tax_total, 2), 98 | ); 99 | } 100 | 101 | $gateway->setCart($cart); 102 | 103 | $response = $gateway->purchase( 104 | array( 105 | 'card' => $formData, 106 | 'transactionId' => $order->get_order_number(), 107 | 'currency' => 'USD', 108 | // add a query parameter to the returnUrl to listen and complete payment 109 | 'returnUrl' => $this->returnUrl, 110 | ) 111 | )->send(); 112 | 113 | 114 | if ($response->isRedirect()) { 115 | $response->getRedirectUrl(); 116 | 117 | } else { 118 | $error = $response->getMessage(); 119 | } 120 | } catch (Exception $e) { 121 | $e->getMessage(); 122 | } 123 | ``` 124 | 125 | ### TwoCheckoutPlus_Token 126 | 127 | ``` php 128 | use Omnipay\Omnipay; 129 | 130 | try { 131 | $gateway = Omnipay::create('TwoCheckoutPlus_Token'); 132 | $gateway->setAccountNumber($this->account_number); 133 | $gateway->setTestMode($this->is_sandbox_test()); 134 | $gateway->setPrivateKey($this->private_key); 135 | 136 | $formData = array( 137 | 'firstName' => $order->get_billing_first_name(), 138 | 'lastName' => $order->get_billing_last_name(), 139 | 'email' => $order->get_billing_email(), 140 | 'billingAddress1' => $order->get_billing_address_1(), 141 | 'billingAddress2' => $order->get_billing_address_2(), 142 | 'billingCity' => $order->get_billing_city(), 143 | 'billingPostcode' => $order->get_billing_postcode(), 144 | 'billingState' => $order->get_billing_state(), 145 | 'billingCountry' => $order->get_billing_country(), 146 | ); 147 | 148 | 149 | $purchase_request_data = array( 150 | 'card' => $formData, 151 | 'token' => sanitize_text_field($_POST['twocheckout_token']), 152 | 'transactionId' => $order->get_order_number(), 153 | 'currency' => 'USD', 154 | 'amount' => $order->order_total, 155 | ); 156 | 157 | $response = $gateway->purchase($purchase_request_data)->send(); 158 | 159 | if ($response->isSuccessful()) { 160 | $transaction_ref = $response->getTransactionReference(); 161 | } else { 162 | $error = $response->getMessage(); 163 | } 164 | } catch (Exception $e) { 165 | $e->getMessage(); 166 | } 167 | ``` 168 | 169 | For general usage instructions, please see the main [Omnipay](https://github.com/thephpleague/omnipay) repository. 170 | 171 | ## Support 172 | 173 | If you are having general issues with Omnipay, we suggest posting on 174 | [Stack Overflow](http://stackoverflow.com/). Be sure to add the 175 | [omnipay tag](http://stackoverflow.com/questions/tagged/omnipay) so it can be easily found. 176 | 177 | If you want to keep up to date with release anouncements, discuss ideas for the project, 178 | or ask more detailed questions, there is also a [mailing list](https://groups.google.com/forum/#!forum/omnipay) which 179 | you can subscribe to. 180 | 181 | If you believe you have found a bug, please report it using the [GitHub issue tracker](https://github.com/collizo4sky/omnipay-2checkout/issues), 182 | or better yet, fork the library and submit a pull request. 183 | 184 | ## Testing 185 | 186 | ``` bash 187 | $ composer test 188 | ``` 189 | 190 | ## Security 191 | 192 | If you discover any security related issues, please email me@w3guy.com instead of using the issue tracker. 193 | 194 | ## Credits 195 | 196 | - [Agbonghama Collins](https://github.com/collizo4sky) 197 | - [All Contributors](../../contributors) 198 | 199 | ## License 200 | 201 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information. 202 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "collizo4sky/omnipay-2checkout", 3 | "description": "2Checkout driver for the Omnipay payment processing library", 4 | "keywords": [ 5 | "omnipay", 6 | "2checkout" 7 | ], 8 | "homepage": "https://github.com/collizo4sky/omnipay-2checkout", 9 | "license": "MIT", 10 | "authors": [ 11 | { 12 | "name": "Agbonghama Collins", 13 | "email": "me@w3guy.com", 14 | "homepage": "http://w3guy.com" 15 | } 16 | ], 17 | "require": { 18 | "omnipay/common": "~2.0" 19 | }, 20 | "require-dev": { 21 | "omnipay/tests": "~2.0", 22 | "satooshi/php-coveralls": "^0.7.1" 23 | }, 24 | "autoload": { 25 | "psr-4": { 26 | "Omnipay\\TwoCheckoutPlus\\": "src" 27 | } 28 | }, 29 | "autoload-dev": { 30 | "psr-4": { 31 | "League\\Skeleton\\Test\\": "tests" 32 | } 33 | }, 34 | "scripts": { 35 | "test": "phpunit" 36 | }, 37 | "extra": { 38 | "branch-alias": { 39 | "dev-master": "1.0-dev" 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | tests 15 | 16 | 17 | 18 | 19 | src/ 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/Gateway.php: -------------------------------------------------------------------------------- 1 | '', 21 | 'secretWord' => '', 22 | // if true, transaction with the live checkout URL will be a demo sale and card won't be charged. 23 | 'demoMode' => false, 24 | 'testMode' => false, 25 | ); 26 | } 27 | 28 | /** 29 | * Getter: get cart items. 30 | * 31 | * @return array 32 | */ 33 | public function getCart() 34 | { 35 | return $this->getParameter('cart'); 36 | } 37 | 38 | /** 39 | * Array of cart items. 40 | * 41 | * format: 42 | * $gateway->setCart(array( 43 | * array( 44 | * 'type' => 'product', 45 | * 'name' => 'Product 1', 46 | * 'description' => 'Description of product 1', 47 | * 'quantity' => 2, 48 | * 'price' => 22, 49 | * 'tangible' => 'N', 50 | * 'product_id' => 12345, 51 | * 'recurrence' => '1 Week', 52 | * 'duration' => '1 Year', 53 | * 'startup_fee' => '5', 54 | * ), 55 | * array( 56 | * 'type' => 'product', 57 | * 'name' => 'Product 2', 58 | * 'quantity' => 1, 59 | * 'price' => 10, 60 | * 'tangible' => 'N' 61 | * 'product_id' => 45678, 62 | * 'recurrence' => '2 Week', 63 | * 'duration' => '1 Year', 64 | * 'startup_fee' => '3', 65 | * ) 66 | * )); 67 | * 68 | * @param array $value 69 | * 70 | * @return $this 71 | */ 72 | public function setCart($value) 73 | { 74 | return $this->setParameter('cart', $value); 75 | } 76 | 77 | /** 78 | * Getter: demo mode. 79 | * 80 | * @return string 81 | */ 82 | public function getDemoMode() 83 | { 84 | return $this->getParameter('demoMode'); 85 | } 86 | 87 | /** 88 | * Setter: demo mode. 89 | * 90 | * @param $value 91 | * 92 | * @return $this 93 | */ 94 | public function setDemoMode($value) 95 | { 96 | return $this->setParameter('demoMode', $value); 97 | } 98 | 99 | /** 100 | * Getter: checkout language. 101 | * 102 | * @return string 103 | */ 104 | public function getLanguage() 105 | { 106 | return $this->getParameter('language'); 107 | } 108 | 109 | /** 110 | * Setter: checkout language. 111 | * 112 | * @param $value 113 | * 114 | * @return $this 115 | */ 116 | public function setLanguage($value) 117 | { 118 | return $this->setParameter('language', $value); 119 | } 120 | 121 | /** 122 | * Getter: purchase step. 123 | * 124 | * @param $value 125 | * 126 | * @return $this 127 | */ 128 | public function getPurchaseStep() 129 | { 130 | return $this->getParameter('purchaseStep'); 131 | } 132 | 133 | /** 134 | * Setter: purchase step. 135 | * 136 | * @param $value 137 | * 138 | * @return $this 139 | */ 140 | public function setPurchaseStep($value) 141 | { 142 | return $this->setParameter('purchaseStep', $value); 143 | } 144 | 145 | /** 146 | * Getter: coupon. 147 | * 148 | * @return string 149 | */ 150 | public function getCoupon() 151 | { 152 | return $this->getParameter('coupon'); 153 | } 154 | 155 | /** 156 | * Setter: coupon. 157 | * 158 | * @param $value 159 | * 160 | * @return $this 161 | */ 162 | public function setCoupon($value) 163 | { 164 | return $this->setParameter('coupon', $value); 165 | } 166 | 167 | /** 168 | * Getter: 2Checkout account number. 169 | * 170 | * @return string 171 | */ 172 | public function getAccountNumber() 173 | { 174 | return $this->getParameter('accountNumber'); 175 | } 176 | 177 | /** 178 | * Setter: 2Checkout account number. 179 | * 180 | * @param $value 181 | * 182 | * @return $this 183 | */ 184 | public function setAccountNumber($value) 185 | { 186 | return $this->setParameter('accountNumber', $value); 187 | } 188 | 189 | /** 190 | * Getter: 2Checkout secret word. 191 | * 192 | * @return string 193 | */ 194 | public function getSecretWord() 195 | { 196 | return $this->getParameter('secretWord'); 197 | } 198 | 199 | /** 200 | * Setter: 2Checkout secret word. 201 | * 202 | * @param $value 203 | * 204 | * @return $this 205 | */ 206 | public function setSecretWord($value) 207 | { 208 | return $this->setParameter('secretWord', $value); 209 | } 210 | 211 | /** 212 | * Setter: sale ID for use by refund. 213 | * 214 | * @param $value 215 | * 216 | * @return $this 217 | */ 218 | public function setSaleId($value) 219 | { 220 | return $this->setParameter('saleId', $value); 221 | } 222 | 223 | /** 224 | * Getter: sale ID for use by refund. 225 | * 226 | * @return string 227 | */ 228 | public function getSaleId() 229 | { 230 | return $this->getParameter('saleId'); 231 | } 232 | 233 | /** 234 | * Setter: sale ID for use by refund. 235 | * 236 | * @param $value 237 | * 238 | * @return $this 239 | */ 240 | public function setInvoiceId($value) 241 | { 242 | return $this->setParameter('invoiceId', $value); 243 | } 244 | 245 | /** 246 | * Getter: sale ID for use by refund. 247 | * 248 | * @return string 249 | */ 250 | public function getInvoiceId() 251 | { 252 | return $this->getParameter('invoiceId'); 253 | } 254 | 255 | 256 | /** 257 | * Getter: admin username for use by refund. 258 | * 259 | * @return string 260 | */ 261 | public function getAdminUsername() 262 | { 263 | return $this->getParameter('adminUsername'); 264 | } 265 | 266 | /** 267 | * Setter: admin username for use by refund. 268 | * 269 | * @param $value 270 | * 271 | * @return $this 272 | */ 273 | public function setAdminUsername($value) 274 | { 275 | return $this->setParameter('adminUsername', $value); 276 | } 277 | 278 | /** 279 | * Getter: admin password for use by refund. 280 | * 281 | * @return string 282 | */ 283 | public function getAdminPassword() 284 | { 285 | return $this->getParameter('adminPassword'); 286 | } 287 | 288 | 289 | /** 290 | * Getter: category for use by refund. 291 | * 292 | * @return string 293 | */ 294 | public function getCategory() 295 | { 296 | return $this->getParameter('category'); 297 | } 298 | 299 | /** 300 | * Setter: category for use by refund. 301 | * 302 | * @param $value 303 | * 304 | * @return $this 305 | */ 306 | public function setCategory($value) 307 | { 308 | return $this->setParameter('category', $value); 309 | } 310 | 311 | /** 312 | * Getter: comment for use by refund. 313 | * 314 | * @return string 315 | */ 316 | public function getComment() 317 | { 318 | return $this->getParameter('comment'); 319 | } 320 | 321 | /** 322 | * Setter: category for use by refund. 323 | * 324 | * @param $value 325 | * 326 | * @return $this 327 | */ 328 | public function setComment($value) 329 | { 330 | return $this->setParameter('comment', $value); 331 | } 332 | 333 | /** 334 | * Setter: lineitem_id for use by stop recurring. 335 | * 336 | * @param $value 337 | * 338 | * @return $this 339 | */ 340 | public function setLineItemId($value) 341 | { 342 | return $this->setParameter('lineItemId', $value); 343 | } 344 | 345 | /** 346 | * Getter: lineitem_id for use by stop recurring. 347 | * 348 | * @return string 349 | */ 350 | public function getLineItemId() 351 | { 352 | return $this->getParameter('lineItemId'); 353 | } 354 | 355 | public function getAmount() 356 | { 357 | return $this->getParameter('amount'); 358 | } 359 | 360 | public function setAmount($value) 361 | { 362 | return parent::setParameter('amount', $value); 363 | } 364 | 365 | public function getCurrency() 366 | { 367 | return parent::getCurrency(); 368 | } 369 | 370 | public function setCurrency($value) 371 | { 372 | return parent::setCurrency($value); 373 | } 374 | 375 | /** 376 | * Setter: admin password for use by refund. 377 | * 378 | * @param $value 379 | * 380 | * @return $this 381 | */ 382 | public function setAdminPassword($value) 383 | { 384 | return $this->setParameter('adminPassword', $value); 385 | } 386 | 387 | /** 388 | * @param array $parameters 389 | * 390 | * @return \Omnipay\Common\Message\AbstractRequest 391 | */ 392 | public function purchase(array $parameters = array()) 393 | { 394 | return $this->createRequest('\Omnipay\TwoCheckoutPlus\Message\PurchaseRequest', $parameters); 395 | } 396 | 397 | public function refund(array $parameters = array()) 398 | { 399 | return $this->createRequest('\Omnipay\TwoCheckoutPlus\Message\RefundRequest', $parameters); 400 | } 401 | 402 | public function fetchSaleDetails(array $parameters = array()) 403 | { 404 | return $this->createRequest('\Omnipay\TwoCheckoutPlus\Message\DetailSaleRequest', $parameters); 405 | } 406 | 407 | public function stopRecurring(array $parameters = array()) 408 | { 409 | return $this->createRequest('\Omnipay\TwoCheckoutPlus\Message\StopRecurringRequest', $parameters); 410 | } 411 | 412 | /** 413 | * @param array $parameters 414 | * 415 | * @return \Omnipay\Common\Message\AbstractRequest 416 | */ 417 | public function completePurchase(array $parameters = array()) 418 | { 419 | return $this->createRequest('\Omnipay\TwoCheckoutPlus\Message\CompletePurchaseRequest', $parameters); 420 | } 421 | 422 | /** 423 | * @param array $parameters 424 | * 425 | * @return \Omnipay\Common\Message\AbstractRequest 426 | */ 427 | public function acceptNotification(array $parameters = array()) 428 | { 429 | return $this->createRequest('\Omnipay\TwoCheckoutPlus\Message\NotificationRequest', $parameters); 430 | } 431 | } 432 | -------------------------------------------------------------------------------- /src/Message/AbstractRequest.php: -------------------------------------------------------------------------------- 1 | getParameter('cart'); 15 | } 16 | 17 | public function setCart($value) 18 | { 19 | return $this->setParameter('cart', $value); 20 | } 21 | 22 | public function getDemoMode() 23 | { 24 | return $this->getParameter('demoMode'); 25 | } 26 | 27 | public function setDemoMode($value) 28 | { 29 | return $this->setParameter('demoMode', $value); 30 | } 31 | 32 | public function getLanguage() 33 | { 34 | return $this->getParameter('language'); 35 | } 36 | 37 | public function setLanguage($value) 38 | { 39 | return $this->setParameter('language', $value); 40 | } 41 | 42 | public function getPurchaseStep() 43 | { 44 | return $this->getParameter('purchaseStep'); 45 | } 46 | 47 | public function setPurchaseStep($value) 48 | { 49 | return $this->setParameter('purchaseStep', $value); 50 | } 51 | 52 | public function getCoupon() 53 | { 54 | return $this->getParameter('coupon'); 55 | } 56 | 57 | public function setCoupon($value) 58 | { 59 | return $this->setParameter('coupon', $value); 60 | } 61 | 62 | public function getAccountNumber() 63 | { 64 | return $this->getParameter('accountNumber'); 65 | } 66 | 67 | public function setAccountNumber($value) 68 | { 69 | return $this->setParameter('accountNumber', $value); 70 | } 71 | 72 | public function getSecretWord() 73 | { 74 | return $this->getParameter('secretWord'); 75 | } 76 | 77 | public function setSecretWord($value) 78 | { 79 | return $this->setParameter('secretWord', $value); 80 | } 81 | 82 | public function getPrivateKey() 83 | { 84 | return $this->getParameter('privateKey'); 85 | } 86 | 87 | public function setPrivateKey($value) 88 | { 89 | return $this->setParameter('privateKey', $value); 90 | } 91 | 92 | /** 93 | * Setter: sale ID for use by refund. 94 | * 95 | * @param $value 96 | * 97 | * @return BaseAbstractRequest 98 | */ 99 | public function setSaleId($value) 100 | { 101 | return $this->setParameter('saleId', $value); 102 | } 103 | 104 | /** 105 | * Getter: sale ID for use by refund. 106 | * 107 | * @return string 108 | */ 109 | public function getSaleId() 110 | { 111 | return $this->getParameter('saleId'); 112 | } 113 | 114 | /** 115 | * Setter: sale ID for use by refund. 116 | * 117 | * @param $value 118 | * 119 | * @return BaseAbstractRequest 120 | */ 121 | public function setInvoiceId($value) 122 | { 123 | return $this->setParameter('invoiceId', $value); 124 | } 125 | 126 | /** 127 | * Getter: sale ID for use by refund. 128 | * 129 | * @return string 130 | */ 131 | public function getInvoiceId() 132 | { 133 | return $this->getParameter('invoiceId'); 134 | } 135 | 136 | /** 137 | * Getter: admin username for use by refund. 138 | * 139 | * @return string 140 | */ 141 | public function getAdminUsername() 142 | { 143 | return $this->getParameter('adminUsername'); 144 | } 145 | 146 | /** 147 | * Setter: admin username for use by refund. 148 | * 149 | * @param $value 150 | * 151 | * @return BaseAbstractRequest 152 | */ 153 | public function setAdminUsername($value) 154 | { 155 | return $this->setParameter('adminUsername', $value); 156 | } 157 | 158 | /** 159 | * Getter: admin password for use by refund. 160 | * 161 | * @return string 162 | */ 163 | public function getAdminPassword() 164 | { 165 | return $this->getParameter('adminPassword'); 166 | } 167 | 168 | /** 169 | * Setter: admin password for use by refund. 170 | * 171 | * @param $value 172 | * 173 | * @return BaseAbstractRequest 174 | */ 175 | public function setAdminPassword($value) 176 | { 177 | return $this->setParameter('adminPassword', $value); 178 | } 179 | 180 | /** 181 | * Getter: category for use by refund. 182 | * 183 | * @return string 184 | */ 185 | public function getCategory() 186 | { 187 | return $this->getParameter('category'); 188 | } 189 | 190 | /** 191 | * Setter: category for use by refund. 192 | * 193 | * @param $value 194 | * 195 | * @return BaseAbstractRequest 196 | */ 197 | public function setCategory($value) 198 | { 199 | return $this->setParameter('category', $value); 200 | } 201 | 202 | /** 203 | * Getter: comment for use by refund. 204 | * 205 | * @return string 206 | */ 207 | public function getComment() 208 | { 209 | return $this->getParameter('comment'); 210 | } 211 | 212 | /** 213 | * Setter: category for use by refund. 214 | * 215 | * @param $value 216 | * 217 | * @return BaseAbstractRequest 218 | */ 219 | public function setComment($value) 220 | { 221 | return $this->setParameter('comment', $value); 222 | } 223 | 224 | /** 225 | * Setter: lineitem_id for use by stop recurring. 226 | * 227 | * @param $value 228 | * 229 | * @return BaseAbstractRequest 230 | */ 231 | public function setLineItemId($value) 232 | { 233 | return $this->setParameter('lineItemId', $value); 234 | } 235 | 236 | /** 237 | * Getter: lineitem_id for use by stop recurring. 238 | * 239 | * @return string 240 | */ 241 | public function getLineItemId() 242 | { 243 | return $this->getParameter('lineItemId'); 244 | } 245 | 246 | public function getAmount() 247 | { 248 | return parent::getAmount(); 249 | } 250 | 251 | public function setAmount($value) 252 | { 253 | return parent::setAmount($value); 254 | } 255 | 256 | public function getCurrency() 257 | { 258 | return parent::getCurrency(); 259 | } 260 | 261 | public function setCurrency($value) 262 | { 263 | return parent::setCurrency($value); 264 | } 265 | } 266 | -------------------------------------------------------------------------------- /src/Message/CompletePurchaseRequest.php: -------------------------------------------------------------------------------- 1 | httpRequest->request->all(); 24 | if (empty($fetchPostBody)) { 25 | $request_type = 'query'; 26 | } else { 27 | $request_type = 'request'; 28 | } 29 | 30 | $orderNo = $this->httpRequest->$request_type->get('order_number'); 31 | $orderAmount = $this->httpRequest->$request_type->get('total'); 32 | 33 | // strange exception specified by 2Checkout 34 | if ($this->getDemoMode()) { 35 | $orderNo = '1'; 36 | } 37 | 38 | $key = md5($this->getSecretWord().$this->getAccountNumber().$orderNo.$orderAmount); 39 | if (strtolower($this->httpRequest->$request_type->get('key')) !== $key) { 40 | throw new InvalidResponseException('Invalid key'); 41 | } 42 | 43 | return $this->httpRequest->$request_type->all(); 44 | } 45 | 46 | /** 47 | * {@inheritdoc} 48 | * 49 | * @param mixed $data 50 | * 51 | * @return CompletePurchaseResponse 52 | */ 53 | public function sendData($data) 54 | { 55 | return $this->response = new CompletePurchaseResponse($this, $data); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Message/CompletePurchaseResponse.php: -------------------------------------------------------------------------------- 1 | data['order_number']) ? $this->data['order_number'] : null; 25 | } 26 | 27 | public function getTransactionInvoice() 28 | { 29 | return isset($this->data['invoice_id']) ? $this->data['invoice_id'] : null; 30 | } 31 | 32 | /** 33 | * Transaction ID. 34 | * 35 | * @return mixed|null 36 | */ 37 | public function getTransactionId() 38 | { 39 | return isset($this->data['merchant_order_id']) ? $this->data['merchant_order_id'] : null; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Message/DetailSaleRequest.php: -------------------------------------------------------------------------------- 1 | getTestMode() ? $this->testEndpoint : $this->liveEndpoint; 25 | } 26 | 27 | /** 28 | * HTTP request headers. 29 | * 30 | * @return array 31 | */ 32 | public function getRequestHeaders() 33 | { 34 | return array( 35 | 'Accept' => 'application/json', 36 | ); 37 | } 38 | 39 | public function isNotNull($value) 40 | { 41 | return !is_null($value); 42 | } 43 | 44 | public function getData() 45 | { 46 | $this->validate('adminUsername', 'adminPassword'); 47 | 48 | $data = array(); 49 | $data['admin_username'] = $this->getAdminUsername(); 50 | $data['admin_password'] = $this->getAdminPassword(); 51 | 52 | $data['sale_id'] = $this->getSaleId(); 53 | $data['invoice_id'] = $this->getInvoiceId(); 54 | 55 | // needed to determine which API endpoint to use in OffsiteResponse 56 | if ($this->getTestMode()) { 57 | $data['sandbox'] = true; 58 | } 59 | 60 | $data = array_filter($data, function ($value) { 61 | return !is_null($value); 62 | }); 63 | 64 | // remove unwanted data 65 | unset($data['sandbox']); 66 | 67 | return $data; 68 | } 69 | 70 | 71 | /** 72 | * @param mixed $data 73 | * 74 | * @return DetailSaleResponse 75 | */ 76 | public function sendData($data) 77 | { 78 | $payload = $data; 79 | unset($payload['admin_username']); 80 | unset($payload['admin_password']); 81 | 82 | $query = ''; 83 | if (!empty($payload['invoice_id'])) { 84 | $query = '?invoice_id=' . $payload['invoice_id']; 85 | } 86 | 87 | if (!empty($payload['sale_id'])) { 88 | $query = '?sale_id=' . $payload['sale_id']; 89 | } 90 | 91 | try { 92 | $response = $this->httpClient->get( 93 | $this->getEndpoint() . $query, 94 | $this->getRequestHeaders() 95 | )->setAuth($data['admin_username'], $data['admin_password'])->send(); 96 | 97 | return new DetailSaleResponse($this, $response->json()); 98 | } catch (BadResponseException $e) { 99 | $response = $e->getResponse(); 100 | 101 | return new DetailSaleResponse($this, $response->json()); 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/Message/DetailSaleResponse.php: -------------------------------------------------------------------------------- 1 | data['errors']); 21 | } 22 | 23 | /** 24 | * {@inheritdoc} 25 | * 26 | * @return bool 27 | */ 28 | public function isRedirect() 29 | { 30 | return false; 31 | } 32 | 33 | /** 34 | * {@inheritdoc} 35 | * 36 | * @return int|null 37 | */ 38 | public function getCode() 39 | { 40 | return isset($this->data['response_code']) ? $this->data['response_code'] : null; 41 | } 42 | 43 | public function getLineItems() 44 | { 45 | return $this->data['sale']['invoices'][0]['lineitems']; 46 | } 47 | 48 | /** 49 | * {@inheritdoc} 50 | */ 51 | public function getMessage() 52 | { 53 | return isset($this->data['sale']) ? $this->data['sale'] : json_encode($this->data['errors']); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Message/NotificationRequest.php: -------------------------------------------------------------------------------- 1 | httpRequest->request->all(); 15 | $data['secretWord'] = $this->getSecretWord(); 16 | $data['accountNumber'] = $this->getAccountNumber(); 17 | 18 | return $data; 19 | } 20 | 21 | /** 22 | * {@inheritdoc} 23 | * 24 | * @param mixed $data 25 | * 26 | * @return NotificationResponse 27 | */ 28 | public function sendData($data) 29 | { 30 | return new NotificationResponse($this, $data); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Message/NotificationResponse.php: -------------------------------------------------------------------------------- 1 | data['secretWord']; # Input your secret word 17 | $hashSid = $this->data['accountNumber']; #Input your seller ID (2Checkout account number) 18 | $hashOrder = $this->data['sale_id']; 19 | $hashInvoice = $this->data['invoice_id']; 20 | $StringToHash = strtoupper(md5($hashOrder.$hashSid.$hashInvoice.$hashSecretWord)); 21 | 22 | return $StringToHash == $this->data['md5_hash']; 23 | } 24 | 25 | /** 26 | * 2Checkout transaction reference. 27 | * 28 | * @return mixed 29 | */ 30 | public function getTransactionReference() 31 | { 32 | return $this->data['sale_id']; 33 | } 34 | 35 | /** 36 | * Order or transaction ID. 37 | * 38 | * @return mixed 39 | */ 40 | public function getTransactionId() 41 | { 42 | return $this->data['vendor_order_id']; 43 | } 44 | 45 | /** 46 | * Indicate what type of 2Checkout notification this is. 47 | * 48 | * @return string 49 | */ 50 | public function getNotificationType() 51 | { 52 | return $this->data['message_type']; 53 | } 54 | 55 | /** 56 | * Get transaction/notification status. 57 | * 58 | * SInce this is an IPN notification, we made this true. 59 | * 60 | * @return bool 61 | */ 62 | public function getTransactionStatus() 63 | { 64 | return true; 65 | } 66 | 67 | /** 68 | * Notification response. 69 | * 70 | * @return mixed 71 | */ 72 | public function getMessage() 73 | { 74 | return $this->data; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/Message/PurchaseRequest.php: -------------------------------------------------------------------------------- 1 | validate('accountNumber', 'returnUrl'); 15 | 16 | $data = array(); 17 | $data['sid'] = $this->getAccountNumber(); 18 | $data['mode'] = '2CO'; 19 | $data['merchant_order_id'] = $this->getTransactionId(); 20 | $data['currency_code'] = $this->getCurrency(); 21 | $data['x_receipt_link_url'] = $this->getReturnUrl(); 22 | 23 | // Do not pass for live sales i.e if its false. 24 | if ($this->getDemoMode()) { 25 | $data['demo'] = 'Y'; 26 | } 27 | 28 | if ($this->getLanguage()) { 29 | $data['lang'] = $this->getLanguage(); 30 | } 31 | 32 | if ($this->getPurchaseStep()) { 33 | $data['purchase_step'] = $this->getPurchaseStep(); 34 | } 35 | 36 | if ($this->getCoupon()) { 37 | $data['coupon'] = $this->getCoupon(); 38 | } 39 | 40 | // needed to determine which API endpoint to use in OffsiteResponse 41 | if ($this->getTestMode()) { 42 | $data['sandbox'] = true; 43 | } 44 | 45 | $i = 0; 46 | 47 | // Setup Products information 48 | foreach ($this->getCart() as $item) { 49 | $data['li_' . $i . '_type'] = $item['type']; 50 | $data['li_' . $i . '_name'] = $item['name']; 51 | $data['li_' . $i . '_price'] = $item['price']; 52 | $data['li_' . $i . '_quantity'] = $item['quantity']; 53 | 54 | // optional item/product parameters 55 | if (isset($item['tangible'])) { 56 | $data['li_' . $i . '_tangible'] = $item['tangible']; 57 | } 58 | if (isset($item['product_id'])) { 59 | $data['li_' . $i . '_product_id'] = $item['product_id']; 60 | } 61 | if (isset($item['description'])) { 62 | $data['li_' . $i . '_description'] = $item['description']; 63 | } 64 | if (isset($item['recurrence'])) { 65 | $data['li_' . $i . '_recurrence'] = $item['recurrence']; 66 | } 67 | if (isset($item['duration'])) { 68 | $data['li_' . $i . '_duration'] = $item['duration']; 69 | } 70 | if (isset($item['startup_fee'])) { 71 | $data['li_' . $i . '_startup_fee'] = $item['startup_fee']; 72 | } 73 | 74 | ++$i; 75 | } 76 | 77 | if ($this->getCard()) { 78 | $data['card_holder_name'] = $this->getCard()->getName(); 79 | $data['street_address'] = $this->getCard()->getAddress1(); 80 | $data['street_address2'] = $this->getCard()->getAddress2(); 81 | $data['city'] = $this->getCard()->getCity(); 82 | $data['state'] = $this->getCard()->getState(); 83 | $data['zip'] = $this->getCard()->getPostcode(); 84 | $data['country'] = $this->getCard()->getCountry(); 85 | $data['phone'] = $this->getCard()->getPhone(); 86 | $data['email'] = $this->getCard()->getEmail(); 87 | } 88 | 89 | $data = array_filter($data, function ($value) { 90 | return !is_null($value); 91 | }); 92 | 93 | return $data; 94 | } 95 | 96 | /** 97 | * @param mixed $data 98 | * 99 | * @return PurchaseResponse 100 | */ 101 | public function sendData($data) 102 | { 103 | return $this->response = new PurchaseResponse($this, $data); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/Message/PurchaseResponse.php: -------------------------------------------------------------------------------- 1 | data['sandbox']) { 24 | return $this->testEndpoint; 25 | } else { 26 | return $this->liveEndpoint; 27 | } 28 | } 29 | 30 | /** 31 | * @return bool 32 | */ 33 | public function isSuccessful() 34 | { 35 | return false; 36 | } 37 | 38 | /** 39 | * @return bool 40 | */ 41 | public function isRedirect() 42 | { 43 | return true; 44 | } 45 | 46 | /** 47 | * @return string 48 | */ 49 | public function getRedirectUrl() 50 | { 51 | $endpoint = $this->getEndPoint(); 52 | 53 | // remove the sandbox parameter. 54 | unset($this->data['sandbox']); 55 | 56 | $url = $endpoint.'?'.http_build_query($this->data); 57 | 58 | // Fix for some sites that encode the entities 59 | return str_replace('&', '&', $url); 60 | } 61 | 62 | /** 63 | * @return string 64 | */ 65 | public function getRedirectMethod() 66 | { 67 | return 'GET'; 68 | } 69 | 70 | /** 71 | * No redirect data. 72 | */ 73 | public function getRedirectData() 74 | { 75 | return; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/Message/RefundRequest.php: -------------------------------------------------------------------------------- 1 | getTestMode() ? $this->testEndpoint : $this->liveEndpoint; 25 | } 26 | 27 | /** 28 | * HTTP request headers. 29 | * 30 | * @return array 31 | */ 32 | public function getRequestHeaders() 33 | { 34 | return array( 35 | 'Accept' => 'application/json', 36 | ); 37 | } 38 | 39 | public function isNotNull($value) 40 | { 41 | return !is_null($value); 42 | } 43 | 44 | public function getData() 45 | { 46 | $this->validate('adminUsername', 'adminPassword', 'saleId', 'comment'); 47 | 48 | $data = array(); 49 | $data['admin_username'] = $this->getAdminUsername(); 50 | $data['admin_password'] = $this->getAdminPassword(); 51 | 52 | $data['sale_id'] = $this->getSaleId(); 53 | $data['invoice_id'] = $this->getInvoiceId(); 54 | $data['amount'] = $this->getParameter('amount'); 55 | $data['currency'] = $this->getCurrency(); 56 | $data['comment'] = 'Buyer deserved a refund'; 57 | $data['category'] = 10; 58 | 59 | // override default category value of 10. 60 | // see https://www.2checkout.com/documentation/api/sales/refund-invoice 61 | if ($this->getCategory()) { 62 | $data['category'] = $this->getCategory(); 63 | } 64 | 65 | // override default comment 66 | if ($this->getComment()) { 67 | $data['comment'] = $this->getComment(); 68 | } 69 | 70 | // override default comment 71 | if (strlen($this->getCurrency()) > 3) { 72 | $data['currency'] = strtolower($this->getCurrency()); 73 | } 74 | 75 | // needed to determine which API endpoint to use in OffsiteResponse 76 | if ($this->getTestMode()) { 77 | $data['sandbox'] = true; 78 | } 79 | 80 | $data = array_filter($data, function ($value) { 81 | return !is_null($value); 82 | }); 83 | 84 | // remove unwanted data 85 | unset($data['sandbox']); 86 | 87 | return $data; 88 | } 89 | 90 | 91 | /** 92 | * @param mixed $data 93 | * 94 | * @return RefundResponse 95 | */ 96 | public function sendData($data) 97 | { 98 | $payload = $data; 99 | unset($payload['admin_username']); 100 | unset($payload['admin_password']); 101 | 102 | try { 103 | $response = $this->httpClient->post( 104 | $this->getEndpoint(), 105 | $this->getRequestHeaders(), 106 | $payload 107 | )->setAuth($data['admin_username'], $data['admin_password'])->send(); 108 | 109 | return new RefundResponse($this, $response->json()); 110 | } catch (BadResponseException $e) { 111 | $response = $e->getResponse(); 112 | 113 | return new RefundResponse($this, $response->json()); 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/Message/RefundResponse.php: -------------------------------------------------------------------------------- 1 | data['response_code']) ? $this->data['response_code'] == 'OK' : false; 21 | } 22 | 23 | /** 24 | * {@inheritdoc} 25 | * 26 | * @return bool 27 | */ 28 | public function isRedirect() 29 | { 30 | return false; 31 | } 32 | 33 | /** 34 | * {@inheritdoc} 35 | * 36 | * @return int|null 37 | */ 38 | public function getCode() 39 | { 40 | return isset($this->data['response_code']) ? $this->data['response_code'] : null; 41 | } 42 | 43 | /** 44 | * {@inheritdoc} 45 | */ 46 | public function getMessage() 47 | { 48 | return isset($this->data['response_message']) ? 49 | $this->data['response_message'] : 50 | json_encode($this->data['errors']); 51 | } 52 | 53 | /** 54 | * Return the first error message in the error basket. 55 | */ 56 | public function getFirstErrorMessage() 57 | { 58 | return $this->data['errors'][0]['message']; 59 | } 60 | 61 | /** 62 | * Return the first error message in the error basket. 63 | */ 64 | public function getFirstErrorCode() 65 | { 66 | return $this->data['errors'][0]['code']; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/Message/StopRecurringRequest.php: -------------------------------------------------------------------------------- 1 | getTestMode() ? $this->testEndpoint : $this->liveEndpoint; 25 | } 26 | 27 | /** 28 | * HTTP request headers. 29 | * 30 | * @return array 31 | */ 32 | public function getRequestHeaders() 33 | { 34 | return array( 35 | 'Accept' => 'application/json', 36 | ); 37 | } 38 | 39 | public function isNotNull($value) 40 | { 41 | return !is_null($value); 42 | } 43 | 44 | public function getData() 45 | { 46 | $this->validate('adminUsername', 'adminPassword', 'lineItemId'); 47 | 48 | $data = array(); 49 | $data['admin_username'] = $this->getAdminUsername(); 50 | $data['admin_password'] = $this->getAdminPassword(); 51 | 52 | $data['lineitem_id'] = $this->getLineItemId(); 53 | 54 | // needed to determine which API endpoint to use in OffsiteResponse 55 | if ($this->getTestMode()) { 56 | $data['sandbox'] = true; 57 | } 58 | 59 | $data = array_filter($data, function ($value) { 60 | return !is_null($value); 61 | }); 62 | 63 | // remove unwanted data 64 | unset($data['sandbox']); 65 | 66 | return $data; 67 | } 68 | 69 | 70 | /** 71 | * @param mixed $data 72 | * 73 | * @return StopRecurringResponse 74 | */ 75 | public function sendData($data) 76 | { 77 | $payload = $data; 78 | unset($payload['admin_username']); 79 | unset($payload['admin_password']); 80 | 81 | try { 82 | $response = $this->httpClient->post( 83 | $this->getEndpoint(), 84 | $this->getRequestHeaders(), 85 | $payload 86 | )->setAuth($data['admin_username'], $data['admin_password'])->send(); 87 | 88 | return new StopRecurringResponse($this, $response->json()); 89 | } catch (BadResponseException $e) { 90 | $response = $e->getResponse(); 91 | 92 | return new StopRecurringResponse($this, $response->json()); 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/Message/StopRecurringResponse.php: -------------------------------------------------------------------------------- 1 | data['errors']) && $this->data['response_code'] == 'OK'; 21 | } 22 | 23 | /** 24 | * {@inheritdoc} 25 | * 26 | * @return bool 27 | */ 28 | public function isRedirect() 29 | { 30 | return false; 31 | } 32 | 33 | /** 34 | * {@inheritdoc} 35 | * 36 | * @return int|null 37 | */ 38 | public function getCode() 39 | { 40 | return isset($this->data['response_code']) ? $this->data['response_code'] : null; 41 | } 42 | 43 | public function getLineItems() 44 | { 45 | return $this->data['sale']['invoices'][0]['lineitems']; 46 | } 47 | 48 | /** 49 | * {@inheritdoc} 50 | */ 51 | public function getMessage() 52 | { 53 | return isset($this->data['response_message']) ? 54 | $this->data['response_message'] : 55 | json_encode($this->data['errors']); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Message/TokenPurchaseRequest.php: -------------------------------------------------------------------------------- 1 | getTestMode() ? $this->testEndpoint : $this->liveEndpoint; 25 | 26 | return $endpoint . $this->getAccountNumber() . '/rs/authService'; 27 | } 28 | 29 | public function isNotNull($value) 30 | { 31 | return !is_null($value); 32 | } 33 | 34 | /** 35 | * HTTP request headers. 36 | * 37 | * @return array 38 | */ 39 | public function getRequestHeaders() 40 | { 41 | return array( 42 | 'Accept' => 'application/json', 43 | 'Content-Type' => 'application/json', 44 | ); 45 | } 46 | 47 | /** 48 | * @return array 49 | * 50 | * @throws \Omnipay\Common\Exception\InvalidRequestException 51 | */ 52 | public function getData() 53 | { 54 | $this->validate('accountNumber', 'privateKey', 'token', 'amount', 'transactionId'); 55 | 56 | $data = array(); 57 | $data['sellerId'] = $this->getAccountNumber(); 58 | $data['privateKey'] = $this->getPrivateKey(); 59 | $data['merchantOrderId'] = $this->getTransactionId(); 60 | $data['token'] = $this->getToken(); 61 | $data['currency'] = $this->getCurrency(); 62 | $data['total'] = $this->getAmount(); 63 | 64 | if ($this->getCard()) { 65 | $data['billingAddr']['name'] = $this->getCard()->getName(); 66 | $data['billingAddr']['addrLine1'] = $this->getCard()->getAddress1(); 67 | $data['billingAddr']['addrLine2'] = $this->getCard()->getAddress2(); 68 | $data['billingAddr']['city'] = $this->getCard()->getCity(); 69 | $data['billingAddr']['state'] = $this->getCard()->getState(); 70 | $data['billingAddr']['zipCode'] = $this->getCard()->getPostcode(); 71 | $data['billingAddr']['email'] = $this->getCard()->getEmail(); 72 | $data['billingAddr']['country'] = $this->getCard()->getCountry(); 73 | $data['billingAddr']['phoneNumber'] = $this->getCard()->getPhone(); 74 | $data['billingAddr']['phoneExt'] = $this->getCard()->getPhoneExtension(); 75 | } 76 | 77 | if ($this->getCart()) { 78 | // remove amount parameter if lineItem attributes / cart is set 79 | unset($data['total']); 80 | 81 | $data['lineItems'] = $this->getCart(); 82 | } 83 | 84 | // remove null values item from $data['billingAddr'] 85 | $data['billingAddr'] = array_filter($data['billingAddr'], array($this, 'isNotNull')); 86 | 87 | // remove null values item from $data. 88 | $data = array_filter($data, array($this, 'isNotNull')); 89 | 90 | return $data; 91 | } 92 | 93 | /** 94 | * @param mixed $data 95 | * 96 | * @return TokenPurchaseResponse 97 | */ 98 | public function sendData($data) 99 | { 100 | try { 101 | $response = $this->httpClient->post( 102 | $this->getEndpoint(), 103 | $this->getRequestHeaders(), 104 | json_encode($data) 105 | )->send(); 106 | 107 | return new TokenPurchaseResponse($this, $response->json()); 108 | } catch (BadResponseException $e) { 109 | $response = $e->getResponse(); 110 | 111 | return new TokenPurchaseResponse($this, $response->json()); 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/Message/TokenPurchaseResponse.php: -------------------------------------------------------------------------------- 1 | data['response']['responseCode']; 21 | 22 | return isset($responseCode) ? $responseCode == 'APPROVED' : false; 23 | } 24 | 25 | /** 26 | * {@inheritdoc} 27 | * 28 | * @return bool 29 | */ 30 | public function isRedirect() 31 | { 32 | return false; 33 | } 34 | 35 | /** 36 | * {@inheritdoc} 37 | * 38 | * @return int|null 39 | */ 40 | public function getCode() 41 | { 42 | return isset($this->data['exception']) ? $this->data['exception']['errorCode'] : null; 43 | } 44 | 45 | /** 46 | * {@inheritdoc} 47 | */ 48 | public function getMessage() 49 | { 50 | return isset($this->data['exception']) ? $this->data['exception']['errorMsg'] : null; 51 | } 52 | 53 | /** 54 | * {@inheritdoc} 55 | */ 56 | public function getTransactionReference() 57 | { 58 | return isset($this->data['response']['orderNumber']) ? $this->data['response']['orderNumber'] : null; 59 | } 60 | 61 | /** 62 | * {@inheritdoc} 63 | */ 64 | public function getTransactionId() 65 | { 66 | return isset($this->data['response']['merchantOrderId']) ? $this->data['response']['merchantOrderId'] : null; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/TokenGateway.php: -------------------------------------------------------------------------------- 1 | '', 21 | 'privateKey' => '', 22 | 'testMode' => false, 23 | ); 24 | } 25 | 26 | /** 27 | * Getter: get cart items | Lineitem Attributes. 28 | * 29 | * @return array 30 | */ 31 | public function getCart() 32 | { 33 | return $this->getParameter('cart'); 34 | } 35 | 36 | /** 37 | * Array of cart items | Lineitem Attributes. 38 | * 39 | * @see https://www.2checkout.com/documentation/payment-api/create-sale 40 | * 41 | * @param array $value 42 | * 43 | * @return $this 44 | */ 45 | public function setCart($value) 46 | { 47 | return $this->setParameter('cart', $value); 48 | } 49 | 50 | /** 51 | * Getter: 2Checkout account number. 52 | * 53 | * @return string 54 | */ 55 | public function getAccountNumber() 56 | { 57 | return $this->getParameter('accountNumber'); 58 | } 59 | 60 | /** 61 | * Setter: 2Checkout account number. 62 | * 63 | * @param string $value 64 | * 65 | * @return $this 66 | */ 67 | public function setAccountNumber($value) 68 | { 69 | return $this->setParameter('accountNumber', $value); 70 | } 71 | 72 | /** 73 | * Getter: 2Checkout private key. 74 | * 75 | * @return string 76 | */ 77 | public function getPrivateKey() 78 | { 79 | return $this->getParameter('privateKey'); 80 | } 81 | 82 | /** 83 | * Setter: 2Checkout private key. 84 | * 85 | * @param $value 86 | * 87 | * @return $this 88 | */ 89 | public function setPrivateKey($value) 90 | { 91 | return $this->setParameter('privateKey', $value); 92 | } 93 | 94 | /** 95 | * @param array $parameters 96 | * 97 | * @return \Omnipay\Common\Message\AbstractRequest 98 | */ 99 | public function purchase(array $parameters = array()) 100 | { 101 | return $this->createRequest('\Omnipay\TwoCheckoutPlus\Message\TokenPurchaseRequest', $parameters); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /tests/GatewayTest.php: -------------------------------------------------------------------------------- 1 | gateway = new Gateway($this->getHttpClient(), $this->getHttpRequest()); 18 | 19 | $this->gateway->setAccountNumber('901290261'); 20 | $this->gateway->setSecretWord('MzBjODg5YTUtNzcwMS00N2NlLWFkODMtNzQ2YzllZWRjMzBj'); 21 | $this->gateway->setTestMode(true); 22 | $this->gateway->setDemoMode(true); 23 | $this->gateway->setLanguage('fr'); 24 | $this->gateway->setPurchaseStep('payment-method'); 25 | $this->gateway->setCoupon('BlackFriday'); 26 | $this->gateway->setCart(array( 27 | array( 28 | 'type' => 'product', 29 | 'name' => 'Product 1', 30 | 'description' => 'Description of product 1', 31 | 'quantity' => 2, 32 | 'price' => 22, 33 | 'tangible' => 'N', 34 | 'product_id' => 12345, 35 | 'recurrence' => '1 Week', 36 | 'duration' => '1 Year', 37 | 'startup_fee' => '5', 38 | ), 39 | array( 40 | 'type' => 'product', 41 | 'name' => 'Product 2', 42 | 'quantity' => 1, 43 | 'price' => 10, 44 | 'tangible' => 'N' 45 | ) 46 | )); 47 | 48 | $this->options = array( 49 | 'card' => $this->getValidCard(), 50 | 'transactionId' => 1234, 51 | 'currency' => 'USD', 52 | 'returnUrl' => 'http://localhost/omnipay-2checkout/complete.php' 53 | ); 54 | } 55 | 56 | public function testGateway() 57 | { 58 | $cart = $this->gateway->getCart(); 59 | $this->assertSame('901290261', $this->gateway->getAccountNumber()); 60 | $this->assertSame('MzBjODg5YTUtNzcwMS00N2NlLWFkODMtNzQ2YzllZWRjMzBj', $this->gateway->getSecretWord()); 61 | $this->assertSame('payment-method', $this->gateway->getPurchaseStep()); 62 | $this->assertSame('BlackFriday', $this->gateway->getCoupon()); 63 | $this->assertSame('fr', $this->gateway->getLanguage()); 64 | $this->assertTrue($this->gateway->getTestMode()); 65 | $this->assertTrue($this->gateway->getDemoMode()); 66 | $this->assertSame('product', $cart[0]['type']); 67 | $this->assertSame('Product 1', $cart[0]['name']); 68 | $this->assertSame(2, $cart[0]['quantity']); 69 | $this->assertSame(22, $cart[0]['price']); 70 | $this->assertSame('N', $cart[0]['tangible']); 71 | $this->assertSame(12345, $cart[0]['product_id']); 72 | } 73 | 74 | public function testPurchase() 75 | { 76 | $request = $this->gateway->purchase($this->options)->send(); 77 | 78 | $this->assertSame(false, $request->isSuccessful()); 79 | $this->assertSame(true, $request->isRedirect()); 80 | $this->assertSame('GET', $request->getRedirectMethod()); 81 | $this->assertSame('https://sandbox.2checkout.com/checkout/purchase', $request->getEndPoint()); 82 | $this->assertNull($request->getRedirectData()); 83 | } 84 | 85 | public function testRefund() 86 | { 87 | $request = $this->gateway->refund(array( 88 | 'adminUsername' => 'username', 89 | 'adminPassword' => 'password', 90 | 'saleId' => 106235469964, 91 | 'comment' => 'Buyer deserved a refund', 92 | 'category' => 13 93 | ))->send(); 94 | 95 | $this->assertSame(false, $request->isSuccessful()); 96 | $this->assertSame(false, $request->isRedirect()); 97 | $this->assertSame('[{"code":"UNAUTHORIZED","message":"Authentication failed"}]', $request->getMessage()); 98 | $this->assertNull($request->getCode()); 99 | } 100 | 101 | public function testCompletePurchaseWithGETParameters() 102 | { 103 | // mock / set a test MD5 hash, total order amount and order number 104 | $this->getHttpRequest()->initialize( 105 | array( 106 | 'order_number' => 1234, 107 | 'merchant_order_id' => 56789, 108 | 'total' => 20, 109 | 'key' => $this->gateway->getTestMode() ? '21937BDC2F33AF28503800677DE7C4F8' : '686C451E66D5766DEC3A1E74379C7BAD', 110 | ) 111 | ); 112 | 113 | $request = $this->gateway->completePurchase($this->options)->send(); 114 | $this->assertSame(true, $request->isSuccessful()); 115 | $this->assertSame(1234, $request->getTransactionReference()); 116 | $this->assertSame(56789, $request->getTransactionId()); 117 | } 118 | 119 | public function testCompletePurchaseWithPOSTParameters() 120 | { 121 | // mock / set a test MD5 hash, total order amount and order number 122 | $this->getHttpRequest()->initialize( 123 | array(), 124 | array( 125 | 'order_number' => 1234, 126 | 'merchant_order_id' => 56789, 127 | 'total' => 20, 128 | 'key' => $this->gateway->getTestMode() ? '21937BDC2F33AF28503800677DE7C4F8' : '686C451E66D5766DEC3A1E74379C7BAD', 129 | ) 130 | ); 131 | 132 | $request = $this->gateway->completePurchase($this->options)->send(); 133 | $this->assertSame(true, $request->isSuccessful()); 134 | $this->assertSame(1234, $request->getTransactionReference()); 135 | $this->assertSame(1234, $request->getTransactionReference()); 136 | } 137 | 138 | /** 139 | * @expectedException Omnipay\Common\Exception\InvalidResponseException 140 | */ 141 | public function testCompletePurchaseInvalidResponseException() 142 | { 143 | // mock / set a test MD5 hash, total order amount and order number 144 | $this->getHttpRequest()->initialize( 145 | array( 146 | 'order_number' => 1234, 147 | 'total' => 20, 148 | 'key' => 'BadMD5harsh', 149 | ) 150 | ); 151 | 152 | $this->gateway->completePurchase($this->options)->send(); 153 | } 154 | 155 | public function testAcceptNotificationFail() 156 | { 157 | 158 | $this->getHttpRequest()->initialize( 159 | array(), 160 | $this->getMockHttpResponse('FraudChangeNotificationFail.txt')->json() 161 | ); 162 | 163 | $response = $this->gateway->acceptNotification()->send(); 164 | 165 | $this->assertFalse($response->isSuccessful()); 166 | $this->assertSame('4742525399', $response->getTransactionReference()); 167 | $this->assertSame('FRAUD_STATUS_CHANGED', $response->getNotificationType()); 168 | $this->assertSame(true, $response->getTransactionStatus()); 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /tests/Message/NotificationRequestTest.php: -------------------------------------------------------------------------------- 1 | getMockBuilder('\Symfony\Component\HttpFoundation\Request') 15 | ->setConstructorArgs( 16 | array( 17 | array(), 18 | // directly passing an array of the POSTed data would do but to prevent 19 | // duplicate array in test, i made it seem like an API response then 20 | // get the response as an array using json() method. 21 | $this->getMockHttpResponse('FraudChangeNotificationFail.txt')->json() 22 | ) 23 | ) 24 | ->setMethods(null) 25 | ->getMock(); 26 | 27 | $this->request = new NotificationRequest($this->getHttpClient(), $mockHttpRequest); 28 | $this->request->setAccountNumber('901290261'); 29 | $this->request->setSecretWord('MzBjODg5YTUtNzcwMS00N2NlLWFkODMtNzQ2YzllZWRjMzBj'); 30 | } 31 | 32 | public function testGetData() 33 | { 34 | $data = $this->request->getData(); 35 | $this->assertSame('2012-07-26', $data['auth_exp']); 36 | $this->assertSame('FRAUD_STATUS_CHANGED', $data['message_type']); 37 | $this->assertSame('MzBjODg5YTUtNzcwMS00N2NlLWFkODMtNzQ2YzllZWRjMzBj', $data['secretWord']); 38 | $this->assertSame('901290261', $data['accountNumber']); 39 | } 40 | 41 | 42 | public function testSendData() 43 | { 44 | $data = $this->request->getData(); 45 | $response = $this->request->sendData($data); 46 | $this->assertSame('Omnipay\TwoCheckoutPlus\Message\NotificationResponse', get_class($response)); 47 | } 48 | 49 | } -------------------------------------------------------------------------------- /tests/Message/NotificationResponseTest.php: -------------------------------------------------------------------------------- 1 | getMockHttpResponse('FraudChangeNotificationFail.txt')->json(); 12 | $data['accountNumber'] = '901290261'; 13 | $data['secretWord'] = 'MzBjODg5YTUtNzcwMS00N2NlLWFkODMtNzQ2YzllZWRjMzBj'; 14 | $response = new NotificationResponse($this->getMockRequest(), $data); 15 | 16 | $this->assertFalse($response->isSuccessful()); 17 | $this->assertSame('4742525399', $response->getTransactionReference()); 18 | $this->assertSame('1234567', $response->getTransactionId()); 19 | $this->assertSame('FRAUD_STATUS_CHANGED', $response->getNotificationType()); 20 | $this->assertTrue($response->getTransactionStatus()); 21 | $this->assertSame($data, $response->getMessage()); 22 | } 23 | public function testResponsePass() 24 | { 25 | $data = $this->getMockHttpResponse('FraudChangeNotificationPass.txt')->json(); 26 | $data['accountNumber'] = '901290261'; 27 | $data['secretWord'] = 'MzBjODg5YTUtNzcwMS00N2NlLWFkODMtNzQ2YzllZWRjMzBj'; 28 | $response = new NotificationResponse($this->getMockRequest(), $data); 29 | 30 | $this->assertTrue($response->isSuccessful()); 31 | $this->assertSame('9093727242912', $response->getTransactionReference()); 32 | $this->assertSame('3737', $response->getTransactionId()); 33 | $this->assertSame('FRAUD_STATUS_CHANGED', $response->getNotificationType()); 34 | $this->assertTrue($response->getTransactionStatus()); 35 | $this->assertSame($data, $response->getMessage()); 36 | } 37 | 38 | public function testForResponseOtherThanFraudReview() { 39 | $data = $this->getMockHttpResponse('FraudChangeNotificationPass.txt')->json(); 40 | $data['accountNumber'] = '901290261'; 41 | $data['secretWord'] = 'MzBjODg5YTUtNzcwMS00N2NlLWFkODMtNzQ2YzllZWRjMzBj'; 42 | $data['message_type'] = 'INVOICE_STATUS_CHANGED'; 43 | $response = new NotificationResponse($this->getMockRequest(), $data); 44 | 45 | $this->assertTrue($response->getTransactionStatus()); 46 | } 47 | } -------------------------------------------------------------------------------- /tests/Message/PurchaseResponseTest.php: -------------------------------------------------------------------------------- 1 | getMockRequest(), 14 | array( 15 | 'sid' => '1441', 16 | 'mode' => '2CO', 17 | 'sandbox' => false 18 | ) 19 | ); 20 | 21 | $this->assertSame('https://www.2checkout.com/checkout/purchase', $response->getEndPoint()); 22 | $this->assertSame('https://www.2checkout.com/checkout/purchase?sid=1441&mode=2CO', $response->getRedirectUrl()); 23 | $this->assertFalse($response->isSuccessful()); 24 | $this->assertTrue($response->isRedirect()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/Message/TokenPurchaseRequestTest.php: -------------------------------------------------------------------------------- 1 | addResponse($this->getMockHttpResponse('TokenPurchaseFailure.txt')); 17 | 18 | $httpClient = $this->getHttpClient(); 19 | $httpClient->addSubscriber($mock); 20 | 21 | $this->request = new TokenPurchaseRequest($httpClient, $this->getHttpRequest()); 22 | $this->request->initialize(array( 23 | 'card' => $this->getValidCard(), 24 | 'token' => 'Y2RkZDdjN2EtNjFmZS00ZGYzLWI4NmEtNGZhMjI3NmExMzQ0', 25 | 'transactionId' => '123456', 26 | 'currency' => 'USD', 27 | 'amount' => '20.5' 28 | )); 29 | 30 | $this->request->setAccountNumber('801290261'); 31 | $this->request->setTestMode(true); 32 | $this->request->setPrivateKey('5F876A36-D506-4E1F-8EE9-DA2358500F9C'); 33 | } 34 | 35 | public function testGetSetCart() 36 | { 37 | $this->request->setCart( 38 | array( 39 | array( 40 | "name" => "Demo Item", 41 | "price" => "4.99", 42 | "type" => "product", 43 | "quantity" => "1", 44 | "recurrence" => "4 Year", 45 | "startupFee" => "9.99" 46 | ), 47 | array( 48 | "name" => "Demo Item 2", 49 | "price" => "6.99", 50 | "type" => "product", 51 | "quantity" => "2", 52 | "recurrence" => "8 Year", 53 | "startupFee" => "19.99" 54 | ) 55 | ) 56 | ); 57 | 58 | $cart = $this->request->getCart(); 59 | $this->assertCount(2, $cart); 60 | 61 | $this->assertSame('Demo Item', $cart[0]['name']); 62 | $this->assertSame('Demo Item 2', $cart[1]['name']); 63 | } 64 | 65 | public function testGetData() 66 | { 67 | $data = $this->request->getData(); 68 | $this->assertSame('5F876A36-D506-4E1F-8EE9-DA2358500F9C', $data['privateKey']); 69 | } 70 | 71 | public function testSendData() 72 | { 73 | $data = $this->request->getData(); 74 | $response = $this->request->sendData($data); 75 | $this->assertSame('Omnipay\TwoCheckoutPlus\Message\TokenPurchaseResponse', get_class($response)); 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /tests/Message/TokenPurchaseResponseTest.php: -------------------------------------------------------------------------------- 1 | 'application/json'), $body); 13 | $response = new TokenPurchaseResponse($this->getMockRequest(), $httpResponse->json()); 14 | 15 | $this->assertTrue($response->isSuccessful()); 16 | $this->assertFalse($response->isRedirect()); 17 | $this->assertNull($response->getCode()); 18 | $this->assertNull($response->getMessage()); 19 | $this->assertSame('205182114555', $response->getTransactionReference()); 20 | } 21 | 22 | public function testFailure() 23 | { 24 | $httpResponse = $this->getMockHttpResponse('TokenPurchaseFailure.txt'); 25 | $response = new TokenPurchaseResponse($this->getMockRequest(), $httpResponse->json()); 26 | 27 | $this->assertFalse($response->isSuccessful()); 28 | $this->assertFalse($response->isRedirect()); 29 | $this->assertSame('602', $response->getCode()); 30 | $this->assertSame('Payment Authorization Failed: Please verify your Credit Card details are entered correctly and try again, or try another payment method.', 31 | $response->getMessage()); 32 | $this->assertNull($response->getTransactionReference()); 33 | } 34 | } -------------------------------------------------------------------------------- /tests/Mock/DetailSaleFailure.txt: -------------------------------------------------------------------------------- 1 | { 2 | "errors": [ 3 | { 4 | "code": "PARAMETER_MISSING", 5 | "message": "Required parameter missing: sale_or_invoice_id", 6 | "parameter": "sale_or_invoice_id" 7 | } 8 | ] 9 | } -------------------------------------------------------------------------------- /tests/Mock/DetailSaleSuccess.txt: -------------------------------------------------------------------------------- 1 | { 2 | "response_code": "OK", 3 | "response_message": "Sale detail retrieved", 4 | "sale": { 5 | "comments": [ 6 | 7 | ], 8 | "customer": { 9 | "address_1": "123 Main Street", 10 | "address_2": null, 11 | "address_id": "9093735704445", 12 | "cardholder_name": "Joe Flagster", 13 | "city": "Townsville", 14 | "country_code": "USA", 15 | "country_code_2": "US", 16 | "country_name": "United States", 17 | "customer_id": "9093735704391", 18 | "email_address": "rater@rater.tk", 19 | "first_name": "Joe", 20 | "lang": "en", 21 | "last_name": "Flagster", 22 | "middle_initial": null, 23 | "pay_method": { 24 | "avs": null, 25 | "cvv": null, 26 | "first_six_digits": "400000", 27 | "last_two_digits": "02", 28 | "method": "credit card" 29 | }, 30 | "phone": "", 31 | "phone_ext": "", 32 | "postal_code": "43206", 33 | "prefix": null, 34 | "state": "OH", 35 | "state_2": null 36 | }, 37 | "date_placed": "2017-05-10 15:57:18", 38 | "detail_ip": { 39 | "address": "41.190.30.242", 40 | "area_code": 0, 41 | "city": "Lagos", 42 | "country": "Nigeria", 43 | "country_code": "NG", 44 | "region": "05", 45 | "zip": null 46 | }, 47 | "invoices": [ 48 | { 49 | "change_id": "9093735704388", 50 | "customer_name": "Joe Flagster", 51 | "customer_snapshot_id": null, 52 | "customer_total": "100.41", 53 | "date_placed": "2017-05-10 15:57:18", 54 | "date_shipped": null, 55 | "date_vendor_paid": null, 56 | "fees_2co": "5.98", 57 | "invoice_id": "9093735704394", 58 | "lineitems": [ 59 | { 60 | "affiliate_vendor_id": null, 61 | "billing": { 62 | "amount": "28.85", 63 | "bill_method": "credit_card", 64 | "billing_id": "9093735704418", 65 | "customer_amount": "28.85", 66 | "customer_id": "9093735704391", 67 | "date_deposited": null, 68 | "date_end": null, 69 | "date_fail": "2017-05-17", 70 | "date_next": "2018-05-10", 71 | "date_pending": null, 72 | "date_start": "2017-05-12", 73 | "lineitem_id": "9093735704415", 74 | "recurring_status": "active", 75 | "status": "bill", 76 | "usd_amount": "28.85", 77 | "vendor_amount": "28.85" 78 | }, 79 | "commission": null, 80 | "commission_affiliate_vendor_id": null, 81 | "commission_flat_rate": null, 82 | "commission_percentage": null, 83 | "commission_type": null, 84 | "commission_usd_amount": null, 85 | "customer_amount": "28.85", 86 | "flat_rate": null, 87 | "installment": "1", 88 | "invoice_id": "9093735704394", 89 | "lc_affiliate_vendor_id": null, 90 | "lc_usd_amount": null, 91 | "lineitem_id": "9093735704415", 92 | "linked_id": null, 93 | "options": [ 94 | 95 | ], 96 | "percentage": null, 97 | "product_description": "", 98 | "product_duration": "Forever", 99 | "product_handling": null, 100 | "product_id": null, 101 | "product_is_cart": "0", 102 | "product_name": "Subscription Product 2", 103 | "product_price": "19.23", 104 | "product_recurrence": "1 Year", 105 | "product_startup_fee": "9.62", 106 | "product_tangible": "N", 107 | "sale_id": "9093735704385", 108 | "status": "bill", 109 | "type": "product", 110 | "usd_amount": "28.85", 111 | "usd_commission": null, 112 | "vendor_amount": "28.85", 113 | "vendor_product_id": "2437" 114 | }, 115 | { 116 | "affiliate_vendor_id": null, 117 | "billing": { 118 | "amount": "28.85", 119 | "bill_method": "credit_card", 120 | "billing_id": "9093735704430", 121 | "customer_amount": "28.85", 122 | "customer_id": "9093735704391", 123 | "date_deposited": null, 124 | "date_end": null, 125 | "date_fail": "2017-05-17", 126 | "date_next": "2018-05-10", 127 | "date_pending": null, 128 | "date_start": "2017-05-12", 129 | "lineitem_id": "9093735704427", 130 | "recurring_status": "active", 131 | "status": "bill", 132 | "usd_amount": "28.85", 133 | "vendor_amount": "28.85" 134 | }, 135 | "commission": null, 136 | "commission_affiliate_vendor_id": null, 137 | "commission_flat_rate": null, 138 | "commission_percentage": null, 139 | "commission_type": null, 140 | "commission_usd_amount": null, 141 | "customer_amount": "28.85", 142 | "flat_rate": null, 143 | "installment": "1", 144 | "invoice_id": "9093735704394", 145 | "lc_affiliate_vendor_id": null, 146 | "lc_usd_amount": null, 147 | "lineitem_id": "9093735704427", 148 | "linked_id": null, 149 | "options": [ 150 | 151 | ], 152 | "percentage": null, 153 | "product_description": "", 154 | "product_duration": "Forever", 155 | "product_handling": null, 156 | "product_id": null, 157 | "product_is_cart": "0", 158 | "product_name": "Subscription Product 2", 159 | "product_price": "19.23", 160 | "product_recurrence": "1 Year", 161 | "product_startup_fee": "9.62", 162 | "product_tangible": "N", 163 | "sale_id": "9093735704385", 164 | "status": "bill", 165 | "type": "product", 166 | "usd_amount": "28.85", 167 | "usd_commission": null, 168 | "vendor_amount": "28.85", 169 | "vendor_product_id": "2437" 170 | }, 171 | { 172 | "affiliate_vendor_id": null, 173 | "billing": { 174 | "amount": "3.86", 175 | "bill_method": "credit_card", 176 | "billing_id": "9093735704442", 177 | "customer_amount": "3.86", 178 | "customer_id": "9093735704391", 179 | "date_deposited": null, 180 | "date_end": "2017-05-17", 181 | "date_fail": "2017-05-17", 182 | "date_next": null, 183 | "date_pending": null, 184 | "date_start": "2017-05-12", 185 | "lineitem_id": "9093735704439", 186 | "recurring_status": null, 187 | "status": "bill", 188 | "usd_amount": "3.86", 189 | "vendor_amount": "3.86" 190 | }, 191 | "commission": null, 192 | "commission_affiliate_vendor_id": null, 193 | "commission_flat_rate": null, 194 | "commission_percentage": null, 195 | "commission_type": null, 196 | "commission_usd_amount": null, 197 | "customer_amount": "3.86", 198 | "flat_rate": null, 199 | "installment": null, 200 | "invoice_id": "9093735704394", 201 | "lc_affiliate_vendor_id": null, 202 | "lc_usd_amount": null, 203 | "lineitem_id": "9093735704439", 204 | "linked_id": null, 205 | "options": [ 206 | 207 | ], 208 | "percentage": null, 209 | "product_description": "", 210 | "product_duration": null, 211 | "product_handling": null, 212 | "product_id": null, 213 | "product_is_cart": "0", 214 | "product_name": "Tax Fee", 215 | "product_price": "3.86", 216 | "product_recurrence": null, 217 | "product_startup_fee": null, 218 | "product_tangible": "N", 219 | "sale_id": "9093735704385", 220 | "status": "bill", 221 | "type": "product", 222 | "usd_amount": "3.86", 223 | "usd_commission": null, 224 | "vendor_amount": "3.86", 225 | "vendor_product_id": null 226 | }, 227 | { 228 | "affiliate_vendor_id": null, 229 | "billing": { 230 | "amount": "28.85", 231 | "bill_method": "credit_card", 232 | "billing_id": "9093735704424", 233 | "customer_amount": "28.85", 234 | "customer_id": "9093735704391", 235 | "date_deposited": null, 236 | "date_end": null, 237 | "date_fail": "2017-05-17", 238 | "date_next": "2018-05-10", 239 | "date_pending": null, 240 | "date_start": "2017-05-12", 241 | "lineitem_id": "9093735704421", 242 | "recurring_status": "active", 243 | "status": "bill", 244 | "usd_amount": "28.85", 245 | "vendor_amount": "28.85" 246 | }, 247 | "commission": null, 248 | "commission_affiliate_vendor_id": null, 249 | "commission_flat_rate": null, 250 | "commission_percentage": null, 251 | "commission_type": null, 252 | "commission_usd_amount": null, 253 | "customer_amount": "28.85", 254 | "flat_rate": null, 255 | "installment": "1", 256 | "invoice_id": "9093735704394", 257 | "lc_affiliate_vendor_id": null, 258 | "lc_usd_amount": null, 259 | "lineitem_id": "9093735704421", 260 | "linked_id": null, 261 | "options": [ 262 | 263 | ], 264 | "percentage": null, 265 | "product_description": "", 266 | "product_duration": "Forever", 267 | "product_handling": null, 268 | "product_id": null, 269 | "product_is_cart": "0", 270 | "product_name": "Subscription Product 2", 271 | "product_price": "19.23", 272 | "product_recurrence": "1 Year", 273 | "product_startup_fee": "9.62", 274 | "product_tangible": "N", 275 | "sale_id": "9093735704385", 276 | "status": "bill", 277 | "type": "product", 278 | "usd_amount": "28.85", 279 | "usd_commission": null, 280 | "vendor_amount": "28.85", 281 | "vendor_product_id": "2437" 282 | }, 283 | { 284 | "affiliate_vendor_id": null, 285 | "billing": { 286 | "amount": "10.00", 287 | "bill_method": "credit_card", 288 | "billing_id": "9093735704436", 289 | "customer_amount": "10.00", 290 | "customer_id": "9093735704391", 291 | "date_deposited": null, 292 | "date_end": "2017-05-17", 293 | "date_fail": "2017-05-17", 294 | "date_next": null, 295 | "date_pending": null, 296 | "date_start": "2017-05-12", 297 | "lineitem_id": "9093735704433", 298 | "recurring_status": null, 299 | "status": "bill", 300 | "usd_amount": "10.00", 301 | "vendor_amount": "10.00" 302 | }, 303 | "commission": null, 304 | "commission_affiliate_vendor_id": null, 305 | "commission_flat_rate": null, 306 | "commission_percentage": null, 307 | "commission_type": null, 308 | "commission_usd_amount": null, 309 | "customer_amount": "10.00", 310 | "flat_rate": null, 311 | "installment": null, 312 | "invoice_id": "9093735704394", 313 | "lc_affiliate_vendor_id": null, 314 | "lc_usd_amount": null, 315 | "lineitem_id": "9093735704433", 316 | "linked_id": null, 317 | "options": [ 318 | 319 | ], 320 | "percentage": null, 321 | "product_description": "", 322 | "product_duration": null, 323 | "product_handling": null, 324 | "product_id": null, 325 | "product_is_cart": "0", 326 | "product_name": "Shipping Fee", 327 | "product_price": "10.00", 328 | "product_recurrence": null, 329 | "product_startup_fee": null, 330 | "product_tangible": "N", 331 | "sale_id": "9093735704385", 332 | "status": "bill", 333 | "type": "product", 334 | "usd_amount": "10.00", 335 | "usd_commission": null, 336 | "vendor_amount": "10.00", 337 | "vendor_product_id": null 338 | } 339 | ], 340 | "new_customer_quote_id": "163", 341 | "new_vendor_quote_id": "163", 342 | "payout_status": "Pending Capture", 343 | "recurring": "1", 344 | "referrer": "http:\/\/wordpress.dev\/checkout-2\/", 345 | "sale_id": "9093735704385", 346 | "shipping": null, 347 | "status": "approved", 348 | "timestamp": "2017-05-10 15:57:18", 349 | "usd_total": "100.41", 350 | "vendor_id": "901290261", 351 | "vendor_order_id": "3699", 352 | "vendor_total": "100.41" 353 | } 354 | ], 355 | "ip_address": "41.190.30.242", 356 | "ip_country": "Nigeria", 357 | "recurring_decline": null, 358 | "sale_id": "9093735704385" 359 | } 360 | } -------------------------------------------------------------------------------- /tests/Mock/FraudChangeNotificationFail.txt: -------------------------------------------------------------------------------- 1 | HTTP/1.1 200 OK 2 | Content-Type: application/json 3 | 4 | { 5 | "auth_exp": "2012-07-26", 6 | "bill_city": "Columbus", 7 | "bill_country": "USA", 8 | "bill_postal_code": "43123", 9 | "bill_state": "OH", 10 | "bill_street_address": "123 Test St", 11 | "bill_street_address2": "dddsdsc", 12 | "cust_currency": "USD", 13 | "customer_email": "noreply@2co.com", 14 | "customer_first_name": "Craig", 15 | "customer_ip": "76.181.170.90", 16 | "customer_ip_country": "United States", 17 | "customer_last_name": "Christenson", 18 | "customer_name": "Craig P Christenson", 19 | "customer_phone": "5555555555", 20 | "fraud_status": "fail", 21 | "invoice_cust_amount": "0.20", 22 | "invoice_id": "4759791636", 23 | "invoice_list_amount": "0.20", 24 | "invoice_status": "deposited", 25 | "invoice_usd_amount": "0.20", 26 | "item_count": "2", 27 | "item_cust_amount_1": "0.10", 28 | "item_cust_amount_2": "0.10", 29 | "item_duration_1": "", 30 | "item_duration_2": "", 31 | "item_id_1": "ebook1", 32 | "item_id_2": "ebook1", 33 | "item_list_amount_1": "0.10", 34 | "item_list_amount_2": "0.10", 35 | "item_name_1": "Download", 36 | "item_name_2": "Download", 37 | "item_rec_date_next_1": "2012-07-26", 38 | "item_rec_date_next_2": "2012-07-26", 39 | "item_rec_install_billed_1": "4", 40 | "item_rec_install_billed_2": "4", 41 | "item_rec_list_amount_1": "0.10", 42 | "item_rec_list_amount_2": "0.10", 43 | "item_rec_status_1": "live", 44 | "item_rec_status_2": "live", 45 | "item_recurrence_1": "1 Week", 46 | "item_recurrence_2": "1 Week", 47 | "item_type_1": "bill", 48 | "item_type_2": "bill", 49 | "item_usd_amount_1": "0.10", 50 | "item_usd_amount_2": "0.10", 51 | "key_count": "68", 52 | "list_currency": "USD", 53 | "md5_hash": "2DAE8544FA29CE313DB20582D540F133", 54 | "message_description": "Order fraud status changed", 55 | "message_id": "3786", 56 | "message_type": "FRAUD_STATUS_CHANGED", 57 | "payment_type": "paypal ec", 58 | "recurring": "1", 59 | "sale_date_placed": "2012-06-28 22:14:23", 60 | "sale_id": "4742525399", 61 | "ship_city": "", 62 | "ship_country": "", 63 | "ship_name": "", 64 | "ship_postal_code": "", 65 | "ship_state": "", 66 | "ship_status": "", 67 | "ship_street_address": "", 68 | "ship_street_address2": "", 69 | "ship_tracking_number": "", 70 | "timestamp": "2012-07-19 17:01:19", 71 | "vendor_id": "532001", 72 | "vendor_order_id": "1234567" 73 | } -------------------------------------------------------------------------------- /tests/Mock/FraudChangeNotificationPass.txt: -------------------------------------------------------------------------------- 1 | HTTP/1.1 200 OK 2 | Content-Type: application/json 3 | 4 | { 5 | "auth_exp": "2012-07-26", 6 | "bill_city": "Columbus", 7 | "bill_country": "USA", 8 | "bill_postal_code": "43123", 9 | "bill_state": "OH", 10 | "bill_street_address": "123 Test St", 11 | "bill_street_address2": "dddsdsc", 12 | "cust_currency": "USD", 13 | "customer_email": "noreply@2co.com", 14 | "customer_first_name": "Craig", 15 | "customer_ip": "76.181.170.90", 16 | "customer_ip_country": "United States", 17 | "customer_last_name": "Christenson", 18 | "customer_name": "Craig P Christenson", 19 | "customer_phone": "5555555555", 20 | "fraud_status": "pass", 21 | "invoice_cust_amount": "0.20", 22 | "invoice_id": "9093727242921", 23 | "invoice_list_amount": "0.20", 24 | "invoice_status": "deposited", 25 | "invoice_usd_amount": "0.20", 26 | "item_count": "2", 27 | "item_cust_amount_1": "0.10", 28 | "item_cust_amount_2": "0.10", 29 | "item_duration_1": "", 30 | "item_duration_2": "", 31 | "item_id_1": "ebook1", 32 | "item_id_2": "ebook1", 33 | "item_list_amount_1": "0.10", 34 | "item_list_amount_2": "0.10", 35 | "item_name_1": "Download", 36 | "item_name_2": "Download", 37 | "item_rec_date_next_1": "2012-07-26", 38 | "item_rec_date_next_2": "2012-07-26", 39 | "item_rec_install_billed_1": "4", 40 | "item_rec_install_billed_2": "4", 41 | "item_rec_list_amount_1": "0.10", 42 | "item_rec_list_amount_2": "0.10", 43 | "item_rec_status_1": "live", 44 | "item_rec_status_2": "live", 45 | "item_recurrence_1": "1 Week", 46 | "item_recurrence_2": "1 Week", 47 | "item_type_1": "bill", 48 | "item_type_2": "bill", 49 | "item_usd_amount_1": "0.10", 50 | "item_usd_amount_2": "0.10", 51 | "key_count": "68", 52 | "list_currency": "USD", 53 | "md5_hash": "F6F69F6039DBF8CC26A5388157685931", 54 | "message_description": "Order fraud status changed", 55 | "message_id": "3786", 56 | "message_type": "FRAUD_STATUS_CHANGED", 57 | "payment_type": "paypal ec", 58 | "recurring": "1", 59 | "sale_date_placed": "2012-06-28 22:14:23", 60 | "sale_id": "9093727242912", 61 | "ship_city": "", 62 | "ship_country": "", 63 | "ship_name": "", 64 | "ship_postal_code": "", 65 | "ship_state": "", 66 | "ship_status": "", 67 | "ship_street_address": "", 68 | "ship_street_address2": "", 69 | "ship_tracking_number": "", 70 | "timestamp": "2016-01-06 06:04:13", 71 | "vendor_id": "532001", 72 | "vendor_order_id": "3737" 73 | } -------------------------------------------------------------------------------- /tests/Mock/StopRecurringFailure.txt: -------------------------------------------------------------------------------- 1 | { 2 | "errors": [ 3 | { 4 | "code": "RECORD_NOT_FOUND", 5 | "message": "Unable to find record." 6 | } 7 | ] 8 | } -------------------------------------------------------------------------------- /tests/Mock/TokenPurchaseFailure.txt: -------------------------------------------------------------------------------- 1 | HTTP/1.1 400 Bad Request 2 | Content-Type: application/json 3 | 4 | { 5 | "validationErrors": null, 6 | "exception": { 7 | "errorMsg": "Payment Authorization Failed: Please verify your Credit Card details are entered correctly and try again, or try another payment method.", 8 | "httpStatus": "400", 9 | "exception": false, 10 | "errorCode": "602" 11 | }, 12 | "response": null 13 | } -------------------------------------------------------------------------------- /tests/Mock/TokenPurchaseSuccess.txt: -------------------------------------------------------------------------------- 1 | { 2 | "validationErrors": null, 3 | "exception": null, 4 | "response": { 5 | "type": "AuthResponse", 6 | "lineItems": [ 7 | { 8 | "options": [], 9 | "price": "6.99", 10 | "quantity": "2", 11 | "recurrence": "1 Month", 12 | "startupFee": null, 13 | "productId": "123", 14 | "tangible": "N", 15 | "name": "Demo Item 1", 16 | "type": "product", 17 | "description": "", 18 | "duration": "1 Year" 19 | }, 20 | { 21 | "options": [ 22 | { 23 | "optName": "Size", 24 | "optValue": "Large", 25 | "optSurcharge": "1.00" 26 | } 27 | ], 28 | "price": "1.99", 29 | "quantity": "1", 30 | "recurrence": null, 31 | "startupFee": null, 32 | "productId": "", 33 | "tangible": "N", 34 | "name": "Demo Item 2", 35 | "type": "product", 36 | "description": "", 37 | "duration": null 38 | }, 39 | { 40 | "options": [], 41 | "price": "3.00", 42 | "quantity": "1", 43 | "recurrence": null, 44 | "startupFee": null, 45 | "productId": "", 46 | "tangible": "Y", 47 | "name": "Shipping Fee", 48 | "type": "shipping", 49 | "description": "", 50 | "duration": null 51 | } 52 | ], 53 | "transactionId": "205182114564", 54 | "billingAddr": { 55 | "addrLine1": "123 Test St", 56 | "addrLine2": null, 57 | "city": "Columbus", 58 | "zipCode": "43123", 59 | "phoneNumber": "5555555555", 60 | "phoneExtension": null, 61 | "email": "example@2co.com", 62 | "name": "Testing Tester", 63 | "state": "Ohio", 64 | "country": "USA" 65 | }, 66 | "shippingAddr": { 67 | "addrLine1": "123 Test St", 68 | "addrLine2": "", 69 | "city": "Columbus", 70 | "zipCode": "43123", 71 | "phoneNumber": null, 72 | "phoneExtension": null, 73 | "email": null, 74 | "name": "Testing Tester", 75 | "state": "OH", 76 | "country": "USA" 77 | }, 78 | "merchantOrderId": "123", 79 | "orderNumber": "205182114555", 80 | "recurrentInstallmentId": null, 81 | "responseMsg": "Successfully authorized the provided credit card", 82 | "responseCode": "APPROVED", 83 | "total": "19.97", 84 | "currencyCode": "USD", 85 | "errors": null 86 | } 87 | } -------------------------------------------------------------------------------- /tests/TokenGatewayTest.php: -------------------------------------------------------------------------------- 1 | addResponse(new Response(200, array('Content-Type' => 'application/json'), $body)) 23 | // alternate style of getting mock response. See how both txt file varies. 24 | ->addResponse($this->getMockHttpResponse('TokenPurchaseFailure.txt')); 25 | 26 | // Add the mock plugin to the client object 27 | $httpClient = $this->getHttpClient(); 28 | $httpClient->addSubscriber($mock); 29 | 30 | $this->gateway = new TokenGateway($httpClient, $this->getHttpRequest()); 31 | $this->options = array( 32 | 'card' => $this->getValidCard(), 33 | 'token' => 'Y2RkZDdjN2EtNjFmZS00ZGYzLWI4NmEtNGZhMjI3NmExMzQ0', 34 | 'transactionId' => '123456', 35 | 'currency' => 'USD', 36 | 'amount' => '20.5' 37 | ); 38 | 39 | $this->gateway->setAccountNumber('801290261'); 40 | $this->gateway->setTestMode(true); 41 | $this->gateway->setPrivateKey('5F876A36-D506-4E1F-8EE9-DA2358500F9C'); 42 | 43 | $this->gateway->setCart( 44 | array( 45 | array( 46 | "name" => "Demo Item", 47 | "price" => "4.99", 48 | "type" => "product", 49 | "quantity" => "1", 50 | "recurrence" => "4 Year", 51 | "startupFee" => "9.99" 52 | ), 53 | array( 54 | "name" => "Demo Item 2", 55 | "price" => "6.99", 56 | "type" => "product", 57 | "quantity" => "2", 58 | "recurrence" => "8 Year", 59 | "startupFee" => "19.99" 60 | ) 61 | ) 62 | ); 63 | } 64 | 65 | public function testGateway() 66 | { 67 | $this->assertSame('801290261', $this->gateway->getAccountNumber()); 68 | $this->assertSame('5F876A36-D506-4E1F-8EE9-DA2358500F9C', $this->gateway->getPrivateKey()); 69 | $this->assertTrue($this->gateway->getTestMode()); 70 | 71 | $cart = $this->gateway->getCart(); 72 | $this->assertCount(2, $cart); 73 | $this->assertSame('Demo Item', $cart[0]['name']); 74 | $this->assertSame('Demo Item 2', $cart[1]['name']); 75 | } 76 | 77 | 78 | public function testPurchase() 79 | { 80 | $response = $this->gateway->purchase($this->options)->send(); 81 | 82 | $this->assertTrue($response->isSuccessful()); 83 | $this->assertFalse($response->isRedirect()); 84 | $this->assertNull($response->getCode()); 85 | $this->assertNull($response->getMessage()); 86 | $this->assertSame('205182114555', $response->getTransactionReference()); 87 | $this->assertSame('123', $response->getTransactionId()); 88 | 89 | $response = $this->gateway->purchase($this->options)->send(); 90 | 91 | $this->assertFalse($response->isSuccessful()); 92 | $this->assertFalse($response->isRedirect()); 93 | $this->assertSame('602', $response->getCode()); 94 | $this->assertSame('Payment Authorization Failed: Please verify your Credit Card details are entered correctly and try again, or try another payment method.', $response->getMessage()); 95 | $this->assertNull($response->getTransactionReference()); 96 | $this->assertNull($response->getTransactionId()); 97 | } 98 | } 99 | --------------------------------------------------------------------------------