Install the Package
composer require answear/payum-pay-u
Note: Laravel lacks native Payum support, so use as a standalone library or integrate via a custom Payum bridge (e.g., payum/payum-bundle for Symfony-like DI).
Configure Payum Gateway
Add to config/services.php (or a custom config file):
'payum' => [
'gateways' => [
'payu' => [
'factory' => 'payu',
'config' => [
'pos_id' => env('PAYU_POS_ID'),
'signature_key' => env('PAYU_SIGNATURE_KEY'),
'oauth_client_id' => env('PAYU_OAUTH_CLIENT_ID'),
'oauth_secret' => env('PAYU_OAUTH_SECRET'),
'environment' => env('PAYU_ENVIRONMENT', 'sandbox'), // 'sandbox' or 'production'
],
'actions' => [
'capture' => \Answear\Payum\PayU\Action\CaptureAction::class,
'refund' => \Answear\Payum\PayU\Action\RefundAction::class,
'notify' => \Answear\Payum\PayU\Action\NotifyAction::class,
'status' => \Answear\Payum\PayU\Action\StatusAction::class,
'convert_payment' => \Answear\Payum\PayU\Action\ConvertPaymentAction::class,
'sync_payment' => \Answear\Payum\PayU\Action\SyncPaymentAction::class,
'cancel' => \Answear\Payum\PayU\Action\CancelAction::class,
],
],
],
],
Register Payum Services Use Laravel’s service provider to bind Payum components:
// app/Providers/AppServiceProvider.php
public function register()
{
$this->app->singleton(\Payum\Core\ApiAwareInterface::class, function ($app) {
return new \Payum\Core\ApiAware();
});
$this->app->bind(\Payum\Core\GatewayFactoryInterface::class, function ($app) {
return new \Payum\Core\GatewayFactory();
});
}
First Use Case: Capture a Payment
use Payum\Core\Request\Capture;
use Payum\Core\GatewayInterface;
$gateway = app()->make(GatewayInterface::class);
$gateway->execute(new Capture($token, $paymentDetails));
Initialize Payment Token
$token = $gateway->getTokenFactory()->createCaptureToken(
'payu',
$paymentDetails,
'https://your-app.com/payment/status' // Notify URL
);
Redirect user to PayU’s payment page using $token->getTargetUrl().
Handle PayU Notification
Create a Laravel route to process PayU’s notify request:
Route::post('/payment/notify', function (Request $request) {
$gateway->execute(new \Answear\Payum\PayU\Request\Notify($request->all()));
return response()->json(['status' => 'success']);
});
Capture Payment After Redirect
$captureRequest = new Capture($token);
$captureRequest->setModel($payment); // Your payment model
$gateway->execute($captureRequest);
$refundRequest = new \Payum\Core\Request\Refund($token);
$refundRequest->setAmount(100); // Amount to refund
$gateway->execute($refundRequest);
$statusRequest = new \Payum\Core\Request\GetStatus($token);
$gateway->execute($statusRequest);
if ($statusRequest->isCaptured()) {
// Payment succeeded
}
logger: 'monolog.logger.payu' in config to debug API calls.configs array in YAML to switch between sandbox/production POS IDs dynamically.CaptureAction) to add business logic (e.g., inventory updates).notify or capture for downstream services:
event(new PaymentProcessed($payment));
Laravel-Payum Mismatch
payum/payum-bridge or manually bind services.GatewayFactory and TokenFactory as singletons in Laravel’s DI container.Missing Features
OrderRequest params for subscriptions (e.g., recurring). Extend \Answear\Payum\PayU\Request\CreateOrder:
$orderRequest = new \Answear\Payum\PayU\Request\CreateOrder();
$orderRequest->setRecurring(true);
$orderRequest->setRecurringPeriod('monthly');
Signature Validation
signature_key matches PayU’s merchant settings.answear_payum_pay_u:
logger: 'monolog.logger.payu'
IP Handling
X-Forwarded-For, but ensure your Laravel app passes this header:
$request->ip(); // Laravel’s request IP may differ from PayU’s expected format.
Notify URL
notify endpoint must be publicly accessible. Use a webhook URL (e.g., https://your-app.com/payment/notify).if (!$request->hasValidPayuSignature()) {
abort(403);
}
HttpClient:
$client = new \GuzzleHttp\Client([
'timeout' => 30, // seconds
]);
notify action:
try {
$gateway->execute($notifyRequest);
} catch (\Answear\Payum\PayU\Exception\PayuException $e) {
\Log::error('PayU Notify Error: ' . $e->getMessage());
}
Custom Requests
Extend \Answear\Payum\PayU\Request\AbstractRequest to add PayU-specific params:
class CustomOrderRequest extends AbstractRequest
{
public function setCustomParam(string $key, $value): self
{
$this->parameters[$key] = $value;
return $this;
}
}
Action Modifiers Override actions to add pre/post-processing:
class CustomCaptureAction extends \Answear\Payum\PayU\Action\CaptureAction
{
protected function executeCapture(\Payum\Core\Request\Capture $request)
{
// Add logic before/after capture
parent::executeCapture($request);
}
}
Logger Integration Replace the default logger with Laravel’s:
$this->app->bind('monolog.logger.payu', function () {
return \Log::channel('payu');
});
environment: 'production' in config to switch between sandbox/live.pos_id matches PayU’s merchant account ID (case-sensitive).oauth_secret changes in PayU’s merchant panel.GatewayInterface must be bound to Laravel’s container. Use a facade or helper:
class PayuGateway
{
public function __construct(private GatewayInterface $gateway) {}
public static function capture($token, $payment)
{
$gateway = app(GatewayInterface::class);
$gateway->execute(new Capture($token, $payment));
}
}
How can I help you explore Laravel packages today?