mirror of
https://github.com/bitwarden/server
synced 2026-01-03 09:03:44 +00:00
[PM-27123] Account Credit not Showing for Premium Upgrade Payment (#6484)
* feat(billing): add PaymentMethod union * feat(billing): add nontokenized payment method * feat(billing): add validation for tokinized and nontokenized payments * feat(billing): update and add payment method requests * feat(billing): update command with new union object * test(billing): add tests for account credit for user. * feat(billing): update premium cloud hosted subscription request * fix(billing): dotnet format * tests(billing): include payment method tests * fix(billing): clean up tests and converter method
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
using Bit.Api.Utilities;
|
||||
|
||||
namespace Bit.Api.Billing.Attributes;
|
||||
|
||||
public class NonTokenizedPaymentMethodTypeValidationAttribute : StringMatchesAttribute
|
||||
{
|
||||
private static readonly string[] _acceptedValues = ["accountCredit"];
|
||||
|
||||
public NonTokenizedPaymentMethodTypeValidationAttribute() : base(_acceptedValues)
|
||||
{
|
||||
ErrorMessage = $"Payment method type must be one of: {string.Join(", ", _acceptedValues)}";
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
namespace Bit.Api.Billing.Attributes;
|
||||
|
||||
public class PaymentMethodTypeValidationAttribute : StringMatchesAttribute
|
||||
public class TokenizedPaymentMethodTypeValidationAttribute : StringMatchesAttribute
|
||||
{
|
||||
private static readonly string[] _acceptedValues = ["bankAccount", "card", "payPal"];
|
||||
|
||||
public PaymentMethodTypeValidationAttribute() : base(_acceptedValues)
|
||||
public TokenizedPaymentMethodTypeValidationAttribute() : base(_acceptedValues)
|
||||
{
|
||||
ErrorMessage = $"Payment method type must be one of: {string.Join(", ", _acceptedValues)}";
|
||||
}
|
||||
@@ -7,7 +7,7 @@ namespace Bit.Api.Billing.Models.Requests.Payment;
|
||||
public class MinimalTokenizedPaymentMethodRequest
|
||||
{
|
||||
[Required]
|
||||
[PaymentMethodTypeValidation]
|
||||
[TokenizedPaymentMethodTypeValidation]
|
||||
public required string Type { get; set; }
|
||||
|
||||
[Required]
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Api.Billing.Attributes;
|
||||
using Bit.Core.Billing.Payment.Models;
|
||||
|
||||
namespace Bit.Api.Billing.Models.Requests.Payment;
|
||||
|
||||
public class NonTokenizedPaymentMethodRequest
|
||||
{
|
||||
[Required]
|
||||
[NonTokenizedPaymentMethodTypeValidation]
|
||||
public required string Type { get; set; }
|
||||
|
||||
public NonTokenizedPaymentMethod ToDomain()
|
||||
{
|
||||
return Type switch
|
||||
{
|
||||
"accountCredit" => new NonTokenizedPaymentMethod { Type = NonTokenizablePaymentMethodType.AccountCredit },
|
||||
_ => throw new InvalidOperationException($"Invalid value for {nameof(NonTokenizedPaymentMethod)}.{nameof(NonTokenizedPaymentMethod.Type)}")
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,10 @@ using Bit.Core.Billing.Payment.Models;
|
||||
|
||||
namespace Bit.Api.Billing.Models.Requests.Premium;
|
||||
|
||||
public class PremiumCloudHostedSubscriptionRequest
|
||||
public class PremiumCloudHostedSubscriptionRequest : IValidatableObject
|
||||
{
|
||||
[Required]
|
||||
public required MinimalTokenizedPaymentMethodRequest TokenizedPaymentMethod { get; set; }
|
||||
public MinimalTokenizedPaymentMethodRequest? TokenizedPaymentMethod { get; set; }
|
||||
public NonTokenizedPaymentMethodRequest? NonTokenizedPaymentMethod { get; set; }
|
||||
|
||||
[Required]
|
||||
public required MinimalBillingAddressRequest BillingAddress { get; set; }
|
||||
@@ -15,11 +15,38 @@ public class PremiumCloudHostedSubscriptionRequest
|
||||
[Range(0, 99)]
|
||||
public short AdditionalStorageGb { get; set; } = 0;
|
||||
|
||||
public (TokenizedPaymentMethod, BillingAddress, short) ToDomain()
|
||||
|
||||
public (PaymentMethod, BillingAddress, short) ToDomain()
|
||||
{
|
||||
var paymentMethod = TokenizedPaymentMethod.ToDomain();
|
||||
// Check if TokenizedPaymentMethod or NonTokenizedPaymentMethod is provided.
|
||||
var tokenizedPaymentMethod = TokenizedPaymentMethod?.ToDomain();
|
||||
var nonTokenizedPaymentMethod = NonTokenizedPaymentMethod?.ToDomain();
|
||||
|
||||
PaymentMethod paymentMethod = tokenizedPaymentMethod != null
|
||||
? tokenizedPaymentMethod
|
||||
: nonTokenizedPaymentMethod!;
|
||||
|
||||
var billingAddress = BillingAddress.ToDomain();
|
||||
|
||||
return (paymentMethod, billingAddress, AdditionalStorageGb);
|
||||
}
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
if (TokenizedPaymentMethod == null && NonTokenizedPaymentMethod == null)
|
||||
{
|
||||
yield return new ValidationResult(
|
||||
"Either TokenizedPaymentMethod or NonTokenizedPaymentMethod must be provided.",
|
||||
new[] { nameof(TokenizedPaymentMethod), nameof(NonTokenizedPaymentMethod) }
|
||||
);
|
||||
}
|
||||
|
||||
if (TokenizedPaymentMethod != null && NonTokenizedPaymentMethod != null)
|
||||
{
|
||||
yield return new ValidationResult(
|
||||
"Only one of TokenizedPaymentMethod or NonTokenizedPaymentMethod can be provided.",
|
||||
new[] { nameof(TokenizedPaymentMethod), nameof(NonTokenizedPaymentMethod) }
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user