Home

Awesome

Omnipay

An easy to use, consistent payment processing library for PHP

Unit Tests Latest Stable Version Total Downloads

Omnipay is a payment processing library for PHP. It has been designed based on ideas from Active Merchant, 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?

TL;DR

Just want to see some code?

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 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 library to make HTTP requests. A Guzzle 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. 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)

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

Note: The package name has been changed from omnipay/omnipay to league/omnipay for v3

Payment Gateways

All payment gateways must implement GatewayInterface, and will usually extend AbstractGateway for basic functionality.

The following gateways are available:

Gateway2.x3.xComposer PackageMaintainer
2c2pdilab/omnipay-2c2pXu Ding
2Checkout-omnipay/2checkoutOmnipay
2Checkout Improved-collizo4sky/omnipay-2checkoutAgbonghama Collins
99Bill-x-class/omnipay-99billLaraveler
Acapture (PayVision)-qup/omnipay-acaptureNiels de Vries
Adyen-academe/omnipay-adyenJason Judge
Affirmeduardlleshi/omnipay-affirmEduard Lleshi
Agms-agmscode/omnipay-agmsMaanas Royy
Alipay(Global)lokielse/omnipay-global-alipayLoki Else
Alipaylokielse/omnipay-alipayLoki Else
Allied Wallet-delatbabel/omnipay-alliedwalletDel
Arca-k3rnel/omnipay-arcaPoghos Boyajyan
Authorize.Netomnipay/authorizenetJason Judge
Authorize.Net API-academe/omnipay-authorizenetapiJason Judge
Authorize.Net Recurring Billing-cimpleo/omnipay-authorizenetrecurringCimpleO
Bankartampeco/omnipay-bankartAmpeco
Barclays ePDQ-digitickets/omnipay-barclays-epdqDigiTickets
BlueOrange bank-deh4eg/omnipay-blueorangeDenis Smolakov
Beanstream-lemonstand/omnipay-beanstreamLemonStand
BitPayhiqdev/omnipay-bitpayHiQDev
BKM Express-yasinkuyu/omnipay-bkmYasin Kuyu
BlueSnap-vimeo/omnipay-bluesnapVimeo
Braintreeomnipay/braintreeOmnipay
Buckaroo-omnipay/buckarooOmnipay
CardGate-cardgate/omnipay-cardgateCardGate
CardSave-omnipay/cardsaveOmnipay
CashBaBaomnipay/cashbabaRecursion Technologies Ltd
Checkout.com-fotografde/checkoutcomfotograf.de
CloudBanking-cloudbanking/omnipay-cloudbankingCloudbanking
Coinbase-omnipay/coinbaseOmnipay
CoinGate-coingate/omnipay-coingateCoinGate
CoinPaymentsInkedCurtis/omnipay-coinpaymentsInkedCurtis
Creditcall-meebio/omnipay-creditcallJohn Jablonski
CSOB (GP WebPay)-bileto/omnipay-csob
Cybersourcedioscouri/omnipay-cybersourceDioscouri Design
Cybersource SOAP-dabsquared/omnipay-cybersource-soapDABSquared
DataCash-digitickets/omnipay-datacashDigiTickets
Datatrans-w-vision/datatransDominik Pfaffenbauer
Datatransacademe/omnipay-datatransJason Judge
Docdata Paymentsuskur/omnipay-docdata-paymentsUskur
Dummyomnipay/dummyDel
Ebanx-descubraomundo/omnipay-ebanxDescubra o Mundo
eGHL-e-ghl/omnipayJawad Humayun
eGHLdilab/omnipay-eghlXu Ding
eCoinhiqdev/omnipay-ecoinHiQDev
ecoPayz-dercoder/omnipay-ecopayzAlexander Fedra
eSewa-sudiptpa/omnipay-esewaSujip Thapa
EgopayRu-pinguinjkeke/omnipay-egopaymentruAlexander Avakov
Elavonlxrco/omnipay-elavonKorri
ePaymentshiqdev/omnipay-epaymentsHiQDev
ePayServicehiqdev/omnipay-epayserviceHiQDev
eWAYomnipay/ewayDel
Fasapay-andreas22/omnipay-fasapayAndreas Christodoulou
FaspayDavid-Kurniawan/omnipay-faspayDavid
Fat Zebra-delatbabel/omnipay-fatzebraDel
FreeKassahiqdev/omnipay-freekassaHiQDev
Fibank-ampeco/omnipay-fibankAmpeco
First Data-omnipay/firstdataOmniPay
Flo2cash-guisea/omnipay-flo2cashAaron Guise
Free / Zero Amount-colinodell/omnipay-zeroColin O'Dell
GiroCheckoutacademe/omnipay-girocheckoutJason Judge
Globalcloudpay-dercoder/omnipay-globalcloudpayAlexander Fedra
GoCardless-omnipay/gocardlessDel
GoPay-bileto/omnipay-gopay
GovPayNet-omnipay/omnipay-govpaynetFlexCoders
GVP (Garanti)-yasinkuyu/omnipay-gvpYasin Kuyu
GVP (Garanti)-emr/omnipay-gvpEmre Akinci
Helcim-academe/omnipay-helcimJason Judge
Icepay Payments-superbrave/omnipay-icepay-paymentsSuperBrave
iDram-ptuchik/omnipay-idramAvik Aghajanyan
iDeal-deniztezcan/omnipay-idealDeniz Tezcan
Ingenico ePayments-deniztezcan/omnipay-ingenico-epaymentsDeniz Tezcan
iPay88dilab/omnipay-ipay88Xu Ding
IfthenPay-ifthenpay/omnipay-ifthenpayRafael Almeida
Ikajohiqdev/omnipay-ikajoHiQDev
InterKassahiqdev/omnipay-interkassaHiQDev
InovioPaymvestil/omnipay-inoviopayMark Vestil
Iyzico-yasinkuyu/omnipay-iyzicoYasin Kuyu
Judo Pay-transportersio/omnipay-judopayTransporters.io
Klarna Checkoutmyonlinestore/omnipay-klarna-checkoutMyOnlineStore
Laybuy-mediabeastnz/omnipay-laybuyMyles Derham
Luminor Gateway-deh4eg/omnipay-luminorDenis Smolakov
Komerci (Rede, former RedeCard)-byjg/omnipay-komerciJoão Gilberto Magalhães
Komoju-vink/omnipay-komojuDanny Vink
Midtransdilab/omnipay-midtransXu Ding
MercadoPago-lucassmacedo/omnipay-mercadopagoLucas Macedo
Magnius-fruitcake/omnipay-magniusFruitcake
Manual-omnipay/manualDel
Migs-omnipay/migsOmnipay
Mpesa-wasksofts/omnipay-mpesawasksofts
MTNCAM Mobile Moneylarrytech7/omnipay-momocmAkah Harvey
Mollieomnipay/mollieBarry vd. Heuvel
MOLPay-leesiongchan/molpayLee Siong Chan
MoMo-phpviet/omnipay-momoPHPViet
Moneris-unoapp-dev/omnipay-monerisUNOapp Dev
MultiCards-incube8/omnipay-multicardsDel
MultiSafepay-omnipay/multisafepayAlexander Deruwe
MyCard-xxtime/omnipay-mycardJoe Chu
MyFatoorah-myfatoorah/omnipayMyFatoorah Plugins Team
National Australia Bank (NAB) Transactsudiptpa/omnipay-nabtransactSujip Thapa
NestPay (EST)-yasinkuyu/omnipay-nestpayYasin Kuyu
NestPay (EST)-uskur/omnipay-nestpayUskur
Netaxept (BBS)-omnipay/netaxeptOmnipay
Netbanx-omnipay/netbanxMaks Rafalko
Neteller-dercoder/omnipay-netellerAlexander Fedra
NetPay-netpay/omnipay-netpayNetPay
Network Merchants Inc. (NMI)-mfauveau/omnipay-nmiMatthieu Fauveau
Nocksnocksapp/omnipay-nocksNocks
Nuvei-nmc9/omnipay-nuveiDiversifiedTech
OkPayhiqdev/omnipay-okpayHiQDev
OnePaydilab/omnipay-onepayXu Ding
Openpay Australiasudiptpa/omnipay-openpaySujip Thapa
Oppwavdbelt/omnipay-oppwaMartin van de Belt
PAY. (Pay.nl & Pay.be)paynl/omnipay-paynlAndy Pieters
PayMongo-oozman/omnipay-paymongoOozman
Payoodilab/omnipay-payooXu Ding
Pacnet-mfauveau/omnipay-pacnetMatthieu Fauveau
Pagar.me-descubraomundo/omnipay-pagarmeDescubra o Mundo
Paratika (Asseco)-yasinkuyu/omnipay-paratikaYasin Kuyu
PayFast-omnipay/payfastOmnipay
PayGate-mvnrsa/paygateMarnus van Niekerk
Payflow-omnipay/payflowDel
PaymentExpress (DPS)omnipay/paymentexpressDel
PaymentExpress / DPS (A2A)-onlinesid/omnipay-paymentexpress-a2aSid
PaymentgateRupinguinjkeke/omnipay-paymentgateruAlexander Avakov
PaymentSense-digitickets/omnipay-paymentsenseDigiTickets
PaymentWall-incube8/omnipay-paymentwallDel
Paynow-pay-now/omnipay-paynowPaynow
PayPalomnipay/paypalDel
PayPro-paypronl/omnipay-payproFruitcake
PAYONEacademe/omnipay-payoneJason Judge
Paysafecard-dercoder/omnipay-paysafecardAlexander Fedra
Paysafecard-worldstream-labs/omnipay-paysafecardWorldstream
Paysafe Payment Hub (Neteller)-worldstream-labs/omnipay-paysafe-payment-hubWorldstream
Paysera-povils/omnipay-payseraPovils
Paysera-semyonchetvertnyh/omnipay-payseraSemyon Chetvertnyh
PaySimple-dranes/omnipay-paysimpleDranes
PaySsion-inkedcurtis/omnipay-payssionCurtis
PayTrace-softcommerce/omnipay-paytraceOleg Ilyushyn
PayU-bileto/omnipay-payu
PayZen-ubitransports/omnipay-payzenUbitransport
Paxumhiqdev/omnipay-paxumHiQDev
Pelecarduskur/omnipay-pelecardUskur
Pin Payments-omnipay/pinDel
Ping++-phoenixg/omnipay-pingppHuang Feng
POLi-burnbright/omnipay-poliSid
Portmanat-dercoder/omnipay-portmanatAlexander Fedra
Posnet-yasinkuyu/omnipay-posnetYasin Kuyu
Postfinance-bummzack/omnipay-postfinanceRoman Schmid
Qiwihiqdev/omnipay-qiwiHiQDev
QQ Wallet(QPay)-kuangjy/omnipay-qpayKuang Jiaye
Quickpay-nobrainerweb/omnipay-quickpayNobrainer Web
Rabobank-omnipay/rabobankBarry vd. Heuvel
Razorpay-razorpay/omnipay-razorpayrazorpay
Realex-digitickets/omnipay-realexDigiTickets
RedSys-nazka/sermepa-omnipayJavier Sampedro
RentMoola-rentmoola/omnipay-rentmoolaGeoff Shaw
RoboKassahiqdev/omnipay-robokassaHiQDev
RocketGatemvestil/omnipay-rocketgateMark Vestil
Sage Payomnipay/sagepayJason Judge
Sberbank-andrewnovikof/omnipay-sberbankAndrew Novikov
SecPay-justinbusschau/omnipay-secpayJustin Busschau
SecurePayomnipay/securepayOmnipay
Secure Trading-meebio/omnipay-secure-tradingJohn Jablonski
Sisowfruitcakestudio/omnipay-sisowFruitcake
Skrill-alfaproject/omnipay-skrillJoão Dias
Sofort-aimeoscom/omnipay-sofortAimeos GmbH
Spreedly-gregoriohc/omnipay-spreedlyGregorio Hernández Caso
Squaretransportersio/omnipay-squareTransporters.io
Starkpaystarkpay/omnipayStarkpay
Stripeomnipay/stripeDel
TargetPay-omnipay/targetpayAlexander Deruwe
TatraBank-omnipay-tatrabank
ToyyibPay-sitehandy/omnipay-toyyibpayAmirol Zolkifli
Tpay-omnipay/tpayTpay.com
UnionPaylokielse/omnipay-unionpayLoki Else
Vantiv-lemonstand/omnipay-vantivLemonStand
Veritrans-andylibrian/omnipay-veritransAndy Librian
Vindicia-vimeo/omnipay-vindiciaVimeo
VivaPayments-delatbabel/omnipay-vivapaymentsDel
VR Payment-antibodies-online/omnipay-vr-paymentantibodies-online
WebMoneydercoder/omnipay-webmoneyAlexander Fedra
WeChat-labs7in0/omnipay-wechat7IN0's Labs
WechatPaylokielse/omnipay-wechatpayLoki Else
WePay-collizo4sky/omnipay-wepayAgbonghama Collins
Wirecardigaponov/omnipay-wirecardIgor Gaponov
Wirecard-academe/omnipay-wirecardJason Judge
Worldpay XML Direct Corporate Gateway-teaandcode/omnipay-worldpay-xmlDave Nash
Worldpay XML Hosted Corporate Gatewaycatharsisjelly/omnipay-worldpay-cg-hostedChris Lock
Worldpay Business Gatewayomnipay/worldpayOmnipay
Yandex.Kassahiqdev/omnipay-yandex-kassaHiQDev
Yandex.Money-yandexmoney/omnipayRoman Ananyev
Yandex.Money for P2P paymentshiqdev/omnipay-yandexmoneyHiQDev
Yekpay-nekofar/omnipay-yekpayMilad Nekofar
ZarinPal-nekofar/omnipay-zarinpalMilad Nekofar

Gateways are created and initialized like so:

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():

$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:

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 object. This provides a safe way to accept user input.

The CreditCard object has the following fields:

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.

$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:

$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 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:

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:

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:

Pass the options through to the method like so:

$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:

The Payment Response

The payment response must implement ResponseInterface. There are two main types of 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:

$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:

$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:

$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:

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:

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:

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.

$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 which is now handled by acceptNotification.

Example Application

An example application is provided in the 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.

Support

If you are having general issues with Omnipay, we suggest posting on Stack Overflow. Be sure to add the omnipay tag 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 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 and point out what you do and don't like, or fork the project and make suggestions. No issue is too small.