Search by

concept24 / omnipay-payu-rest

mihaictinescu

PayU REST API (OpenPayU v2.1, PayU GPO) driver for the Omnipay payment processing library

Package info

bitbucket.org/concept24/omnipay-payu-rest

pkg:composer/concept24/omnipay-payu-rest

Statistics

Installs: 4

Dependents: 0

Suggesters: 0

v1.0.0 2026-11-12 12:30 UTC

This package is auto-updated.

Last update: 2026-11-12 13:41:47 UTC


README

PayU REST API (OpenPayU v2.1, PayU GPO — including PayU GPO Romania) driver for the Omnipay payment processing library.

For the older PayU Romania LiveUpdate / IPN integration (MERCHANT + secret key) use a LiveUpdate driver instead; this package talks to secure.payu.com/api/v2_1 with OAuth.

Requirements

  • PHP 8.2+ (Laravel 12 and 13 compatible — dependencies: omnipay/common 3.x, Guzzle 7)
  • PayU POS data: POS id, OAuth client_id / client_secret, second key (MD5)

Installation

composer require concept24/omnipay-payu-rest

Usage

use Omnipay\Omnipay;

$gateway = Omnipay::create('PayURest');              // or new \Omnipay\PayURest\Gateway
$gateway->initialize([
    'posId'        => '…',
    'clientId'     => '…',   // usually the POS id
    'clientSecret' => '…',
    'secondKey'    => '…',   // signs the notifications
    'testMode'     => true,  // secure.snd.payu.com; false → secure.payu.com ('endpoint' overrides both)
]);

// 1. create the order and send the client to PayU
$response = $gateway->purchase([
    'amount'        => '122.89',
    'currency'      => 'RON',                          // default RON
    'description'   => 'Order C24-77',
    'transactionId' => 'C24-77-'.bin2hex(random_bytes(3)), // extOrderId: unique per POS, so unique per attempt
    'returnUrl'     => 'https://shop.ro/pay/77',       // continueUrl
    'notifyUrl'     => 'https://shop.ro/payu/notify',
    'clientIp'      => $request->ip(),
    'language'      => 'ro',
    'buyer'         => ['email' => 'client@example.com', 'firstName' => 'Ana', 'lastName' => 'Pop', 'phone' => '0722…'],
    // 'products'   => [['name' => '…', 'unitPrice' => '12289', 'quantity' => '1']], // default: one line with the total
])->send();

if ($response->isRedirect()) {
    $orderId = $response->getTransactionReference();   // keep it with the payment: continueUrl does not carry it
    $response->redirect();
}

// 2. PayU POSTs every status change to notifyUrl — answer HTTP 200 (duplicates are possible)
$notification = $gateway->acceptNotification();
if ($notification->isValid()) {                         // OpenPayu-Signature checked with the second key
    $notification->getOrderStatus();                    // COMPLETED, CANCELED, PENDING, WAITING_FOR_CONFIRMATION
    $notification->getTransactionReference();           // PayU orderId
    $notification->getTransactionId();                  // your extOrderId
    $notification->getAmountInteger();                  // minor units
}

// 3. when the client comes back (or any time later)
$status = $gateway->fetchTransaction(['transactionReference' => $orderId])->send();
$status->isSuccessful();   // COMPLETED
$status->isPending();      // NEW, PENDING, WAITING_FOR_CONFIRMATION
$status->isCancelled();    // CANCELED

The OAuth token is reused until shortly before it expires (cached per endpoint + client id, for the life of the PHP process). The default HTTP client does not follow redirects: PayU answers the order creation with HTTP 302 and the JSON body.

Refund and cancel

$gateway->refund(['transactionReference' => $orderId])->send();                                  // full
$gateway->refund(['transactionReference' => $orderId, 'amount' => '10.00', 'description' => 'Return'])->send(); // partial
$gateway->void(['transactionReference' => $orderId])->send();                                    // cancel an order still in progress

Tests

composer install
vendor/bin/phpunit                                                                 # unit tests, no network
PAYU_POS_ID=… PAYU_CLIENT_ID=… PAYU_CLIENT_SECRET=… vendor/bin/phpunit --group sandbox  # against PayU's sandbox

Sandbox cards (expiry 12/29, CVV 123): 4444333322221111 approved · 5000105018126595 declined · 4245757666349685 3-D Secure challenge (the sandbox sends the challenge to an internal PayU simulator that is not publicly reachable). When PayU recognises the buyer's e-mail in Click to Pay, choose "Card" to enter a new card.

Changelog

  • 1.0.0 — first release.

License

MIT — see LICENSE.