public async Task <Dictionary <string, dynamic> > CapturePaypalOrder([FromQuery] string orderId) { using (var context = new DbContext()) { // Refuse capture if customer is not properly authenticated var customer = _accountService.ValidateCustomerSession(Request.Cookies, context, true); if (customer == null) { Response.StatusCode = 401; // Unauthorised return(null); } // Refuse capture if // Capture funds through Paypal var order = await _paypalService.CaptureOrder(orderId); // Create transaction object var transaction = context.CustomerTransactions.Add(new CustomerTransaction { CustomerId = customer.Id, CustomerName = customer.FirstName + " " + customer.LastName, Date = DateTime.UtcNow.AddHours(10), // Force Sydney timezone PaypalTransactionId = order.Id, Total = decimal.Parse(order.PurchaseUnits[0].AmountWithBreakdown.Value) }); // Create transaction item objects var items = order.PurchaseUnits[0].Items; var lootBoxItems = new List <int>(); var boughtTogetherRecordsAlreadyHandledA = new HashSet <int>(); foreach (var item in items) { var itemId = int.Parse(item.Sku); var itemEntity = context.Items .Include(x => x.Seller) .First(x => x.Id == itemId); context.TransactionItems.Add(new TransactionItem { CustomerTransaction = transaction.Entity, ItemSaleId = itemId, ItemSalePrice = decimal.Parse(item.UnitAmount.Value), ItemSaleName = item.Name, SellerSaleId = itemEntity.SellerId, SellerSaleName = itemEntity.Seller.Name }); // Handle bought together records and purchase count if (!boughtTogetherRecordsAlreadyHandledA.Contains(itemId)) { boughtTogetherRecordsAlreadyHandledA.Add(itemId); itemEntity.Purchases++; var boughtTogetherRecordsAlreadyHandledB = new HashSet <int>(); foreach (var itemB in items) { var itemBId = int.Parse(itemB.Sku); // Skip if item already handled or same (means duplicate mostViewed don't impact the count) if (boughtTogetherRecordsAlreadyHandledB.Contains(itemBId) || itemBId == itemId) { continue; } boughtTogetherRecordsAlreadyHandledB.Add(itemBId); // Get existing bought together record var boughtTogetherRecord = context.ItemsBoughtTogether .FirstOrDefault(x => x.ItemAId == itemId && x.ItemBId == itemBId); // If record doesn't exist, create it. if (boughtTogetherRecord == null) { boughtTogetherRecord = context.ItemsBoughtTogether.Add(new ItemsBoughtTogether { ItemAId = itemId, ItemBId = itemBId, Count = 0 }).Entity; } // Increment bought together count boughtTogetherRecord.Count++; } } // If item is a loot box, also add in a random item below its price. if (itemEntity.Id == 86) { var eligibleItems = context.Items .Include(x => x.Seller) .Where(x => !x.Hidden && x.Price < itemEntity.Price); var skip = (int)(new Random().NextDouble() * eligibleItems.Count()); var chosenItem = eligibleItems.Skip(skip).Take(1).FirstOrDefault(); TransactionItem transactionItem; if (chosenItem == null) { transactionItem = context.TransactionItems.Add(new TransactionItem { CustomerTransaction = transaction.Entity, ItemSaleId = -1, ItemSalePrice = 0, ItemSaleName = "Empty Cardboard Box", SellerSaleId = itemEntity.SellerId, SellerSaleName = itemEntity.Seller.Name }).Entity; } else { transactionItem = context.TransactionItems.Add(new TransactionItem { CustomerTransaction = transaction.Entity, ItemSaleId = chosenItem.Id, ItemSalePrice = 0, ItemSaleName = chosenItem.Name + " (from Loot Box)", SellerSaleId = chosenItem.SellerId, SellerSaleName = chosenItem.Seller.Name }).Entity; } Console.WriteLine("Loot box item unlocked: " + transactionItem.ItemSaleName); lootBoxItems.Add(transactionItem.ItemSaleId); } } // Clear user's shopping cart var itemsToRemove = context.CartItems.Where(x => x.SessionId == customer.Account.SessionId); context.CartItems.RemoveRange(itemsToRemove); context.SaveChanges(); if (lootBoxItems.IsNullOrEmpty()) { lootBoxItems = null; } return(new Dictionary <string, dynamic> { ["order"] = order, ["lootBoxItems"] = lootBoxItems }); } }