littleshop/LittleShop.Client/README.md
sysadmin 1f7c0af497 Add LittleShop.Client SDK library with complete API wrapper
Features:
- Complete .NET client SDK for LittleShop API
- JWT authentication with automatic token management
- Catalog service for products and categories
- Order service with payment creation
- Retry policies using Polly for resilience
- Error handling middleware
- Dependency injection support
- Comprehensive documentation and examples

SDK Components:
- Authentication service with token refresh
- Strongly-typed models for all API responses
- HTTP handlers for retry and error handling
- Extension methods for easy DI registration
- Example console application demonstrating usage

Test Updates:
- Fixed test compilation errors
- Updated test data builders for new models
- Corrected service constructor dependencies
- Fixed enum value changes (PaymentStatus, OrderStatus)

Documentation:
- Complete project README with features and usage
- Client SDK README with detailed examples
- API endpoint documentation
- Security considerations
- Deployment guidelines

Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-20 18:15:35 +01:00

373 lines
9.8 KiB
Markdown

# LittleShop Client SDK
A .NET client library for interacting with the LittleShop e-commerce API. This SDK provides a strongly-typed, easy-to-use interface for all LittleShop API endpoints with built-in authentication, retry policies, and error handling.
## Installation
Add the LittleShop.Client library to your project:
```bash
dotnet add reference ../LittleShop.Client/LittleShop.Client.csproj
```
Or via NuGet (when published):
```bash
dotnet add package LittleShop.Client
```
## Quick Start
### Basic Setup with Dependency Injection
```csharp
using LittleShop.Client.Extensions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
var host = Host.CreateDefaultBuilder(args)
.ConfigureServices((context, services) =>
{
// Add LittleShop client with configuration
services.AddLittleShopClient(options =>
{
options.BaseUrl = "https://localhost:5001";
options.TimeoutSeconds = 30;
options.MaxRetryAttempts = 3;
options.EnableLogging = true;
});
})
.Build();
// Get the client from DI
var client = host.Services.GetRequiredService<ILittleShopClient>();
```
### Simple Console Application Example
```csharp
using LittleShop.Client;
using LittleShop.Client.Extensions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
// Setup DI container
var services = new ServiceCollection();
services.AddLogging(builder => builder.AddConsole());
services.AddLittleShopClient("https://localhost:5001");
var serviceProvider = services.BuildServiceProvider();
var client = serviceProvider.GetRequiredService<ILittleShopClient>();
// Authenticate
var loginResult = await client.Authentication.LoginAsync("admin", "admin");
if (loginResult.IsSuccess)
{
Console.WriteLine($"Logged in as: {loginResult.Data.Username}");
Console.WriteLine($"Token expires: {loginResult.Data.ExpiresAt}");
}
// Get categories
var categoriesResult = await client.Catalog.GetCategoriesAsync();
if (categoriesResult.IsSuccess)
{
foreach (var category in categoriesResult.Data)
{
Console.WriteLine($"Category: {category.Name} - {category.Description}");
}
}
// Get products with filtering
var productsResult = await client.Catalog.GetProductsAsync(
pageNumber: 1,
pageSize: 10,
searchTerm: "wireless",
minPrice: 10,
maxPrice: 100
);
if (productsResult.IsSuccess)
{
Console.WriteLine($"Found {productsResult.Data.TotalCount} products");
foreach (var product in productsResult.Data.Items)
{
Console.WriteLine($"Product: {product.Name} - £{product.Price}");
}
}
```
## Authentication
The SDK handles JWT authentication automatically. Once you log in, the token is stored and automatically included in subsequent requests.
```csharp
// Login
var loginResult = await client.Authentication.LoginAsync("username", "password");
if (!loginResult.IsSuccess)
{
Console.WriteLine($"Login failed: {loginResult.ErrorMessage}");
return;
}
// Check if authenticated
if (client.Authentication.IsAuthenticated())
{
Console.WriteLine("User is authenticated");
}
// Get current token (if needed for external use)
var token = client.Authentication.GetToken();
// Logout
client.Authentication.Logout();
```
## Catalog Operations
### Get All Categories
```csharp
var result = await client.Catalog.GetCategoriesAsync();
if (result.IsSuccess)
{
foreach (var category in result.Data)
{
Console.WriteLine($"{category.Name}: {category.Description}");
}
}
```
### Get Products with Pagination and Filtering
```csharp
var result = await client.Catalog.GetProductsAsync(
pageNumber: 1,
pageSize: 20,
categoryId: categoryGuid, // Optional: Filter by category
searchTerm: "headphones", // Optional: Search term
minPrice: 50, // Optional: Minimum price
maxPrice: 200 // Optional: Maximum price
);
if (result.IsSuccess)
{
Console.WriteLine($"Page {result.Data.PageNumber} of {result.Data.TotalPages}");
Console.WriteLine($"Total products: {result.Data.TotalCount}");
foreach (var product in result.Data.Items)
{
Console.WriteLine($"{product.Name} - £{product.Price}");
if (product.Photos.Any())
{
Console.WriteLine($" Photo: {product.Photos.First().Url}");
}
}
}
```
### Get Single Product
```csharp
var result = await client.Catalog.GetProductByIdAsync(productId);
if (result.IsSuccess)
{
var product = result.Data;
Console.WriteLine($"Name: {product.Name}");
Console.WriteLine($"Price: £{product.Price}");
Console.WriteLine($"Weight: {product.Weight} {product.WeightUnit}");
}
```
## Order Operations
### Create Order
```csharp
var orderRequest = new CreateOrderRequest
{
IdentityReference = "CUST123",
ShippingName = "John Smith",
ShippingAddress = "123 Main Street",
ShippingCity = "London",
ShippingPostCode = "SW1A 1AA",
ShippingCountry = "United Kingdom",
Notes = "Please deliver to reception",
Items = new List<CreateOrderItem>
{
new CreateOrderItem
{
ProductId = productId1,
Quantity = 2
},
new CreateOrderItem
{
ProductId = productId2,
Quantity = 1
}
}
};
var result = await client.Orders.CreateOrderAsync(orderRequest);
if (result.IsSuccess)
{
Console.WriteLine($"Order created: {result.Data.Id}");
Console.WriteLine($"Total: £{result.Data.TotalAmount}");
}
```
### Get Orders by Customer Identity
```csharp
var result = await client.Orders.GetOrdersByIdentityAsync("CUST123");
if (result.IsSuccess)
{
foreach (var order in result.Data)
{
Console.WriteLine($"Order {order.Id}: {order.Status} - £{order.TotalAmount}");
Console.WriteLine($" Created: {order.CreatedAt}");
if (!string.IsNullOrEmpty(order.TrackingNumber))
{
Console.WriteLine($" Tracking: {order.TrackingNumber}");
}
}
}
```
### Create Cryptocurrency Payment
```csharp
var result = await client.Orders.CreatePaymentAsync(orderId, "BTC");
if (result.IsSuccess)
{
var payment = result.Data;
Console.WriteLine($"Payment ID: {payment.Id}");
Console.WriteLine($"Send {payment.RequiredAmount} {payment.Currency} to:");
Console.WriteLine($"Address: {payment.WalletAddress}");
Console.WriteLine($"Expires: {payment.ExpiresAt}");
if (!string.IsNullOrEmpty(payment.BTCPayCheckoutUrl))
{
Console.WriteLine($"Or pay via: {payment.BTCPayCheckoutUrl}");
}
}
```
## Error Handling
All API methods return an `ApiResponse<T>` wrapper that includes success status, data, and error information:
```csharp
var result = await client.Catalog.GetProductByIdAsync(productId);
if (result.IsSuccess)
{
// Success - access data
var product = result.Data;
Console.WriteLine($"Product: {product.Name}");
}
else
{
// Error - handle appropriately
Console.WriteLine($"Error: {result.ErrorMessage}");
Console.WriteLine($"Status Code: {result.StatusCode}");
switch (result.StatusCode)
{
case HttpStatusCode.NotFound:
Console.WriteLine("Product not found");
break;
case HttpStatusCode.Unauthorized:
Console.WriteLine("Please login first");
break;
case HttpStatusCode.BadRequest:
Console.WriteLine("Invalid request");
break;
default:
Console.WriteLine("An error occurred");
break;
}
}
```
## Advanced Configuration
### Custom HTTP Client Configuration
The SDK uses Polly for retry policies and includes automatic retry for transient failures:
```csharp
services.AddLittleShopClient(options =>
{
options.BaseUrl = "https://api.littleshop.com";
options.TimeoutSeconds = 60; // Request timeout
options.MaxRetryAttempts = 5; // Number of retries for transient failures
options.EnableLogging = true; // Enable detailed logging
});
```
### Using in ASP.NET Core Web Application
```csharp
// In Program.cs or Startup.cs
builder.Services.AddLittleShopClient(options =>
{
options.BaseUrl = builder.Configuration["LittleShop:ApiUrl"];
options.TimeoutSeconds = 30;
});
// In a controller or service
public class ProductController : Controller
{
private readonly ILittleShopClient _client;
public ProductController(ILittleShopClient client)
{
_client = client;
}
public async Task<IActionResult> Index()
{
var result = await _client.Catalog.GetProductsAsync();
if (result.IsSuccess)
{
return View(result.Data.Items);
}
return View("Error", result.ErrorMessage);
}
}
```
## Features
-**Strongly Typed Models** - All API responses are mapped to C# classes
-**Automatic Authentication** - JWT tokens are managed automatically
-**Retry Policies** - Automatic retry for transient failures
-**Error Handling** - Consistent error responses with detailed information
-**Logging Support** - Built-in logging for debugging
-**Dependency Injection** - Full DI support for ASP.NET Core applications
-**Async/Await** - All methods are async for better performance
-**Pagination Support** - Built-in pagination for product listings
-**Filtering & Search** - Advanced filtering options for products
## API Coverage
- **Authentication**
- Login
- Token refresh
- Logout
- **Catalog**
- Get all categories
- Get category by ID
- Get products (with pagination and filtering)
- Get product by ID
- **Orders**
- Create order
- Get orders by customer identity
- Get order by ID
- Create cryptocurrency payment
- Get order payments
## Requirements
- .NET 9.0 or later
- LittleShop API server running and accessible
## License
This SDK is part of the LittleShop e-commerce platform.