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>
This commit is contained in:
180
LittleShop.Client.Example/Program.cs
Normal file
180
LittleShop.Client.Example/Program.cs
Normal file
@@ -0,0 +1,180 @@
|
||||
using LittleShop.Client;
|
||||
using LittleShop.Client.Extensions;
|
||||
using LittleShop.Client.Models;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Text.Json;
|
||||
|
||||
// Setup dependency injection
|
||||
var services = new ServiceCollection();
|
||||
|
||||
// Add logging
|
||||
services.AddLogging(builder => builder
|
||||
.AddConsole()
|
||||
.SetMinimumLevel(LogLevel.Information));
|
||||
|
||||
// Add LittleShop client
|
||||
services.AddLittleShopClient(options =>
|
||||
{
|
||||
options.BaseUrl = "https://localhost:5001"; // Update this to your API URL
|
||||
options.TimeoutSeconds = 30;
|
||||
options.MaxRetryAttempts = 3;
|
||||
options.EnableLogging = true;
|
||||
});
|
||||
|
||||
// Build service provider
|
||||
var serviceProvider = services.BuildServiceProvider();
|
||||
|
||||
// Get the client
|
||||
var client = serviceProvider.GetRequiredService<ILittleShopClient>();
|
||||
|
||||
Console.WriteLine("=== LittleShop Client Example ===\n");
|
||||
|
||||
try
|
||||
{
|
||||
// Step 1: Authenticate
|
||||
Console.WriteLine("1. Authenticating...");
|
||||
var loginResult = await client.Authentication.LoginAsync("admin", "admin");
|
||||
|
||||
if (!loginResult.IsSuccess)
|
||||
{
|
||||
Console.WriteLine($"Login failed: {loginResult.ErrorMessage}");
|
||||
return;
|
||||
}
|
||||
|
||||
Console.WriteLine($"✓ Logged in as: {loginResult.Data!.Username}");
|
||||
Console.WriteLine($" Token expires: {loginResult.Data.ExpiresAt}\n");
|
||||
|
||||
// Step 2: Get Categories
|
||||
Console.WriteLine("2. Fetching categories...");
|
||||
var categoriesResult = await client.Catalog.GetCategoriesAsync();
|
||||
|
||||
if (categoriesResult.IsSuccess && categoriesResult.Data!.Any())
|
||||
{
|
||||
Console.WriteLine($"✓ Found {categoriesResult.Data.Count} categories:");
|
||||
foreach (var category in categoriesResult.Data)
|
||||
{
|
||||
Console.WriteLine($" - {category.Name}: {category.Description}");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
// Step 3: Get Products
|
||||
Console.WriteLine("3. Fetching products...");
|
||||
var productsResult = await client.Catalog.GetProductsAsync(
|
||||
pageNumber: 1,
|
||||
pageSize: 5
|
||||
);
|
||||
|
||||
if (productsResult.IsSuccess && productsResult.Data!.Items.Any())
|
||||
{
|
||||
Console.WriteLine($"✓ Found {productsResult.Data.TotalCount} products (showing first {productsResult.Data.Items.Count}):");
|
||||
foreach (var product in productsResult.Data.Items)
|
||||
{
|
||||
Console.WriteLine($" - {product.Name}");
|
||||
Console.WriteLine($" Price: £{product.Price:F2}");
|
||||
Console.WriteLine($" Weight: {product.Weight} {product.WeightUnit}");
|
||||
Console.WriteLine($" Category: {product.CategoryName}");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
// Step 4: Create a sample order
|
||||
Console.WriteLine("4. Creating a sample order...");
|
||||
|
||||
// Get first product for the order
|
||||
var firstProduct = productsResult.Data!.Items.FirstOrDefault();
|
||||
if (firstProduct != null)
|
||||
{
|
||||
var orderRequest = new CreateOrderRequest
|
||||
{
|
||||
IdentityReference = "CLIENT_DEMO_001",
|
||||
ShippingName = "Demo Customer",
|
||||
ShippingAddress = "123 Test Street",
|
||||
ShippingCity = "London",
|
||||
ShippingPostCode = "SW1A 1AA",
|
||||
ShippingCountry = "United Kingdom",
|
||||
Notes = "Test order from client SDK",
|
||||
Items = new List<CreateOrderItem>
|
||||
{
|
||||
new CreateOrderItem
|
||||
{
|
||||
ProductId = firstProduct.Id,
|
||||
Quantity = 1
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var orderResult = await client.Orders.CreateOrderAsync(orderRequest);
|
||||
|
||||
if (orderResult.IsSuccess)
|
||||
{
|
||||
Console.WriteLine($"✓ Order created successfully!");
|
||||
Console.WriteLine($" Order ID: {orderResult.Data!.Id}");
|
||||
Console.WriteLine($" Total: £{orderResult.Data.TotalAmount:F2}");
|
||||
Console.WriteLine($" Status: {orderResult.Data.Status}\n");
|
||||
|
||||
// Step 5: Create a payment for the order
|
||||
Console.WriteLine("5. Creating Bitcoin payment for the order...");
|
||||
var paymentResult = await client.Orders.CreatePaymentAsync(orderResult.Data.Id, "BTC");
|
||||
|
||||
if (paymentResult.IsSuccess)
|
||||
{
|
||||
Console.WriteLine($"✓ Payment created successfully!");
|
||||
Console.WriteLine($" Payment ID: {paymentResult.Data!.Id}");
|
||||
Console.WriteLine($" Amount: {paymentResult.Data.RequiredAmount} BTC");
|
||||
Console.WriteLine($" Send to: {paymentResult.Data.WalletAddress}");
|
||||
Console.WriteLine($" Expires: {paymentResult.Data.ExpiresAt}");
|
||||
|
||||
if (!string.IsNullOrEmpty(paymentResult.Data.BTCPayCheckoutUrl))
|
||||
{
|
||||
Console.WriteLine($" Checkout URL: {paymentResult.Data.BTCPayCheckoutUrl}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"✗ Payment creation failed: {paymentResult.ErrorMessage}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"✗ Order creation failed: {orderResult.ErrorMessage}");
|
||||
}
|
||||
}
|
||||
|
||||
// Step 6: Get orders for the identity
|
||||
Console.WriteLine("\n6. Fetching orders for identity 'CLIENT_DEMO_001'...");
|
||||
var ordersResult = await client.Orders.GetOrdersByIdentityAsync("CLIENT_DEMO_001");
|
||||
|
||||
if (ordersResult.IsSuccess && ordersResult.Data!.Any())
|
||||
{
|
||||
Console.WriteLine($"✓ Found {ordersResult.Data.Count} orders:");
|
||||
foreach (var order in ordersResult.Data)
|
||||
{
|
||||
Console.WriteLine($" - Order {order.Id}");
|
||||
Console.WriteLine($" Status: {order.Status}");
|
||||
Console.WriteLine($" Total: £{order.TotalAmount:F2}");
|
||||
Console.WriteLine($" Created: {order.CreatedAt}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine(" No orders found for this identity.");
|
||||
}
|
||||
|
||||
Console.WriteLine("\n=== Example completed successfully! ===");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"\n✗ Error: {ex.Message}");
|
||||
if (ex.InnerException != null)
|
||||
{
|
||||
Console.WriteLine($" Inner: {ex.InnerException.Message}");
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Cleanup
|
||||
client.Authentication.Logout();
|
||||
Console.WriteLine("\nLogged out.");
|
||||
}
|
||||
Reference in New Issue
Block a user