1
0
mirror of https://github.com/bitwarden/server synced 2025-12-17 08:43:27 +00:00

APIs for premium. Billing helpers.

This commit is contained in:
Kyle Spearrin
2017-07-06 14:55:58 -04:00
parent 2afef85f85
commit d346ee5169
22 changed files with 789 additions and 313 deletions

View File

@@ -16,11 +16,16 @@ using U2fLib = U2F.Core.Crypto.U2F;
using U2F.Core.Models;
using U2F.Core.Utils;
using Bit.Core.Exceptions;
using Stripe;
using Bit.Core.Utilities;
namespace Bit.Core.Services
{
public class UserService : UserManager<User>, IUserService, IDisposable
{
private const string PremiumPlanId = "premium-annually";
private const string StoragePlanId = "storage-gb-annually";
private readonly IUserRepository _userRepository;
private readonly ICipherRepository _cipherRepository;
private readonly IOrganizationUserRepository _organizationUserRepository;
@@ -492,6 +497,109 @@ namespace Bit.Core.Services
return true;
}
public async Task SignUpPremiumAsync(User user, string paymentToken, short additionalStorageGb)
{
if(user.Premium)
{
throw new BadRequestException("Already a premium user.");
}
var customerService = new StripeCustomerService();
var customer = await customerService.CreateAsync(new StripeCustomerCreateOptions
{
Description = user.Name,
Email = user.Email,
SourceToken = paymentToken
});
var subCreateOptions = new StripeSubscriptionCreateOptions
{
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(customer.Id, subCreateOptions);
}
catch(StripeException)
{
await customerService.DeleteAsync(customer.Id);
throw;
}
user.Premium = true;
user.MaxStorageGb = (short)(1 + additionalStorageGb);
user.RevisionDate = DateTime.UtcNow;
user.StripeCustomerId = customer.Id;
user.StripeSubscriptionId = subscription.Id;
try
{
await SaveUserAsync(user);
}
catch
{
await BillingHelpers.CancelAndRecoverChargesAsync(subscription.Id, customer.Id);
throw;
}
}
public async Task AdjustStorageAsync(User user, short storageAdjustmentGb)
{
if(user == null)
{
throw new ArgumentNullException(nameof(user));
}
if(!user.Premium)
{
throw new BadRequestException("Not a premium user.");
}
await BillingHelpers.AdjustStorageAsync(user, storageAdjustmentGb, StoragePlanId);
await SaveUserAsync(user);
}
public async Task ReplacePaymentMethodAsync(User user, string paymentToken)
{
var updated = await BillingHelpers.UpdatePaymentMethodAsync(user, paymentToken);
if(updated)
{
await SaveUserAsync(user);
}
}
public async Task CancelPremiumAsync(User user, bool endOfPeriod = false)
{
await BillingHelpers.CancelSubscriptionAsync(user, endOfPeriod);
}
public async Task ReinstatePremiumAsync(User user)
{
await BillingHelpers.ReinstateSubscriptionAsync(user);
}
private async Task<IdentityResult> UpdatePasswordHash(User user, string newPassword, bool validatePassword = true)
{
if(validatePassword)