1
0
mirror of https://github.com/bitwarden/server synced 2025-12-18 09:13:19 +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:
Stephon Brown
2025-10-23 14:47:23 -04:00
committed by GitHub
parent b15913ce73
commit ff4b3eb9e5
10 changed files with 391 additions and 37 deletions

View File

@@ -0,0 +1,69 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using OneOf;
namespace Bit.Core.Billing.Payment.Models;
[JsonConverter(typeof(PaymentMethodJsonConverter))]
public class PaymentMethod(OneOf<TokenizedPaymentMethod, NonTokenizedPaymentMethod> input)
: OneOfBase<TokenizedPaymentMethod, NonTokenizedPaymentMethod>(input)
{
public static implicit operator PaymentMethod(TokenizedPaymentMethod tokenized) => new(tokenized);
public static implicit operator PaymentMethod(NonTokenizedPaymentMethod nonTokenized) => new(nonTokenized);
public bool IsTokenized => IsT0;
public bool IsNonTokenized => IsT1;
}
internal class PaymentMethodJsonConverter : JsonConverter<PaymentMethod>
{
public override PaymentMethod Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var element = JsonElement.ParseValue(ref reader);
if (!element.TryGetProperty("type", out var typeProperty))
{
throw new JsonException("PaymentMethod requires a 'type' property");
}
var type = typeProperty.GetString();
if (Enum.TryParse<TokenizablePaymentMethodType>(type, true, out var tokenizedType) &&
Enum.IsDefined(typeof(TokenizablePaymentMethodType), tokenizedType))
{
var token = element.TryGetProperty("token", out var tokenProperty) ? tokenProperty.GetString() : null;
if (string.IsNullOrEmpty(token))
{
throw new JsonException("TokenizedPaymentMethod requires a 'token' property");
}
return new TokenizedPaymentMethod { Type = tokenizedType, Token = token };
}
if (Enum.TryParse<NonTokenizablePaymentMethodType>(type, true, out var nonTokenizedType) &&
Enum.IsDefined(typeof(NonTokenizablePaymentMethodType), nonTokenizedType))
{
return new NonTokenizedPaymentMethod { Type = nonTokenizedType };
}
throw new JsonException($"Unknown payment method type: {type}");
}
public override void Write(Utf8JsonWriter writer, PaymentMethod value, JsonSerializerOptions options)
{
writer.WriteStartObject();
value.Switch(
tokenized =>
{
writer.WriteString("type",
tokenized.Type.ToString().ToLowerInvariant()
);
writer.WriteString("token", tokenized.Token);
},
nonTokenized => { writer.WriteString("type", nonTokenized.Type.ToString().ToLowerInvariant()); }
);
writer.WriteEndObject();
}
}