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

Sdk Core Php Laravel Package

paypal/sdk-core-php

Core PHP library for PayPal SDKs, providing shared utilities, HTTP client abstractions, credential handling, and common infrastructure used by PayPal REST API integrations to build payments, orders, and related API calls in PHP applications.

View on GitHub
Deep Wiki
Context7

Getting Started

What this package actually is. paypal/sdk-core-php is the shared foundation underneath PayPal's classic SDKs (paypal/merchant-sdk-php, adaptivepayments-sdk-php, adaptiveaccounts-sdk-php, permissions-sdk-php, invoice-sdk-php). It ships the config loader, credential model, HTTP transport, XML serialization envelope, logging, and the IPN validator. You rarely install it deliberately — it arrives as a transitive dependency — but two things in it are legitimately useful on their own: PPIPNMessage and PPAPIService.

Minimal steps

composer require paypal/sdk-core-php
  1. Create sdk_config.ini (see below) and point the SDK at it.
  2. Resolve credentials through PPCredentialManager.
  3. Either validate an IPN, or dispatch a request through a concrete SDK service.

Look here first, in this order

Class Why you care
PPConfigManager Singleton over sdk_config.ini; getInstance()->get('mode'), get('acct1.UserName')
PPCredentialManager Turns config keys into PPSignatureCredential / PPCertificateCredential objects
PPAPIService The request dispatcher every concrete SDK service delegates to
PPConnection / PPHttpConnection The cURL layer — your mock seam and your timeout/proxy seam
PPXmlMessage Base envelope: toXMLString(), __toString(), nested-object marshalling
PPIPNMessage Standalone IPN post-back validator
PPLoggingManager File logger driven by the log.* config keys

First use case — IPN validation without the merchant SDK. This is the highest-value direct use, and it fits a Laravel webhook controller cleanly:

use PPIPNMessage;
use PPConfigManager;

Route::post('/webhooks/paypal', function (Request $request) {
    PPConfigManager::getInstance()->setConfigFile(base_path('sdk_config.ini'));

    $ipn = new PPIPNMessage($request->getContent(), 'sandbox');
    if (! $ipn->validate()) {
        abort(400);
    }

    // $ipn->getData() / $ipn->getData('txn_id')
    return response('OK');
});

Config file shape (copy from the repo's sdk_config.ini sample and edit):

[Sandbox]
acct1.UserName  = facilitator_api1.example.com
acct1.Password  = XXXX
acct1.Signature = XXXX
acct1.AppId     = APP-80W284485P519543T
acct1.ServiceName = PayPalAPI

http.ConnectionTimeOut = 30
http.Retry = 1

log.LogEnabled = true
log.FileName   = /absolute/path/to/storage/logs/paypal.log
log.LogLevel   = INFO

[Live]
; same keys, live credentials

Implementation Patterns

Config-driven mode switching. Keep one sdk_config.ini with [Sandbox] and [Live] sections, and select via PPConfigManager::getInstance()->get('mode'). In Laravel, bind the resolved mode from config('services.paypal.mode') in a service provider rather than hardcoding the 'sandbox' argument at call sites.

Credential construction. Never hand-build credentials; let the manager do it so certificate vs. signature is decided by which keys exist:

$creds = PPCredentialManager::getInstance()->getCredentials(['acct1']);
// returns PPSignatureCredential or PPCertificateCredential

Third-party / subject authorization. For calls on behalf of a merchant, attach a PPSubjectAuthorization to the credential:

$auth = new PPSubjectAuthorization();
$auth->setSubject('[email protected]');
$creds->setThirdPartyAuthorization($auth);

PPThirdPartyAuthorization is the abstract parent — you can subclass it if you need token-based delegation instead of a plain subject.

Dispatching a call through a classic SDK. Concrete services (e.g. PayPalAPIInterfaceServiceService) are thin: they build a PPXmlMessage subclass and pass it to PPAPIService::makeRequest($request, $serviceName, $handlers, $apiName). Pattern is always the same:

$service  = new PayPalAPIInterfaceServiceService($config);
$request  = new SetExpressCheckoutRequestType();
// ... populate ...
$response = $service->SetExpressCheckout($request);
if (strtoupper($response->Ack) !== 'SUCCESS') { /* handle */ }

Custom endpoints / operations not covered by a shipped SDK. Subclass PPXmlMessage for the request, mirror the response shape into a plain class, then call PPAPIService directly with your own $apiName. This is how the community added operations PayPal never published a wrapper for.

Transport substitution. For tests, swap PPHttpConnection for a subclass whose execute($data) returns a canned XML body. Everything above it (PPAPIService, response hydration) is unaware, so you get full round-trip coverage without network calls.

Logging integration. PPLoggingManager::getInstance(__CLASS__) gives you info(), warn(), error(), fine(), filtered by log.LogLevel. In Laravel, point log.FileName at storage_path('logs/paypal.log') and let logrotate handle it; don't try to bridge it into Monolog, the singleton doesn't accept a PSR-3 handler.

Retry and proxy. http.Retry, http.ConnectionTimeOut, and the http.Proxy.* keys are read per-request from PPConfigManager. If you need per-tenant proxies, override the config file path in a middleware before the singleton is first resolved — after that it's cached for the process.

Gotchas and Tips

Global namespace, no PSR-4 root. The classes live in the global namespace (PPAPIService, PPConnection, PPIpNMessage…). Anything importing them pollutes your autoload map with unprefixed names. Only load this package in the process that actually needs it, and never use a PP* class in a file that also ships a same-named helper.

Deprecation status is real. PayPal has sunset these classic NVP/SOAP SDKs; there has been no meaningful release in years. For new work, prefer the REST APIs and the current Checkout SDKs. Treat this package as a maintenance liability: it is fine for existing merchant/adaptive integrations and IPN validation, and a bad choice for greenfield. The zero stars / zero direct dependents is a signal that virtually nobody consumes it as a first-class dependency — it lives only downstream.

PHP 8 friction. Expect breakage on modern PHP:

  • cURL handle type checks written against resource fail when CurlHandle objects are returned.
  • Dynamic property creation on response DTOs is deprecated — hydration of unknown <...> nodes emits notices.
  • Older releases use each(), create_function(), and reflection patterns that are gone in 8.x.
  • Pin to the newest 2.x tag you can find and audit the transport class before upgrading PHP.

sdk_config.ini resolution is the #1 source of "why is it using sandbox?" The default path is derived from the package's own directory, not your project root. A copy that's one directory off silently falls back to defaults. Always verify:

PPConfigManager::getInstance()->setConfigFile(base_path('sdk_config.ini'));
$pcm = PPConfigManager::getInstance();
dd($pcm->get('mode'), $pcm->get('acct1.UserName'));

The singleton caches on first read, so call setConfigFile() before any credential or connection object is constructed.

Empty-string vs. missing keys. PPCredentialManager decides signature-vs-certificate by key presence. An acct1.CertPath = line with no value counts as present in some parser paths and produces a PPInvalidCredentialException that reads like a path error. Delete unused keys entirely rather than blanking them.

Errors are exceptions, not return codes. PPConnectionException (network/HTTP), PPInvalidCredentialException, and PPTransformerException (XML parse) are the three to catch. PPConnectionException carries getUrl() and getData() — log both, because PayPal's SOAP faults come back in the body with a 200 or 500 status depending on transport error, and the message alone is uninformative.

TLS. Current PayPal requires TLS 1.2+. Very old versions of the transport set CURLOPT_SSLVERSION in ways that can pin you below it. If you see handshake failures on a box with a modern OpenSSL, override PPHttpConnection and explicitly set CURLOPT_SSLVERSION => CURL_SSLVERSION_TLSv1_2.

Response objects are dumb containers. $response->Ack is a string you must strtoupper() and compare to 'SUCCESS' / 'SUCCESSWITHWARNING'. SUCCESSWITHWARNING still means the operation succeeded — treating it as failure is a classic bug. Field names are case-sensitive XML node names, so a null where you expect data usually means the camelCase assumption was wrong.

Retries are not idempotent-safe. http.Retry > 1 will re-POST DoCapture/DoAuthorization on timeout, which can double-charge or double-capture. Leave retry at 0 or 1 and implement idempotency at the application layer with your own request keys.

IPN specifics. PPIPNMessage::validate() posts the raw body back to PayPal — it needs outbound HTTPS and will fail silently-ish behind a restrictive egress firewall (you'll get false, not an exception). Also, the constructor's second argument takes the mode string, not a boolean; passing true puts you in an undefined config section. Read the raw body from $request->getContent(), not from $_POST — re-encoding loses the original ordering and the signature check is byte-sensitive.

Extension points that actually hold up: subclass PPConnection/PPHttpConnection (transport, retries, TLS, mocking), subclass PPXmlMessage (new request envelopes), and subclass PPThirdPartyAuthorization (auth schemes). Avoid monkey-patching PPAPIService internals — the private $config/$connection fields and their initialization order vary between 2.x point releases.

Where to look when something breaks. Turn log.LogLevel = FINE and read the raw request/response XML in the log file; it contains the un-escaped SOAP envelope, which is the fastest way to confirm whether a bad field or a bad credential is at fault. Set it back to INFO afterwards — FINE dumps credentials in cleartext.

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.
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource