Skip to content

Migrate PayPal Commerce plugin from custom HTTP client to official PayPal Server SDK #8185

Description

@aliraza1231

Summary

The Nop.Plugin.Payments.PayPalCommerce plugin currently uses a custom HttpClient-based implementation to interact with PayPal REST APIs. This involves manually constructing HTTP requests, handling OAuth2 authentication, serializing/deserializing JSON payloads, and parsing error responses.

PayPal now provides an official .NET SDK (PayPalServerSDK) that handles all of this out of the box. Migrating to the official SDK would improve maintainability, security, and alignment with PayPal's recommended best practices.

Motivation

  • Maintainability: The current implementation manually builds HTTP requests, manages access tokens, and parses error responses. The official SDK abstracts all of this, reducing the surface area for bugs.
  • Security: The SDK handles OAuth2 client credentials flow internally, eliminating the need to manually manage and cache access tokens.
  • Alignment with PayPal best practices: Using the official SDK ensures the plugin stays compatible with PayPal API changes and follows their recommended integration patterns.
  • Reduced code complexity: Error handling, request serialization, and authentication are all managed by the SDK.

Proposed Changes

Architecture

Use an adapter pattern inside PayPalCommerceHttpClient to route supported operations through the official SDK while preserving the existing RequestAsync<TRequest, TResponse> interface. This ensures zero changes are needed in PayPalCommerceServiceManager (~3700 lines) or any other consumers.

SDK-Routed Operations

  • Orders: Create, Get, Patch, Authorize, Capture, Tracking
  • Payments: Capture Authorization, Void, Refund
  • Vault: Create Setup Token, Create/Get/List/Delete Payment Tokens

HTTP-Fallback Operations (not available in the SDK)

  • Webhooks (create, list, delete, verify signature)
  • Identity/Access Tokens
  • Onboarding Credentials

Files to Change

File Change
Nop.Plugin.Payments.PayPalCommerce.csproj Add PayPalServerSDK v2.0.0 NuGet package, enable CopyLocalLockFileAssemblies
Services/PayPalSdkClientFactory.cs New file — thread-safe factory that caches PaypalServerSdkClient instances per credential/environment
Services/PayPalCommerceHttpClient.cs Rewrite as adapter — route supported request types through SDK, fall back to direct HTTP for the rest
Infrastructure/NopStartup.cs Register PayPalSdkClientFactory as singleton; remove PayPal SDK assembly from MVC ApplicationPartManager to prevent Autofac conflicts

Important: Autofac Compatibility

The PayPal SDK assembly contains types named BaseController, OrdersController, PaymentsController, etc. NopCommerce loads all plugin reference DLLs as MVC ApplicationPart entries. When AddControllersAsServices() runs, MVC's naming convention discovers these SDK types and Autofac attempts to register them — but BaseController only has an internal constructor, causing a NoConstructorsFoundException at startup.

The fix is to remove the PayPalServerSDK assembly from ApplicationPartManager.ApplicationParts in the plugin's NopStartup.ConfigureServices, which runs before AddControllersAsServices.

Model Conversion Approach

Both the internal plugin models and the SDK models use Newtonsoft.Json with [JsonProperty] attributes that map to the same PayPal REST API JSON schema. This enables a reliable JSON round-trip conversion (serialize internal model → JSON → deserialize to SDK model, and vice versa) without needing explicit property-by-property mapping code.

Acceptance Criteria

  • All existing PayPal Commerce plugin functionality works as before (orders, payments, refunds, vaulting, tracking, webhooks)
  • Supported operations use the official PayPal Server SDK instead of raw HTTP calls
  • Unsupported operations (webhooks, identity tokens, onboarding) continue working via direct HTTP
  • Application starts without Autofac errors
  • Solution builds with zero compilation errors

Metadata

Metadata

Assignees

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions