mirror of
https://github.com/bitwarden/server.git
synced 2025-04-15 10:08:14 -05:00
change payment API
This commit is contained in:
parent
6467cafde3
commit
18d2715c71
@ -115,6 +115,19 @@ namespace Bit.Api.Controllers
|
||||
return new OrganizationResponseModel(organization);
|
||||
}
|
||||
|
||||
[HttpPut("{id}/payment")]
|
||||
[HttpPost("{id}/payment")]
|
||||
public async Task PutPayment(string id, [FromBody]OrganizationPaymentRequestModel model)
|
||||
{
|
||||
var orgIdGuid = new Guid(id);
|
||||
if(!_currentContext.OrganizationOwner(orgIdGuid))
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
await _organizationService.ReplacePaymentMethodAsync(orgIdGuid, model.PaymentToken);
|
||||
}
|
||||
|
||||
[HttpDelete("{id}")]
|
||||
[HttpPost("{id}/delete")]
|
||||
public async Task Delete(string id)
|
||||
|
@ -19,7 +19,7 @@ namespace Bit.Core.Models.Api
|
||||
public PlanType PlanType { get; set; }
|
||||
[Required]
|
||||
public string Key { get; set; }
|
||||
public string CardToken { get; set; }
|
||||
public string PaymentToken { get; set; }
|
||||
[Range(0, double.MaxValue)]
|
||||
public short AdditionalUsers { get; set; }
|
||||
public bool Monthly { get; set; }
|
||||
@ -32,7 +32,7 @@ namespace Bit.Core.Models.Api
|
||||
OwnerKey = Key,
|
||||
Name = Name,
|
||||
Plan = PlanType,
|
||||
PaymentToken = CardToken,
|
||||
PaymentToken = PaymentToken,
|
||||
AdditionalUsers = AdditionalUsers,
|
||||
BillingEmail = BillingEmail,
|
||||
BusinessName = BusinessName,
|
||||
@ -42,9 +42,9 @@ namespace Bit.Core.Models.Api
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
if(PlanType != PlanType.Free && string.IsNullOrWhiteSpace(CardToken))
|
||||
if(PlanType != PlanType.Free && string.IsNullOrWhiteSpace(PaymentToken))
|
||||
{
|
||||
yield return new ValidationResult("Card required.", new string[] { nameof(CardToken) });
|
||||
yield return new ValidationResult("Payment required.", new string[] { nameof(PaymentToken) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,10 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Core.Models.Api
|
||||
{
|
||||
public class OrganizationPaymentRequestModel
|
||||
{
|
||||
[Required]
|
||||
public string PaymentToken { get; set; }
|
||||
}
|
||||
}
|
@ -58,7 +58,8 @@ namespace Bit.Core.Models.Api
|
||||
switch(source.Type)
|
||||
{
|
||||
case SourceType.Card:
|
||||
Description = $"{source.Card.Brand}, *{source.Card.Last4}";
|
||||
Description = $"{source.Card.Brand}, *{source.Card.Last4}, " +
|
||||
$"{source.Card.ExpirationMonth}/{source.Card.ExpirationYear}";
|
||||
CardBrand = source.Card.Brand;
|
||||
break;
|
||||
case SourceType.BankAccount:
|
||||
|
@ -9,6 +9,7 @@ namespace Bit.Core.Services
|
||||
public interface IOrganizationService
|
||||
{
|
||||
Task<OrganizationBilling> GetBillingAsync(Organization organization);
|
||||
Task ReplacePaymentMethodAsync(Guid organizationId, string paymentToken);
|
||||
Task<Tuple<Organization, OrganizationUser>> SignUpAsync(OrganizationSignup organizationSignup);
|
||||
Task<OrganizationUser> InviteUserAsync(Guid organizationId, Guid invitingUserId, string email,
|
||||
Enums.OrganizationUserType type, IEnumerable<SubvaultUser> subvaults);
|
||||
|
@ -51,7 +51,19 @@ namespace Bit.Core.Services
|
||||
var customer = await customerService.GetAsync(organization.StripeCustomerId);
|
||||
if(customer != null)
|
||||
{
|
||||
orgBilling.PaymentSource = customer.DefaultSource;
|
||||
if(!string.IsNullOrWhiteSpace(customer.DefaultSourceId) && customer.Sources?.Data != null)
|
||||
{
|
||||
if(customer.DefaultSourceId.StartsWith("card_"))
|
||||
{
|
||||
orgBilling.PaymentSource =
|
||||
customer.Sources.Data.FirstOrDefault(s => s.Card?.Id == customer.DefaultSourceId);
|
||||
}
|
||||
else if(customer.DefaultSourceId.StartsWith("ba_"))
|
||||
{
|
||||
orgBilling.PaymentSource =
|
||||
customer.Sources.Data.FirstOrDefault(s => s.BankAccount?.Id == customer.DefaultSourceId);
|
||||
}
|
||||
}
|
||||
|
||||
var charges = await chargeService.ListAsync(new StripeChargeListOptions
|
||||
{
|
||||
@ -74,6 +86,47 @@ namespace Bit.Core.Services
|
||||
return orgBilling;
|
||||
}
|
||||
|
||||
public async Task ReplacePaymentMethodAsync(Guid organizationId, string paymentToken)
|
||||
{
|
||||
var organization = await _organizationRepository.GetByIdAsync(organizationId);
|
||||
if(organization == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
var cardService = new StripeCardService();
|
||||
var customerService = new StripeCustomerService();
|
||||
StripeCustomer customer = null;
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(organization.StripeCustomerId))
|
||||
{
|
||||
customer = await customerService.GetAsync(organization.StripeCustomerId);
|
||||
}
|
||||
|
||||
if(customer == null)
|
||||
{
|
||||
customer = await customerService.CreateAsync(new StripeCustomerCreateOptions
|
||||
{
|
||||
Description = organization.BusinessName,
|
||||
Email = organization.BillingEmail,
|
||||
SourceToken = paymentToken
|
||||
});
|
||||
|
||||
organization.StripeCustomerId = customer.Id;
|
||||
await _organizationRepository.ReplaceAsync(organization);
|
||||
}
|
||||
|
||||
await cardService.CreateAsync(customer.Id, new StripeCardCreateOptions
|
||||
{
|
||||
SourceToken = paymentToken
|
||||
});
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(customer.DefaultSourceId))
|
||||
{
|
||||
await cardService.DeleteAsync(customer.Id, customer.DefaultSourceId);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Tuple<Organization, OrganizationUser>> SignUpAsync(OrganizationSignup signup)
|
||||
{
|
||||
var plan = StaticStore.Plans.FirstOrDefault(p => p.Type == signup.Plan && !p.Disabled);
|
||||
@ -87,7 +140,8 @@ namespace Bit.Core.Services
|
||||
StripeCustomer customer = null;
|
||||
StripeSubscription subscription = null;
|
||||
|
||||
if(signup.AdditionalUsers > plan.MaxAdditionalUsers.GetValueOrDefault(0))
|
||||
if(plan.CanBuyAdditionalUsers && plan.MaxAdditionalUsers.HasValue &&
|
||||
signup.AdditionalUsers > plan.MaxAdditionalUsers.Value)
|
||||
{
|
||||
throw new BadRequestException($"Selected plan allows a maximum of " +
|
||||
$"{plan.MaxAdditionalUsers.GetValueOrDefault(0)} additional users.");
|
||||
@ -143,7 +197,7 @@ namespace Bit.Core.Services
|
||||
PlanType = plan.Type,
|
||||
MaxUsers = (short)(plan.BaseUsers + (plan.CanBuyAdditionalUsers ? signup.AdditionalUsers : 0)),
|
||||
MaxSubvaults = plan.MaxSubvaults,
|
||||
Plan = plan.ToString(),
|
||||
Plan = plan.Name,
|
||||
StripeCustomerId = customer?.Id,
|
||||
StripeSubscriptionId = subscription?.Id,
|
||||
CreationDate = DateTime.UtcNow,
|
||||
|
Loading…
x
Reference in New Issue
Block a user