84 lines
2.3 KiB
C#
84 lines
2.3 KiB
C#
using Hutopy.Infrastructure.Security;
|
|
using Hutopy.Modules.Creators.Contracts;
|
|
using Hutopy.Modules.Memberships.Contracts;
|
|
using Hutopy.Modules.Memberships.Data;
|
|
|
|
namespace Hutopy.Modules.Memberships.Handlers;
|
|
|
|
[PublicAPI]
|
|
public class SubscribeRequest
|
|
{
|
|
public Guid CreatorId { get; set; }
|
|
public Guid MembershipTierId { get; set; }
|
|
public required string CheckoutSuccessUrl { get; init; }
|
|
public required string CheckoutCancelledUrl { get; init; }
|
|
}
|
|
|
|
[PublicAPI]
|
|
public record struct SubscriptionResponse(
|
|
string StripeCheckoutUrl);
|
|
|
|
[PublicAPI]
|
|
public class SubscribeValidator : Validator<SubscribeRequest>
|
|
{
|
|
public SubscribeValidator()
|
|
{
|
|
RuleFor(x => x.MembershipTierId).NotEmpty();
|
|
}
|
|
}
|
|
|
|
[PublicAPI]
|
|
public class SubscribeHandler(
|
|
MembershipsDbContext dbContext,
|
|
ICreatorLookup creatorLookup,
|
|
IMembershipPaymentProcessor membershipPaymentProcessor)
|
|
: Endpoint<SubscribeRequest, SubscriptionResponse>
|
|
{
|
|
public override void Configure()
|
|
{
|
|
Post("/api/memberships/subscribe");
|
|
Options(o => o.WithTags("Memberships"));
|
|
}
|
|
|
|
public override async Task HandleAsync(
|
|
SubscribeRequest req,
|
|
CancellationToken ct)
|
|
{
|
|
MembershipTier? tier = await dbContext
|
|
.MembershipTiers
|
|
.Where(tier => tier.Id == req.MembershipTierId)
|
|
.FirstOrDefaultAsync(ct);
|
|
if (tier == null)
|
|
{
|
|
await SendNotFoundAsync(ct);
|
|
return;
|
|
}
|
|
|
|
CreatorReference? creator = await creatorLookup.GetCreatorAsync(tier.CreatorId, ct);
|
|
if (creator == null)
|
|
{
|
|
await SendNotFoundAsync(ct);
|
|
return;
|
|
}
|
|
|
|
if (!creator.AcceptCharges)
|
|
{
|
|
await SendErrorsAsync(StatusCodes.Status400BadRequest, ct);
|
|
return;
|
|
}
|
|
|
|
// Process Stripe subscription
|
|
MembershipCheckoutSession checkoutSession = await membershipPaymentProcessor.CreateCheckoutSessionAsync(
|
|
User.GetUserId(),
|
|
creator,
|
|
tier.Id,
|
|
tier.StripePriceId,
|
|
req.CheckoutSuccessUrl,
|
|
req.CheckoutCancelledUrl);
|
|
|
|
await SendOkAsync(
|
|
new SubscriptionResponse { StripeCheckoutUrl = checkoutSession.Url },
|
|
ct);
|
|
}
|
|
}
|