Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Merchant Sdk Php Laravel Package

paypal/merchant-sdk-php

PayPal's classic Merchant SDK for PHP lets you integrate Express Checkout, Payments Pro, Adaptive Payments, and related APIs using generated service classes. Best suited to legacy integrations, as PayPal now recommends the newer REST SDKs.

Deep Wiki
Context7

Getting Started

Treat this as a legacy-maintenance package, not a greenfield choice. The repository is archived, the last release was 2017, and it targets the classic SOAP/NVP PayPal APIs. If you are maintaining an existing Express Checkout or Payments Pro integration, start here; if you are building new checkout, use PayPal Orders v2 REST or a maintained gateway instead.

Minimal setup

composer require paypal/merchant-sdk-php

If Composer refuses due to old platform constraints, do not blindly use --ignore-platform-reqs in production. Prefer pinning the application to PHP 7.4 in a legacy branch, or fork/vendor the package with tested compatibility patches.

Provide credentials either through sdk_config.ini or a config array passed to the service. In Laravel, keep credentials in config/services.php and resolve them through a wrapper service, not with env() calls scattered through controllers.

// config/services.php
'paypal_merchant' => [
    'mode' => env('PAYPAL_MODE', 'sandbox'),
    'username' => env('PAYPAL_API_USERNAME'),
    'password' => env('PAYPAL_API_PASSWORD'),
    'signature' => env('PAYPAL_API_SIGNATURE'),
    'app_id' => env('PAYPAL_APP_ID'),
],
use PayPal\Service\PayPalAPIInterfaceServiceService;

$service = new PayPalAPIInterfaceServiceService([
    'mode' => config('services.paypal_merchant.mode'),
    'acct1.UserName' => config('services.paypal_merchant.username'),
    'acct1.Password' => config('services.paypal_merchant.password'),
    'acct1.Signature' => config('services.paypal_merchant.signature'),
    'acct1.AppId' => config('services.paypal_merchant.app_id'),
    'service.EndPoint' => config('services.paypal_merchant.mode') === 'live'
        ? 'https://api-3t.paypal.com/2.0/'
        : 'https://api-3t.sandbox.paypal.com/2.0/',
]);

If using sdk_config.ini, define PP_CONFIG_PATH before the SDK reads it and ensure the file is deployed outside the public web root.

Where to look first

  • samples/ in the package: the fastest way to see request/response object construction.
  • Generated request classes under PayPal\PayPalAPI\* and request-detail classes under PayPal\EBLBaseComponents\*.
  • The service class PayPalAPIInterfaceServiceService: each API call is a method such as SetExpressCheckout, GetExpressCheckoutDetails, DoExpressCheckoutPayment, DoDirectPayment, RefundTransaction.
  • PayPal’s classic API error-code documentation: responses come back with Ack and Errors, not exceptions, for normal business failures.

First use case: Express Checkout sale

use PayPal\Core\BasicAmountType;
use PayPal\EBLBaseComponents\PaymentDetailsType;
use PayPal\EBLBaseComponents\SetExpressCheckoutRequestDetailsType;
use PayPal\PayPalAPI\SetExpressCheckoutReq;
use PayPal\PayPalAPI\SetExpressCheckoutRequestType;

$details = new SetExpressCheckoutRequestDetailsType();
$details->ReturnURL = route('paypal.return');
$details->CancelURL = route('paypal.cancel');
$details->PaymentAction = 'Sale';
$details->SolutionType = 'Sole';

$payment = new PaymentDetailsType();
$payment->OrderTotal = new BasicAmountType('USD', '49.00');
$details->PaymentDetails = [$payment];

$request = new SetExpressCheckoutReq();
$request->SetExpressCheckoutRequest = new SetExpressCheckoutRequestType($details);

$response = $service->SetExpressCheckout($request);

if (!in_array($response->Ack, ['Success', 'SuccessWithWarning'], true)) {
    // inspect $response->Errors
}

$token = $response->Token;
// Persist token and order before redirecting.
return redirect('https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=' . urlencode($token));

Implementation Patterns

Wrap the SDK behind an application service. Do not let controllers build nested PayPal request objects. Create an adapter such as App\Services\PayPalMerchantGateway with methods like startExpressCheckout(Order $order), completeExpressCheckout(string $token, string $payerId), refund(Transaction $txn), and capture(Authorization $auth). This keeps test doubles possible and centralizes credential, endpoint, and error handling.

Persist state before and after every PayPal call. A practical Express Checkout flow is:

  1. Create a local order/payment record with status = pending.
  2. Call SetExpressCheckout, save token, set status = redirected.
  3. Redirect to PayPal using the sandbox or live redirect URL matching the endpoint.
  4. On return, validate the token against the stored record and session.
  5. Call GetExpressCheckoutDetails to obtain PayerID and payer info; do not trust query-string data alone.
  6. Call DoExpressCheckoutPayment with the same token, payer ID, amount, and currency.
  7. Save TransactionID, PaymentStatus, and response payload; set status = paid only after a successful Ack.
  8. Send order confirmation and trigger fulfillment.

Use Authorization + Capture for delayed fulfillment. Set PaymentAction = 'Authorization' on SetExpressCheckout, then call DoCapture later with the AuthorizationID. Use DoVoid to release an authorization. Use Sale only when you capture immediately.

Refunds and partial refunds. Use RefundTransactionReq; for a full refund set RefundType = 'Full', for partial set RefundType = 'Partial' plus Amount. Store every refund transaction ID separately and update local payment state idempotently.

Recurring payments. Use CreateRecurringPaymentsProfileReq with billing frequency, billing period, profile start date, and amount. Store the profile ID. Use ManageRecurringPaymentsProfileStatus for suspend/cancel/reactivate, and reconcile profile status through GetRecurringPaymentsProfileDetails.

IPN or reconciliation job. Classic APIs are asynchronous in places. For Express Checkout, DoExpressCheckoutPayment gives the immediate result, but IPN messages can still arrive. Implement a verified IPN endpoint:

  • Post the raw body back to PayPal with cmd=_notify-validate.
  • Verify payment_status, receiver_email, mc_gross, mc_currency, and txn_id.
  • Enforce a unique constraint on txn_id so duplicate IPNs are harmless.
  • Only fulfill after validation succeeds.

For missed IPNs, add a scheduled reconciliation job using GetTransactionDetails or TransactionSearch.

Payments Pro direct card flow. DoDirectPaymentReq accepts card details, payer info, and payment details. This puts your application in PCI scope. In practice, do not log CreditCardDetailsType, do not store raw card numbers, and prefer hosted fields or a modern tokenized gateway if possible. If you must use it, mask all card data before logging exceptions or request dumps.

Laravel integration tips. Bind the configured gateway as a singleton or scoped service. Store PayPal request/response payloads in a paypal_transactions table with columns for token, payer ID, transaction ID, status, amount, currency, and raw error JSON. Use database transactions and row locks around payment state transitions, not around the remote PayPal call itself.

Testing. There is no useful HTTP mocking layer in this SDK; it uses its own cURL wrapper. Mock your gateway adapter in unit tests. For integration tests, use PayPal sandbox business and buyer accounts. Test success, cancellation, declined card, amount mismatch, duplicate invoice, refund, and timeout/retry paths.

Gotchas and Tips

This package is archived and unmaintained. Do not start new work with it. There are no security patches, and PHP 8 compatibility is not guaranteed. Expect dynamic-property deprecations, old cURL assumptions, and generated classes that rely on public properties rather than modern typed APIs. If you must run it on PHP 8, patch and test a fork; do not suppress all errors globally.

Ack is not a boolean. Check for both Success and SuccessWithWarning. Business errors arrive in $response->Errors, which may be a single object or an array depending on the response. Normalize it before mapping to user-facing messages.

Sandbox/live endpoint and redirect URL must match. A common failure is calling the live API but redirecting to sandbox.paypal.com, or vice versa. Assert the endpoint in your gateway constructor and derive the redirect base URL from the same mode setting.

Amounts must match across Express Checkout steps. The amount and currency in DoExpressCheckoutPayment should match what was set in SetExpressCheckout. If the cart total changes, restart the Express Checkout flow rather than changing only the final request.

ReturnURL and CancelURL must be absolute, publicly reachable URLs. Localhost often works poorly in sandbox testing; use a tunnel or staging domain. Live URLs should be HTTPS.

Validate the return token. On the return route, compare the token query parameter with the token stored for the current order or session. Then call GetExpressCheckoutDetails; never treat the return URL alone as proof of payment.

Use string amounts with two decimals. Construct BasicAmountType values like new BasicAmountType('USD', '49.00'). Avoid floats and localized decimal separators.

Duplicate charges are your responsibility. The classic API does not provide a modern idempotency key. Use a unique local payment attempt, a unique invoice ID, database state guards, and reconciliation through GetTransactionDetails. Do not blindly retry DoExpressCheckoutPayment after a timeout until you have checked whether the transaction already exists.

TLS and CA configuration can break the SDK. PayPal requires modern TLS. If cURL calls fail, verify curl.cainfo, the system CA bundle, and the SDK’s HTTP configuration. Do not disable certificate verification to “make it work.”

Logging is dangerous here. Enable SDK logging only with redaction. Requests for DoDirectPayment and recurring profiles can contain card data. Log token, transaction ID, Ack, error code, and correlation data instead.

sdk_config.ini quirks. Values containing special characters may need quoting. Confirm the expected environment section and keys for your installed version (acct1.UserName, acct1.Password, acct1.Signature, acct1.AppId, service.EndPoint). If PP_CONFIG_PATH is unset or wrong, credentials silently come from defaults or fail at call time.

Laravel config caching. Do not call env() inside your gateway after php artisan config:cache. Put credentials in config/services.php and read them through config().

Adaptive Payments is a separate/retired concern. This package is primarily used for Express Checkout and Payments Pro. Confirm the classes you need actually exist in your installed version; do not assume the description’s Adaptive Payments mention means the API is usable for new integrations. Adaptive Payments has been retired by PayPal.

Extension points are limited but usable. Wrapper services, service subclassing for logging/metrics, and custom HTTP/cURL configuration are the practical extension points. There is no clean middleware pipeline. Keep all PayPal-specific code in one adapter and keep domain logic outside it.

Migration path. For new features, isolate the legacy gateway behind an interface and plan a move to PayPal Orders v2 REST or another maintained provider. Run both paths in parallel behind feature flags if you need a gradual migration.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource