Search by

concept24 / omnipay-ingwebpay

mihaictinescu

ING WebPay (ING Bank România) driver for the Omnipay payment processing library

Package info

bitbucket.org/concept24/omnipay-ingwebpay

pkg:composer/concept24/omnipay-ingwebpay

Statistics

Installs: 6

Dependents: 0

Suggesters: 0

v1.0.2 2026-11-12 11:07 UTC

This package is auto-updated.

Last update: 2026-11-12 12:09:54 UTC


README

ING WebPay (ING Bank România) driver for the Omnipay payment processing library, REST API mpi/rest.

Requirements

  • PHP 8.2+ (Laravel 12 and 13 compatible — the only dependency is omnipay/common 3.x)
  • an HTTP client for Omnipay, e.g. php-http/guzzle7-adapter

Installation

composer require concept24/omnipay-ingwebpay

Usage

use Omnipay\Omnipay;

$gateway = Omnipay::create('IngWebPay');           // or new \Omnipay\IngWebPay\Gateway
$gateway->initialize([
    'userName' => '…',   // API user from ING
    'password' => '…',
    'testMode' => true,  // securepay-uat.ing.ro; false → securepay.ing.ro
]);

// 1. register the payment and send the client to ING
$response = $gateway->purchase([
    'amount'        => '122.89',
    'currency'      => 'RON',                      // RON (946) or EUR (978); default RON
    'returnUrl'     => 'https://shop.ro/ing/return',
    'description'   => 'Order C24-77',
    'language'      => 'ro',                       // ro / en
    // 'transactionId' => 'C24-77',                // → orderNumber, only if ING configured your account to receive it
    // 'email'         => 'client@example.com',
])->send();

if ($response->isRedirect()) {
    $orderId = $response->getTransactionReference();   // keep it with the payment: ING's mdOrder
    $response->redirect();                              // GET to formUrl; ING gives the client 10 minutes
} else {
    $response->getMessage();                            // ING error (errorCode in getCode())
}

// 2. on returnUrl ING adds ?orderId=…
$status = $gateway->completePurchase()->send();          // reads orderId from the current request

// 3. later, for clients who never came back (ING sends no server notification)
$status = $gateway->fetchTransaction(['transactionReference' => $orderId])->send();

Statuses (getOrderStatusExtended.do)

getOrderStatus() (constants on StatusResponse)INGResponse
0registered, not paidisPending()
1pre-authorizedisSuccessful()
2paidisSuccessful()
3authorization reversed (cancelled before settlement)isCancelled()
4refunded — ING's test environment reports it also after a partial refundisRefunded()
53-D Secure in progress at the issuerisPending()
6declined — also when the 10-minute payment session expires (getActionCode() -2007, Session time limit)isDeclined()
7partially refunded (code of the processing platform; not seen from ING)isRefunded()
nullunknown order / ING errornone

getMessage() gives the bank's answer for the card (e.g. Wrong expiry date.), getActionCode() its code, getTransactionId() ING's orderNumber, getAmountInteger() the amount in bani, getDate() when the order was registered.

Card details, once the client entered a card: getCardMask() (466286**6040), getCardholderName(), getCardExpiry() (YYYYMM), getApprovalCode() (approved payments only).

ING does not notify the merchant's server. Its integration requirements: check the status when the client returns, and automatically about 10 minutes after registration for the clients who don't.

Pre-authorization

$gateway->authorize([...same as purchase...])->send();                  // registerPreAuth.do
$gateway->capture(['transactionReference' => $orderId])->send();       // deposit.do — no amount = full amount
$gateway->capture(['transactionReference' => $orderId, 'amount' => '50.00'])->send();
$gateway->void(['transactionReference' => $orderId])->send();          // reverse.do (same day, before 22:00)

Refund

$gateway->refund(['transactionReference' => $orderId, 'amount' => '122.89'])->send();  // refund.do — full or partial

Several partial refunds are allowed up to the paid amount. After any refund, full or partial, ING reports the order with status 4; getOrderStatusExtended.do does not say how much was refunded (only ING's short getOrderStatus.do shows the remaining depositAmount). An order that isn't paid answers errorCode 7 (Refund is impossible for current transaction state).

deposit.do, reverse.do and refund.do need extra rights requested from ING; without them, the same operations are done from the ING WebPay console.

Not supported by ING's API

ING sends no server-to-server notification (no webhook/IPN), has no transaction list method, and saved cards cannot be charged through the API (paymentOrderBinding.do is not available). Google Pay and Apple Pay appear on ING's payment page without any integration work.

Tests

composer install
vendor/bin/phpunit                                                    # unit tests, no network
ING_USER=… ING_PASS=… vendor/bin/phpunit --group uat                  # against ING's test environment

On ING's test payment page (securepay-uat.ing.ro), card 4662861119116040, any future expiry and CVV 203 gives an approved payment; another CVV is declined. 3-D Secure: "Confirmare autentificare". The test API user and password come from ING with the merchant's test access.

License

MIT — see LICENSE.

Changelog

  • unreleased — documents that ING reports status 4 also after a partial refund (checked on ING's test environment).
  • 1.0.2 — status 4 is a full refund (StatusResponse::REFUNDED, isRefunded()), not a cancellation; status 7 (partial refund) added; isCancelled() now means status 3 only. StatusResponse::REVERSED stays as a deprecated alias of REFUNDED.
  • 1.0.0 — first release.