BlazorBasics.PayPal 1.0.2

dotnet add package BlazorBasics.PayPal --version 1.0.2
                    
NuGet\Install-Package BlazorBasics.PayPal -Version 1.0.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="BlazorBasics.PayPal" Version="1.0.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="BlazorBasics.PayPal" Version="1.0.2" />
                    
Directory.Packages.props
<PackageReference Include="BlazorBasics.PayPal" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add BlazorBasics.PayPal --version 1.0.2
                    
#r "nuget: BlazorBasics.PayPal, 1.0.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package BlazorBasics.PayPal@1.0.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=BlazorBasics.PayPal&version=1.0.2
                    
Install as a Cake Addin
#tool nuget:?package=BlazorBasics.PayPal&version=1.0.2
                    
Install as a Cake Tool

Nuget Nuget

BlazorBasics.PayPal

A Blazor component library that integrates the PayPal JavaScript SDK to render a PayPal checkout button with full cart support, currency handling, and transaction callbacks.


Table of Contents


Installation

Install the NuGet package:

dotnet add package BlazorBasics.PayPal

Setup

Register the JS interop in your index.html (or App.razor host page). The component automatically loads JS module import — no additional script tag is required.


Usage

Add the PaypalButton component to any Blazor page or component:

<PaypalButton
    MerchantId="YOUR_PAYPAL_CLIENT_ID"
    CalculateTotalToPay="GetTotals"
    GetProducts="GetCartProducts"
    OnApproved="HandleApproved"
    OnCancel="HandleCancel"
    OnTransactionError="HandleError"
    OnLoad="HandleLoad" />

Parameters

Parameter Type Required Description
MerchantId string Yes Your PayPal client/merchant ID.
CalculateTotalToPay Func<Task<CartTotals>> Yes Async function that returns the cart totals (total, tax, shipping, etc.).
GetProducts Func<Task<IEnumerable<PaypalProduct>>> Yes Async function that returns the list of products in the cart.
ButtonId string No Custom HTML element ID for the PayPal button container. Defaults to #PayPalButton.
EnableDebugMode bool No Enables PayPal SDK debug logging. Defaults to false.
SetDescription Func<Task<string>> No Async function that returns a custom transaction description. Defaults to "Shop".
OnLoad EventCallback No Fired when the PayPal button finishes loading successfully.
OnApproved EventCallback<PaypalTransaction> No Fired when the buyer approves the transaction. Receives a PaypalTransaction with totals and raw data.
OnCancel EventCallback No Fired when the buyer cancels the payment flow.
OnTransactionError EventCallback No Fired when PayPal reports an error during the transaction.

Models

CartTotals

Represents the full breakdown of cart amounts passed to PayPal.

public class CartTotals
{
    public Money Total { get; set; }
    public Money Discounts { get; set; }
    public Money Shipping { get; set; }
    public Money Tax { get; set; }
    public Money Handling { get; set; }
    public Money Insurance { get; set; }
}

Constructor:

new CartTotals(
    total: new Money(100.00m, "USD"),
    discounts: new Money(5.00m, "USD"),
    shipping: new Money(10.00m, "USD"),
    tax: new Money(8.50m, "USD")
)

All optional fields default to Money(0, total.Currency) if not provided.


PaypalProduct

Represents a single line item in the PayPal order. Property names are serialized as lowercase JSON to match PayPal SDK expectations.

Property Type Default Description
Name string Product display name.
Description string Product description.
Quantity double 1 Quantity. Supports decimals using . as separator.
Price decimal 0 Unit price. Supports decimals using . as separator.
Tax decimal 0 Tax applied to this product.
Sku string Guid.NewGuid() Product code / SKU. Auto-generated if not set.
Currency string ISO currency code (e.g. USD, EUR).

PaypalTransaction

Returned in the OnApproved callback. Contains the computed total and the raw PayPal response.

public class PaypalTransaction
{
    public string Id { get; set; }           // PayPal order ID (or generated fallback)
    public Money Total { get; set; }         // Computed total from purchase units
    public ApproveData TransactionData { get; set; } // Raw PayPal approve data
}

If PayPal does not return a transaction ID, a fallback ID is generated in the format PAYPAL-YYYYMMDD-XXXXXXXX.


Money

A value object representing a monetary amount with currency. Supports arithmetic and comparison operators.

Money price = new Money(49.99m, "USD");
Money tax   = new Money(4.50m, "USD");
Money total = price + tax; // Money(54.49, "USD")

Supported operators: +, -, *, /, %, ++, --, ==, !=, <, >, <=, >=

Implicit cast to decimal:

decimal value = price; // 49.99

Currency conversion (requires ICurrencyConvertion):

Money converted = await price.TotalMoneyToCurrency(conversionService, "EUR");

Arithmetic and comparison operations between Money instances require matching currencies. A mismatch throws InvalidOperationException.


Interfaces

ICurrencyConvertion

Implement this interface to provide currency conversion support for Money.TotalMoneyToCurrency.

public interface ICurrencyConvertion
{
    Task<Money> ConvertToCurrency(Money originCurrency, string destinationCurrency);
    Task<string> GetCurrency();
}

Register your implementation in DI:

builder.Services.AddScoped<ICurrencyConvertion, MyCurrencyService>();

Callbacks

OnApproved

Receives a PaypalTransaction with the computed total across all purchase units. Currencies are validated — if multiple currencies are detected within the same order, only the first currency is used and mismatched values are ignored (a warning is printed to the console).

private async Task HandleApproved(PaypalTransaction transaction)
{
    Console.WriteLine($"Payment approved: {transaction.Id}");
    Console.WriteLine($"Total: {transaction.Total}"); // e.g. "54.49 USD"
}

OnCancel

private async Task HandleCancel()
{
    Console.WriteLine("Payment cancelled by user.");
}

OnTransactionError

private async Task HandleError()
{
    Console.WriteLine("A PayPal error occurred.");
}

Examples

Minimal setup

@code {
    private async Task<CartTotals> GetTotals()
    {
        return new CartTotals(new Money(29.99m, "USD"));
    }

    private async Task<IEnumerable<PaypalProduct>> GetCartProducts()
    {
        return new List<PaypalProduct>
        {
            new PaypalProduct
            {
                Name = "Basic Plan",
                Price = 29.99m,
                Currency = "USD"
            }
        };
    }

    private async Task HandleApproved(PaypalTransaction transaction)
    {
        // Save transaction.Id and transaction.Total to your backend
    }
}

<PaypalButton
    MerchantId="YOUR_PAYPAL_CLIENT_ID"
    CalculateTotalToPay="GetTotals"
    GetProducts="GetCartProducts"
    OnApproved="HandleApproved" />

With full cart breakdown and custom description

<PaypalButton
    MerchantId="YOUR_PAYPAL_CLIENT_ID"
    CalculateTotalToPay="GetTotals"
    GetProducts="GetCartProducts"
    SetDescription="GetDescription"
    EnableDebugMode="true"
    OnApproved="HandleApproved"
    OnCancel="HandleCancel"
    OnTransactionError="HandleError"
    OnLoad="HandleLoad" />

@code {
    private async Task<string> GetDescription() => "My Store - Order #1042";

    private async Task<CartTotals> GetTotals()
    {
        return new CartTotals(
            total:     new Money(113.49m, "USD"),
            discounts: new Money(10.00m,  "USD"),
            shipping:  new Money(5.00m,   "USD"),
            tax:       new Money(8.50m,   "USD"),
            handling:  new Money(0.00m,   "USD"),
            insurance: new Money(0.00m,   "USD")
        );
    }

    private async Task<IEnumerable<PaypalProduct>> GetCartProducts()
    {
        return new List<PaypalProduct>
        {
            new PaypalProduct { Name = "Widget A", Price = 60.00m, Quantity = 1, Currency = "USD" },
            new PaypalProduct { Name = "Widget B", Price = 50.00m, Quantity = 1, Currency = "USD" }
        };
    }

    private async Task HandleApproved(PaypalTransaction t) => Console.WriteLine(t.Id);
    private async Task HandleCancel()                       => Console.WriteLine("Cancelled");
    private async Task HandleError()                        => Console.WriteLine("Error");
    private async Task HandleLoad()                         => Console.WriteLine("Button loaded");
}

License

MIT

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.2 219 3/7/2026
1.0.1 104 3/7/2026
1.0.0 102 3/7/2026

Version 1.0.2: Fixed a name space.
Version 1.0.1: Fixed Repository Url and Packge project url.
Version 1.0.0: First release.