omnipay/eway
Omnipay eWAY driver for processing payments through Australia's eWAY gateway. Supports Rapid 3.1 and Direct APIs, tokenisation, refunds, and secure card handling within the Omnipay payment abstraction layer.
composer require omnipay/eway league/omnipay php-http/guzzle7-adapter
Omnipay 3 (which omnipay/eway v3 targets) relies on PSR-18 / HTTPlug discovery, so a client adapter is required or you'll hit DiscoveryFailedException at runtime.
Pick the right gateway. The package ships three drivers, and choosing the wrong one is the most common first mistake:
Eway_Rapid — eWay Rapid 3.1 API (current AU/NZ card payments). Use this for almost everything new.Eway_Direct — legacy XML Direct API (AU/NZ). Only use it if you're maintaining an existing integration.Eway_Shared — hosted "Responsive Shared Page" flow where the customer is redirected to eWay.Look first at src/RapidGateway.php and src/Message/Rapid/ — that folder lists the actual supported requests (purchase, authorize, capture, refund, void, createCard, fetchTransaction). If a method isn't there, the gateway doesn't support it, regardless of what the README implies.
Configure once (Laravel example):
// config/services.php
'eway' => [
'api_key' => env('EWAY_API_KEY'),
'password' => env('EWAY_PASSWORD'),
'test' => env('EWAY_TEST', true),
],
use Omnipay\Omnipay;
$gateway = Omnipay::create('Eway_Rapid');
$gateway->setApiKey(config('services.eway.api_key'));
$gateway->setPassword(config('services.eway.password'));
$gateway->setTestMode(config('services.eway.test'));
$response = $gateway->purchase([
'amount' => '10.00',
'currency' => 'AUD',
'transactionId' => (string) $order->id,
'card' => [
'number' => '4444333322221111',
'expiryMonth' => '12',
'expiryYear' => '2030',
'cvv' => '123',
'firstName' => 'Jane',
'lastName' => 'Doe',
],
])->send();
if ($response->isSuccessful()) {
$order->update(['eway_transaction_id' => $response->getTransactionReference()]);
} else {
Log::warning('eWay purchase failed', ['code' => $response->getCode(), 'msg' => $response->getMessage()]);
}
Use the documented sandbox test card (4444333322221111) and setTestMode(true) to hit the eWay sandbox.
Bind the gateway in the container. Don't scatter credential setup through controllers. A small factory or singleton produces a pre-configured instance:
$this->app->singleton(\Omnipay\Common\GatewayInterface::class, function () {
$g = \Omnipay\Omnipay::create('Eway_Rapid');
$g->setApiKey(config('services.eway.api_key'));
$g->setPassword(config('services.eway.password'));
$g->setTestMode(config('services.eway.test'));
return $g;
});
Two-phase authorize/capture. For pre-auth flows, call authorize() then capture() later with the returned transactionReference:
$auth = $gateway->authorize(['amount' => '49.95', 'currency' => 'AUD', 'card' => $card])->send();
// later…
$capture = $gateway->capture([
'amount' => '49.95',
'currency' => 'AUD',
'transactionReference' => $auth->getTransactionReference(),
])->send();
Void and refund follow the same reference-based pattern. void() only works before settlement; once settled, you must refund().
Stored cards / tokens. Use createCard on Rapid to register a customer token, then reuse it via a cardReference (or the customer token) in later purchase calls — this is how you implement "save card for next time" without ever storing PAN data. Persist only getTransactionReference() / token, never the raw card.
Hosted-page / 3DS flow. With Eway_Shared, purchase() returns a redirect response:
$response = $gateway->purchase([...])->send();
if ($response->isRedirect()) {
return redirect($response->getRedirectUrl());
}
Then handle the return URL by calling completePurchase() with the request data, and verify success before fulfilling the order.
Webhooks. eWay Rapid can notify you of transaction events asynchronously. Don't trust the webhook payload alone — re-fetch the transaction with fetchTransaction(['transactionReference' => $id]) and reconcile against your order before marking it paid. This also gives you a clean place to handle the "customer abandoned the shared page" case.
Logging and observability. Inject a PSR-3 logger via $gateway->setLogger($logger) so Omnipay logs HTTP traffic. Prefer building your own context array (order_id, amount, response code) rather than logging $response->getData() wholesale.
Testing. In feature tests, mock the HTTP client or bind a fake gateway that returns canned PurchaseResponse objects. Never let CI hit the live eWay endpoint — even the sandbox requires credentials and network access.
omnipay/eway v2.x. Mixing versions produces confusing class not found / method-signature errors. Check composer show omnipay/common first.DiscoveryFailedException: No PSR-18 client found. Add php-http/guzzle7-adapter (or equivalent). This is an Omnipay issue, not an eWay issue.'10.00', not 10.0 — floats cause rounding surprises since eWay works in minor units internally. Keep amounts as strings end-to-end.setTestMode(true) with production keys produces auth failures that look like bad credentials. Verify both the flag and the key pair together.isSuccessful() is not HTTP 200. eWay returns 200 for declined transactions too. Always check $response->isSuccessful() and inspect $response->getCode() / getMessage() before trusting anything.$response->getData() on a purchase contains the request payload on error in some paths — scrub number, cvv, and expiry before logging.transactionId) so a retried purchase doesn't double-charge.transactionId must be unique per attempt if you want meaningful reconciliation; reuse across retries only if you're re-sending the same logical transaction.AbstractGateway/AbstractRequest in src/Message/Rapid/ and register the gateway with Omnipay::extend(). Forking the package is easier than monkey-patching, given its age.How can I help you explore Laravel packages today?