Skip to content

v3.1.0 - PSR-18, local webhooks, Fastlane, and 20+ fixes

Choose a tag to compare

@bashgeek bashgeek released this 16 Apr 04:47
29d2122

New maintainership

Starting with v3.1, Blendbyte is taking over active maintenance of srmklive/paypal. We're a cloud infrastructure and software development company that builds and operates Laravel applications for our own products and for clients. This package has been a dependency in our stack for years across dozens of projects, so when the opportunity came up to take over maintainership we didn't think twice. We're stoked to give it the attention it deserves.

A huge thank you to @srmklive for building and maintaining this package across 110+ releases and nearly 4 million Packagist installs. His work gave the Laravel ecosystem a reliable PayPal integration for years, and we're grateful for the trust he's placed in us to carry it forward. He'll stay on as a contributor.


Highlights

This release is fully backward-compatible with v3.0. No API changes, no removed methods, no migration needed. If your project runs on PHP 8.2+ and Laravel 12, composer update picks this up automatically.

Platform support

  • PHP 8.2 through 8.5 (aligned with Laravel 12's own floor; PHP 8.2 is in security support until Dec 2026)
  • Laravel 12 and 13
  • Standalone usage without Laravel: pass credentials directly to setApiCredentials(), no service provider needed

New features

  • PSR-18 HTTP client support. Swap Guzzle for any compliant client via setClient().
  • Configurable timeouts and retry. New timeout, connect_timeout, max_retries config keys with exponential backoff on 5xx and network errors.
  • Exception-based error handling. Call withExceptions() to get PayPalApiException with getHttpStatus() and getPayPalError() instead of error arrays. Fully opt-in, existing code keeps working.
  • Local webhook verification. verifyWebHookLocally() does in-memory RSA-SHA256 with cert caching. No PayPal API roundtrip, SSRF-guarded cert URL validation.
  • PayPal Fastlane. generateClientToken() for one-click guest checkout flows.
  • Vault v3 complete. deletePaymentSetupToken(), setCustomerId(), full setup and permanent token lifecycle.
  • Apple Pay, Google Pay, and ACDC card helpers. setPaymentSourceApplePay(), setPaymentSourceGooglePay(), setCardBillingAddress(), setCardVaulting(), setCardVerification().
  • getCaptureIdFromOrder(). Extract the capture/transaction ID from order responses in one call.
  • createOrderWithPaymentSource(). Create orders with an attached payment source directly.
  • sendDisputeMessage(). Send messages in dispute conversations.
  • withIdempotencyKey(). Set idempotency keys for safe request retries.
  • setShippingAddressChangeCallback(). Server-side shipping callbacks for Orders v2.

Bug fixes

  • Monetary amounts now serialize as 2-decimal strings, preventing float noise like 49.990000000000002
  • generateInvoiceNumber() sends an empty JSON body to prevent 415 Unsupported Media Type from PayPal
  • Moved experience_context from deprecated application_context to payment_source.paypal.experience_context
  • Aligned setStoredPaymentSource() with PayPal's Feb 2025 API change (usage renamed to usage_pattern)
  • Removed sanctioned currency (RUB) from currency list, sorted alphabetically, improved error messages
  • validate_ssl=false was silently ignored because empty() treated false as empty
  • listTrackingDetails(), listUsers() SCIM filter, and query params now properly URL-encoded
  • addInvoiceFilterByDateRange() normalizes dates to Y-m-d
  • verifyIPN() and json_decode results properly guarded against null
  • previous_network_transaction_reference strips null values instead of sending them to PayPal
  • Fixed stray leading slash in provideDisputeEvidence() endpoint; acceptDisputeClaim() no longer overwrites caller's accept_claim_type
  • listPaymentSourceTokens() throws RuntimeException when called without a customer ID
  • Local webhook verification retries on certificate fetch failure
  • makeHttpRequest() no longer drops auth and form_params on the PSR-18 code path

Code quality

  • 100% test coverage with Pest v4 and PHPUnit 12
  • PHPStan level 8
  • Laravel Pint formatting across the entire codebase
  • PHP 8.2 through 8.5 CI matrix via GitHub Actions
  • Removed dead code, unused Docker files, and legacy CI configs
  • Replaced collect() and Illuminate\Support\Str calls with native PHP where possible
  • Deprecated PaymentExperienceWebProfiles (PayPal deprecated /v1/payment-experience/web-profiles)
  • Dropped ext-curl hard requirement

Upgrading from v3.0

composer require srmklive/paypal:^3.1

No code changes needed. All existing method signatures and return types are preserved. The three new config keys (timeout, connect_timeout, max_retries) have sensible defaults and are fully optional. Your existing config/paypal.php works as-is.