Files
social-media/backend/Modules/Creators/Features/ConnectStripe.cs

92 lines
3.1 KiB
C#

using Hutopy.Infrastructure.Configuration;
using Hutopy.Infrastructure.Payments.Stripe.Configuration;
using Hutopy.Infrastructure.Security;
using Hutopy.Modules.Creators.Data;
using Microsoft.Extensions.Options;
using Stripe;
namespace Hutopy.Modules.Creators.Features;
[PublicAPI]
public record ConnectStripeResponse(
string Url);
public class ConnectStripeIdHandler(
IOptionsSnapshot<WebsiteOptions> websiteOptions,
IOptionsSnapshot<StripeOptions> stripeOptions,
CreatorsDbContext dbContext)
: EndpointWithoutRequest<ConnectStripeResponse>
{
public override void Configure()
{
Post("/api/stripe/connect");
Options(o => o.WithTags("Creators"));
}
public override async Task HandleAsync(
CancellationToken ct)
{
// 1. Get the creator's information
Guid creatorId = HttpContext.User.GetUserId();
string email = HttpContext.User.GetEmail();
// 2. Get or create the creator
Creator? creator = await dbContext
.Creators
.SingleOrDefaultAsync(
c => c.Id == creatorId,
ct);
if (creator is null)
{
await SendNotFoundAsync(ct);
return;
}
// 3. Create a Stripe account
StripeConfiguration.ApiKey = stripeOptions.Value.SecretKey;
AccountService accountService = new();
if (string.IsNullOrWhiteSpace(creator.StripeAccountId))
{
Account? account = await accountService.CreateAsync(
new AccountCreateOptions
{
Type = "express",
Capabilities = new AccountCapabilitiesOptions
{
CardPayments = new AccountCapabilitiesCardPaymentsOptions { Requested = true },
Transfers = new AccountCapabilitiesTransfersOptions { Requested = true }
},
Email = email
},
cancellationToken: ct);
// 5. Update the creator's Stripe account ID
creator.StripeAccountId = account.Id;
await dbContext.SaveChangesAsync(ct);
}
// 4. Check if the creator already has a Stripe account
if (creator is { IsStripeDetailsSubmitted: true, IsStripeChargesEnabled: true, IsStripePayoutReady: true })
{
await SendErrorsAsync(cancellation: ct);
return;
}
// 5. Create an account link
AccountLinkService accountLinkService = new();
AccountLink? accountLink = await accountLinkService.CreateAsync(
new AccountLinkCreateOptions
{
Account = creator.StripeAccountId,
RefreshUrl = $"{websiteOptions.Value.FrontendBaseUrl}/profile?stripe=retry",
ReturnUrl = $"{websiteOptions.Value.FrontendBaseUrl}/profile?stripe=complete",
Type = "account_onboarding"
},
cancellationToken: ct);
// 6. Return the account link URL to the client
await SendOkAsync(new ConnectStripeResponse(accountLink.Url), ct);
}
}