Fix BTCPay Server integration for production deployment

- Fixed invoice creation to use GBP (fiat) instead of cryptocurrency amounts
- BTCPay Server now handles automatic crypto conversion
- Updated payment flow to use checkout links instead of raw wallet addresses
- Added comprehensive logging for debugging payment issues
- Created diagnostic endpoints for testing BTCPay connection and payments
- Added documentation for deployment and troubleshooting

The key issue was that BTCPay v2 manages wallet addresses internally and provides checkout links for customers to complete payments, rather than exposing raw crypto addresses.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
SilverLabs DevTeam
2025-09-19 10:21:04 +01:00
parent 54618348ab
commit 6f0efa6252
4 changed files with 329 additions and 45 deletions

View File

@@ -16,35 +16,41 @@ public class BTCPayServerService : IBTCPayServerService
{
private readonly BTCPayServerClient _client;
private readonly IConfiguration _configuration;
private readonly ILogger<BTCPayServerService> _logger;
private readonly string _storeId;
private readonly string _webhookSecret;
private readonly string _baseUrl;
public BTCPayServerService(IConfiguration configuration)
public BTCPayServerService(IConfiguration configuration, ILogger<BTCPayServerService> logger)
{
_configuration = configuration;
var baseUrl = _configuration["BTCPayServer:BaseUrl"] ?? throw new ArgumentException("BTCPayServer:BaseUrl not configured");
_logger = logger;
_baseUrl = _configuration["BTCPayServer:BaseUrl"] ?? throw new ArgumentException("BTCPayServer:BaseUrl not configured");
var apiKey = _configuration["BTCPayServer:ApiKey"] ?? throw new ArgumentException("BTCPayServer:ApiKey not configured");
_storeId = _configuration["BTCPayServer:StoreId"] ?? throw new ArgumentException("BTCPayServer:StoreId not configured");
_webhookSecret = _configuration["BTCPayServer:WebhookSecret"] ?? throw new ArgumentException("BTCPayServer:WebhookSecret not configured");
_webhookSecret = _configuration["BTCPayServer:WebhookSecret"] ?? "";
_logger.LogInformation("Initializing BTCPay Server connection to {BaseUrl} with Store ID: {StoreId}", _baseUrl, _storeId);
// Create HttpClient with certificate bypass for internal networks
var httpClient = new HttpClient(new HttpClientHandler()
{
ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true
});
_client = new BTCPayServerClient(new Uri(baseUrl), apiKey, httpClient);
_client = new BTCPayServerClient(new Uri(_baseUrl), apiKey, httpClient);
}
public async Task<string> CreateInvoiceAsync(decimal amount, CryptoCurrency currency, string orderId, string? description = null)
{
var currencyCode = GetCurrencyCode(currency);
var paymentMethod = GetPaymentMethod(currency);
var metadata = new JObject
{
["orderId"] = orderId,
["currency"] = currencyCode
["requestedCurrency"] = currency.ToString(),
["paymentMethod"] = paymentMethod
};
if (!string.IsNullOrEmpty(description))
@@ -52,37 +58,39 @@ public class BTCPayServerService : IBTCPayServerService
metadata["itemDesc"] = description;
}
// Create invoice in GBP (fiat) - BTCPay will handle crypto conversion
var request = new CreateInvoiceRequest
{
Amount = amount,
Currency = currencyCode,
Currency = "GBP", // Always use fiat currency for the amount
Metadata = metadata,
Checkout = new CreateInvoiceRequest.CheckoutOptions
{
Expiration = TimeSpan.FromHours(24)
Expiration = TimeSpan.FromHours(24),
PaymentMethods = new[] { paymentMethod }, // Specify which crypto to accept
DefaultPaymentMethod = paymentMethod
}
};
try
{
_logger.LogDebug("Creating BTCPay invoice - Amount: {Amount} GBP, Payment Method: {PaymentMethod}, Order: {OrderId}",
amount, paymentMethod, orderId);
var invoice = await _client.CreateInvoice(_storeId, request);
_logger.LogInformation("✅ Created BTCPay invoice {InvoiceId} for Order {OrderId} - Amount: {Amount} GBP, Method: {PaymentMethod}, Checkout: {CheckoutLink}",
invoice.Id, orderId, amount, paymentMethod, invoice.CheckoutLink);
return invoice.Id;
}
catch (Exception ex)
{
// Log the specific error for debugging
Console.WriteLine($"BTCPay Server error for {currencyCode}: {ex.Message}");
// Try to continue with real API call for all cryptocurrencies with configured wallets
if (currency == CryptoCurrency.BTC || currency == CryptoCurrency.LTC || currency == CryptoCurrency.DASH || currency == CryptoCurrency.XMR)
{
throw; // Let the calling service handle errors for supported currencies
}
// For XMR and ETH, we have nodes but BTCPay Server might not be configured yet
// Log the error and fall back to placeholder for now
Console.WriteLine($"Falling back to placeholder for {currencyCode} - BTCPay Server integration pending");
return $"invoice_{Guid.NewGuid()}";
_logger.LogError(ex, "❌ Failed to create BTCPay invoice - Amount: {Amount} GBP, Method: {PaymentMethod}, Store: {StoreId}, BaseUrl: {BaseUrl}",
amount, paymentMethod, _storeId, _baseUrl);
// Always throw - never generate fake invoices
throw;
}
}