diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index 0d77ee1a..00000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1 +0,0 @@ -github: [barryvdh] diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml deleted file mode 100644 index 33e89767..00000000 --- a/.github/workflows/run-tests.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: Unit Tests - -on: - push: - branches: - - master - pull_request: - branches: - - "*" - schedule: - - cron: '0 0 * * *' - -jobs: - php-tests: - runs-on: ubuntu-latest - timeout-minutes: 15 - env: - COMPOSER_NO_INTERACTION: 1 - - strategy: - matrix: - php: [8.5, 8.4, 8.3, 8.2, 8.1, 8.0, 7.4, 7.3] - dependency-version: [prefer-lowest, prefer-stable] - - name: P${{ matrix.php }} - ${{ matrix.dependency-version }} - - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - coverage: none - tools: composer:v2 - - - name: Install dependencies - run: | - composer update --${{ matrix.dependency-version }} --prefer-dist --no-progress - - - name: Execute Unit Tests - run: composer test diff --git a/.gitignore b/.gitignore index daea6b43..c08f9add 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1 @@ -/vendor -composer.lock -composer.phar -phpunit.xml -.idea/* +_site \ No newline at end of file diff --git a/CNAME b/CNAME new file mode 100644 index 00000000..151fc561 --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +omnipay.thephpleague.com \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 6ad2b7f9..00000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,11 +0,0 @@ -# Contributing Guidelines - -* Fork the project. -* Make your feature addition or bug fix. -* Add tests for it. This is important so I don't break it in a future version unintentionally. -* Commit just the modifications, do not mess with the composer.json or CHANGELOG.md files. -* Ensure your code is nicely formatted in the [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md) - style and that all tests pass. -* Don't forget to check all versionnumbers and tag it correctly in GIT ;) -* Send the pull request. -* Check that the Travis CI build passed. If not, rinse and repeat. diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 55cf185f..00000000 --- a/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2012-2018 Adrian Macneil - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/_data/images.yml b/_data/images.yml new file mode 100644 index 00000000..7d475040 --- /dev/null +++ b/_data/images.yml @@ -0,0 +1,8 @@ +# Path to project specific favicon.ico, leave blank to use default +favicon: + +# Path to project specific apple-touch-icon-precomposed.png, leave blank to use default +apple_touch: + +# Path to project logo +logo: \ No newline at end of file diff --git a/_data/menu.yml b/_data/menu.yml new file mode 100644 index 00000000..948c7388 --- /dev/null +++ b/_data/menu.yml @@ -0,0 +1,19 @@ +Getting Started: + Introduction: '/' + Simple Example: '/simple-example/' + Installation: '/installation/' + Changelog: '/changelog/' +Gateways: + Community: '/gateways/community/' + Build your own: '/gateways/build-your-own/' + Configuring: '/gateways/configuring/' +API: + Cards: '/api/cards/' + Authorizing: '/api/authorizing/' + Charging: '/api/charging/' + Refunds: '/api/refunds/' + Voiding: '/api/voiding/' + Responses: '/api/responses/' + Error Handling: '/api/error-handling/' + Token Billing: '/api/token-billing/' + Recurring Billing: '/api/recurring-billing/' \ No newline at end of file diff --git a/_data/project.yml b/_data/project.yml new file mode 100644 index 00000000..39ec041a --- /dev/null +++ b/_data/project.yml @@ -0,0 +1,5 @@ +title: Omnipay +tagline: Multi-gateway payment processing library +description: +google_analytics_tracking_id: UA-46050814-12 +base_href: //omnipay.thephpleague.com/ diff --git a/_layouts/default.html b/_layouts/default.html new file mode 100644 index 00000000..02daea27 --- /dev/null +++ b/_layouts/default.html @@ -0,0 +1,102 @@ + + + + + + + {% if page.url == '/' %} + {{ site.data.project.title }} - {{ site.data.project.tagline }} + {% else %} + {{ page.title }} - {{ site.data.project.title }} + {% endif %} + {% if site.data.project.description %} + + {% endif %} + {% if site.data.project.base_href %} + + {% endif %} + {% if site.data.images.favicon %} + + {% else %} + + {% endif %} + {% if site.data.images.apple_touch %} + + {% else %} + + {% endif %} + + + + +
+ + The League of Extraordinary Packages + +

Our Packages:

+ +
+ +
+ + + Presented by The League of Extraordinary Packages + +
+ + + + +
+ + {% for section in site.data.menu %} +

{{ section[0] }}

+ + {% endfor %} +
+
+ {{ content }} +
+
+ + + + + + + +{% if site.data.project.google_analytics_tracking_id %} + +{% endif %} + + + diff --git a/api/authorizing.md b/api/authorizing.md new file mode 100644 index 00000000..1c2fef78 --- /dev/null +++ b/api/authorizing.md @@ -0,0 +1,63 @@ +--- +layout: default +permalink: api/authorizing/ +title: Authorizing +--- + +Authorizing +=========== + +The main methods implemented by gateways are: + +* `authorize($options)` - Authorize an amount on the customer's card. +* `completeAuthorize($options)` - Handle return from off-site gateways after authorization. On-site gateways do not need to implement the `completeAuthorize` method, and will throw `BadMethodCallException` if called. +* `capture($options)` - Capture an amount you have previously authorized. + +All gateway methods take an `$options` array as an argument. Each gateway differs in which +parameters are required, and the gateway will throw `InvalidRequestException` if you +omit any required parameters. All gateways will accept a subset of these options: + +* card +* token +* amount +* currency +* description +* transactionId +* clientIp +* returnUrl +* cancelUrl + +Pass the options through to the method like so: + +~~~ php +$card = new CreditCard($formData); +$request = $gateway->authorize([ + 'amount' => '10.00', // this represents $10.00 + 'card' => $card, + 'returnUrl' => 'https://www.example.com/return', +]); +~~~ + +When calling the `completeAuthorize` or `completePurchase` methods, the exact same arguments should be provided as +when you made the initial `authorize` or `purchase` call (some gateways will need to verify for example the actual +amount paid equals the amount requested). The only parameter you can omit is `card`. + + +To summarize the various parameters you have available to you: + +* Gateway settings (e.g. username and password) are set directly on the gateway. These settings apply to all payments, and generally you will store these in a configuration file or in the database. +* Method options are used for any payment-specific options, which are not set by the customer. For example, the payment `amount`, `currency`, `transactionId` and `returnUrl`. +* CreditCard parameters are data which the user supplies. For example, you want the user to specify their `firstName` and `billingCountry`, but you don't want a user to specify the payment `currency` or `returnUrl`. + +The parameters can be set in two ways: + +* As an array when creating the request object, as shown above. +* Using setter methods on the request object following a similar naming convention. + +For example, the card and amount can be set after the `authorize` request has been created like this: + +```php +$request = $gateway->authorize(['returnUrl' => 'https://www.example.com/return']); +$request->setCard($card); +$request->setAmount('10.00'); +``` diff --git a/api/cards.md b/api/cards.md new file mode 100644 index 00000000..d3a1d25e --- /dev/null +++ b/api/cards.md @@ -0,0 +1,85 @@ +--- +layout: default +permalink: api/cards/ +title: Cards +--- + +Cards +===== + +User form input is directed to an [CreditCard](https://github.com/thephpleague/omnipay-common/blob/master/src/Common/CreditCard.php) +object. This provides a safe way to accept user input. + +The `CreditCard` object has the following fields: + +~~~ php +[ + 'firstName', + 'lastName', + 'number', + 'expiryMonth', + 'expiryYear', + 'startMonth', + 'startYear', + 'cvv', + 'issueNumber', + 'type', + 'billingAddress1', + 'billingAddress2', + 'billingCity', + 'billingPostcode', + 'billingState', + 'billingCountry', + 'billingPhone', + 'shippingAddress1', + 'shippingAddress2', + 'shippingCity', + 'shippingPostcode', + 'shippingState', + 'shippingCountry', + 'shippingPhone', + 'company', + 'email' +] +~~~ + +Even off-site gateways make use of the `CreditCard` object, because often you need to pass +customer billing or shipping details through to the gateway. + +The `CreditCard` object can be initialized with untrusted user input via the constructor. +Any fields passed to the constructor which are not recognized will be ignored. + +~~~ php +$formInputData = array( + 'firstName' => 'Bobby', + 'lastName' => 'Tables', + 'number' => '4111111111111111', +); +$card = new CreditCard($formInputData); +~~~ + +You can also just pass the form data array directly to the gateway, and a `CreditCard` object +will be created for you. + +CreditCard fields can be accessed using getters and setters: + +~~~ php +$number = $card->getNumber(); +$card->setFirstName('Adrian'); +~~~ + +If you submit credit card details which are obviously invalid (missing required fields, or a number +which fails the Luhn check), [InvalidCreditCardException](https://github.com/thephpleague/omnipay-common/blob/master/src/Common/Exception/InvalidCreditCardException.php) +will be thrown. You should validate the card details using your framework's validation library +before submitting the details to your gateway, to avoid unnecessary API calls. + +For on-site payment gateways, the following card fields are generally required: + +* firstName +* lastName +* number +* expiryMonth +* expiryYear +* cvv + +You can also verify the card number using the Luhn algorithm by calling `Helper::validateLuhn($number)`. diff --git a/api/charging.md b/api/charging.md new file mode 100644 index 00000000..096eb69b --- /dev/null +++ b/api/charging.md @@ -0,0 +1,19 @@ +--- +layout: default +permalink: api/charging/ +title: Charging +--- + +Charging +======== + +The main methods implemented by gateways are: + +* `purchase($options)` - authorize and immediately capture an amount on the customer's card +* `completePurchase($options)` - handle return from off-site gateways after purchase + +On-site gateways do not need to implement the `completePurchase` method, and will throw `BadMethodCallException` if called. + +When calling the `completeAuthorize` or `completePurchase` methods, the exact same arguments should be provided as +when you made the initial `authorize` or `purchase` call (some gateways will need to verify for example the actual +amount paid equals the amount requested). The only parameter you can omit is `card`. \ No newline at end of file diff --git a/api/error-handling.md b/api/error-handling.md new file mode 100644 index 00000000..d50ad431 --- /dev/null +++ b/api/error-handling.md @@ -0,0 +1,33 @@ +--- +layout: default +permalink: api/error-handling/ +title: Error handling +--- + +Error handling +============== + +You can test for a successful response by calling `isSuccessful()` on the response object. If there +was an error communicating with the gateway, or your request was obviously invalid, an exception +will be thrown. In general, if the gateway does not throw an exception, but returns an unsuccessful +response, it is a message you should display to the customer. If an exception is thrown, it is +either a bug in your code (missing required fields), or a communication error with the gateway. + +You can handle both scenarios by wrapping the entire request in a try-catch block: + +~~~ php +try { + $response = $gateway->purchase(['amount' => '10.00', 'card' => $card])->send(); + if ($response->isSuccessful()) { + // mark order as complete + } elseif ($response->isRedirect()) { + $response->redirect(); + } else { + // display error to customer + exit($response->getMessage()); + } +} catch (\Exception $e) { + // internal error, log exception and display a generic message to the customer + exit('Sorry, there was an error processing your payment. Please try again later.'); +} +~~~ \ No newline at end of file diff --git a/api/recurring-billing.md b/api/recurring-billing.md new file mode 100644 index 00000000..669bc55d --- /dev/null +++ b/api/recurring-billing.md @@ -0,0 +1,14 @@ +--- +layout: default +permalink: api/recurring-billing/ +title: Recurring billing +--- + +Recurring billing +================= + +At this stage, automatic recurring payments functionality is out of scope for this library. +This is because there is likely far too many differences between how each gateway handles +recurring billing profiles. Also in most cases token billing will cover your needs, as you can +store a credit card then charge it on whatever schedule you like. Feel free to get in touch if +you really think this should be a core feature and worth the effort. \ No newline at end of file diff --git a/api/refunds.md b/api/refunds.md new file mode 100644 index 00000000..94374c21 --- /dev/null +++ b/api/refunds.md @@ -0,0 +1,14 @@ +--- +layout: default +permalink: api/refunds/ +title: Refunds +--- + +Refunds +======= + +The main method implemented by gateways are: + +* `refund($options)` - refund an already processed transaction + +If any gateway does not support certain features (such as refunds), it will throw `BadMethodCallException`. \ No newline at end of file diff --git a/api/responses.md b/api/responses.md new file mode 100644 index 00000000..70059a9b --- /dev/null +++ b/api/responses.md @@ -0,0 +1,60 @@ +--- +layout: default +permalink: api/responses/ +title: Responses +--- + +Responses +========= + +## The Payment Response + +The payment response must implement [ResponseInterface](https://github.com/thephpleague/omnipay-common/blob/master/src/Common/Message/ResponseInterface.php). There are two main types of response: + +* Payment was successful (standard response) +* Website requires redirect to off-site payment form (redirect response) + +### Successful Response + +For a successful responses, a reference will normally be generated, which can be used to capture or refund the transaction +at a later date. The following methods are always available: + +~~~ php +$response = $gateway->purchase(['amount' => '10.00', 'card' => $card])->send(); + +$response->isSuccessful(); // is the response successful? +$response->isRedirect(); // is the response a redirect? +$response->getTransactionReference(); // a reference generated by the payment gateway +$response->getMessage(); // a message generated by the payment gateway +~~~ + +In addition, most gateways will override the response object, and provide access to any extra fields returned by the gateway. + +### Redirect Response + +The redirect response is further broken down by whether the customer's browser must redirect using GET (RedirectResponse object), or +POST (FormRedirectResponse). These could potentially be combined into a single response class, with a `getRedirectMethod()`. + +After processing a payment, the cart should check whether the response requires a redirect, and if so, redirect accordingly: + +~~~ php +$response = $gateway->purchase(['amount' => '10.00', 'card' => $card])->send(); +if ($response->isSuccessful()) { + // payment is complete +} elseif ($response->isRedirect()) { + $response->redirect(); // this will automatically forward the customer +} else { + // not successful +} +~~~ + +The customer isn't automatically forwarded on, because often the cart or developer will want to customize the redirect method +(or if payment processing is happening inside an AJAX call they will want to return JS to the browser instead). + +To display your own redirect page, simply call `getRedirectUrl()` on the response, then display it accordingly: + +~~~ php +$url = $response->getRedirectUrl(); +// for a form redirect, you can also call the following method: +$data = $response->getRedirectData(); // associative array of fields which must be posted to the redirectUrl +~~~ diff --git a/api/token-billing.md b/api/token-billing.md new file mode 100644 index 00000000..5e56fb84 --- /dev/null +++ b/api/token-billing.md @@ -0,0 +1,22 @@ +--- +layout: default +permalink: api/token-billing/ +title: Token billing +--- + +Token billing +============== + +Token billing allows you to store a credit card with your gateway, and charge it at a later date. +Token billing is not supported by all gateways. For supported gateways, the following methods +are available: + +* `createCard($options)` - returns a response object which includes a `cardReference`, which can be used for future transactions +* `updateCard($options)` - update a stored card, not all gateways support this method +* `deleteCard($options)` - remove a stored card, not all gateways support this method + +Once you have a `cardReference`, you can use it instead of the `card` parameter when creating a charge: + +~~~ php +$gateway->purchase(['amount' => '10.00', 'cardReference' => 'abc']); +~~~ \ No newline at end of file diff --git a/api/voiding.md b/api/voiding.md new file mode 100644 index 00000000..4cfdae5a --- /dev/null +++ b/api/voiding.md @@ -0,0 +1,12 @@ +--- +layout: default +permalink: api/voiding/ +title: Voiding +--- + +Voiding +======= + +The main method implemented by gateways are: + +* `void($options)` - generally can only be called up to 24 hours after submitting a transaction \ No newline at end of file diff --git a/CHANGELOG.md b/changelog.md similarity index 98% rename from CHANGELOG.md rename to changelog.md index 951c346f..2f54c229 100644 --- a/CHANGELOG.md +++ b/changelog.md @@ -1,9 +1,16 @@ +--- +layout: default +permalink: changelog/ +title: Changelog +--- + Changelog ========= ## v3.2 - 2021-06-01 -Omnipay 3.2 is compatible with PHP8. This is done by upgrading the test suite to PHPUnit 8/9, with the release of omnipay/tests v4 and omnipay/common v3.1. This change is primarily for gateway developers, to make it possible to actually test PHP8, but they will need to upgrade their tests to use PHPUnit 9 (the currently supported PHPUnit version). +Omnipay 3.2 is compatible with PHP8. This is done by upgrading the test suite to PHPUnit 8/9, with the release of omnipay/tests v4 and omnipay/common v3.1. This change is primarily for gateway developers, to make it possible to actually test PHP8, but they will need to upgrade their tests to use PHPUnit 9 (the currently supported PHPUnit version). + ## v3.1 - 2020-10-29 Omnipay 3.1 uses Guzzle 7 by default (using the Guzzle 7 adapter). This doesn't change omnipay-common because they will work with any compatible Http Client. diff --git a/composer.json b/composer.json deleted file mode 100644 index 9bbc6db9..00000000 --- a/composer.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "name": "league/omnipay", - "type": "metapackage", - "description": "Omnipay payment processing library", - "keywords": [ - "omnipay", - "checkout", - "creditcard", - "payment" - ], - "homepage": "https://omnipay.thephpleague.com/", - "license": "MIT", - "authors": [ - { - "name": "Adrian Macneil", - "email": "adrian@adrianmacneil.com" - }, - { - "name": "Barry vd. Heuvel", - "email": "barryvdh@gmail.com" - } - ], - "require": { - "php": "^7.2|^8.0", - "omnipay/common": "^3.1", - "php-http/discovery": "^1.14", - "php-http/guzzle7-adapter": "^1" - }, - "require-dev": { - "omnipay/tests": "^3|^4" - }, - "autoload-dev": { - "psr-4": { "Omnipay\\Tests\\" : "tests" } - }, - "extra": { - "branch-alias": { - "dev-master": "3.2.x-dev" - } - }, - "scripts": { - "test": "phpunit" - }, - "minimum-stability": "dev", - "prefer-stable": true -} diff --git a/gateways/build-your-own.md b/gateways/build-your-own.md new file mode 100644 index 00000000..c6d2b5e3 --- /dev/null +++ b/gateways/build-your-own.md @@ -0,0 +1,37 @@ +--- +layout: default +permalink: gateways/build-your-own/ +title: Build your own driver +--- + +Build your own driver +===================== + +Omnipay is a collection of packages which all depend on the +[omnipay/common](https://github.com/thephpleague/omnipay-common) package to provide +a consistent interface. There are no dependencies on official payment gateway PHP packages - +we prefer to work with the HTTP API directly. Under the hood, we use the popular and powerful +[PHP-HTTP](http://docs.php-http.org/en/latest/index.html) library to make HTTP requests. +A [Guzzle](http://guzzlephp.org/) adapter is required by default, when using `league/omnipay`. + +New gateways can be created by cloning the layout of an existing package. When choosing a +name for your package, please don't use the `omnipay` vendor prefix, as this implies that +it is officially supported. You should use your own username as the vendor prefix, and prepend +`omnipay-` to the package name to make it clear that your package works with Omnipay. +For example, if your GitHub username was `santa`, and you were implementing the `giftpay` +payment library, a good name for your composer package would be `santa/omnipay-giftpay`. + + +## Omnipay Terminology + +- **Merchant Site** - The website or application that initiates the payment. Typically this will be an ecommerce store or some other online system that needs to take payments from customers. +- **Merchant** - The owner or operator of the Merchant Site. +- **Payment Gateway** - The remote payment processing system that handles the communication and transfer of funds between the Merchant Site, the customer's bank, and the Merchant's bank. These are typically large companies that handle many thousands of payments for many Merchants every day. See https://en.wikipedia.org/wiki/Payment_gateway for more details. +- **Driver** - The code written to extend the core Omnipay functionality so that it can communicate with a specifc Payment Gateway. There are several 'official' Omnipay drivers, and many others written by individuals. If the Payment Gateway that you wish to use doesn't currently have a driver written for it, you can create your own and share it with the community. +- **Transaction** - An single attempt (successful or otherwise) to make a payment. + +## Omnipay Conventions + +When developing your own payment gateway driver, it's worth remembering that ideally the person using your driver should be able to switch between drivers easily, without modifying their own code. With that in mind, here are some conventions that are used in Omnipay: + - **transactionId vs transactionReference** - `transactionId` is the Merchant's reference to the transaction - so typically the ID of the payment record in the Merchant Site's database. `transactionReference` is the Payment Gateway's reference to the transaction. They will usually generate a unique reference for each payment attempt a customer makes. It is common practice to store this value in the Merchant Site's database, so that the transaction can be cross-referenced with the Payment Gateway's own records. Some Omnipay drivers also rely on this value being available in order to process refunds or repeat payments. + - **returnUrl vs notifyUrl** - `returnUrl` is used by drivers when they need to tell the Payment Gateway where to redirect the customer following a transaction. Typically this is used by off-site 'redirect' gateway integrations. `notifyUrl` is used by drivers to tell the Payment Gateway where to send their server-to-server notification, informing the Merchant Site about the outcome of a transaction. The `notifyUrl` will typically be a script on the Merchant Site that handles the updating of the database to record whether a payment was successful or not. diff --git a/README.md b/gateways/community.md similarity index 57% rename from README.md rename to gateways/community.md index 3b1f96a5..b60f4454 100644 --- a/README.md +++ b/gateways/community.md @@ -1,99 +1,11 @@ -# Omnipay +--- +layout: default +permalink: gateways/community/ +title: Community gateways +--- -**An easy to use, consistent payment processing library for PHP** - -[![Unit Tests](https://github.com/thephpleague/omnipay/actions/workflows/run-tests.yml/badge.svg)](https://github.com/thephpleague/omnipay/actions/workflows/run-tests.yml) -[![Latest Stable Version](https://poser.pugx.org/omnipay/common/version)](https://packagist.org/packages/omnipay/common) -[![Total Downloads](https://poser.pugx.org/omnipay/common/d/total)](https://packagist.org/packages/omnipay/common) - -Omnipay is a payment processing library for PHP. It has been designed based on -ideas from [Active Merchant](http://activemerchant.org/), plus experience implementing -dozens of gateways for [CI Merchant]. It has a clear and consistent API, -is fully unit tested, and even comes with an example application to get you started. - -**Why use Omnipay instead of a gateway's official PHP package/example code?** - -* Because you can learn one API and use it in multiple projects using different payment gateways -* Because if you need to change payment gateways you won't need to rewrite your code -* Because most official PHP payment gateway libraries are a mess -* Because most payment gateways have exceptionally poor documentation -* Because you are writing a shopping cart and need to support multiple gateways - -## TL;DR - -Just want to see some code? - -```php -use Omnipay\Omnipay; - -$gateway = Omnipay::create('Stripe'); -$gateway->setApiKey('abc123'); - -$formData = array('number' => '4242424242424242', 'expiryMonth' => '6', 'expiryYear' => '2030', 'cvv' => '123'); -$response = $gateway->purchase(array('amount' => '10.00', 'currency' => 'USD', 'card' => $formData))->send(); - -if ($response->isRedirect()) { - // redirect to offsite payment gateway - $response->redirect(); -} elseif ($response->isSuccessful()) { - // payment was successful: update database - print_r($response); -} else { - // payment failed: display message to customer - echo $response->getMessage(); -} -``` - -As you can see, Omnipay has a consistent, well thought out API. We try to abstract as much -as possible the differences between the various payments gateways. - -## Package Layout - -Omnipay is a collection of packages which all depend on the -[omnipay/common](https://github.com/thephpleague/omnipay-common) package to provide -a consistent interface. There are no dependencies on official payment gateway PHP packages - -we prefer to work with the HTTP API directly. Under the hood, we use the popular and powerful -[PHP-HTTP](http://docs.php-http.org/en/latest/index.html) library to make HTTP requests. -A [Guzzle](http://guzzlephp.org/) adapter is required by default, when using `league/omnipay`. - -New gateways can be created by cloning the layout of an existing package. When choosing a -name for your package, please don't use the `omnipay` vendor prefix, as this implies that -it is officially supported. You should use your own username as the vendor prefix, and prepend -`omnipay-` to the package name to make it clear that your package works with Omnipay. -For example, if your GitHub username was `santa`, and you were implementing the `giftpay` -payment library, a good name for your composer package would be `santa/omnipay-giftpay`. - -## Installation - -Omnipay is installed via [Composer](https://getcomposer.org/). -For most uses, you will need to require `league/omnipay` and an individual gateway: - -``` -composer require league/omnipay:^3 omnipay/paypal -``` - -If you want to use your own HTTP Client instead of Guzzle (which is the default for `league/omnipay`), -you can require `omnipay/common` and any `php-http/client-implementation` (see [PHP Http](http://docs.php-http.org/en/latest/clients.html)) - -``` -composer require league/common:^3 omnipay/paypal php-http/buzz-adapter -``` - -## Upgrade from v2 to v3 - -If your gateway is supported for v3, you can require that version. Make sure you require `league/omnipay` or a separate Http Adapter. - -If there is no version for v3 yet, please raise an issue or upgrade the gateways yourself and create a PR. -See the [Upgrade guide for omnipay/common](https://github.com/thephpleague/omnipay-common/blob/master/UPGRADE.md) - -> Note: The package name has been changed from `omnipay/omnipay` to `league/omnipay` for v3 - -## Payment Gateways - -All payment gateways must implement [GatewayInterface](https://github.com/thephpleague/omnipay-common/blob/master/src/Common/GatewayInterface.php), and will usually -extend [AbstractGateway](https://github.com/thephpleague/omnipay-common/blob/master/src/Common/AbstractGateway.php) for basic functionality. - -The following gateways are available: +Community gateways +================= Gateway | 2.x | 3.x | Composer Package | Maintainer --- | --- | --- | --- | --- @@ -122,8 +34,12 @@ Gateway | 2.x | 3.x | Composer Package | Maintainer [Braintree](https://github.com/thephpleague/omnipay-braintree) | ✓ | ✓ | omnipay/braintree | [Omnipay](https://github.com/thephpleague/omnipay) [Buckaroo](https://github.com/thephpleague/omnipay-buckaroo) | ✓ | - | omnipay/buckaroo | [Omnipay](https://github.com/thephpleague/omnipay) [CardGate](https://github.com/cardgate/omnipay-cardgate) | ✓ | - | cardgate/omnipay-cardgate | [CardGate](https://github.com/cardgate) +[Cardinity](https://github.com/janwebdev/omnipay-cardinity) | - | ✓ | janwebdev/omnipay-cardinity | [Yan Rogozinsky](https://github.com/janwebdev) [CardSave](https://github.com/thephpleague/omnipay-cardsave) | ✓ | - | omnipay/cardsave | [Omnipay](https://github.com/thephpleague/omnipay) [CashBaBa](https://github.com/tapos007/omnipay-cashbaba) | ✓ | ✓ | omnipay/cashbaba | [Recursion Technologies Ltd](https://github.com/tapos007) +[Cashfree](https://github.com/cashfree/omnipay-cashfree) | - | ✓ | cashfree/omnipay-cashfree | [Cashfree](https://github.com/cashfree) +[CCV Online Payments](https://github.com/CCV/ccvonlinepayments-omnipay) | - | ✓ | ccv/omnipay | [CCV](https://github.com/CCV) +[Chargebee](https://github.com/jsdecena/omnipay-chargebee) | - | ✓ | jsdecena/omnipay-chargebee | [Jeff Simons Decena](https://github.com/jsdecena) [Checkout.com](https://github.com/fotografde/omnipay-checkoutcom) | ✓ | - | fotografde/checkoutcom | [fotograf.de](https://github.com/fotografde) [CloudBanking](https://github.com/spsingh/omnipay-cloudbanking) | ✓ | - | cloudbanking/omnipay-cloudbanking | [Cloudbanking](http://cloudbanking.com.au/) [Coinbase](https://github.com/thephpleague/omnipay-coinbase) | ✓ | - | omnipay/coinbase | [Omnipay](https://github.com/thephpleague/omnipay) @@ -154,6 +70,7 @@ Gateway | 2.x | 3.x | Composer Package | Maintainer [Fat Zebra](https://github.com/delatbabel/omnipay-fatzebra) | ✓ | - | delatbabel/omnipay-fatzebra | [Del](https://github.com/delatbabel) [FreeKassa](https://github.com/hiqdev/omnipay-freekassa) | ✓ | ✓ | hiqdev/omnipay-freekassa | [HiQDev](https://github.com/hiqdev) [Fibank](https://github.com/ampeco/omnipay-fibank) | - | ✓ | ampeco/omnipay-fibank | [Ampeco](https://github.com/ampeco) +[First Atlantic Commerce](https://github.com/cloudcogsio/omnipay-firstatlanticcommerce-gateway) | - | ✓ | cloudcogsio/omnipay-firstatlanticcommerce-gateway | [Cloudcogs.io](https://github.com/cloudcogsio) [First Data](https://github.com/thephpleague/omnipay-firstdata) | ✓ | - | omnipay/firstdata | [OmniPay](https://github.com/thephpleague/omnipay) [Flo2cash](https://github.com/guisea/omnipay-flo2cash) | ✓ | - | guisea/omnipay-flo2cash | [Aaron Guise](https://github.com/guisea) [Free / Zero Amount](https://github.com/colinodell/omnipay-zero) | ✓ | - | colinodell/omnipay-zero | [Colin O'Dell](https://github.com/colinodell) @@ -169,12 +86,13 @@ Gateway | 2.x | 3.x | Composer Package | Maintainer [iDram](https://github.com/ptuchik/omnipay-idram) | - | ✓ | ptuchik/omnipay-idram | [Avik Aghajanyan](https://github.com/ptuchik) [iDeal](https://github.com/deniztezcan/omnipay-ideal) | - | ✓ | deniztezcan/omnipay-ideal | [Deniz Tezcan](https://github.com/deniztezcan) [Ingenico ePayments](https://github.com/deniztezcan/omnipay-ingenico-epayments) | - | ✓ | deniztezcan/omnipay-ingenico-epayments | [Deniz Tezcan](https://github.com/deniztezcan) +[iPara](https://github.com/tcgunel/omnipay-ipara) | - | ✓ | tcgunel/omnipay-ipara | [Tolga Can Günel](https://github.com/tcgunel) [iPay88](https://github.com/dilab/omnipay-ipay88) | ✓ | ✓ | dilab/omnipay-ipay88 | [Xu Ding](https://github.com/dilab) [IfthenPay](https://github.com/ifthenpay/omnipay-ifthenpay) | ✓ | - | ifthenpay/omnipay-ifthenpay | [Rafael Almeida](https://github.com/rafaelcpalmeida) [Ikajo](https://github.com/hiqdev/omnipay-ikajo) | ✓ | ✓ | hiqdev/omnipay-ikajo | [HiQDev](https://github.com/hiqdev) [InterKassa](https://github.com/hiqdev/omnipay-interkassa) | ✓ | ✓ | hiqdev/omnipay-interkassa | [HiQDev](https://github.com/hiqdev) [InovioPay](https://github.com/mvestil/omnipay-inoviopay) | ✓ | ✓ | mvestil/omnipay-inoviopay | [Mark Vestil](https://github.com/mvestil) -[Iyzico](https://github.com/yasinkuyu/omnipay-iyzico) | ✓ | - | yasinkuyu/omnipay-iyzico | [Yasin Kuyu](https://github.com/yasinkuyu) +[Iyzico](https://github.com/yasinkuyu/omnipay-iyzico) | ✓ | ✓ | yasinkuyu/omnipay-iyzico | [Yasin Kuyu](https://github.com/yasinkuyu) [Judo Pay](https://github.com/Transportersio/omnipay-judopay) | ✓ | - | transportersio/omnipay-judopay | [Transporters.io](https://github.com/Transportersio) [Klarna Checkout](https://github.com/MyOnlineStore/omnipay-klarna-checkout) | ✓ | ✓ | myonlinestore/omnipay-klarna-checkout | [MyOnlineStore](https://github.com/MyOnlineStore) [Laybuy](https://github.com/mediabeastnz/omnipay-laybuy) | ✓ | - | mediabeastnz/omnipay-laybuy | [Myles Derham](https://github.com/mediabeastnz) @@ -195,7 +113,6 @@ Gateway | 2.x | 3.x | Composer Package | Maintainer [MultiCards](https://github.com/incube8/omnipay-multicards) | ✓ | - | incube8/omnipay-multicards | [Del](https://github.com/delatbabel) [MultiSafepay](https://github.com/thephpleague/omnipay-multisafepay) | ✓ | - | omnipay/multisafepay | [Alexander Deruwe](https://github.com/aderuwe) [MyCard](https://github.com/xxtime/omnipay-mycard) | ✓ | - | xxtime/omnipay-mycard | [Joe Chu](https://github.com/xxtime) -[MyFatoorah](https://github.com/my-fatoorah/omnipay-myfatoorah) | - | ✓ | myfatoorah/omnipay | [MyFatoorah Plugins Team](https://github.com/my-fatoorah) [National Australia Bank (NAB) Transact](https://github.com/sudiptpa/omnipay-nabtransact) | ✓ | ✓ | sudiptpa/omnipay-nabtransact | [Sujip Thapa](https://github.com/sudiptpa) [NestPay (EST)](https://github.com/yasinkuyu/omnipay-nestpay) | ✓ | - | yasinkuyu/omnipay-nestpay | [Yasin Kuyu](https://github.com/yasinkuyu) [NestPay (EST)](https://github.com/uskur/omnipay-nestpay) | - | ✓ | uskur/omnipay-nestpay | [Uskur](https://github.com/uskur) @@ -224,7 +141,6 @@ Gateway | 2.x | 3.x | Composer Package | Maintainer [PaymentgateRu](https://github.com/pinguinjkeke/omnipay-paymentgateru) | ✓ | ✓ | pinguinjkeke/omnipay-paymentgateru | [Alexander Avakov](https://github.com/pinguinjkeke) [PaymentSense](https://github.com/digitickets/omnipay-paymentsense) | ✓ | - | digitickets/omnipay-paymentsense | [DigiTickets](https://github.com/digitickets) [PaymentWall](https://github.com/incube8/omnipay-paymentwall) | ✓ | - | incube8/omnipay-paymentwall | [Del](https://github.com/delatbabel) -[Paynow](https://github.com/pay-now/omnipay-paynow) | - | ✓ | pay-now/omnipay-paynow | [Paynow](https://github.com/pay-now) [PayPal](https://github.com/thephpleague/omnipay-paypal) | ✓ | ✓ | omnipay/paypal | [Del](https://github.com/delatbabel) [PayPro](https://github.com/payproNL/omnipay-paypro) | ✓ | - | paypronl/omnipay-paypro | [Fruitcake](https://github.com/fruitcake) [PAYONE](https://github.com/academe/omnipay-payone) | ✓ | ✓ | academe/omnipay-payone | [Jason Judge](https://github.com/judgej) @@ -236,6 +152,7 @@ Gateway | 2.x | 3.x | Composer Package | Maintainer [PaySimple](https://github.com/dranes/omnipay-paysimple) | ✓ | - | dranes/omnipay-paysimple | [Dranes](https://github.com/dranes) [PaySsion](https://github.com/InkedCurtis/omnipay-payssion) | ✓ | - | inkedcurtis/omnipay-payssion | [Curtis](https://github.com/inkedcurtis) [PayTrace](https://github.com/iddqdidkfa/omnipay-paytrace) | ✓ | - | softcommerce/omnipay-paytrace | [Oleg Ilyushyn](https://github.com/iddqdidkfa) +[PayTR](https://github.com/tcgunel/omnipay-paytr) | - | ✓ | tcgunel/omnipay-paytr | [Tolga Can Günel](https://github.com/tcgunel) [PayU](https://github.com/bileto/omnipay-payu) | ✓ | - | bileto/omnipay-payu | [PayZen](https://github.com/ubitransports/omnipay-payzen) | ✓ | - | ubitransports/omnipay-payzen | [Ubitransport](https://github.com/ubitransports) [Paxum](https://github.com/hiqdev/omnipay-paxum) | ✓ | ✓ | hiqdev/omnipay-paxum | [HiQDev](https://github.com/hiqdev) @@ -246,6 +163,7 @@ Gateway | 2.x | 3.x | Composer Package | Maintainer [Portmanat](https://github.com/dercoder/omnipay-portmanat) | ✓ | - | dercoder/omnipay-portmanat | [Alexander Fedra](https://github.com/dercoder) [Posnet](https://github.com/yasinkuyu/omnipay-posnet) | ✓ | - | yasinkuyu/omnipay-posnet | [Yasin Kuyu](https://github.com/yasinkuyu) [Postfinance](https://github.com/bummzack/omnipay-postfinance) | ✓ | - | bummzack/omnipay-postfinance | [Roman Schmid](https://github.com/bummzack) +[Przelewy24](https://github.com/mysiar/omnipay-przelewy24v1)| - | ✓ | mysiar/omnipay-przelewy24v1 | [Piotr Synowiec](https://github.com/mysiar) & [Nykilor](https://github.com/Nykilor) [Qiwi](https://github.com/hiqdev/omnipay-qiwi) | ✓ | ✓ | hiqdev/omnipay-qiwi | [HiQDev](https://github.com/hiqdev) [QQ Wallet(QPay)](https://github.com/kuangjy2/omnipay-qpay) | - | ✓ | kuangjy/omnipay-qpay | [Kuang Jiaye](https://github.com/kuangjy2) [Quickpay](https://github.com/NobrainerWeb/omnipay-quickpay) | ✓ | - | nobrainerweb/omnipay-quickpay | [Nobrainer Web](https://github.com/NobrainerWeb) @@ -256,7 +174,7 @@ Gateway | 2.x | 3.x | Composer Package | Maintainer [RentMoola](https://github.com/rentmoola/omnipay-rentmoola) | ✓ | - | rentmoola/omnipay-rentmoola | [Geoff Shaw](https://github.com/Shawg) [RoboKassa](https://github.com/hiqdev/omnipay-robokassa) | ✓ | ✓ | hiqdev/omnipay-robokassa | [HiQDev](https://github.com/hiqdev) [RocketGate](https://github.com/mvestil/omnipay-rocketgate) | ✓ | ✓ | mvestil/omnipay-rocketgate | [Mark Vestil](https://github.com/mvestil) -[Sage Pay](https://github.com/thephpleague/omnipay-sagepay) | ✓ | ✓ | omnipay/sagepay | [Jason Judge](https://github.com/judgej) +[Sage Pay (aka Opayo)](https://github.com/thephpleague/omnipay-sagepay) | ✓ | ✓ | omnipay/sagepay | [Jason Judge](https://github.com/judgej) [Sberbank](https://github.com/AndrewNovikof/omnipay-sberbank) | - | ✓ | andrewnovikof/omnipay-sberbank | [Andrew Novikov](https://github.com/AndrewNovikof) [SecPay](https://github.com/justinbusschau/omnipay-secpay) | ✓ | - | justinbusschau/omnipay-secpay | [Justin Busschau](https://github.com/justinbusschau) [SecurePay](https://github.com/thephpleague/omnipay-securepay) | ✓ | ✓ | omnipay/securepay | [Omnipay](https://github.com/thephpleague/omnipay) @@ -268,6 +186,7 @@ Gateway | 2.x | 3.x | Composer Package | Maintainer [Square](https://github.com/Transportersio/omnipay-square) | ✓ | ✓ | transportersio/omnipay-square | [Transporters.io](https://github.com/Transportersio) [Starkpay](https://github.com/starkpay/omnipay) | ✓ | ✓ | starkpay/omnipay | [Starkpay](https://github.com/starkpay) [Stripe](https://github.com/thephpleague/omnipay-stripe) | ✓ | ✓ | omnipay/stripe | [Del](https://github.com/delatbabel) +[Swile](https://bitbucket.org/potagercity/swile-connector/src/master/) | ✓ | ✓ | potagercity/swile | [Potagercity](https://packagist.org/users/potagercity/) [TargetPay](https://github.com/thephpleague/omnipay-targetpay) | ✓ | - | omnipay/targetpay | [Alexander Deruwe](https://github.com/aderuwe) [TatraBank](https://github.com/bileto/omnipay-tatrabank) | ✓ | - | omnipay-tatrabank | [ToyyibPay](https://github.com/sitehandy/omnipay-toyyibpay) | - | ✓ | sitehandy/omnipay-toyyibpay | [Amirol Zolkifli](https://github.com/sitehandy) @@ -287,353 +206,9 @@ Gateway | 2.x | 3.x | Composer Package | Maintainer [Worldpay XML Direct Corporate Gateway](https://github.com/teaandcode/omnipay-worldpay-xml) | ✓ | - | teaandcode/omnipay-worldpay-xml | [Dave Nash](https://github.com/teaandcode) [Worldpay XML Hosted Corporate Gateway](https://github.com/catharsisjelly/omnipay-worldpay-cg-hosted) | ✓ | ✓ | catharsisjelly/omnipay-worldpay-cg-hosted | [Chris Lock](https://github.com/catharsisjelly) [Worldpay Business Gateway](https://github.com/thephpleague/omnipay-worldpay) | ✓ | ✓ | omnipay/worldpay | [Omnipay](https://github.com/thephpleague/omnipay) +[Xendit Invoice](https://github.com/David-Kurniawan/omnipay-xeninvoice) | - | ✓ | david-kurniawan/omnipay-xeninvoice | [David Kurniawan](https://github.com/David-Kurniawan) [Yandex.Kassa](https://github.com/hiqdev/omnipay-yandex-kassa) | ✓ | ✓ | hiqdev/omnipay-yandex-kassa | [HiQDev](https://github.com/hiqdev) [Yandex.Money](https://github.com/yandex-money/yandex-money-cms-omnipay) | ✓ | - | yandexmoney/omnipay | [Roman Ananyev](https://github.com/aTastyCookie/) [Yandex.Money for P2P payments](https://github.com/hiqdev/omnipay-yandexmoney) | ✓ | ✓ | hiqdev/omnipay-yandexmoney | [HiQDev](https://github.com/hiqdev) [Yekpay](https://github.com/nekofar/omnipay-yekpay) | - | ✓ | nekofar/omnipay-yekpay | [Milad Nekofar](https://github.com/nekofar) [ZarinPal](https://github.com/nekofar/omnipay-zarinpal) | - | ✓ | nekofar/omnipay-zarinpal | [Milad Nekofar](https://github.com/nekofar) - -Gateways are created and initialized like so: - -```php -use Omnipay\Omnipay; - -$gateway = Omnipay::create('PayPal_Express'); -$gateway->setUsername('adrian'); -$gateway->setPassword('12345'); -``` - -Most settings are gateway specific. If you need to query a gateway to get a list -of available settings, you can call `getDefaultParameters()`: - -```php -$settings = $gateway->getDefaultParameters(); -// default settings array format: -array( - 'username' => '', // string variable - 'testMode' => false, // boolean variable - 'landingPage' => array('billing', 'login'), // enum variable, first item should be treated as default -); -``` - -Generally most payment gateways can be classified as one of two types: - -* Off-site gateways such as PayPal Express, where the customer is redirected to a third party site to enter payment details -* On-site (merchant-hosted) gateways such as PayPal Pro, where the customer enters their credit card details on your site - -However, there are some gateways such as Sage Pay Direct, where you take credit card details on site, then optionally redirect -if the customer's card supports 3D Secure authentication. Therefore, there is no point differentiating between the two types of -gateway (other than by the methods they support). - -## Credit Card / Payment Form Input - -User form input is directed to an [CreditCard](https://github.com/thephpleague/omnipay-common/blob/master/src/Common/CreditCard.php) -object. This provides a safe way to accept user input. - -The `CreditCard` object has the following fields: - -* firstName -* lastName -* number -* expiryMonth -* expiryYear -* startMonth -* startYear -* cvv -* issueNumber -* type -* billingAddress1 -* billingAddress2 -* billingCity -* billingPostcode -* billingState -* billingCountry -* billingPhone -* shippingAddress1 -* shippingAddress2 -* shippingCity -* shippingPostcode -* shippingState -* shippingCountry -* shippingPhone -* company -* email - -Even off-site gateways make use of the `CreditCard` object, because often you need to pass -customer billing or shipping details through to the gateway. - -The `CreditCard` object can be initialized with untrusted user input via the constructor. -Any fields passed to the constructor which are not recognized will be ignored. - -```php -$formInputData = array( - 'firstName' => 'Bobby', - 'lastName' => 'Tables', - 'number' => '4111111111111111', -); -$card = new CreditCard($formInputData); -``` - -You can also just pass the form data array directly to the gateway, and a `CreditCard` object -will be created for you. - -CreditCard fields can be accessed using getters and setters: - -```php -$number = $card->getNumber(); -$card->setFirstName('Adrian'); -``` - -If you submit credit card details which are obviously invalid (missing required fields, or a number -which fails the Luhn check), [InvalidCreditCardException](https://github.com/thephpleague/omnipay-common/blob/master/src/Omnipay/Common/Exception/InvalidCreditCardException.php) -will be thrown. You should validate the card details using your framework's validation library -before submitting the details to your gateway, to avoid unnecessary API calls. - -For on-site payment gateways, the following card fields are generally required: - -* firstName -* lastName -* number -* expiryMonth -* expiryYear -* cvv - -You can also verify the card number using the Luhn algorithm by calling `Helper::validateLuhn($number)`. - -## Gateway Methods - -The main methods implemented by gateways are: - -* `authorize($options)` - authorize an amount on the customer's card -* `completeAuthorize($options)` - handle return from off-site gateways after authorization -* `capture($options)` - capture an amount you have previously authorized -* `purchase($options)` - authorize and immediately capture an amount on the customer's card -* `completePurchase($options)` - handle return from off-site gateways after purchase -* `refund($options)` - refund an already processed transaction -* `void($options)` - generally can only be called up to 24 hours after submitting a transaction -* `acceptNotification()` - convert an incoming request from an off-site gateway to a generic notification object - for further processing -* `createCard` - get a cardReference that can be used for future payments. This might be used in a monthly billing scenario, for example. - -On-site gateways do not need to implement the `completeAuthorize` and `completePurchase` methods. Gateways that don't -receive payment notifications don't need to implement `acceptNotification`. If any gateway does not support certain -features (such as refunds), it will throw `BadMethodCallException`. - -All gateway methods except `acceptNotification` take an `$options` array as an argument. The `acceptNotification` method -does not take any parameters and will access the HTTP URL variables or POST data implicitly. Each gateway differs in -which parameters are required, and the gateway will throw `InvalidRequestException` if you omit any required parameters. -All gateways will accept a subset of these options: - -* card -* token -* amount -* currency -* description -* transactionId -* clientIp -* returnUrl -* cancelUrl - -Pass the options through to the method like so: - -```php -$card = new CreditCard($formData); -$request = $gateway->authorize(array( - 'amount' => '10.00', // this represents $10.00 - 'card' => $card, - 'returnUrl' => 'https://www.example.com/return', -)); -``` - -When calling the `completeAuthorize` or `completePurchase` methods, the exact same arguments should be provided as -when you made the initial `authorize` or `purchase` call (some gateways will need to verify for example the actual -amount paid equals the amount requested). The only parameter you can omit is `card`. - -To summarize the various parameters you have available to you: - -* Gateway settings (e.g. username and password) are set directly on the gateway. These settings apply to all payments, and generally you will store these in a configuration file or in the database. -* Method options are used for any payment-specific options, which are not set by the customer. For example, the payment `amount`, `currency`, `transactionId` and `returnUrl`. -* CreditCard parameters are data which the user supplies. For example, you want the user to specify their `firstName` and `billingCountry`, but you don't want a user to specify the payment `currency` or `returnUrl`. - -## The Payment Response - -The payment response must implement [ResponseInterface](https://github.com/thephpleague/omnipay-common/blob/master/src/Omnipay/Common/Message/ResponseInterface.php). There are two main types of response: - -* Payment was successful (standard response) -* Website requires redirect to off-site payment form (redirect response) - -### Successful Response - -For a successful responses, a reference will normally be generated, which can be used to capture or refund the transaction -at a later date. The following methods are always available: - -```php -$response = $gateway->purchase(array('amount' => '10.00', 'card' => $card))->send(); - -$response->isSuccessful(); // is the response successful? -$response->isRedirect(); // is the response a redirect? -$response->getTransactionReference(); // a reference generated by the payment gateway -$response->getTransactionId(); // the reference set by the originating website if available. -$response->getMessage(); // a message generated by the payment gateway -``` - -In addition, most gateways will override the response object, and provide access to any extra fields returned by the gateway. -If the payment authorization is re-usable the gateway will implement ```$response->getCardReference();```. This -method is always available (but may return NULL) from 3.1.1 - -### Redirect Response - -The redirect response is further broken down by whether the customer's browser must redirect using GET (RedirectResponse object), or -POST (FormRedirectResponse). These could potentially be combined into a single response class, with a `getRedirectMethod()`. - -After processing a payment, the cart should check whether the response requires a redirect, and if so, redirect accordingly: - -```php -$response = $gateway->purchase(array('amount' => '10.00', 'card' => $card))->send(); -if ($response->isSuccessful()) { - // payment is complete -} elseif ($response->isRedirect()) { - $response->redirect(); // this will automatically forward the customer -} else { - // not successful -} -``` - -The customer isn't automatically forwarded on, because often the cart or developer will want to customize the redirect method -(or if payment processing is happening inside an AJAX call they will want to return JS to the browser instead). - -To display your own redirect page, simply call `getRedirectUrl()` on the response, then display it accordingly: - -```php -$url = $response->getRedirectUrl(); -// for a form redirect, you can also call the following method: -$data = $response->getRedirectData(); // associative array of fields which must be posted to the redirectUrl -``` - -## Error Handling - -You can test for a successful response by calling `isSuccessful()` on the response object. If there -was an error communicating with the gateway, or your request was obviously invalid, an exception -will be thrown. In general, if the gateway does not throw an exception, but returns an unsuccessful -response, it is a message you should display to the customer. If an exception is thrown, it is -either a bug in your code (missing required fields), or a communication error with the gateway. - -You can handle both scenarios by wrapping the entire request in a try-catch block: - -```php -try { - $response = $gateway->purchase(array('amount' => '10.00', 'card' => $card))->send(); - if ($response->isSuccessful()) { - // mark order as complete - } elseif ($response->isRedirect()) { - $response->redirect(); - } else { - // display error to customer - exit($response->getMessage()); - } -} catch (\Exception $e) { - // internal error, log exception and display a generic message to the customer - exit('Sorry, there was an error processing your payment. Please try again later.'); -} -``` - -## Test mode and developer mode - Most gateways allow you to set up a sandbox or developer account which uses a different url - and credentials. Some also allow you to do test transactions against the live site, which does - not result in a live transaction. - - Gateways that implement only the developer account (most of them) call it testMode. Authorize.net, - however, implements both and refers to this mode as developerMode. - - When implementing with multiple gateways you should use a construct along the lines of the following: -```php -if ($is_developer_mode) { - if (method_exists($gateway, 'setDeveloperMode')) { - $gateway->setDeveloperMode(TRUE); - } else { - $gateway->setTestMode(TRUE); - } -} -``` - -## Token Billing - -Token billing allows you to store a credit card with your gateway, and charge it at a later date. -Token billing is not supported by all gateways. For supported gateways, the following methods -are available: - -* `createCard($options)` - returns a response object which includes a `cardReference`, which can be used for future transactions -* `updateCard($options)` - update a stored card, not all gateways support this method -* `deleteCard($options)` - remove a stored card, not all gateways support this method - -Once you have a `cardReference`, (which should be available from the response object -using getCardReference) you can use it instead of the `card` parameter when creating a charge: - - $gateway->purchase(array('amount' => '10.00', 'cardReference' => 'abc')); - -In many cases the createCard action will also process the initial payment at the same time. -In these cases you should pass in the 'action' ('authorize' or 'purchase') in the createCard -options. - -## Recurring Billing - -At this stage, automatic recurring payments functionality is out of scope for this library. -This is because there is likely far too many differences between how each gateway handles -recurring billing profiles. Also in most cases token billing will cover your needs, as you can -store a credit card then charge it on whatever schedule you like. Feel free to get in touch if -you really think this should be a core feature and worth the effort. - -## Incoming Notifications - -Some gateways (e.g. Cybersource, GoPay) offer HTTP notifications to inform the merchant about the completion (or, in -general, status) of the payment. To assist with handling such notifications, the `acceptNotification()` method will -extract the transaction reference and payment status from the HTTP request and return a generic `NotificationInterface`. - -```php -$notification = $gateway->acceptNotification(); - -$notification->getTransactionReference(); // A reference provided by the gateway to represent this transaction -$notification->getTransactionStatus(); // Current status of the transaction, one of NotificationInterface::STATUS_* -$notification->getMessage(); // Additional message, if any, provided by the gateway - -// update the status of the corresponding transaction in your database -``` - -**Note:** some earlier gateways used the `completeAuthorize` and `completePurchase` messages to handle the incoming -notifications. These are being converted and the `complete*` messages deprecated. -They won't be removed in OmniPay 2.x, but it is advisable to switch to the `acceptNotification` message when convenient. -An example is Sage Pay Server [completeAuthorize](https://github.com/thephpleague/omnipay-sagepay/blob/master/src/ServerGateway.php#L81) -which is now handled by [acceptNotification](https://github.com/thephpleague/omnipay-sagepay/blob/master/src/ServerGateway.php#L40). - -## Example Application - -An example application is provided in the [omnipay/example](https://github.com/thephpleague/omnipay-example) repo. -You can run it using PHP's built in web server (PHP 5.4+): - - $ php composer.phar update --dev - $ php -S localhost:8000 - -For more information, see the [Omnipay example application](https://github.com/thephpleague/omnipay-example). - -## Support - -If you are having general issues with Omnipay, we suggest posting on -[Stack Overflow](http://stackoverflow.com/). Be sure to add the -[omnipay tag](http://stackoverflow.com/questions/tagged/omnipay) so it can be easily found. - -If you want to keep up to date with release anouncements, discuss ideas for the project, -or ask more detailed questions, there is also a [mailing list](https://groups.google.com/forum/#!forum/omnipay) which -you can subscribe to. - -If you believe you have found a bug, please report it using the GitHub issue tracker -for the appropriate package, or better yet, fork the library and submit a pull request. - -## Security -If you discover any security related issues, please email barryvdh@gmail.com instead of using the issue tracker. - - -## Feedback - -**Please provide feedback!** We want to make this library useful in as many projects as possible. -Please head on over to the [mailing list](https://groups.google.com/forum/#!forum/omnipay) -and point out what you do and don't like, or fork the project and make suggestions. **No issue is too small.** diff --git a/gateways/configuring.md b/gateways/configuring.md new file mode 100644 index 00000000..38d5116d --- /dev/null +++ b/gateways/configuring.md @@ -0,0 +1,59 @@ +--- +layout: default +permalink: gateways/configuring/ +title: Configuring gateways +--- + +Configuring gateways +==================== + +All payment gateways must implement [GatewayInterface](https://github.com/thephpleague/omnipay-common/blob/master/src/Common/GatewayInterface.php), and will usually +extend [AbstractGateway](https://github.com/thephpleague/omnipay-common/blob/master/src/Common/AbstractGateway.php) for basic functionality. + +## Initialize a gateway + +Gateways are created and initialized like so: + +~~~ php +use Omnipay\Omnipay; + +$gateway = Omnipay::create('PayPal_Express'); +$gateway->setUsername('adrian'); +$gateway->setPassword('12345'); +~~~ + +Alternatively, multiple parameters can be initialized at once, directly from data: + +~~~ php +... +$gateway->initialize([ + 'username' => 'adrian', + 'password' => '12345', +]); +~~~ + +Setting parameters this way will start by taking the default parameters as a base, +and then merging your supplied parameters over the top. + +## Gateway settings + +Most settings are gateway specific. If you need to query a gateway to get a list of available settings, you can call `getDefaultParameters()`: + +~~~ php +$settings = $gateway->getDefaultParameters(); +// default settings array format: +array( + 'username' => '', // string variable + 'testMode' => false, // boolean variable + 'landingPage' => array('billing', 'login'), // enum variable, first item should be treated as default +); +~~~ + +## Gateway types + +Generally most payment gateways can be classified as one of two types: + +- **Off-site** gateways such as PayPal Express, where the customer is redirected to a third party site to enter payment details +- **On-site** (merchant-hosted) gateways such as PayPal Pro, where the customer enters their credit card details on your site + +However, there are some gateways such as Sage Pay Direct, where you take credit card details on site, then optionally redirect if the customer's card supports 3D Secure authentication. Therefore, there is no point differentiating between the two types of gateway (other than by the methods they support). diff --git a/index.md b/index.md new file mode 100644 index 00000000..2dc50ff9 --- /dev/null +++ b/index.md @@ -0,0 +1,53 @@ +--- +layout: default +permalink: / +title: Introduction +--- + +Introduction +============ + +[![Source Code](//img.shields.io/badge/source-league/omnipay-blue.svg?style=flat-square)](https://github.com/thephpleague/omnipay) +[![Build Status](https://img.shields.io/travis/thephpleague/omnipay-common/master.svg?style=flat-square)](https://travis-ci.org/thephpleague/omnipay-common) +[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](//github.com/thephpleague/omnipay/blob/master/LICENSE) +[![Latest Stable Version](https://img.shields.io/packagist/v/omnipay/common.svg?style=flat-square)](https://packagist.org/packages/omnipay/common) +[![Total Downloads](https://poser.pugx.org/omnipay/common/d/total.png)](https://packagist.org/packages/omnipay/common) + +Omnipay is a payment processing library for PHP. It has been designed based on +ideas from [Active Merchant](//activemerchant.org/), plus experience implementing +dozens of gateways for [CI Merchant](https://github.com/expressodev/ci-merchant). It has a clear and consistent API, +is fully unit tested, and even comes with an example application to get you started. + +## Why use Omnipay? + +So, why use Omnipay instead of a gateway's official PHP package/example code? + +- Because you can learn one API and use it in multiple projects using different payment gateways +- Because if you need to change payment gateways you won't need to rewrite your code +- Because most official PHP payment gateway libraries are a mess +- Because most payment gateways have exceptionally poor documentation +- Because you are writing a shopping cart and need to support multiple gateways + +## Upgrading to 3.0 + +If you are upgrading from a pre-3.0 version of Omnipay, please note that there are some changes regarding the HTTP Client. +There have also been some changes to how gateway instances are created. See the [full release notes](/changelog/) for more details. + +## Support + +If you are having general issues with Omnipay, we suggest posting on +[Stack Overflow](//stackoverflow.com/). Be sure to add the +[omnipay tag](//stackoverflow.com/questions/tagged/omnipay) so it can be easily found. + +If you want to keep up to date with release anouncements, discuss ideas for the project, +or ask more detailed questions, there is also a [mailing list](https://groups.google.com/forum/#!forum/omnipay) which +you can subscribe to. + +If you believe you have found a bug, please report it using the GitHub issue tracker +for the appropriate package, or better yet, fork the library and submit a pull request. + +## Feedback + +**Please provide feedback!** We want to make this library useful in as many projects as possible. +Please head on over to the [mailing list](https://groups.google.com/forum/#!forum/omnipay) +and point out what you do and don't like, or fork the project and make suggestions. **No issue is too small.** diff --git a/installation.md b/installation.md new file mode 100644 index 00000000..3935934d --- /dev/null +++ b/installation.md @@ -0,0 +1,22 @@ +--- +layout: default +permalink: installation/ +title: Installation +--- + +Installation +============ + +Omnipay is installed via [Composer](https://getcomposer.org/). +For most uses, you will need to require `league/omnipay` and an individual gateway: + +``` +composer require league/omnipay:^3 omnipay/paypal +``` + +If you want to use your own HTTP Client instead of Guzzle (which is the default for `league/omnipay`), +you can require `omnipay/common` and any `php-http/client-implementation` (see [PHP Http](http://docs.php-http.org/en/latest/clients.html)) + +``` +composer require omnipay/common:^3 omnipay/paypal php-http/buzz-adapter +``` \ No newline at end of file diff --git a/phpunit.xml.dist b/phpunit.xml.dist deleted file mode 100644 index 1347f357..00000000 --- a/phpunit.xml.dist +++ /dev/null @@ -1,23 +0,0 @@ - - - - - ./src - - - - - ./tests/ - - - diff --git a/simple-example.md b/simple-example.md new file mode 100644 index 00000000..092f0026 --- /dev/null +++ b/simple-example.md @@ -0,0 +1,72 @@ +--- +layout: default +permalink: simple-example/ +title: Simple example +--- + +Simple example +============== + +Here is a simple example of how to use Omnipay. As you can see, Omnipay has a consistent, well thought out API. As much as possible, we try to abstract the differences between the various payments gateways. + +~~~ php +use Omnipay\Omnipay; + +// Setup payment gateway +$gateway = Omnipay::create('Stripe'); +$gateway->setApiKey('abc123'); + +// Example form data +$formData = [ + 'number' => '4242424242424242', + 'expiryMonth' => '6', + 'expiryYear' => '2016', + 'cvv' => '123' +]; + +// Send purchase request +$response = $gateway->purchase( + [ + 'amount' => '10.00', + 'currency' => 'USD', + 'card' => $formData + ] +)->send(); + +// Process response +if ($response->isSuccessful()) { + + // Payment was successful + print_r($response); + +} elseif ($response->isRedirect()) { + + // Redirect to offsite payment gateway + $response->redirect(); + +} else { + + // Payment failed + echo $response->getMessage(); +} +~~~ + +## Example Application + +An example application is also provided in the [omnipay/example](https://github.com/thephpleague/omnipay-example) repo. + +~~~ bash +# Clone project +git clone https://github.com/thephpleague/omnipay-example.git omnipay-example + +# Go to project directory +cd omnipay-example + +# Install dependencies +composer install + +# Run using the built-in PHP web server +php -S localhost:8000 +~~~ + +For more information, see the [Omnipay example application](https://github.com/thephpleague/omnipay-example). \ No newline at end of file diff --git a/tests/OmnipayTest.php b/tests/OmnipayTest.php deleted file mode 100644 index 766ce5d1..00000000 --- a/tests/OmnipayTest.php +++ /dev/null @@ -1,35 +0,0 @@ -assertInstanceOf('Omnipay\Common\GatewayFactory', $factory); - } - - - /** - * Verify a new Client instance can be instantiated - */ - public function testNewClient() - { - $client = new Client(); - - $this->assertInstanceOf('Omnipay\Common\Http\Client', $client); - } -} \ No newline at end of file