futureecom/omnipay-paypal

PayPal driver for the Omnipay payment processing library.

Maintainers

Package info

github.com/futureecom/omnipay-paypal

Homepage

pkg:composer/futureecom/omnipay-paypal

Transparency log

Statistics

Installs: 119

Dependents: 0

Suggesters: 0

Stars: 1

Open Issues: 0

1.2.1 2026-07-28 15:00 UTC

This package is auto-updated.

Last update: 2026-07-28 15:01:13 UTC


README

PayPal gateway for the Omnipay payment processing library

This standalone package implements PayPal Orders v2 and Vault/Payment Method Tokens v3 for Omnipay using PSR-compatible HTTP and cache interfaces.

Installation

Install the gateway using Composer:

composer require futureecom/omnipay-paypal

Configuration

First, you need to obtain your PayPal API credentials:

  1. Go to PayPal Developer Dashboard
  2. Create or select your app
  3. Copy your Client ID and Client Secret

Usage

Initialize the Gateway

use Omnipay\Omnipay;

$gateway = Omnipay::create('PayPal');
$gateway->setClientId('your-client-id');
$gateway->setClientSecret('your-client-secret');
$gateway->setTestMode(true); // Set to false for live transactions

OAuth tokens are cached in memory by default and are isolated by environment and client ID. Long-running or multi-process applications can provide any PSR-16 cache:

/** @var \Psr\SimpleCache\CacheInterface $cache */
$gateway->setCache($cache);

The gateway retries a PayPal operation once when PayPal rejects an expired access token with HTTP 401.

Create an Authorization (Auth Only)

Creates a PayPal order with intent to authorize. The customer must approve the order before you can authorize.

$response = $gateway->authorize([
    'amount' => '100.00',
    'currency' => 'USD',
    'returnUrl' => 'https://example.com/payment/return',
    'cancelUrl' => 'https://example.com/payment/cancel',
    'transactionId' => 'ORDER-123',
    'description' => 'Order #123',
    'brandName' => 'My Store',
])->send();

if ($response->isRedirect()) {
    // Redirect the customer to PayPal for approval
    $redirectUrl = $response->getRedirectUrl();
    $orderId = $response->getTransactionReference(); // Save this!
    
    // Redirect to $redirectUrl
} else {
    echo "Error: " . $response->getMessage();
}

Create a Purchase (Auth + Capture)

Creates a PayPal order with intent to capture. Similar flow as authorize.

$response = $gateway->purchase([
    'amount' => '50.00',
    'currency' => 'USD',
    'returnUrl' => 'https://example.com/payment/return',
    'cancelUrl' => 'https://example.com/payment/cancel',
])->send();

if ($response->isRedirect()) {
    $redirectUrl = $response->getRedirectUrl();
    $orderId = $response->getTransactionReference();
    
    // Redirect to $redirectUrl
}

For non-vaulted Standard Checkout, provide explicit identifiers and PayPal experience context. No Vault v3 operation or vault attribute is used:

$response = $gateway->purchase([
    'amount' => '100.00',
    'currency' => 'ILS',
    'referenceId' => 'internal-attempt-id',
    'invoiceId' => 'unique-invoice-id',
    'customId' => 'cart:cart-id',
    'payPalRequestId' => 'stable-create-idempotency-key',
    'returnUrl' => 'https://example.com/paypal/return',
    'cancelUrl' => 'https://example.com/paypal/cancel',
    'userAction' => 'PAY_NOW',
    'shippingPreference' => 'NO_SHIPPING',
])->send();

Retrieve an Order

Retrieve an order after an interrupted or ambiguous capture:

$response = $gateway->fetchOrder([
    'transactionReference' => $orderId,
])->send();

Advanced Checkout and Vault v3

Advanced integrations can create and confirm Vault v3 setup tokens, retrieve or delete payment tokens, and then pass a token as cardReference to an Orders v2 request. These operations are opt-in; Orders v2 requests do not invoke Vault v3 automatically.

$setup = $gateway->createSetupToken([
    'paymentSource' => ['card' => []],
    'payPalRequestId' => 'stable-setup-token-key',
])->send();

$token = $gateway->confirmSetupToken([
    'transactionReference' => $setup->getSetupTokenId(),
    'payPalRequestId' => 'stable-confirm-key',
])->send();

Verify a REST Webhook

The library verifies signatures through PayPal. Persisting and reconciling events remains the consuming application's responsibility.

$response = $gateway->verifyWebhookSignature([
    'webhookId' => $webhookId,
    'transmissionId' => $headers['PAYPAL-TRANSMISSION-ID'],
    'transmissionTime' => $headers['PAYPAL-TRANSMISSION-TIME'],
    'certUrl' => $headers['PAYPAL-CERT-URL'],
    'authAlgo' => $headers['PAYPAL-AUTH-ALGO'],
    'transmissionSignature' => $headers['PAYPAL-TRANSMISSION-SIG'],
    'webhookEvent' => $decodedEvent,
])->send();

if (!$response->isWebhookSignatureValid()) {
    // Reject the event.
}

Capture an Order

After the customer approves the order, capture the payment:

$response = $gateway->capture([
    'transactionReference' => $orderId, // Order ID from authorize/purchase
])->send();

if ($response->isSuccessful()) {
    echo "Payment captured successfully!";
    $captureId = $response->getCaptureId(); // Save for refunds
} else {
    echo "Capture failed: " . $response->getMessage();
}

Partial Capture

$response = $gateway->capture([
    'transactionReference' => $orderId,
    'amount' => '50.00',
    'currency' => 'USD',
])->send();

Refund a Payment

Refund a captured payment using the capture ID:

// Full refund
$response = $gateway->refund([
    'transactionReference' => $captureId, // Capture ID from capture response
])->send();

// Partial refund
$response = $gateway->refund([
    'transactionReference' => $captureId,
    'amount' => '25.00',
    'currency' => 'USD',
])->send();

if ($response->isSuccessful()) {
    echo "Refund successful!";
    echo "Refund ID: " . $response->getTransactionReference();
} else {
    echo "Refund failed: " . $response->getMessage();
}

Void an Authorization

Void an authorized payment (must be done before capture):

$response = $gateway->void([
    'transactionReference' => $authorizationId, // Authorization ID
])->send();

if ($response->isSuccessful()) {
    echo "Authorization voided successfully!";
}

Complete Payment Flow Example

use Omnipay\Omnipay;

// 1. Initialize gateway
$gateway = Omnipay::create('PayPal');
$gateway->setClientId('your-client-id');
$gateway->setClientSecret('your-client-secret');
$gateway->setTestMode(true);

// 2. Create order
$response = $gateway->purchase([
    'amount' => '99.99',
    'currency' => 'USD',
    'returnUrl' => 'https://example.com/payment/complete',
    'cancelUrl' => 'https://example.com/payment/cancel',
    'transactionId' => 'ORDER-456',
    'description' => 'Premium subscription',
    'brandName' => 'My Store',
    'locale' => 'en-US',
    'landingPage' => 'LOGIN',
    'userAction' => 'PAY_NOW',
])->send();

// 3. Redirect customer to PayPal
if ($response->isRedirect()) {
    // Store order ID in session
    $_SESSION['paypal_order_id'] = $response->getTransactionReference();
    
    header('Location: ' . $response->getRedirectUrl());
    exit;
}

// 4. On return URL, capture the payment
$orderId = $_SESSION['paypal_order_id'];

$captureResponse = $gateway->capture([
    'transactionReference' => $orderId,
])->send();

if ($captureResponse->isSuccessful()) {
    // Payment successful!
    $captureId = $captureResponse->getCaptureId();
    
    // Store capture ID for potential refunds
    // Update order status
    // Send confirmation email
} else {
    // Handle error
    $error = $captureResponse->getMessage();
}

Response Methods

All responses support these methods:

Method Description
isSuccessful() Whether the request was successful
isRedirect() Whether a redirect is required
getRedirectUrl() The PayPal approval URL
getTransactionReference() Order ID or Refund ID
getAuthorizationId() Authorization ID (after authorize)
getCaptureId() Capture ID (after capture)
getMessage() Error message if failed
getCode() Status code (CREATED, COMPLETED, etc.)
getHttpStatus() PayPal HTTP response status
getDebugId() PayPal diagnostic debug ID
getDetails() Structured PayPal error details
getIssues() PayPal issue codes
isWebhookSignatureValid() Whether PayPal verified a REST webhook
getData() Full response data array

Sandbox Testing

  1. Create sandbox accounts at PayPal Developer Dashboard
  2. Use sandbox credentials with setTestMode(true)
  3. Test with sandbox buyer accounts

Support

If you have any questions or issues, please open an issue on GitHub.

License

This package is open-sourced software licensed under the MIT license.