public OrderDto CreateNewOrder(string email, OrderInputModel order) { // Retrieve information for the user with the email passed in var user = _dbContext.Users.FirstOrDefault(u => u.Email == email); if (user == null) { throw new Exception("User not found"); } // Retrieve information for the address with the address id passed in var address = _dbContext.Addresses.FirstOrDefault(a => a.Id == order.AddressId); // Retrieve information for the payment card with the payment card id passed in var card = _dbContext.PaymentCards.FirstOrDefault(c => c.Id == order.PaymentCardId); var cardNumber = card.CardNumber; var shoppingCart = _dbContext.ShoppingCarts.FirstOrDefault(s => s.UserId == user.Id); var fullName = user.FullName; float totalPrice = 0; for (int i = 0; i < shoppingCart.ShoppingCartItems.Count(); i++) { totalPrice += shoppingCart.ShoppingCartItems[i].UnitPrice * shoppingCart.ShoppingCartItems[i].Quantity; } // Create a new order where the credit card number has been masked, e.g. ************5555 var entity = new OrderEntity { Email = user.Email, FullName = fullName, StreetName = address.StreetName, HouseNumber = address.HouseNumber, ZipCode = address.ZipCode, Country = address.Country, City = address.City, CardHolderName = card.CardHolderName, MaskedCreditCard = PaymentCardHelper.MaskPaymentCard(card.CardNumber), OrderDate = DateTime.Now, TotalPrice = totalPrice }; _dbContext.Orders.Add(entity); _dbContext.SaveChanges(); // Return the order but here the credit card number should not be masked return(new OrderDto { Id = entity.Id, FullName = entity.FullName, Email = entity.Email, StreetName = entity.StreetName, HouseNumber = entity.HouseNumber, ZipCode = entity.ZipCode, Country = entity.Country, CardholderName = entity.CardHolderName, CreditCard = cardNumber, OrderDate = entity.OrderDate.ToString("dd.MM.yyyy"), TotalPrice = entity.TotalPrice }); }
public bool ValidatePaymentInfo(Dictionary <string, string> parameters, out string error) { var stripeSettings = DependencyResolver.Resolve <StripeSettings>(); error = null; if (stripeSettings.UseRedirectionFlow) { return(true); //we don't collect anything on our site in case of redirection flow } parameters.TryGetValue("cardNumber", out var cardNumber); parameters.TryGetValue("cardName", out var cardName); parameters.TryGetValue("expireMonth", out var expireMonthStr); parameters.TryGetValue("expireYear", out var expireYearStr); parameters.TryGetValue("cvv", out var cvv); if (!PaymentCardHelper.IsCardNumberValid(cardNumber)) { error = LocalizationHelper.Localize("The card number is incorrect"); return(false); } if (cardName.IsNullEmptyOrWhiteSpace()) { error = LocalizationHelper.Localize("The card name can not be empty"); return(false); } if (cvv.IsNullEmptyOrWhiteSpace()) { error = LocalizationHelper.Localize("The card security code can not be empty"); return(false); } try { if (ExpiryCheck(expireMonthStr, expireYearStr)) { error = LocalizationHelper.Localize("The card expiry is incorrect or card has expired"); return(false); } } catch { error = LocalizationHelper.Localize("The card expiry is incorrect or card has expired"); return(false); } return(true); }
private Order CreateOrder(User user, Address address, PaymentCard paymentCard) { var newOrder = new Order { User = user, FullName = user.FullName, Email = user.Email, Country = address.Country, City = address.City, StreetName = address.StreetName, HouseNumber = address.HouseNumber, ZipCode = address.ZipCode, CardHolderName = paymentCard.CardholderName, MaskedCreditCard = PaymentCardHelper.MaskPaymentCard(paymentCard.CardNumber), OrderDate = DateTime.Now }; _dbContext.Add(newOrder); _dbContext.SaveChanges(); return(newOrder); }
public MappingProfile() { CreateMap <Address, AddressDto>() .ForSourceMember(x => x.UserId, opt => opt.DoNotValidate()); CreateMap <Order, OrderDto>() .ForMember(o => o.CreditCard, opt => opt.MapFrom(src => src.MaskedCreditCard)) .ForMember(o => o.OrderDate, opt => opt.MapFrom(src => src.OrderDate.ToString("MM.dd.yyyy"))) .ForSourceMember(p => p.UserId, opt => opt.DoNotValidate()); CreateMap <OrderItem, OrderItemDto>() .ForSourceMember(o => o.OrderId, y => y.DoNotValidate()) .ForSourceMember(o => o.Order, y => y.DoNotValidate()); CreateMap <PaymentCard, PaymentCardDto>() .ForSourceMember(p => p.UserId, opt => opt.DoNotValidate()) .ForMember(o => o.CardNumber, opt => opt.MapFrom(src => PaymentCardHelper.MaskPaymentCard(src.CardNumber))); CreateMap <ShoppingCartItem, ShoppingCartItemDto>() .ForMember(c => c.TotalPrice, src => src.MapFrom(src => src.UnitPrice * src.Quantity)) .ForSourceMember(c => c.ShoppingCartId, opt => opt.DoNotValidate()); CreateMap <User, UserDto>() .ForSourceMember(u => u.Addresses, opt => opt.DoNotValidate()) .ForSourceMember(u => u.PaymentCards, opt => opt.DoNotValidate()) .ForSourceMember(u => u.Orders, opt => opt.DoNotValidate()) .ForSourceMember(u => u.ShoppingCart, opt => opt.DoNotValidate()); }
public IHttpActionResult ProcessPayment(FormCollection parameters) { //first get the payment processor var paymentMethodName = parameters.Get(PaymentParameterNames.PaymentMethodTypeName); if (string.IsNullOrEmpty(paymentMethodName)) { VerboseReporter.ReportError("Invalid payment method", "process_payment"); return(RespondFailure()); } //the transaction amount decimal amount; var amountString = parameters.Get(PaymentParameterNames.Amount) ?? "0"; decimal.TryParse(amountString, out amount); PaymentMethodType methodType; if (System.Enum.TryParse(paymentMethodName, out methodType)) { methodType = PaymentMethodType.CreditCard; } //get the payment processor now var paymentProcessor = _paymentProcessingService.GetPaymentProcessorPlugin(amount, methodType); if (paymentProcessor == null) { VerboseReporter.ReportError("Invalid payment method", "process_payment"); return(RespondFailure()); } //convert form collection to dictionary to check if parameters are valid var formCollectionDictionary = parameters.ToDictionary(pair => pair.Key, pair => (object)pair.Value); var isValid = paymentProcessor.AreParametersValid(formCollectionDictionary); UserPaymentMethod paymentMethod = null; if (!isValid) { //the parameters are not valid. but that may also mean that the user is selecting an already saved payment method //and so he wouldn't have sent that data again var savedPaymentMethodIdString = parameters.Get(PaymentParameterNames.UserSavedPaymentMethodId); int savedPaymentMethodId; if (int.TryParse(savedPaymentMethodIdString, out savedPaymentMethodId)) { var userPaymentMethods = _paymentMethodService.Get(x => x.UserId == ApplicationContext.Current.CurrentUser.Id && x.Id == savedPaymentMethodId, null); if (userPaymentMethods.Any()) { paymentMethod = userPaymentMethods.First(); isValid = true; } } //still invalid? something is not right then. if (!isValid) { VerboseReporter.ReportError("Invalid parameters to process payment", "process_payment"); return(RespondFailure()); } } //we save the payment method in our database if it's CreditCard if (paymentProcessor.Supports(PaymentMethodType.CreditCard)) { if (paymentMethod == null) { #region saving payment method to database var creditCardNumber = parameters.Get(PaymentParameterNames.CardNumber); //let's validate the card for level 1 check (luhn's test) first before storing var isCardValid = PaymentCardHelper.IsCardNumberValid(creditCardNumber); //card number if (!isCardValid) { VerboseReporter.ReportError("Invalid card number", "process_payment"); return(RespondFailure()); } //expiration date var expireMonth = parameters.Get(PaymentParameterNames.ExpireMonth); var expireYear = parameters.Get(PaymentParameterNames.ExpireYear); if (!expireYear.IsInteger() || !expireMonth.IsInteger()) { VerboseReporter.ReportError("Invalid expiration month or year", "process_payment"); return(RespondFailure()); } //card issuer var cardIssuer = PaymentCardHelper.GetCardTypeFromNumber(creditCardNumber); if (!cardIssuer.HasValue) { VerboseReporter.ReportError("Unsupported card provider", "process_payment"); return(RespondFailure()); } var nameOnCard = parameters.Get(PaymentParameterNames.NameOnCard); //encrypt credit card info to store in db var key = ConfigurationManager.AppSettings.Get("EncryptionKey"); var salt = ConfigurationManager.AppSettings.Get("Salt"); var cardNumber = _cryptographyService.Encrypt(creditCardNumber, key, salt); //encrypt the card info //fine if the card is valid, but is the card number already in our record, then not possible to save the same again if (_paymentMethodService.DoesCardNumberExist(cardNumber)) { VerboseReporter.ReportError("The card number is already saved in records", "process_payment"); return(RespondFailure()); } paymentMethod = new UserPaymentMethod() { UserId = ApplicationContext.Current.CurrentUser.Id, IsVerified = false, PaymentMethodType = PaymentMethodType.CreditCard, CardIssuerType = cardIssuer.ToString().ToLowerInvariant(), CardNumber = creditCardNumber, CardNumberMasked = PaymentCardHelper.MaskCardNumber(creditCardNumber), NameOnCard = nameOnCard, }; //save this payment method _paymentMethodService.Insert(paymentMethod); #endregion } } //we need to see if we should only authorize or capture as well //the idea is if it's a sponsorship context, it's better to authorize the payment transaction and capture later when //the sponsorship is accepted //we thought of initially only authorizing sponsorship transactions and capture when it's accepted. //but that flow doesn't seem to work quite well, thoughts? var authorizeOnly = false; // (parameters.Get(PaymentParameterNames.PaymentContext) ?? string.Empty) == "sponsor"; //so we are ready for payment processing, let's create a paymenttrasaction for storing in our db var paymentTransaction = new PaymentTransaction() { IsLocalTransaction = true, PaymentStatus = PaymentStatus.Pending, TransactionAmount = amount, TransactionGuid = Guid.NewGuid(), CreatedOn = DateTime.UtcNow, UserIpAddress = WebHelper.GetClientIpAddress() }; _paymentTransactionService.Insert(paymentTransaction); //now proceed further with the payment //create the transaction request var transactionRequest = new TransactionRequest() { Amount = amount, CurrencyIsoCode = "USD",//TODO: SET CURRENCY AS SELECTED BY USER PaymentProcessorSystemName = paymentProcessor.PluginInfo.SystemName, UserId = ApplicationContext.Current.CurrentUser.Id, Parameters = formCollectionDictionary, TransactionUniqueId = paymentTransaction.TransactionGuid.ToString() }; var response = paymentProcessor.Process(transactionRequest, authorizeOnly); //update values of transaction parameters for future reference paymentTransaction.TransactionCodes = response.ResponseParameters; //update payment transaction _paymentTransactionService.Update(paymentTransaction); if (response.Success) { //let's verify the payment method first if it's not if (paymentMethod != null && !paymentMethod.IsVerified) { paymentMethod.IsVerified = true; _paymentMethodService.Update(paymentMethod); } //now since the response was success, we can actually assign some credits to the user var creditCount = amount * (1 / _paymentSettings.CreditExchangeRate); var credit = new Credit() { PaymentTransactionId = paymentTransaction.Id, CreatedOnUtc = DateTime.UtcNow, CreditCount = creditCount, CreditExchangeRate = _paymentSettings.CreditExchangeRate, //if it's authorize only transaction, we assign the credits, but they won't be usable before they are approved by capture CreditTransactionType = CreditTransactionType.Issued, CreditType = CreditType.Transactional, IsExpired = false }; //save credit _creditService.Insert(credit); //get total available credits of user var usableCreditCount = _creditService.GetUsableCreditsCount(ApplicationContext.Current.CurrentUser.Id); return(RespondSuccess(new { UsableCreditCount = usableCreditCount })); } VerboseReporter.ReportError("An error occured while processing payment", "process_payment"); return(RespondFailure()); }
public OrderDto CreateNewOrder(string email, OrderInputModel order) { // Get user information var user = _dbContext.Users.FirstOrDefault(u => u.Email == email); if (user == null) { throw new ResourceMissingException("No user was found with this email."); } // Get user address, throw exception if none is found Address address; if (order.AddressId != 0) { // Find given address address = _dbContext.Addresses.FirstOrDefault(a => a.Id == order.AddressId); } else { // Find a address if none is given address = _dbContext.Addresses.FirstOrDefault(a => a.UserId == user.Id); } if (address == null) { throw new ResourceNotFoundException($"No address with id {order.AddressId} was found."); } // Get user card information, throw exception if none is found PaymentCard paymentCard; if (order.PaymentCardId != 0) { // Find given payment card paymentCard = _dbContext.PaymentCards.FirstOrDefault(c => c.Id == order.PaymentCardId); } else { // Find a payment if none is given paymentCard = _dbContext.PaymentCards.FirstOrDefault(c => c.UserId == user.Id); } if (paymentCard == null) { throw new ResourceNotFoundException($"No payment card with id {order.PaymentCardId} was found."); } // Get user shoppingcart or create new cart if none exists var cart = _dbContext.ShoppingCarts.FirstOrDefault(c => c.UserId == user.Id); if (cart == null) { throw new ResourceMissingException("Shopping cart is empty."); } // Create order items from cart items var orderItems = _dbContext.ShoppingCartItems .Where(i => i.ShoppingCartId == cart.Id) .Select(i => new OrderItem { Id = i.Id, ProductIdentifier = i.ProductIdentifier, Quantity = i.Quantity, UnitPrice = i.UnitPrice, TotalPrice = i.Quantity * i.UnitPrice }) .ToList(); if (!orderItems.Any()) { throw new ResourceMissingException("Shopping cart is empty."); } // Calculate total order price var totalPrice = 0F; foreach (var item in orderItems) { totalPrice += item.TotalPrice; } var maskedCardNumber = PaymentCardHelper.MaskPaymentCard(paymentCard.CardNumber); // Create and save order var entity = new Order { Email = user.Email, FullName = user.FullName, StreetName = address.StreetName, HouseNumber = address.HouseNumber, ZipCode = address.ZipCode, Country = address.Country, City = address.City, CardholderName = paymentCard.CardholderName, MaskedCreditCard = maskedCardNumber, OrderDate = DateTime.Now, TotalPrice = totalPrice }; _dbContext.Orders.Add(entity); _dbContext.SaveChanges(); // Save order items AddOrderItems(entity.Id, orderItems); // Create and return order DTO var dto = ToOrderDto(entity); dto.CreditCard = paymentCard.CardNumber; dto.OrderItems = GetOrderItems(dto.Id); return(dto); }
public OrderDto CreateNewOrder(string email, OrderInputModel order) { // Find user var user = _dbContext.Users.FirstOrDefault(u => u.Email == email); // Find address var address = _dbContext.Addresses.FirstOrDefault(a => a.UserId == user.Id && a.Id == order.AddressId); if (address == null) { throw new ResourceNotFoundException($"Address with id {order.AddressId} not found."); } // Find payment card var paymentCard = _dbContext.PaymentCards.FirstOrDefault(p => p.UserId == user.Id && p.Id == order.PaymentCardId); if (paymentCard == null) { throw new ResourceNotFoundException($"Payment card with id {order.PaymentCardId} not found."); } var cart = _dbContext.ShoppingCarts.FirstOrDefault(s => s.UserId == user.Id); if (cart == null) { throw new Exception("Shopping cart is empty."); } var cartItems = _dbContext.ShoppingCartItems.Where(s => s.ShoppingCartId == cart.Id); if (!cartItems.Any()) { throw new Exception("Shopping cart is empty."); } // Find the total price var totalPrice = 0.0; foreach (var cartItem in cartItems) { totalPrice += cartItem.Quantity * cartItem.UnitPrice; } // Mask the credit card with helper function var maskedCreditCard = PaymentCardHelper.MaskPaymentCard(paymentCard.CardNumber); // Add the order to the database var newOrder = new Order { UserId = user.Id, Email = user.Email, FullName = user.FullName, StreetName = address.StreetName, HouseNumber = address.HouseNumber, ZipCode = address.ZipCode, Country = address.Country, City = address.City, CardholderName = paymentCard.CardholderName, MaskedCreditCard = maskedCreditCard, OrderDate = DateTime.Now, TotalPrice = (float)totalPrice, }; _dbContext.Orders.Add(newOrder); _dbContext.SaveChanges(); // Map cart items to order items foreach (var cartItem in cartItems) { var newOrderItem = new OrderItem { ProductIdentifier = cartItem.ProductIdentifier, Quantity = cartItem.Quantity, UnitPrice = cartItem.UnitPrice, TotalPrice = cartItem.Quantity * cartItem.UnitPrice, OrderId = newOrder.Id }; _dbContext.OrderItems.Add(newOrderItem); } _dbContext.SaveChanges(); var orderItems = _dbContext.OrderItems.Where(o => o.OrderId == newOrder.Id).ToList(); // Map order items to dto var orderItemsDtoList = _mapper.Map <List <OrderItemDto> >(orderItems); // Map order to dto and return var newOrderDto = new OrderDto { Id = newOrder.Id, Email = user.Email, FullName = user.FullName, StreetName = address.StreetName, HouseNumber = address.HouseNumber, ZipCode = address.ZipCode, Country = address.Country, City = address.City, CardholderName = paymentCard.CardholderName, CreditCard = paymentCard.CardNumber, OrderDate = newOrder.OrderDate.ToString("MM.dd.yyyy"), TotalPrice = (float)totalPrice, OrderItems = orderItemsDtoList }; return(newOrderDto); }