public async Task PurchasePremiumAsync(User user, string paymentToken, short additionalStorageGb) { var customerService = new StripeCustomerService(); var customer = await customerService.CreateAsync(new StripeCustomerCreateOptions { Description = user.Name, Email = user.Email, SourceToken = paymentToken }); var subCreateOptions = new StripeSubscriptionCreateOptions { CustomerId = customer.Id, Items = new List <StripeSubscriptionItemOption>(), Metadata = new Dictionary <string, string> { ["userId"] = user.Id.ToString() } }; subCreateOptions.Items.Add(new StripeSubscriptionItemOption { PlanId = PremiumPlanId, Quantity = 1 }); if (additionalStorageGb > 0) { subCreateOptions.Items.Add(new StripeSubscriptionItemOption { PlanId = StoragePlanId, Quantity = additionalStorageGb }); } StripeSubscription subscription = null; try { var subscriptionService = new StripeSubscriptionService(); subscription = await subscriptionService.CreateAsync(subCreateOptions); } catch (StripeException) { await customerService.DeleteAsync(customer.Id); throw; } user.Gateway = Enums.GatewayType.Stripe; user.GatewayCustomerId = customer.Id; user.GatewaySubscriptionId = subscription.Id; user.Premium = true; user.PremiumExpirationDate = subscription.CurrentPeriodEnd; }
public static async Task CreateSubscription(string customerId, string planId) { StripeConfiguration.SetApiKey("sk_test_5nCTR2UZmnOPWgZASvirbYDy"); List <StripeSubscriptionItemOption> items = new List <StripeSubscriptionItemOption> { new StripeSubscriptionItemOption { PlanId = planId } }; StripeSubscriptionCreateOptions subscriptionOptions = new StripeSubscriptionCreateOptions { Items = items, BillingCycleAnchor = DateTimeOffset.FromUnixTimeSeconds(1539331009).UtcDateTime, Prorate = true }; StripeSubscriptionService subscriptionService = new StripeSubscriptionService(); StripeSubscription subscription = await subscriptionService.CreateAsync(customerId, subscriptionOptions); await RequiredInvoice(subscription.Id); await UpdateInvoice(await RequiredInvoice(subscription.Id)); }
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 async Task <Tuple <Organization, OrganizationUser> > SignUpAsync(OrganizationSignup signup) { var plan = StaticStore.Plans.FirstOrDefault(p => p.Type == signup.Plan && !p.Disabled); if (plan == null) { throw new BadRequestException("Plan not found."); } var customerService = new StripeCustomerService(); var subscriptionService = new StripeSubscriptionService(); StripeCustomer customer = null; StripeSubscription subscription = null; if (!plan.CanBuyAdditionalSeats && signup.AdditionalSeats > 0) { throw new BadRequestException("Plan does not allow additional users."); } if (plan.CanBuyAdditionalSeats && plan.MaxAdditionalSeats.HasValue && signup.AdditionalSeats > plan.MaxAdditionalSeats.Value) { throw new BadRequestException($"Selected plan allows a maximum of " + $"{plan.MaxAdditionalSeats.GetValueOrDefault(0)} additional users."); } if (plan.Type == PlanType.Free) { var ownerExistingOrgCount = await _organizationUserRepository.GetCountByFreeOrganizationAdminUserAsync(signup.Owner.Id); if (ownerExistingOrgCount > 0) { throw new BadRequestException("You can only be an admin of one free organization."); } } else { customer = await customerService.CreateAsync(new StripeCustomerCreateOptions { Description = signup.BusinessName, Email = signup.BillingEmail, SourceToken = signup.PaymentToken }); var subCreateOptions = new StripeSubscriptionCreateOptions { Items = new List <StripeSubscriptionItemOption> { new StripeSubscriptionItemOption { PlanId = plan.StripePlanId, Quantity = 1 } } }; if (signup.AdditionalSeats > 0) { subCreateOptions.Items.Add(new StripeSubscriptionItemOption { PlanId = plan.StripeSeatPlanId, Quantity = signup.AdditionalSeats }); } try { subscription = await subscriptionService.CreateAsync(customer.Id, subCreateOptions); } catch (StripeException) { if (customer != null) { await customerService.DeleteAsync(customer.Id); } throw; } } var organization = new Organization { Name = signup.Name, BillingEmail = signup.BillingEmail, BusinessName = signup.BusinessName, PlanType = plan.Type, Seats = (short)(plan.BaseSeats + signup.AdditionalSeats), MaxSubvaults = plan.MaxSubvaults, Plan = plan.Name, StripeCustomerId = customer?.Id, StripeSubscriptionId = subscription?.Id, CreationDate = DateTime.UtcNow, RevisionDate = DateTime.UtcNow }; try { await _organizationRepository.CreateAsync(organization); var orgUser = new OrganizationUser { OrganizationId = organization.Id, UserId = signup.Owner.Id, Key = signup.OwnerKey, Type = OrganizationUserType.Owner, Status = OrganizationUserStatusType.Confirmed, AccessAllSubvaults = true, CreationDate = DateTime.UtcNow, RevisionDate = DateTime.UtcNow }; await _organizationUserRepository.CreateAsync(orgUser); // push await _pushService.PushSyncOrgKeysAsync(signup.Owner.Id); return(new Tuple <Organization, OrganizationUser>(organization, orgUser)); } catch { if (subscription != null) { await subscriptionService.CancelAsync(subscription.Id, false); } if (customer != null) { var chargeService = new StripeChargeService(); var charges = await chargeService.ListAsync(new StripeChargeListOptions { CustomerId = customer.Id }); if (charges?.Data != null) { var refundService = new StripeRefundService(); foreach (var charge in charges.Data.Where(c => !c.Refunded)) { await refundService.CreateAsync(charge.Id); } } await customerService.DeleteAsync(customer.Id); } if (organization.Id != default(Guid)) { await _organizationRepository.DeleteAsync(organization); } throw; } }
public async Task UpgradePlanAsync(Guid organizationId, PlanType plan, int additionalSeats) { var organization = await _organizationRepository.GetByIdAsync(organizationId); if (organization == null) { throw new NotFoundException(); } if (string.IsNullOrWhiteSpace(organization.StripeCustomerId)) { throw new BadRequestException("No payment method found."); } var existingPlan = StaticStore.Plans.FirstOrDefault(p => p.Type == organization.PlanType); if (existingPlan == null) { throw new BadRequestException("Existing plan not found."); } var newPlan = StaticStore.Plans.FirstOrDefault(p => p.Type == plan && !p.Disabled); if (newPlan == null) { throw new BadRequestException("Plan not found."); } if (existingPlan.Type == newPlan.Type) { throw new BadRequestException("Organization is already on this plan."); } if (existingPlan.UpgradeSortOrder >= newPlan.UpgradeSortOrder) { throw new BadRequestException("You cannot upgrade to this plan."); } if (!newPlan.CanBuyAdditionalSeats && additionalSeats > 0) { throw new BadRequestException("Plan does not allow additional seats."); } if (newPlan.CanBuyAdditionalSeats && newPlan.MaxAdditionalSeats.HasValue && additionalSeats > newPlan.MaxAdditionalSeats.Value) { throw new BadRequestException($"Selected plan allows a maximum of " + $"{newPlan.MaxAdditionalSeats.Value} additional seats."); } var newPlanSeats = (short)(newPlan.BaseSeats + (newPlan.CanBuyAdditionalSeats ? additionalSeats : 0)); if (!organization.Seats.HasValue || organization.Seats.Value > newPlanSeats) { var userCount = await _organizationUserRepository.GetCountByOrganizationIdAsync(organization.Id); if (userCount >= newPlanSeats) { throw new BadRequestException($"Your organization currently has {userCount} seats filled. Your new plan " + $"only has ({newPlanSeats}) seats. Remove some users."); } } if (newPlan.MaxSubvaults.HasValue && (!organization.MaxSubvaults.HasValue || organization.MaxSubvaults.Value > newPlan.MaxSubvaults.Value)) { var subvaultCount = await _subvaultRepository.GetCountByOrganizationIdAsync(organization.Id); if (subvaultCount > newPlan.MaxSubvaults.Value) { throw new BadRequestException($"Your organization currently has {subvaultCount} subvaults. " + $"Your new plan allows for a maximum of ({newPlan.MaxSubvaults.Value}) subvaults. " + "Remove some subvaults."); } } var subscriptionService = new StripeSubscriptionService(); if (string.IsNullOrWhiteSpace(organization.StripeSubscriptionId)) { // They must have been on a free plan. Create new sub. var subCreateOptions = new StripeSubscriptionCreateOptions { Items = new List <StripeSubscriptionItemOption> { new StripeSubscriptionItemOption { PlanId = newPlan.StripePlanId, Quantity = 1 } } }; if (additionalSeats > 0) { subCreateOptions.Items.Add(new StripeSubscriptionItemOption { PlanId = newPlan.StripeSeatPlanId, Quantity = additionalSeats }); } await subscriptionService.CreateAsync(organization.StripeCustomerId, subCreateOptions); } else { // Update existing sub. var subUpdateOptions = new StripeSubscriptionUpdateOptions { Items = new List <StripeSubscriptionItemUpdateOption> { new StripeSubscriptionItemUpdateOption { PlanId = newPlan.StripePlanId, Quantity = 1 } } }; if (additionalSeats > 0) { subUpdateOptions.Items.Add(new StripeSubscriptionItemUpdateOption { PlanId = newPlan.StripeSeatPlanId, Quantity = additionalSeats }); } await subscriptionService.UpdateAsync(organization.StripeSubscriptionId, subUpdateOptions); } }