From 6c95ed3145bededcfa637d1b3c0749b874a90c4a Mon Sep 17 00:00:00 2001 From: SysAdmin Date: Mon, 6 Oct 2025 16:55:19 +0100 Subject: [PATCH] Fix: Add TeleBot integration and expired payment handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TeleBot Configuration: - Added TeleBot API URL and API key to docker-compose.yml - Configured to connect to telebot-service:5000 internally - Enables customer notifications via Telegram bot Expired Payment Handling: - Auto-cancel orders when payment status is Expired - Only cancels orders in PendingPayment status - Logs cancellation for audit trail Customer View Improvements: - Hide cancelled orders from customer order lists - Filters applied to both GetOrdersByIdentityAsync and GetOrdersByCustomerIdAsync - Prevents confusion from displaying cancelled/expired orders This resolves: - No notifications to customers (TeleBot not configured) - No notifications to admin (TeleBot connection failed) - Expired orders remaining visible to customers - Orders not auto-cancelled when payment expires 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- LittleShop/Services/CryptoPaymentService.cs | 30 +++++++++++++-------- LittleShop/Services/OrderService.cs | 4 +-- docker-compose.yml | 2 ++ 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/LittleShop/Services/CryptoPaymentService.cs b/LittleShop/Services/CryptoPaymentService.cs index fc23f44..29a4731 100644 --- a/LittleShop/Services/CryptoPaymentService.cs +++ b/LittleShop/Services/CryptoPaymentService.cs @@ -139,24 +139,32 @@ public class CryptoPaymentService : ICryptoPaymentService payment.PaidAmount = amount; payment.TransactionHash = transactionHash; + // Load order for status updates + var order = await _context.Orders + .Include(o => o.Customer) + .FirstOrDefaultAsync(o => o.Id == payment.OrderId); + + // Handle expired payments - auto-cancel the order + if (status == PaymentStatus.Expired && order != null) + { + if (order.Status == OrderStatus.PendingPayment) + { + order.Status = OrderStatus.Cancelled; + order.UpdatedAt = DateTime.UtcNow; + _logger.LogInformation("Auto-cancelled order {OrderId} due to payment expiration", orderId); + } + } + // Determine if payment is confirmed (ready to fulfill order) var isPaymentConfirmed = status == PaymentStatus.Paid || status == PaymentStatus.Overpaid || (status == PaymentStatus.Completed && confirmations >= 3); - if (isPaymentConfirmed) + if (isPaymentConfirmed && order != null) { payment.PaidAt = DateTime.UtcNow; - - // Update order status - var order = await _context.Orders - .Include(o => o.Customer) - .FirstOrDefaultAsync(o => o.Id == payment.OrderId); - if (order != null) - { - order.Status = OrderStatus.PaymentReceived; - order.PaidAt = DateTime.UtcNow; - } + order.Status = OrderStatus.PaymentReceived; + order.PaidAt = DateTime.UtcNow; } await _context.SaveChangesAsync(); diff --git a/LittleShop/Services/OrderService.cs b/LittleShop/Services/OrderService.cs index 308b22b..b745161 100644 --- a/LittleShop/Services/OrderService.cs +++ b/LittleShop/Services/OrderService.cs @@ -51,7 +51,7 @@ public class OrderService : IOrderService .Include(o => o.Items) .ThenInclude(oi => oi.ProductVariant) .Include(o => o.Payments) - .Where(o => o.IdentityReference == identityReference) + .Where(o => o.IdentityReference == identityReference && o.Status != OrderStatus.Cancelled) .OrderByDescending(o => o.CreatedAt) .ToListAsync(); @@ -69,7 +69,7 @@ public class OrderService : IOrderService .Include(o => o.Items) .ThenInclude(oi => oi.ProductVariant) .Include(o => o.Payments) - .Where(o => o.CustomerId == customerId) + .Where(o => o.CustomerId == customerId && o.Status != OrderStatus.Cancelled) .OrderByDescending(o => o.CreatedAt) .ToListAsync(); diff --git a/docker-compose.yml b/docker-compose.yml index 7a1dced..72c053f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -24,6 +24,8 @@ services: - WebPush__VapidPublicKey=BDJtQu7zV0H3KF4FkrZ8nPwP3YD_3cEz3hqJvQ6L_gvNpG8ANksQB-FZy2-PDmFAu6duiN4p3mkcNAGnN4YRbws - WebPush__VapidPrivateKey=Hm_ttUKUqoLn5R8WQP5O1SIGxm0kVJXMZGCPMD1tUDY - WebPush__VapidSubject=mailto:admin@littleshop.local + - TeleBot__ApiUrl=${TELEBOT_API_URL:-http://telebot-service:5000} + - TeleBot__ApiKey=${TELEBOT_API_KEY:-littleshop-internal-api-key} volumes: - littleshop_data:/app/data - littleshop_uploads:/app/wwwroot/uploads