Files
social-media/src/Web/Features/Memberships/Handlers/SendTip.cs
2024-10-22 16:41:11 -04:00

87 lines
2.2 KiB
C#

using Hutopy.Web.Common.Security;
using Hutopy.Web.Features.Memberships.Data;
using Hutopy.Web.Features.Memberships.Infrastructure;
namespace Hutopy.Web.Features.Memberships.Handlers;
[PublicAPI]
public record SendTipRequest(
Guid CreatorId,
decimal Amount,
string Currency,
string Message,
string CheckoutSuccessUrl,
string CheckoutCancelledUrl);
[PublicAPI]
public record SendTipResponse(
string Status,
string StripeCheckoutUrl);
[PublicAPI]
public class SendTipRequestValidator : Validator<SendTipRequest>
{
public SendTipRequestValidator()
{
RuleFor(x => x.Amount)
.GreaterThan(0)
.WithMessage("Tip amount must be greater than 0");
RuleFor(x => x.CreatorId)
.NotEmpty()
.WithMessage("Creator ID is required");
RuleFor(x => x.CheckoutSuccessUrl)
.NotEmpty()
.WithMessage("CheckoutSuccessUrl is required");
RuleFor(x => x.CheckoutCancelledUrl)
.NotEmpty()
.WithMessage("CheckoutCancelledUrl is required");
}
}
[PublicAPI]
public class SendTipHandler(
MembershipDbContext dbContext,
StripeService stripeService)
: Endpoint<SendTipRequest, SendTipResponse>
{
public override void Configure()
{
Post("/api/tips");
Options(o => o.WithTags("Memberships"));
}
public override async Task HandleAsync(
SendTipRequest req,
CancellationToken ct)
{
var creator = await dbContext.Creators.FindAsync(
[req.CreatorId],
cancellationToken: ct);
if (creator == null)
{
await SendNotFoundAsync(ct);
return;
}
var checkoutSession = await stripeService.CreateTipCheckoutSessionAsync(
User.GetUserId(),
User.GetAlias()!,
creator.Id,
creator.Name,
req.Amount,
req.Currency,
req.Message,
creator.StripeAccountId,
req.CheckoutSuccessUrl,
req.CheckoutCancelledUrl);
await SendAsync(
new SendTipResponse("Pending", checkoutSession.Url),
cancellation: ct);
}
}