Fix multiple TeleBot and admin panel issues
- Fix admin panel to show all pending orders (PendingPayment + PaymentReceived) - Fix currency display from USD ($) to GBP (£) throughout TeleBot - Update payment methods to use dynamic SilverPay currency list - Consolidate shipping address collection into single message - Implement cart backup/restore on payment failure - Remove unsupported XMR from TeleBot config 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
e7d97f581c
commit
524f0639e1
@ -32,23 +32,27 @@ public class CurrencyController : ControllerBase
|
||||
// Get SilverPay supported currencies
|
||||
var silverPayCurrencies = await _silverPayService.GetSupportedCurrenciesAsync();
|
||||
|
||||
// Production currencies (always enabled if supported by SilverPay)
|
||||
var productionCurrencies = new[] { "BTC", "ETH" };
|
||||
foreach (var currency in productionCurrencies)
|
||||
{
|
||||
if (silverPayCurrencies.Contains(currency))
|
||||
{
|
||||
availableCurrencies.Add(currency);
|
||||
}
|
||||
}
|
||||
// Test currencies that should be excluded unless explicitly enabled
|
||||
var testCurrencies = new[] { "TBTC", "TETH", "TLTC", "TESTBTC", "TESTNET" };
|
||||
|
||||
// Test currencies (enabled via admin settings)
|
||||
var testCurrencies = new[] { "TBTC", "TLTC" };
|
||||
foreach (var currency in testCurrencies)
|
||||
// Add all SilverPay supported currencies except test ones
|
||||
foreach (var currency in silverPayCurrencies)
|
||||
{
|
||||
if (silverPayCurrencies.Contains(currency) &&
|
||||
await _systemSettingsService.IsTestCurrencyEnabledAsync(currency))
|
||||
var isTestCurrency = testCurrencies.Any(tc =>
|
||||
currency.Contains(tc, StringComparison.OrdinalIgnoreCase) ||
|
||||
currency.StartsWith("T", StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (isTestCurrency)
|
||||
{
|
||||
// Only add test currencies if explicitly enabled in settings
|
||||
if (await _systemSettingsService.IsTestCurrencyEnabledAsync(currency))
|
||||
{
|
||||
availableCurrencies.Add(currency);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add all production currencies
|
||||
availableCurrencies.Add(currency);
|
||||
}
|
||||
}
|
||||
|
||||
@ -511,7 +511,18 @@ public class OrderService : IOrderService
|
||||
|
||||
public async Task<IEnumerable<OrderDto>> GetOrdersRequiringActionAsync()
|
||||
{
|
||||
return await GetOrdersByStatusAsync(OrderStatus.PaymentReceived);
|
||||
var orders = await _context.Orders
|
||||
.Include(o => o.Customer)
|
||||
.Include(o => o.Items)
|
||||
.ThenInclude(oi => oi.Product)
|
||||
.Include(o => o.Items)
|
||||
.ThenInclude(oi => oi.ProductMultiBuy)
|
||||
.Include(o => o.Payments)
|
||||
.Where(o => o.Status == OrderStatus.PendingPayment || o.Status == OrderStatus.PaymentReceived)
|
||||
.OrderByDescending(o => o.CreatedAt)
|
||||
.ToListAsync();
|
||||
|
||||
return orders.Select(MapToDto);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<OrderDto>> GetOrdersForPackingAsync()
|
||||
|
||||
@ -649,7 +649,11 @@ namespace TeleBot.Handlers
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear cart after successful order
|
||||
// Backup cart in case payment fails - we'll need to restore it
|
||||
var cartBackup = System.Text.Json.JsonSerializer.Serialize(session.Cart);
|
||||
session.TempData["cart_backup"] = cartBackup;
|
||||
|
||||
// Clear cart after successful order (will restore if payment fails)
|
||||
session.Cart.Clear();
|
||||
|
||||
// Store order ID for payment
|
||||
@ -700,6 +704,20 @@ namespace TeleBot.Handlers
|
||||
|
||||
if (payment == null)
|
||||
{
|
||||
// Restore cart from backup since payment failed
|
||||
if (session.TempData.TryGetValue("cart_backup", out var cartBackupObj) && cartBackupObj is string cartBackupJson)
|
||||
{
|
||||
try
|
||||
{
|
||||
session.Cart = System.Text.Json.JsonSerializer.Deserialize<ShoppingCart>(cartBackupJson) ?? new ShoppingCart();
|
||||
session.TempData.Remove("cart_backup");
|
||||
}
|
||||
catch
|
||||
{
|
||||
// If restoration fails, cart remains empty
|
||||
}
|
||||
}
|
||||
|
||||
await SafeEditMessageAsync(
|
||||
bot,
|
||||
message.Chat.Id,
|
||||
@ -709,14 +727,17 @@ namespace TeleBot.Handlers
|
||||
$"This might be due to:\n" +
|
||||
$"• Payment gateway temporarily unavailable\n" +
|
||||
$"• Network connectivity issues\n\n" +
|
||||
$"Please try again in a few minutes.",
|
||||
$"Your cart has been restored. Please try again.",
|
||||
Telegram.Bot.Types.Enums.ParseMode.Markdown,
|
||||
MenuBuilder.MainMenu()
|
||||
MenuBuilder.CartMenu(session.Cart)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Payment created successfully, continue with display
|
||||
// Payment created successfully, remove cart backup
|
||||
session.TempData.Remove("cart_backup");
|
||||
|
||||
// Continue with display
|
||||
var paymentText = MessageFormatter.FormatPayment(payment);
|
||||
|
||||
await DisplayPaymentInfo(bot, message, payment, paymentText);
|
||||
@ -725,6 +746,20 @@ namespace TeleBot.Handlers
|
||||
{
|
||||
_logger.LogError(ex, "Failed to create payment for order {OrderId} with currency {Currency}", orderId, currency);
|
||||
|
||||
// Restore cart from backup since payment failed
|
||||
if (session.TempData.TryGetValue("cart_backup", out var cartBackupObj) && cartBackupObj is string cartBackupJson)
|
||||
{
|
||||
try
|
||||
{
|
||||
session.Cart = System.Text.Json.JsonSerializer.Deserialize<ShoppingCart>(cartBackupJson) ?? new ShoppingCart();
|
||||
session.TempData.Remove("cart_backup");
|
||||
}
|
||||
catch
|
||||
{
|
||||
// If restoration fails, cart remains empty
|
||||
}
|
||||
}
|
||||
|
||||
await SafeEditMessageAsync(
|
||||
bot,
|
||||
message.Chat.Id,
|
||||
@ -732,9 +767,9 @@ namespace TeleBot.Handlers
|
||||
$"❌ *Payment System Error*\n\n" +
|
||||
$"Sorry, there was a technical issue creating your {currency} payment.\n\n" +
|
||||
$"Our payment system may be undergoing maintenance.\n" +
|
||||
$"Please try again later or contact support.",
|
||||
$"Your cart has been restored. Please try again later.",
|
||||
Telegram.Bot.Types.Enums.ParseMode.Markdown,
|
||||
MenuBuilder.MainMenu()
|
||||
MenuBuilder.CartMenu(session.Cart)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -98,99 +98,41 @@ namespace TeleBot.Handlers
|
||||
switch (session.OrderFlow.CurrentStep)
|
||||
{
|
||||
case OrderFlowStep.CollectingName:
|
||||
if (string.IsNullOrWhiteSpace(input))
|
||||
// Parse multi-line address input
|
||||
var lines = input.Split('\n', StringSplitOptions.TrimEntries);
|
||||
|
||||
if (lines.Length < 4)
|
||||
{
|
||||
await bot.SendTextMessageAsync(
|
||||
message.Chat.Id,
|
||||
"❌ Name cannot be empty. Please enter your shipping name:"
|
||||
"📦 *Checkout - Delivery Details*\n\n" +
|
||||
"Please provide all delivery details in one message:\n\n" +
|
||||
"• Shipping Name\n" +
|
||||
"• Street Address\n" +
|
||||
"• City Name\n" +
|
||||
"• Post/Zip Code\n" +
|
||||
"• Country (or leave blank for UK)\n\n" +
|
||||
"_Example:_\n" +
|
||||
"`John Smith\n" +
|
||||
"123 Main Street\n" +
|
||||
"London\n" +
|
||||
"SW1A 1AA\n" +
|
||||
"United Kingdom`",
|
||||
parseMode: Telegram.Bot.Types.Enums.ParseMode.Markdown
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
session.OrderFlow.ShippingName = input;
|
||||
session.OrderFlow.CurrentStep = OrderFlowStep.CollectingAddress;
|
||||
|
||||
await bot.SendTextMessageAsync(
|
||||
message.Chat.Id,
|
||||
"📦 *Checkout - Step 2/5*\n\n" +
|
||||
"Please enter your shipping address:\n\n" +
|
||||
"_Reply with your street address_",
|
||||
parseMode: Telegram.Bot.Types.Enums.ParseMode.Markdown
|
||||
);
|
||||
break;
|
||||
|
||||
case OrderFlowStep.CollectingAddress:
|
||||
if (string.IsNullOrWhiteSpace(input))
|
||||
{
|
||||
await bot.SendTextMessageAsync(
|
||||
message.Chat.Id,
|
||||
"❌ Address cannot be empty. Please enter your shipping address:"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
session.OrderFlow.ShippingAddress = input;
|
||||
session.OrderFlow.CurrentStep = OrderFlowStep.CollectingCity;
|
||||
|
||||
await bot.SendTextMessageAsync(
|
||||
message.Chat.Id,
|
||||
"📦 *Checkout - Step 3/5*\n\n" +
|
||||
"Please enter your city:\n\n" +
|
||||
"_Reply with your city name_",
|
||||
parseMode: Telegram.Bot.Types.Enums.ParseMode.Markdown
|
||||
);
|
||||
break;
|
||||
|
||||
case OrderFlowStep.CollectingCity:
|
||||
if (string.IsNullOrWhiteSpace(input))
|
||||
{
|
||||
await bot.SendTextMessageAsync(
|
||||
message.Chat.Id,
|
||||
"❌ City cannot be empty. Please enter your city:"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
session.OrderFlow.ShippingCity = input;
|
||||
session.OrderFlow.CurrentStep = OrderFlowStep.CollectingPostCode;
|
||||
|
||||
await bot.SendTextMessageAsync(
|
||||
message.Chat.Id,
|
||||
"📦 *Checkout - Step 4/5*\n\n" +
|
||||
"Please enter your postal/ZIP code:\n\n" +
|
||||
"_Reply with your postal code_",
|
||||
parseMode: Telegram.Bot.Types.Enums.ParseMode.Markdown
|
||||
);
|
||||
break;
|
||||
|
||||
case OrderFlowStep.CollectingPostCode:
|
||||
if (string.IsNullOrWhiteSpace(input))
|
||||
{
|
||||
await bot.SendTextMessageAsync(
|
||||
message.Chat.Id,
|
||||
"❌ Postal code cannot be empty. Please enter your postal code:"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
session.OrderFlow.ShippingPostCode = input;
|
||||
session.OrderFlow.CurrentStep = OrderFlowStep.CollectingCountry;
|
||||
|
||||
await bot.SendTextMessageAsync(
|
||||
message.Chat.Id,
|
||||
"📦 *Checkout - Step 5/5*\n\n" +
|
||||
"Please enter your country (or press Enter for United Kingdom):\n\n" +
|
||||
"_Reply with your country name_",
|
||||
parseMode: Telegram.Bot.Types.Enums.ParseMode.Markdown
|
||||
);
|
||||
break;
|
||||
|
||||
case OrderFlowStep.CollectingCountry:
|
||||
if (!string.IsNullOrWhiteSpace(input))
|
||||
{
|
||||
session.OrderFlow.ShippingCountry = input;
|
||||
}
|
||||
// Parse the address fields
|
||||
session.OrderFlow.ShippingName = lines[0];
|
||||
session.OrderFlow.ShippingAddress = lines[1];
|
||||
session.OrderFlow.ShippingCity = lines[2];
|
||||
session.OrderFlow.ShippingPostCode = lines[3];
|
||||
session.OrderFlow.ShippingCountry = lines.Length > 4 && !string.IsNullOrWhiteSpace(lines[4])
|
||||
? lines[4]
|
||||
: "United Kingdom";
|
||||
|
||||
// Skip to review step
|
||||
session.OrderFlow.CurrentStep = OrderFlowStep.ReviewingOrder;
|
||||
|
||||
// Show order summary
|
||||
@ -204,6 +146,32 @@ namespace TeleBot.Handlers
|
||||
);
|
||||
break;
|
||||
|
||||
// Legacy steps - redirect to new single-message collection
|
||||
case OrderFlowStep.CollectingAddress:
|
||||
case OrderFlowStep.CollectingCity:
|
||||
case OrderFlowStep.CollectingPostCode:
|
||||
case OrderFlowStep.CollectingCountry:
|
||||
// Reset to name collection with new format
|
||||
session.OrderFlow.CurrentStep = OrderFlowStep.CollectingName;
|
||||
await bot.SendTextMessageAsync(
|
||||
message.Chat.Id,
|
||||
"📦 *Checkout - Delivery Details*\n\n" +
|
||||
"Please provide all delivery details in one message:\n\n" +
|
||||
"• Shipping Name\n" +
|
||||
"• Street Address\n" +
|
||||
"• City Name\n" +
|
||||
"• Post/Zip Code\n" +
|
||||
"• Country (or leave blank for UK)\n\n" +
|
||||
"_Example:_\n" +
|
||||
"`John Smith\n" +
|
||||
"123 Main Street\n" +
|
||||
"London\n" +
|
||||
"SW1A 1AA\n" +
|
||||
"United Kingdom`",
|
||||
parseMode: Telegram.Bot.Types.Enums.ParseMode.Markdown
|
||||
);
|
||||
break;
|
||||
|
||||
case OrderFlowStep.CollectingNotes:
|
||||
session.OrderFlow.Notes = string.IsNullOrWhiteSpace(input) ? null : input;
|
||||
session.OrderFlow.CurrentStep = OrderFlowStep.ReviewingOrder;
|
||||
|
||||
@ -59,7 +59,7 @@ namespace TeleBot.UI
|
||||
foreach (var product in products.Items)
|
||||
{
|
||||
sb.AppendLine($"*{product.Name}*");
|
||||
sb.AppendLine($"💰 Price: ${product.Price:F2}");
|
||||
sb.AppendLine($"💰 Price: £{product.Price:F2}");
|
||||
|
||||
if (!string.IsNullOrEmpty(product.Description))
|
||||
{
|
||||
@ -122,7 +122,7 @@ namespace TeleBot.UI
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine($"🛍️ *{product.Name}*\n");
|
||||
sb.AppendLine($"💰 *Price:* ${product.Price:F2}");
|
||||
sb.AppendLine($"💰 *Price:* £{product.Price:F2}");
|
||||
sb.AppendLine($"⚖️ *Weight:* {product.Weight} {product.WeightUnit}");
|
||||
sb.AppendLine($"📁 *Category:* {product.CategoryName ?? "Uncategorized"}");
|
||||
|
||||
@ -203,12 +203,12 @@ namespace TeleBot.UI
|
||||
foreach (var item in cart.Items)
|
||||
{
|
||||
sb.AppendLine($"• *{item.ProductName}*");
|
||||
sb.AppendLine($" Qty: {item.Quantity} × ${item.UnitPrice:F2} = *${item.TotalPrice:F2}*");
|
||||
sb.AppendLine($" Qty: {item.Quantity} × £{item.UnitPrice:F2} = *£{item.TotalPrice:F2}*");
|
||||
}
|
||||
|
||||
sb.AppendLine($"\n📊 *Summary:*");
|
||||
sb.AppendLine($"Items: {cart.GetTotalItems()}");
|
||||
sb.AppendLine($"*Total: ${cart.GetTotalAmount():F2}*");
|
||||
sb.AppendLine($"*Total: £{cart.GetTotalAmount():F2}*");
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
@ -238,7 +238,7 @@ namespace TeleBot.UI
|
||||
sb.AppendLine($"Notes: {orderFlow.Notes}");
|
||||
}
|
||||
|
||||
sb.AppendLine($"\n*Order Total: ${cart.GetTotalAmount():F2}*");
|
||||
sb.AppendLine($"\n*Order Total: £{cart.GetTotalAmount():F2}*");
|
||||
sb.AppendLine($"Items: {cart.GetTotalItems()}");
|
||||
|
||||
sb.AppendLine("\nPlease confirm your order:");
|
||||
@ -253,7 +253,7 @@ namespace TeleBot.UI
|
||||
sb.AppendLine($"📦 *Order Details*\n");
|
||||
sb.AppendLine($"*Order ID:* `{order.Id}`");
|
||||
sb.AppendLine($"*Status:* {FormatOrderStatus(order.Status)}");
|
||||
sb.AppendLine($"*Total:* ${order.TotalAmount:F2}");
|
||||
sb.AppendLine($"*Total:* £{order.TotalAmount:F2}");
|
||||
sb.AppendLine($"*Created:* {order.CreatedAt:yyyy-MM-dd HH:mm} UTC");
|
||||
|
||||
if (order.PaidAt.HasValue)
|
||||
@ -276,7 +276,7 @@ namespace TeleBot.UI
|
||||
sb.AppendLine("\n*Items:*");
|
||||
foreach (var item in order.Items)
|
||||
{
|
||||
sb.AppendLine($"• {item.ProductName} - Qty: {item.Quantity} - ${item.TotalPrice:F2}");
|
||||
sb.AppendLine($"• {item.ProductName} - Qty: {item.Quantity} - £{item.TotalPrice:F2}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -70,9 +70,9 @@
|
||||
},
|
||||
"Cryptocurrencies": [
|
||||
"BTC",
|
||||
"XMR",
|
||||
"ETH",
|
||||
"LTC",
|
||||
"DASH"
|
||||
"DOGE"
|
||||
],
|
||||
"Kestrel": {
|
||||
"Endpoints": {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user