mirror of
https://github.com/bitwarden/server.git
synced 2025-04-08 22:58:11 -05:00
purchase org with paypal support
This commit is contained in:
parent
952d624d72
commit
9f876d9bff
@ -476,6 +476,11 @@ namespace Bit.Core.Services
|
|||||||
throw new BadRequestException("Plan does not allow additional storage.");
|
throw new BadRequestException("Plan does not allow additional storage.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(signup.AdditionalStorageGb < 0)
|
||||||
|
{
|
||||||
|
throw new BadRequestException("You can't subtract storage!");
|
||||||
|
}
|
||||||
|
|
||||||
if(!plan.CanBuyPremiumAccessAddon && signup.PremiumAccessAddon)
|
if(!plan.CanBuyPremiumAccessAddon && signup.PremiumAccessAddon)
|
||||||
{
|
{
|
||||||
throw new BadRequestException("This plan does not allow you to buy the premium access addon.");
|
throw new BadRequestException("This plan does not allow you to buy the premium access addon.");
|
||||||
@ -486,6 +491,11 @@ namespace Bit.Core.Services
|
|||||||
throw new BadRequestException("You do not have any seats!");
|
throw new BadRequestException("You do not have any seats!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(signup.AdditionalSeats < 0)
|
||||||
|
{
|
||||||
|
throw new BadRequestException("You can't subtract seats!");
|
||||||
|
}
|
||||||
|
|
||||||
if(!plan.CanBuyAdditionalSeats && signup.AdditionalSeats > 0)
|
if(!plan.CanBuyAdditionalSeats && signup.AdditionalSeats > 0)
|
||||||
{
|
{
|
||||||
throw new BadRequestException("Plan does not allow additional users.");
|
throw new BadRequestException("Plan does not allow additional users.");
|
||||||
@ -498,96 +508,10 @@ namespace Bit.Core.Services
|
|||||||
$"{plan.MaxAdditionalSeats.GetValueOrDefault(0)} additional users.");
|
$"{plan.MaxAdditionalSeats.GetValueOrDefault(0)} additional users.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var customerService = new CustomerService();
|
|
||||||
var subscriptionService = new SubscriptionService();
|
|
||||||
Customer customer = null;
|
|
||||||
Subscription subscription = null;
|
|
||||||
|
|
||||||
// Pre-generate the org id so that we can save it with the Stripe subscription..
|
|
||||||
var newOrgId = CoreHelpers.GenerateComb();
|
|
||||||
|
|
||||||
if(plan.Type == PlanType.Free)
|
|
||||||
{
|
|
||||||
var adminCount =
|
|
||||||
await _organizationUserRepository.GetCountByFreeOrganizationAdminUserAsync(signup.Owner.Id);
|
|
||||||
if(adminCount > 0)
|
|
||||||
{
|
|
||||||
throw new BadRequestException("You can only be an admin of one free organization.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
customer = await customerService.CreateAsync(new CustomerCreateOptions
|
|
||||||
{
|
|
||||||
Description = signup.BusinessName,
|
|
||||||
Email = signup.BillingEmail,
|
|
||||||
SourceToken = signup.PaymentToken
|
|
||||||
});
|
|
||||||
|
|
||||||
var subCreateOptions = new SubscriptionCreateOptions
|
|
||||||
{
|
|
||||||
CustomerId = customer.Id,
|
|
||||||
TrialPeriodDays = plan.TrialPeriodDays,
|
|
||||||
Items = new List<SubscriptionItemOption>(),
|
|
||||||
Metadata = new Dictionary<string, string> {
|
|
||||||
{ "organizationId", newOrgId.ToString() }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if(plan.StripePlanId != null)
|
|
||||||
{
|
|
||||||
subCreateOptions.Items.Add(new SubscriptionItemOption
|
|
||||||
{
|
|
||||||
PlanId = plan.StripePlanId,
|
|
||||||
Quantity = 1
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if(signup.AdditionalSeats > 0 && plan.StripeSeatPlanId != null)
|
|
||||||
{
|
|
||||||
subCreateOptions.Items.Add(new SubscriptionItemOption
|
|
||||||
{
|
|
||||||
PlanId = plan.StripeSeatPlanId,
|
|
||||||
Quantity = signup.AdditionalSeats
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if(signup.AdditionalStorageGb > 0)
|
|
||||||
{
|
|
||||||
subCreateOptions.Items.Add(new SubscriptionItemOption
|
|
||||||
{
|
|
||||||
PlanId = plan.StripeStoragePlanId,
|
|
||||||
Quantity = signup.AdditionalStorageGb
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if(signup.PremiumAccessAddon && plan.StripePremiumAccessPlanId != null)
|
|
||||||
{
|
|
||||||
subCreateOptions.Items.Add(new SubscriptionItemOption
|
|
||||||
{
|
|
||||||
PlanId = plan.StripePremiumAccessPlanId,
|
|
||||||
Quantity = 1
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
subscription = await subscriptionService.CreateAsync(subCreateOptions);
|
|
||||||
}
|
|
||||||
catch(StripeException)
|
|
||||||
{
|
|
||||||
if(customer != null)
|
|
||||||
{
|
|
||||||
await customerService.DeleteAsync(customer.Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var organization = new Organization
|
var organization = new Organization
|
||||||
{
|
{
|
||||||
Id = newOrgId,
|
// Pre-generate the org id so that we can save it with the Stripe subscription..
|
||||||
|
Id = CoreHelpers.GenerateComb(),
|
||||||
Name = signup.Name,
|
Name = signup.Name,
|
||||||
BillingEmail = signup.BillingEmail,
|
BillingEmail = signup.BillingEmail,
|
||||||
BusinessName = signup.BusinessName,
|
BusinessName = signup.BusinessName,
|
||||||
@ -605,16 +529,43 @@ namespace Bit.Core.Services
|
|||||||
SelfHost = plan.SelfHost,
|
SelfHost = plan.SelfHost,
|
||||||
UsersGetPremium = plan.UsersGetPremium || signup.PremiumAccessAddon,
|
UsersGetPremium = plan.UsersGetPremium || signup.PremiumAccessAddon,
|
||||||
Plan = plan.Name,
|
Plan = plan.Name,
|
||||||
Gateway = plan.Type == PlanType.Free ? null : (GatewayType?)GatewayType.Stripe,
|
Gateway = null,
|
||||||
GatewayCustomerId = customer?.Id,
|
|
||||||
GatewaySubscriptionId = subscription?.Id,
|
|
||||||
Enabled = true,
|
Enabled = true,
|
||||||
ExpirationDate = subscription?.CurrentPeriodEnd,
|
|
||||||
LicenseKey = CoreHelpers.SecureRandomString(20),
|
LicenseKey = CoreHelpers.SecureRandomString(20),
|
||||||
CreationDate = DateTime.UtcNow,
|
CreationDate = DateTime.UtcNow,
|
||||||
RevisionDate = DateTime.UtcNow
|
RevisionDate = DateTime.UtcNow
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if(plan.Type == PlanType.Free)
|
||||||
|
{
|
||||||
|
var adminCount =
|
||||||
|
await _organizationUserRepository.GetCountByFreeOrganizationAdminUserAsync(signup.Owner.Id);
|
||||||
|
if(adminCount > 0)
|
||||||
|
{
|
||||||
|
throw new BadRequestException("You can only be an admin of one free organization.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PaymentMethodType paymentMethodType;
|
||||||
|
if(signup.PaymentToken.StartsWith("btok_"))
|
||||||
|
{
|
||||||
|
paymentMethodType = PaymentMethodType.BankAccount;
|
||||||
|
}
|
||||||
|
else if(signup.PaymentToken.StartsWith("tok_"))
|
||||||
|
{
|
||||||
|
paymentMethodType = PaymentMethodType.Card;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
paymentMethodType = PaymentMethodType.PayPal;
|
||||||
|
}
|
||||||
|
|
||||||
|
await _stripePaymentService.PurchaseOrganizationAsync(organization, paymentMethodType,
|
||||||
|
signup.PaymentToken, plan, signup.AdditionalStorageGb, signup.AdditionalSeats,
|
||||||
|
signup.PremiumAccessAddon);
|
||||||
|
}
|
||||||
|
|
||||||
return await SignUpAsync(organization, signup.Owner.Id, signup.OwnerKey, signup.CollectionName, true);
|
return await SignUpAsync(organization, signup.Owner.Id, signup.OwnerKey, signup.CollectionName, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,126 @@ namespace Bit.Core.Services
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task PurchaseOrganizationAsync(Organization org, PaymentMethodType paymentMethodType,
|
||||||
|
string paymentToken, Models.StaticStore.Plan plan, short additionalStorageGb,
|
||||||
|
short additionalSeats, bool premiumAccessAddon)
|
||||||
|
{
|
||||||
|
var invoiceService = new InvoiceService();
|
||||||
|
var customerService = new CustomerService();
|
||||||
|
|
||||||
|
Braintree.Customer braintreeCustomer = null;
|
||||||
|
string stipeCustomerSourceToken = null;
|
||||||
|
var stripeCustomerMetadata = new Dictionary<string, string>();
|
||||||
|
var stripePaymentMethod = paymentMethodType == PaymentMethodType.Card ||
|
||||||
|
paymentMethodType == PaymentMethodType.BankAccount;
|
||||||
|
|
||||||
|
if(stripePaymentMethod)
|
||||||
|
{
|
||||||
|
stipeCustomerSourceToken = paymentToken;
|
||||||
|
}
|
||||||
|
else if(paymentMethodType == PaymentMethodType.PayPal)
|
||||||
|
{
|
||||||
|
var randomSuffix = Utilities.CoreHelpers.RandomString(3, upper: false, numeric: false);
|
||||||
|
var customerResult = await _btGateway.Customer.CreateAsync(new Braintree.CustomerRequest
|
||||||
|
{
|
||||||
|
PaymentMethodNonce = paymentToken,
|
||||||
|
Email = org.BillingEmail,
|
||||||
|
Id = "o" + org.Id.ToString("N").ToLower() + randomSuffix
|
||||||
|
});
|
||||||
|
|
||||||
|
if(!customerResult.IsSuccess() || customerResult.Target.PaymentMethods.Length == 0)
|
||||||
|
{
|
||||||
|
throw new GatewayException("Failed to create PayPal customer record.");
|
||||||
|
}
|
||||||
|
|
||||||
|
braintreeCustomer = customerResult.Target;
|
||||||
|
stripeCustomerMetadata.Add("btCustomerId", braintreeCustomer.Id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new GatewayException("Payment method is not supported at this time.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var subCreateOptions = new SubscriptionCreateOptions
|
||||||
|
{
|
||||||
|
TrialPeriodDays = plan.TrialPeriodDays,
|
||||||
|
Items = new List<SubscriptionItemOption>(),
|
||||||
|
Metadata = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
["organizationId"] = org.Id.ToString()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if(plan.StripePlanId != null)
|
||||||
|
{
|
||||||
|
subCreateOptions.Items.Add(new SubscriptionItemOption
|
||||||
|
{
|
||||||
|
PlanId = plan.StripePlanId,
|
||||||
|
Quantity = 1
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if(additionalSeats > 0 && plan.StripeSeatPlanId != null)
|
||||||
|
{
|
||||||
|
subCreateOptions.Items.Add(new SubscriptionItemOption
|
||||||
|
{
|
||||||
|
PlanId = plan.StripeSeatPlanId,
|
||||||
|
Quantity = additionalSeats
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if(additionalStorageGb > 0)
|
||||||
|
{
|
||||||
|
subCreateOptions.Items.Add(new SubscriptionItemOption
|
||||||
|
{
|
||||||
|
PlanId = plan.StripeStoragePlanId,
|
||||||
|
Quantity = additionalStorageGb
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if(premiumAccessAddon && plan.StripePremiumAccessPlanId != null)
|
||||||
|
{
|
||||||
|
subCreateOptions.Items.Add(new SubscriptionItemOption
|
||||||
|
{
|
||||||
|
PlanId = plan.StripePremiumAccessPlanId,
|
||||||
|
Quantity = 1
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Customer customer = null;
|
||||||
|
Subscription subscription = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
customer = await customerService.CreateAsync(new CustomerCreateOptions
|
||||||
|
{
|
||||||
|
Description = org.BusinessName,
|
||||||
|
Email = org.BillingEmail,
|
||||||
|
SourceToken = stipeCustomerSourceToken,
|
||||||
|
Metadata = stripeCustomerMetadata
|
||||||
|
});
|
||||||
|
subCreateOptions.CustomerId = customer.Id;
|
||||||
|
var subscriptionService = new SubscriptionService();
|
||||||
|
subscription = await subscriptionService.CreateAsync(subCreateOptions);
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
if(customer != null)
|
||||||
|
{
|
||||||
|
await customerService.DeleteAsync(customer.Id);
|
||||||
|
}
|
||||||
|
if(braintreeCustomer != null)
|
||||||
|
{
|
||||||
|
await _btGateway.Customer.DeleteAsync(braintreeCustomer.Id);
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
org.Gateway = GatewayType.Stripe;
|
||||||
|
org.GatewayCustomerId = customer.Id;
|
||||||
|
org.GatewaySubscriptionId = subscription.Id;
|
||||||
|
org.ExpirationDate = subscription.CurrentPeriodEnd;
|
||||||
|
}
|
||||||
|
|
||||||
public async Task PurchasePremiumAsync(User user, PaymentMethodType paymentMethodType, string paymentToken,
|
public async Task PurchasePremiumAsync(User user, PaymentMethodType paymentMethodType, string paymentToken,
|
||||||
short additionalStorageGb)
|
short additionalStorageGb)
|
||||||
{
|
{
|
||||||
|
@ -682,6 +682,11 @@ namespace Bit.Core.Services
|
|||||||
throw new BadRequestException("Already a premium user.");
|
throw new BadRequestException("Already a premium user.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(additionalStorageGb < 0)
|
||||||
|
{
|
||||||
|
throw new BadRequestException("You can't subtract storage!");
|
||||||
|
}
|
||||||
|
|
||||||
IPaymentService paymentService = null;
|
IPaymentService paymentService = null;
|
||||||
if(_globalSettings.SelfHosted)
|
if(_globalSettings.SelfHosted)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user