BlazorBasics.PayPal
1.0.2
dotnet add package BlazorBasics.PayPal --version 1.0.2
NuGet\Install-Package BlazorBasics.PayPal -Version 1.0.2
<PackageReference Include="BlazorBasics.PayPal" Version="1.0.2" />
<PackageVersion Include="BlazorBasics.PayPal" Version="1.0.2" />
<PackageReference Include="BlazorBasics.PayPal" />
paket add BlazorBasics.PayPal --version 1.0.2
#r "nuget: BlazorBasics.PayPal, 1.0.2"
#:package BlazorBasics.PayPal@1.0.2
#addin nuget:?package=BlazorBasics.PayPal&version=1.0.2
#tool nuget:?package=BlazorBasics.PayPal&version=1.0.2
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
Moneyinstances require matching currencies. A mismatch throwsInvalidOperationException.
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 | Versions 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. |
-
net10.0
- Microsoft.AspNetCore.Components.Web (>= 10.0.3)
-
net9.0
- Microsoft.AspNetCore.Components.Web (>= 9.0.13)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
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.