
Security News
Crates.io Users Targeted by Phishing Emails
The Rust Security Response WG is warning of phishing emails from rustfoundation.dev targeting crates.io users.
Panda.Billbee.CustomShopSdk
Advanced tools
A .NET SDK for easy integration with the Billbee Custom Shop API. Provides complete HTTP request handling, parameter parsing, and routing according to the Billbee API specification. Zero dependencies!
Connect your custom .NET e-commerce platform to Billbee in minutes, not weeks.
A complete .NET SDK that transforms the complex Billbee Custom Shop API into simple method implementations. No HTTP handling, no authentication complexity, no routing headaches.
⚠️ Authorization Required: The Billbee Custom Shop API requires explicit permission from Billbee GmbH.
⚠️ Unofficial: This SDK is maintained by Mr. & Mrs. Panda, not Billbee GmbH.
Without this SDK:
// Complex HTTP request handling
// Manual HMAC-SHA256 authentication
// Parameter parsing and validation
// JSON serialization/deserialization
// Error handling and status codes
// 200+ lines of boilerplate code
With this SDK:
public class MyShop : BillbeeCustomShopService
{
protected override async Task<OrderResponse> GetOrdersAsync(DateTime startDate, int page, int pageSize)
=> await _database.GetOrdersSince(startDate, page, pageSize);
protected override string GetApiKey() => _config["Billbee:ApiKey"];
}
Billbee is a multichannel e-commerce management platform that centralizes:
While Billbee supports major platforms (Shopify, Amazon, eBay), custom shops need this API.
# Core SDK (required)
dotnet add package Panda.Billbee.CustomShopSdk
# ASP.NET Core helpers (recommended)
dotnet add package Panda.Billbee.CustomShopSdk.AspNetCore
using Panda.Billbee.CustomShopSdk.Services;
using Panda.Billbee.CustomShopSdk.Models;
using Panda.Billbee.CustomShopSdk.Models.Orders;
using Panda.Billbee.CustomShopSdk.Models.Products;
public class MyShopService : BillbeeCustomShopService
{
private readonly IMyDatabase _database;
private readonly IConfiguration _config;
public MyShopService(IMyDatabase database, IConfiguration config)
{
_database = database;
_config = config;
}
protected override string GetApiKey() => _config["Billbee:ApiKey"];
protected override async Task<OrderResponse> GetOrdersAsync(DateTime startDate, int page, int pageSize)
{
var orders = await _database.GetOrdersSince(startDate, page, pageSize);
return new OrderResponse
{
Orders = orders.Select(MapToOrder).ToList(),
Paging = new PagingInfo
{
Page = page,
PageSize = pageSize,
TotalCount = await _database.CountOrdersSince(startDate)
}
};
}
protected override async Task<Order?> GetOrderAsync(string orderId)
{
var order = await _database.GetOrderById(orderId);
return order == null ? null : MapToOrder(order);
}
protected override async Task AckOrderAsync(string orderId)
{
await _database.MarkOrderAsAcknowledged(orderId);
}
protected override async Task SetOrderStateAsync(SetOrderStateRequest request)
{
await _database.UpdateOrderStatus(request.OrderId, request.NewStateId, request.Comment);
if (!string.IsNullOrEmpty(request.TrackingCode))
await _database.SetTrackingInfo(request.OrderId, request.TrackingCode, request.TrackingUrl);
}
protected override async Task<Product?> GetProductAsync(string productId)
{
var product = await _database.GetProductById(productId);
return product == null ? null : MapToProduct(product);
}
protected override async Task<ProductResponse> GetProductsAsync(int page, int pageSize)
{
var products = await _database.GetProducts(page, pageSize);
return new ProductResponse
{
Products = products.Select(MapToProduct).ToList(),
Paging = new PagingInfo { Page = page, PageSize = pageSize, TotalCount = await _database.CountProducts() }
};
}
protected override async Task SetStockAsync(SetStockRequest request)
{
if (request.AvailableStock.HasValue)
await _database.UpdateStock(request.ProductId, request.AvailableStock.Value);
}
protected override async Task<List<ShippingProfile>> GetShippingProfilesAsync()
{
return new List<ShippingProfile>
{
new() { Id = "standard", Name = "Standard Shipping" },
new() { Id = "express", Name = "Express Shipping" }
};
}
private Order MapToOrder(MyOrderModel order) => new()
{
OrderId = order.Id.ToString(),
OrderNumber = order.Number,
OrderDate = order.CreatedAt,
Email = order.CustomerEmail,
CurrencyCode = order.Currency,
ShipCost = order.ShippingCost,
InvoiceAddress = MapToAddress(order.BillingAddress),
DeliveryAddress = MapToAddress(order.ShippingAddress),
OrderProducts = order.Items?.Select(MapToOrderProduct).ToList()
};
private Product MapToProduct(MyProductModel product) => new()
{
Id = product.Id.ToString(),
Title = product.Name,
Description = product.Description,
Price = product.Price,
Quantity = product.Stock,
Sku = product.Sku,
Weight = product.Weight
};
}
using Microsoft.AspNetCore.Mvc;
using Panda.Billbee.CustomShopSdk.AspNetCore.Controllers;
[ApiController]
[Route("api/billbee")] // Your webhook URL
public class BillbeeController : BillbeeControllerBase
{
private readonly MyShopService _shopService;
public BillbeeController(MyShopService shopService) => _shopService = shopService;
protected override IBillbeeCustomShopService BillbeeService => _shopService;
}
// Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddScoped<MyShopService>();
builder.Services.AddScoped<IMyDatabase, MyDatabase>();
var app = builder.Build();
app.MapControllers();
app.Run();
In your appsettings.json:
{
"Billbee": {
"ApiKey": "your-secret-api-key-from-billbee"
}
}
In Billbee dashboard:
https://yourshop.com/api/billbee
Done! 🎉 Your shop is now integrated with Billbee.
The SDK automatically handles these endpoints:
Method | Endpoint | Purpose |
---|---|---|
GET | ?Action=GetOrders&StartDate=2024-01-01&Page=1&PageSize=100 | Fetch orders since date |
GET | ?Action=GetOrder&OrderId=12345 | Get single order |
GET | ?Action=GetProduct&ProductId=67890 | Get single product |
GET | ?Action=GetProducts&Page=1&PageSize=50 | Get products list |
GET | ?Action=GetShippingProfiles | Get shipping methods |
POST | ?Action=AckOrder | Acknowledge order receipt |
POST | ?Action=SetOrderState | Update order status |
POST | ?Action=SetStock | Update product inventory |
public class Order
{
public string? OrderId { get; set; } // Required: Your order ID
public string? OrderNumber { get; set; } // Customer-visible number
public DateTime? OrderDate { get; set; } // When placed
public string? Email { get; set; } // Customer email
public string? CurrencyCode { get; set; } // EUR, USD, etc.
public decimal ShipCost { get; set; } // Shipping cost
public Address? InvoiceAddress { get; set; } // Billing address
public Address? DeliveryAddress { get; set; } // Shipping address
public List<OrderProduct>? OrderProducts { get; set; } // Line items
}
public class Product
{
public string? Id { get; set; } // Required: Product ID
public string? Title { get; set; } // Product name
public string? Description { get; set; } // Full description
public string? Sku { get; set; } // SKU/Article number
public decimal? Price { get; set; } // Current price
public decimal? Quantity { get; set; } // Available stock
public decimal? Weight { get; set; } // Weight in kg
public List<ProductImage>? Images { get; set; } // Product images
}
public class BillbeeController : BillbeeControllerBase
{
public BillbeeController(MyShopService shopService, ILogger<BillbeeController> logger)
: base(logger)
{
_shopService = shopService;
}
protected override async Task NotifyErrorAsync(ServiceResult serviceResult)
{
await base.NotifyErrorAsync(serviceResult); // Default logging
// Custom error handling
if (serviceResult.ErrorType == ServiceErrorType.InternalServerError)
{
await _alertingService.SendAlert(serviceResult.GetErrorMessage());
}
}
}
protected override string GetApiKey() => _config["Billbee:ApiKey"];
protected override (string? Username, string? Password) GetBasicAuthCredentials()
=> (_config["Billbee:Username"], _config["Billbee:Password"]);
Create separate service classes and controllers:
BookstoreService
with /bookstore-api
routeElectronicsService
with /electronics-api
routeprotected override string? GetApiKey()
{
#if DEBUG
return null; // Disable auth in development
#else
return _config["Billbee:ApiKey"];
#endif
}
Error | Solution |
---|---|
"Action parameter is required" | Ensure Billbee sends ?Action=GetOrders in URL |
401 Unauthorized | Verify API key matches Billbee configuration |
404 Not Found | Check controller route matches Billbee webhook URL |
Orders not syncing | Verify OrderDate and date filtering logic |
Stock updates failing | Implement SetStockAsync and check ProductId mapping |
✅ Always use HTTPS in production
✅ Implement proper async/await patterns
✅ Handle time zones correctly (Billbee uses UTC)
✅ Monitor performance for large datasets
✅ Test with small batches before going live
✅ Log important events (orders exported, stock updated)
Billbee ──GET──→ Your API ──→ Your Database
↑ ↓ ↓
│ (Fetch Orders) (Load Data)
│ ↓ ↓
└─────JSON Response ←──── SDK Mapping
Before (complex):
public class MyShop : BillbeeCustomShopService
{
protected override IOrderService GetOrderService() => new MyOrderService();
protected override IProductService GetProductService() => new MyProductService();
}
After (simple):
public class MyShop : BillbeeCustomShopService
{
protected override async Task<OrderResponse> GetOrdersAsync(DateTime startDate, int page, int pageSize)
=> await LoadOrdersFromDatabase(startDate, page, pageSize);
// Direct implementation - much cleaner!
}
Legal Notice: Using the Billbee Custom Shop API requires permission from Billbee GmbH.
FAQs
A .NET SDK for easy integration with the Billbee Custom Shop API. Provides complete HTTP request handling, parameter parsing, and routing according to the Billbee API specification. Zero dependencies!
We found that panda.billbee.customshopsdk demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
The Rust Security Response WG is warning of phishing emails from rustfoundation.dev targeting crates.io users.
Product
Socket now lets you customize pull request alert headers, helping security teams share clear guidance right in PRs to speed reviews and reduce back-and-forth.
Product
Socket's Rust support is moving to Beta: all users can scan Cargo projects and generate SBOMs, including Cargo.toml-only crates, with Rust-aware supply chain checks.