92 lines
3.1 KiB
C#
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);
|
|
}
|
|
}
|