public JsonResult ChangePlan(string organizationId, string planId)
        {
            if (String.IsNullOrEmpty(organizationId) || !User.CanAccessOrganization(organizationId))
            {
                throw new ArgumentException("Invalid organization id.", "organizationId"); // TODO: These should probably throw http Response exceptions.
            }
            Organization organization = _repository.GetById(organizationId);

            if (organization == null)
            {
                return(Json(new { Success = false, Message = "Invalid OrganizationId." }));
            }

            BillingPlan plan = _billingManager.GetBillingPlan(planId);

            if (plan == null)
            {
                return(Json(new { Success = false, Message = "Invalid PlanId." }));
            }

            organization.BillingStatus = !String.Equals(plan.Id, BillingManager.FreePlan.Id) ? BillingStatus.Active : BillingStatus.Trialing;
            organization.RemoveSuspension();
            _billingManager.ApplyBillingPlan(organization, plan, User.UserEntity, false);

            _repository.Update(organization);
            _notificationSender.PlanChanged(organization.Id);

            return(Json(new { Success = true }));
        }
        public async Task <IActionResult> ChangePlanAsync([FromQuery] string organizationId, [FromQuery] string planId)
        {
            if (String.IsNullOrEmpty(organizationId) || !CanAccessOrganization(organizationId))
            {
                return(Ok(new { Success = false, Message = "Invalid Organization Id." }));
            }

            var organization = await _organizationRepository.GetByIdAsync(organizationId);

            if (organization == null)
            {
                return(Ok(new { Success = false, Message = "Invalid Organization Id." }));
            }

            var plan = BillingManager.GetBillingPlan(planId);

            if (plan == null)
            {
                return(Ok(new { Success = false, Message = "Invalid PlanId." }));
            }

            organization.BillingStatus = !String.Equals(plan.Id, BillingManager.FreePlan.Id) ? BillingStatus.Active : BillingStatus.Trialing;
            organization.RemoveSuspension();
            BillingManager.ApplyBillingPlan(organization, plan, CurrentUser, false);

            await _organizationRepository.SaveAsync(organization);

            await _messagePublisher.PublishAsync(new PlanChanged {
                OrganizationId = organization.Id
            });

            return(Ok(new { Success = true }));
        }
Exemple #3
0
        public IHttpActionResult ChangePlan(string organizationId, string planId)
        {
            if (String.IsNullOrEmpty(organizationId) || !CanAccessOrganization(organizationId))
            {
                return(Ok(new { Success = false, Message = "Invalid Organization Id." }));
            }

            var organization = _repository.GetById(organizationId);

            if (organization == null)
            {
                return(Ok(new { Success = false, Message = "Invalid Organization Id." }));
            }

            var plan = BillingManager.GetBillingPlan(planId);

            if (plan == null)
            {
                return(Ok(new { Success = false, Message = "Invalid PlanId." }));
            }

            organization.BillingStatus = !String.Equals(plan.Id, BillingManager.FreePlan.Id) ? BillingStatus.Active : BillingStatus.Trialing;
            organization.RemoveSuspension();
            _billingManager.ApplyBillingPlan(organization, plan, ExceptionlessUser, false);

            _repository.Save(organization);
            _messagePublisher.Publish(new PlanChanged {
                OrganizationId = organization.Id
            });

            return(Ok(new { Success = true }));
        }
Exemple #4
0
        private void UpgradePlan(Organization organization)
        {
            var plan = _billingManager.GetBillingPlan(organization.PlanId);

            if (plan == null)
            {
                Log.LogError("Unable to find a valid plan for organization: {organization}", organization.Id);
                return;
            }

            _billingManager.ApplyBillingPlan(organization, plan, user: null, updateBillingPrice: false);
        }
        private void UpgradePlan(Organization organization)
        {
            var plan = BillingManager.GetBillingPlan(organization.PlanId);

            if (plan == null)
            {
                _logger.Error().Message("Unable to find a valid plan for organization: {0}", organization.Id).Write();
                return;
            }

            BillingManager.ApplyBillingPlan(organization, plan, user: null, updateBillingPrice: false);
        }
Exemple #6
0
        public override void UpdateDocument(MongoCollection <BsonDocument> collection, BsonDocument document)
        {
            if (document.Contains("ErrorCount"))
            {
                document.ChangeName("ErrorCount", "EventCount");
            }

            if (document.Contains("TotalErrorCount"))
            {
                document.ChangeName("TotalErrorCount", "TotalEventCount");
            }

            if (document.Contains("LastErrorDate"))
            {
                document.ChangeName("LastErrorDate", "LastEventDate");
            }

            if (document.Contains("MaxErrorsPerMonth"))
            {
                document.ChangeName("MaxErrorsPerMonth", "MaxEventsPerMonth");
            }

            if (document.Contains("SuspensionCode"))
            {
                var value = document.GetValue("SuspensionCode");
                document.Remove("SuspensionCode");

                SuspensionCode suspensionCode;
                if (value.IsString && Enum.TryParse(value.AsString, true, out suspensionCode))
                {
                    document.Set("SuspensionCode", suspensionCode);
                }
            }

            if (document.Contains("PlanId"))
            {
                string planId      = document.GetValue("PlanId").AsString;
                var    currentPlan = BillingManager.GetBillingPlan(planId);

                document.Set("PlanName", currentPlan != null ? currentPlan.Name : planId);
                document.Set("PlanDescription", currentPlan != null ? currentPlan.Description : planId);
            }

            collection.Save(document);
        }
Exemple #7
0
        public async Task <IHttpActionResult> ChangePlanAsync(string id, string planId, string stripeToken = null, string last4 = null, string couponId = null)
        {
            if (String.IsNullOrEmpty(id) || !CanAccessOrganization(id))
            {
                return(NotFound());
            }

            if (!Settings.Current.EnableBilling)
            {
                return(Ok(ChangePlanResult.FailWithMessage("Plans cannot be changed while billing is disabled.")));
            }

            var organization = await GetModelAsync(id, false);

            if (organization == null)
            {
                return(Ok(ChangePlanResult.FailWithMessage("Invalid OrganizationId.")));
            }

            var plan = BillingManager.GetBillingPlan(planId);

            if (plan == null)
            {
                return(Ok(ChangePlanResult.FailWithMessage("Invalid PlanId.")));
            }

            if (String.Equals(organization.PlanId, plan.Id) && String.Equals(BillingManager.FreePlan.Id, plan.Id))
            {
                return(Ok(ChangePlanResult.SuccessWithMessage("Your plan was not changed as you were already on the free plan.")));
            }

            // Only see if they can downgrade a plan if the plans are different.
            if (!String.Equals(organization.PlanId, plan.Id))
            {
                var result = await _billingManager.CanDownGradeAsync(organization, plan, CurrentUser);

                if (!result.Success)
                {
                    return(Ok(result));
                }
            }

            var customerService     = new StripeCustomerService(Settings.Current.StripeApiKey);
            var subscriptionService = new StripeSubscriptionService(Settings.Current.StripeApiKey);

            try {
                // If they are on a paid plan and then downgrade to a free plan then cancel their stripe subscription.
                if (!String.Equals(organization.PlanId, BillingManager.FreePlan.Id) && String.Equals(plan.Id, BillingManager.FreePlan.Id))
                {
                    if (!String.IsNullOrEmpty(organization.StripeCustomerId))
                    {
                        var subs = await subscriptionService.ListAsync(new StripeSubscriptionListOptions { CustomerId = organization.StripeCustomerId });

                        foreach (var sub in subs.Where(s => !s.CanceledAt.HasValue))
                        {
                            await subscriptionService.CancelAsync(sub.Id);
                        }
                    }

                    organization.BillingStatus = BillingStatus.Trialing;
                    organization.RemoveSuspension();
                }
                else if (String.IsNullOrEmpty(organization.StripeCustomerId))
                {
                    if (String.IsNullOrEmpty(stripeToken))
                    {
                        return(Ok(ChangePlanResult.FailWithMessage("Billing information was not set.")));
                    }

                    organization.SubscribeDate = SystemClock.UtcNow;

                    var createCustomer = new StripeCustomerCreateOptions {
                        SourceToken = stripeToken,
                        PlanId      = planId,
                        Description = organization.Name,
                        Email       = CurrentUser.EmailAddress
                    };

                    if (!String.IsNullOrWhiteSpace(couponId))
                    {
                        createCustomer.CouponId = couponId;
                    }

                    var customer = await customerService.CreateAsync(createCustomer);

                    organization.BillingStatus = BillingStatus.Active;
                    organization.RemoveSuspension();
                    organization.StripeCustomerId = customer.Id;
                    if (customer.Sources.TotalCount > 0)
                    {
                        organization.CardLast4 = customer.Sources.Data.First().Card.Last4;
                    }
                }
                else
                {
                    var update = new StripeSubscriptionUpdateOptions {
                        PlanId = planId
                    };
                    var  create      = new StripeSubscriptionCreateOptions();
                    bool cardUpdated = false;

                    if (!String.IsNullOrEmpty(stripeToken))
                    {
                        update.Source = stripeToken;
                        create.Source = stripeToken;
                        cardUpdated   = true;
                    }

                    var subscriptionList = await subscriptionService.ListAsync(new StripeSubscriptionListOptions { CustomerId = organization.StripeCustomerId });

                    var subscription = subscriptionList.FirstOrDefault(s => !s.CanceledAt.HasValue);
                    if (subscription != null)
                    {
                        await subscriptionService.UpdateAsync(subscription.Id, update);
                    }
                    else
                    {
                        await subscriptionService.CreateAsync(organization.StripeCustomerId, planId, create);
                    }

                    await customerService.UpdateAsync(organization.StripeCustomerId, new StripeCustomerUpdateOptions {
                        Email = CurrentUser.EmailAddress
                    });

                    if (cardUpdated)
                    {
                        organization.CardLast4 = last4;
                    }

                    organization.BillingStatus = BillingStatus.Active;
                    organization.RemoveSuspension();
                }

                BillingManager.ApplyBillingPlan(organization, plan, CurrentUser);
                await _repository.SaveAsync(organization, o => o.Cache());

                await _messagePublisher.PublishAsync(new PlanChanged { OrganizationId = organization.Id });
            } catch (Exception e) {
                _logger.Error().Exception(e).Message("An error occurred while trying to update your billing plan: " + e.Message).Critical().Identity(CurrentUser.EmailAddress).Property("User", CurrentUser).SetActionContext(ActionContext).Write();
                return(Ok(ChangePlanResult.FailWithMessage(e.Message)));
            }

            return(Ok(new ChangePlanResult {
                Success = true
            }));
        }
 public void GetBillingPlan()
 {
     Assert.Equal(BillingManager.FreePlan.Id, BillingManager.GetBillingPlan(BillingManager.FreePlan.Id).Id);
 }
        public async Task <ActionResult <Invoice> > GetInvoiceAsync(string id)
        {
            if (!Settings.Current.EnableBilling)
            {
                return(NotFound());
            }

            if (!id.StartsWith("in_"))
            {
                id = "in_" + id;
            }

            StripeInvoice stripeInvoice = null;

            try {
                var invoiceService = new StripeInvoiceService(Settings.Current.StripeApiKey);
                stripeInvoice = await invoiceService.GetAsync(id);
            } catch (Exception ex) {
                using (_logger.BeginScope(new ExceptionlessState().Tag("Invoice").Identity(CurrentUser.EmailAddress).Property("User", CurrentUser).SetHttpContext(HttpContext)))
                    _logger.LogError(ex, "An error occurred while getting the invoice: {InvoiceId}", id);
            }

            if (String.IsNullOrEmpty(stripeInvoice?.CustomerId))
            {
                return(NotFound());
            }

            var organization = await _repository.GetByStripeCustomerIdAsync(stripeInvoice.CustomerId);

            if (organization == null || !CanAccessOrganization(organization.Id))
            {
                return(NotFound());
            }

            var invoice = new Invoice {
                Id               = stripeInvoice.Id.Substring(3),
                OrganizationId   = organization.Id,
                OrganizationName = organization.Name,
                Date             = stripeInvoice.Date.GetValueOrDefault(),
                Paid             = stripeInvoice.Paid,
                Total            = stripeInvoice.Total / 100.0
            };

            foreach (var line in stripeInvoice.StripeInvoiceLineItems.Data)
            {
                var item = new InvoiceLineItem {
                    Amount = line.Amount / 100.0
                };

                if (line.Plan != null)
                {
                    string planName = line.Plan.Nickname ?? BillingManager.GetBillingPlan(line.Plan.Id)?.Name;
                    item.Description = $"Exceptionless - {planName} Plan ({(line.Plan.Amount / 100.0):c}/{line.Plan.Interval})";
                }
                else
                {
                    item.Description = line.Description;
                }

                item.Date = $"{(line.StripePeriod.Start ?? stripeInvoice.PeriodStart).ToShortDateString()} - {(line.StripePeriod.End ?? stripeInvoice.PeriodEnd).ToShortDateString()}";
                invoice.Items.Add(item);
            }

            var coupon = stripeInvoice.StripeDiscount?.StripeCoupon;

            if (coupon != null)
            {
                if (coupon.AmountOff.HasValue)
                {
                    double discountAmount = coupon.AmountOff.GetValueOrDefault() / 100.0;
                    string description    = $"{coupon.Id} ({discountAmount.ToString("C")} off)";
                    invoice.Items.Add(new InvoiceLineItem {
                        Description = description, Amount = discountAmount
                    });
                }
                else
                {
                    double discountAmount = (stripeInvoice.Subtotal / 100.0) * (coupon.PercentOff.GetValueOrDefault() / 100.0);
                    string description    = $"{coupon.Id} ({coupon.PercentOff.GetValueOrDefault()}% off)";
                    invoice.Items.Add(new InvoiceLineItem {
                        Description = description, Amount = discountAmount
                    });
                }
            }

            return(Ok(invoice));
        }
        public IHttpActionResult ChangePlan(string id, string planId, string stripeToken = null, string last4 = null, string couponId = null)
        {
            if (String.IsNullOrEmpty(id) || !CanAccessOrganization(id))
            {
                return(BadRequest("Invalid organization id."));
            }

            if (!Settings.Current.EnableBilling)
            {
                return(Ok(new { Success = false, Message = "Plans cannot be changed while billing is disabled." }));
            }

            Organization organization = _repository.GetById(id);

            if (organization == null)
            {
                return(Ok(new { Success = false, Message = "Invalid OrganizationId." }));
            }

            BillingPlan plan = BillingManager.GetBillingPlan(planId);

            if (plan == null)
            {
                return(Ok(new { Success = false, Message = "Invalid PlanId." }));
            }

            if (String.Equals(organization.PlanId, plan.Id) && String.Equals(BillingManager.FreePlan.Id, plan.Id))
            {
                return(Ok(new { Success = true, Message = "Your plan was not changed as you were already on the free plan." }));
            }

            // Only see if they can downgrade a plan if the plans are different.
            string message;

            if (!String.Equals(organization.PlanId, plan.Id) && !_billingManager.CanDownGrade(organization, plan, ExceptionlessUser, out message))
            {
                return(Ok(new { Success = false, Message = message }));
            }

            var customerService     = new StripeCustomerService();
            var subscriptionService = new StripeSubscriptionService();

            try {
                // If they are on a paid plan and then downgrade to a free plan then cancel their stripe subscription.
                if (!String.Equals(organization.PlanId, BillingManager.FreePlan.Id) && String.Equals(plan.Id, BillingManager.FreePlan.Id))
                {
                    if (!String.IsNullOrEmpty(organization.StripeCustomerId))
                    {
                        var subs = subscriptionService.List(organization.StripeCustomerId).Where(s => !s.CanceledAt.HasValue);
                        foreach (var sub in subs)
                        {
                            subscriptionService.Cancel(organization.StripeCustomerId, sub.Id);
                        }
                    }

                    organization.BillingStatus = BillingStatus.Trialing;
                    organization.RemoveSuspension();
                }
                else if (String.IsNullOrEmpty(organization.StripeCustomerId))
                {
                    if (String.IsNullOrEmpty(stripeToken))
                    {
                        return(Ok(new { Success = false, Message = "Billing information was not set." }));
                    }

                    organization.SubscribeDate = DateTime.Now;

                    var createCustomer = new StripeCustomerCreateOptions {
                        TokenId     = stripeToken,
                        PlanId      = planId,
                        Description = organization.Name,
                        Email       = ExceptionlessUser.EmailAddress
                    };

                    if (!String.IsNullOrWhiteSpace(couponId))
                    {
                        createCustomer.CouponId = couponId;
                    }

                    StripeCustomer customer = customerService.Create(createCustomer);

                    organization.BillingStatus = BillingStatus.Active;
                    organization.RemoveSuspension();
                    organization.StripeCustomerId = customer.Id;
                    if (customer.StripeCardList.StripeCards.Count > 0)
                    {
                        organization.CardLast4 = customer.StripeCardList.StripeCards[0].Last4;
                    }
                }
                else
                {
                    var update = new StripeSubscriptionUpdateOptions {
                        PlanId = planId
                    };
                    var  create      = new StripeSubscriptionCreateOptions();
                    bool cardUpdated = false;

                    if (!String.IsNullOrEmpty(stripeToken))
                    {
                        update.TokenId = stripeToken;
                        create.TokenId = stripeToken;
                        cardUpdated    = true;
                    }

                    var subscription = subscriptionService.List(organization.StripeCustomerId).FirstOrDefault(s => !s.CanceledAt.HasValue);
                    if (subscription != null)
                    {
                        subscriptionService.Update(organization.StripeCustomerId, subscription.Id, update);
                    }
                    else
                    {
                        subscriptionService.Create(organization.StripeCustomerId, planId, create);
                    }

                    customerService.Update(organization.StripeCustomerId, new StripeCustomerUpdateOptions {
                        Email = ExceptionlessUser.EmailAddress
                    });

                    if (cardUpdated)
                    {
                        organization.CardLast4 = last4;
                    }

                    organization.BillingStatus = BillingStatus.Active;
                    organization.RemoveSuspension();
                }

                _billingManager.ApplyBillingPlan(organization, plan, ExceptionlessUser);
                _repository.Save(organization);

                _messagePublisher.Publish(new PlanChanged {
                    OrganizationId = organization.Id
                });
            } catch (Exception e) {
                Log.Error().Exception(e).Message("An error occurred while trying to update your billing plan: " + e.Message).Report(r => r.MarkAsCritical()).Write();
                return(Ok(new { Success = false, Message = e.Message }));
            }

            return(Ok(new { Success = true }));
        }
Exemple #11
0
        public JsonResult ChangePlan(string organizationId, string planId, string stripeToken, string last4)
        {
            if (String.IsNullOrEmpty(organizationId) || !User.CanAccessOrganization(organizationId))
            {
                throw new ArgumentException("Invalid organization id.", "organizationId"); // TODO: These should probably throw http Response exceptions.
            }
            if (!Settings.Current.EnableBilling)
            {
                return(Json(new { Success = false, Message = "Plans cannot be changed while billing is disabled." }));
            }

            Organization organization = _repository.GetById(organizationId);

            if (organization == null)
            {
                return(Json(new { Success = false, Message = "Invalid OrganizationId." }));
            }

            BillingPlan plan = _billingManager.GetBillingPlan(planId);

            if (plan == null)
            {
                return(Json(new { Success = false, Message = "Invalid PlanId." }));
            }

            if (String.Equals(organization.PlanId, plan.Id) && String.Equals(BillingManager.FreePlan.Id, plan.Id))
            {
                return(Json(new { Success = true, Message = "Your plan was not changed as you were already on the free plan." }));
            }

            // Only see if they can downgrade a plan if the plans are different.
            string message;

            if (!String.Equals(organization.PlanId, plan.Id) && !_billingManager.CanDownGrade(organization, plan, User.UserEntity, out message))
            {
                return(Json(new { Success = false, Message = message }));
            }

            var customerService = new StripeCustomerService();

            try {
                // If they are on a paid plan and then downgrade to a free plan then cancel their stripe subscription.
                if (!String.Equals(organization.PlanId, BillingManager.FreePlan.Id) && String.Equals(plan.Id, BillingManager.FreePlan.Id))
                {
                    if (!String.IsNullOrEmpty(organization.StripeCustomerId))
                    {
                        customerService.CancelSubscription(organization.StripeCustomerId);
                    }

                    organization.BillingStatus = BillingStatus.Trialing;
                    organization.RemoveSuspension();
                }
                else if (String.IsNullOrEmpty(organization.StripeCustomerId))
                {
                    if (String.IsNullOrEmpty(stripeToken))
                    {
                        return(Json(new { Success = false, Message = "Billing information was not set." }));
                    }

                    organization.SubscribeDate = DateTime.Now;

                    StripeCustomer customer = customerService.Create(new StripeCustomerCreateOptions {
                        TokenId     = stripeToken,
                        PlanId      = planId,
                        Description = organization.Name
                    });

                    organization.BillingStatus = BillingStatus.Active;
                    organization.RemoveSuspension();
                    organization.StripeCustomerId = customer.Id;
                    if (customer.StripeCardList.StripeCards.Count > 0)
                    {
                        organization.CardLast4 = customer.StripeCardList.StripeCards[0].Last4;
                    }
                }
                else
                {
                    var update = new StripeCustomerUpdateSubscriptionOptions {
                        PlanId = planId
                    };
                    bool cardUpdated = false;

                    if (!String.IsNullOrEmpty(stripeToken))
                    {
                        update.TokenId = stripeToken;
                        cardUpdated    = true;
                    }

                    customerService.UpdateSubscription(organization.StripeCustomerId, update);
                    if (cardUpdated)
                    {
                        organization.CardLast4 = last4;
                    }

                    organization.BillingStatus = BillingStatus.Active;
                    organization.RemoveSuspension();
                }

                _billingManager.ApplyBillingPlan(organization, plan, User.UserEntity);
                _repository.Update(organization);

                _notificationSender.PlanChanged(organization.Id);
            } catch (Exception e) {
                Log.Error().Exception(e).Message("An error occurred while trying to update your billing plan: " + e.Message).Report().Write();
                return(Json(new { Success = false, Message = e.Message }));
            }

            return(Json(new { Success = true }));
        }