public ActionResult Subscribe(SubscriptionRegistration registrationInformation)
        {
            registrationInformation.AvailableSubscriptionTypes = _database.SubscriptionTypes.Include(st => st.SubscriptionFrequency).Where(st => st.IsAvailableToUsers && !st.IsAddOn);
            registrationInformation.Countries = _database.Countries.AsEnumerable();

            if (registrationInformation.SelectedSubscriptionTypeId == 0)
            {
                ModelState.AddModelError(string.Empty, "Please choose a subscription to continue.");
            }

            // If all credit card information has been supplied, then try to validate the request with Authorize.NET
            if (ModelState.IsValid)
            {
                ISubscriptionGateway gateway = GetSubscriptionGateway();

                ISubscriptionRequest subscriptionRequest  = MembersController.CreateAuthorizeDotNetSubscriptionRequest(registrationInformation);
                ISubscriptionRequest subscriptionResponse = null;

                try
                {
                    subscriptionResponse = gateway.CreateSubscription(subscriptionRequest);
                }
                catch (InvalidOperationException exception)
                {
                    ModelState.AddModelError(string.Empty, exception.Message);

                    return(View(registrationInformation));
                }

                // If we reach this part of the code, we have successfully scheduled a subscription, make a note of it in our system
                WebSite.Models.User currentUser = Authentication.GetCurrentUser();
                DatabaseContext     db          = _database;

                // Encrypt the credit card information of the user
                registrationInformation.CreditCard.Encrypt();

                // Construct a subscription for the user
                Subscription userSubscription = new Subscription()
                {
                    ActivationDate             = DateTime.UtcNow,
                    AuthorizeNETSubscriptionId = subscriptionResponse.SubscriptionID,
                    CancellationDate           = null,
                    SubscriptionTypeId         = registrationInformation.SelectedSubscriptionTypeId,
                    CreditCard = registrationInformation.CreditCard
                };

                // Associate the subscription with the user
                currentUser.AddSubscription(userSubscription);

                db.SaveChanges();

                return(this.RedirectToAction("Index"));
            }

            return(View(registrationInformation));
        }
        public ActionResult AddAutoTrading(AddonRegistration registrationInformation)
        {
            if (ModelState.IsValid)
            {
                SubscriptionType autoTradingAddOn = _database.SubscriptionTypes.Include(st => st.SubscriptionFrequency).Where(st => st.IsAvailableToUsers && st.IsAddOn).FirstOrDefault();

                if (autoTradingAddOn != null)
                {
                    ISubscriptionGateway gateway             = GetSubscriptionGateway();
                    ISubscriptionRequest subscriptionRequest = MembersController.CreateAuthorizeDotNetSubscriptionRequest(registrationInformation.CreditCard, autoTradingAddOn);

                    ISubscriptionRequest subscriptionResponse = null;

                    try
                    {
                        subscriptionResponse = gateway.CreateSubscription(subscriptionRequest);
                    }
                    catch (InvalidOperationException exception)
                    {
                        ModelState.AddModelError(string.Empty, exception.Message);

                        return(View(registrationInformation));
                    }

                    // If the code reaches here then the payment went through
                    WebSite.Models.User currentUser = Authentication.GetCurrentUser();

                    // Encrypt the credit card information of the user
                    registrationInformation.CreditCard.Encrypt();

                    // Construct a subscription for the user
                    Subscription userSubscription = new Subscription()
                    {
                        ActivationDate             = DateTime.UtcNow,
                        AuthorizeNETSubscriptionId = subscriptionResponse.SubscriptionID,
                        CancellationDate           = null,
                        SubscriptionTypeId         = autoTradingAddOn.SubscriptionTypeId,
                        CreditCard = registrationInformation.CreditCard
                    };

                    // Associate the subscription with the user
                    currentUser.AddAddOnSubscription(userSubscription);

                    _database.SaveChanges();

                    return(this.RedirectToAction("Index"));
                }
                else
                {
                    this.ModelState.AddModelError(string.Empty, "Can't locate auto-trading add-on in server");
                }
            }

            return(View(registrationInformation));
        }
        /// <summary>
        /// Tries to enable the auto-trading add-on using an existing credit card from the user
        /// </summary>
        /// <returns></returns>
        private ActionResult TryAddingAutoTradingFromExistingCreditCard()
        {
            User       currentUser          = Authentication.GetCurrentUser();
            CreditCard successfulCreditCard = null;

            foreach (CreditCard card in currentUser.CreditCards)
            {
                try
                {
                    card.Decrypt();
                }
                catch
                {
                    continue;
                }

                successfulCreditCard = card;
                break;
            }

            // If we could not find any credit cards then bail
            if (successfulCreditCard == null)
            {
                return(null);
            }

            SubscriptionType autoTradingAddOn = _database.SubscriptionTypes.Include(st => st.SubscriptionFrequency).Where(st => st.IsAvailableToUsers && st.IsAddOn).FirstOrDefault();

            if (autoTradingAddOn == null)
            {
                return(null);
            }

            ISubscriptionGateway gateway              = GetSubscriptionGateway();
            ISubscriptionRequest subscriptionRequest  = MembersController.CreateAuthorizeDotNetSubscriptionRequest(successfulCreditCard, autoTradingAddOn);
            ISubscriptionRequest subscriptionResponse = null;

            try
            {
                subscriptionResponse = gateway.CreateSubscription(subscriptionRequest);
            }
            catch (InvalidOperationException)
            {
                return(null);
            }

            // Encrypt the credit card information of the user
            successfulCreditCard.Encrypt();

            // Construct a subscription for the user
            Subscription userSubscription = new Subscription()
            {
                ActivationDate             = DateTime.UtcNow,
                AuthorizeNETSubscriptionId = subscriptionResponse.SubscriptionID,
                CancellationDate           = null,
                SubscriptionTypeId         = autoTradingAddOn.SubscriptionTypeId,
                CreditCard = successfulCreditCard
            };

            // Associate the subscription with the user
            currentUser.AddAddOnSubscription(userSubscription);

            _database.SaveChanges();

            return(this.RedirectToAction("Index"));
        }
        public void PostBack()
        {
            // If the post back is about a recurring payment, it'll have a subscription ID field in the request
            if (string.IsNullOrEmpty(Request.Form["x_subscription_id"]))
            {
                return;
            }

            // We can't handle a request if there is no response code sent to us
            if (string.IsNullOrEmpty(Request.Form["x_response_code"]))
            {
                return;
            }

            // If the payment was successful, we don't really care to do anything
            if (string.CompareOrdinal(Request.Form["x_response_code"], "1") == 0)
            {
                return;
            }

            // For any other response code the payment has failed, we need to set the subscription of the user to suspended and send them an email
            // letting them know something is wrong
            string subscriptionId = Request.Form["x_subscription_id"];

            DatabaseContext db = _database;

            // Load the subscription and figure out which user it belongs to
            Subscription subscription = db.Subscriptions.Include(s => s.CreditCard).FirstOrDefault(s => s.AuthorizeNETSubscriptionId == subscriptionId);

            // Could we successfully load the subscription Authorize.NET is talking about?
            if (subscription == null)
            {
                // TODO: Log Error
                return;
            }

            User affectedUser = (from user in db.Users.Include(u => u.Subscription)
                                 where user.SubscriptionId.HasValue && user.Subscription.SubscriptionId == subscription.SubscriptionId
                                 select user).FirstOrDefault();

            // Could we locate a user with an active subscription?
            if (affectedUser == null)
            {
                // TODO: Log Error
                return;
            }

            bool successfulRenewal = false;

            // Mark the subscription as suspended
            subscription.IsSuspended = true;

            // Check to see whether the card is expired, if so, try to renew the subscription with a new year
            if (subscription.CreditCard.IsExpired())
            {
                // Decrypt to get the card information again
                bool successfulDecryption = true;
                try
                {
                    subscription.CreditCard.Decrypt();
                }
                catch (Exception)
                {
                    successfulDecryption = false;
                }

                if (successfulDecryption)
                {
                    // Bump up the expiry by 2 years
                    CreditCard newCard = new CreditCard()
                    {
                        AddressId           = subscription.CreditCard.AddressId,
                        BillingAddress      = subscription.CreditCard.BillingAddress,
                        CardholderFirstName = subscription.CreditCard.CardholderFirstName,
                        CardholderLastName  = subscription.CreditCard.CardholderLastName,
                        CVV             = subscription.CreditCard.CVV,
                        ExpirationMonth = subscription.CreditCard.ExpirationMonth,
                        ExpirationYear  = (short)(subscription.CreditCard.ExpirationYear + 2),
                        Number          = subscription.CreditCard.Number
                    };

                    ISubscriptionGateway gateway = MembersController.GetSubscriptionGateway();

                    ISubscriptionRequest subscriptionRequest  = MembersController.CreateAuthorizeDotNetSubscriptionRequest(newCard, subscription.SubscriptionType, affectedUser);
                    ISubscriptionRequest subscriptionResponse = null;

                    bool successfulTry = true;

                    try
                    {
                        subscriptionResponse = gateway.CreateSubscription(subscriptionRequest);
                    }
                    catch (InvalidOperationException)
                    {
                        // Payment failed again
                        successfulTry = false;
                    }

                    successfulRenewal = successfulTry;

                    if (successfulTry)
                    {
                        // Encrypt the credit card information of the user
                        newCard.Encrypt();

                        // Construct a subscription for the user
                        Subscription userSubscription = new Subscription()
                        {
                            ActivationDate             = DateTime.UtcNow,
                            AuthorizeNETSubscriptionId = subscriptionResponse.SubscriptionID,
                            CancellationDate           = null,
                            SubscriptionTypeId         = subscription.SubscriptionTypeId,
                            CreditCard = newCard
                        };

                        // Associate the new subscription with the user
                        affectedUser.AddSubscription(userSubscription);
                    }
                }
            }

            db.SaveChanges();

            if (!successfulRenewal)
            {
                // If we could not automatically renew the payment, then notify the user
                EmailResult email = new WebSite.Mailers.Account().PaymentSuspendedEmail(affectedUser);

                WebSite.Helpers.Email.SendEmail(email, new List <Models.User>()
                {
                    affectedUser
                });
            }

            return;
        }