feat: pivot to social media workflow app
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Hutopy.Infrastructure.Payments.Stripe.Configuration;
|
||||
namespace Socialize.Infrastructure.Payments.Stripe.Configuration;
|
||||
|
||||
public class StripeOptions
|
||||
{
|
||||
@@ -10,5 +10,5 @@ public class StripeOptions
|
||||
|
||||
[Required] public required string WebhookSecret { get; init; }
|
||||
|
||||
[Required] [Range(0, 1)] public required decimal HutopyRate { get; init; }
|
||||
[Required] [Range(0, 1)] public required decimal SocializeRate { get; init; }
|
||||
}
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
using Hutopy.Modules.Memberships.Contracts;
|
||||
using Stripe;
|
||||
|
||||
namespace Hutopy.Infrastructure.Payments.Stripe.Services;
|
||||
|
||||
public sealed class MembershipCancellationProcessor
|
||||
: IMembershipCancellationProcessor
|
||||
{
|
||||
public async Task<DateTimeOffset?> CancelAsync(
|
||||
string subscriptionId,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
SubscriptionService subscriptionService = new();
|
||||
|
||||
// Stripe - Cancel Subscription immediately
|
||||
// var subscription = await subscriptionService.CancelAsync(
|
||||
// subscriptionId,
|
||||
// cancellationToken: ct);
|
||||
|
||||
// Stripe - Cancel Subscription AtPeriodEnd
|
||||
Subscription? subscription = await subscriptionService.UpdateAsync(
|
||||
subscriptionId,
|
||||
new SubscriptionUpdateOptions { CancelAtPeriodEnd = true },
|
||||
cancellationToken: ct);
|
||||
|
||||
return subscription.CancelAt ?? subscription.CanceledAt;
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
using Hutopy.Infrastructure.Payments.Stripe.Configuration;
|
||||
using Hutopy.Modules.Creators.Contracts;
|
||||
using Hutopy.Modules.Memberships.Contracts;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Stripe;
|
||||
using Stripe.Checkout;
|
||||
|
||||
namespace Hutopy.Infrastructure.Payments.Stripe.Services;
|
||||
|
||||
public class MembershipPaymentProcessor(
|
||||
IOptions<StripeOptions> stripeOptions)
|
||||
: IMembershipPaymentProcessor
|
||||
{
|
||||
public async Task<MembershipCheckoutSession> CreateCheckoutSessionAsync(
|
||||
Guid userId,
|
||||
CreatorReference creatorReference,
|
||||
Guid tierId,
|
||||
string priceId,
|
||||
string successUrl,
|
||||
string cancelUrl)
|
||||
{
|
||||
StripeConfiguration.ApiKey = stripeOptions.Value.SecretKey;
|
||||
|
||||
// Create Stripe customer for the user if not already created
|
||||
CustomerService customerService = new();
|
||||
Customer? customer = await customerService.CreateAsync(
|
||||
new CustomerCreateOptions
|
||||
{
|
||||
Metadata = new Dictionary<string, string> { { "userId", userId.ToString() } }
|
||||
});
|
||||
|
||||
// Create Checkout Session for the subscription
|
||||
SessionService sessionService = new();
|
||||
Session? session = await sessionService.CreateAsync(
|
||||
new SessionCreateOptions
|
||||
{
|
||||
Customer = customer.Id,
|
||||
PaymentMethodTypes = ["card"],
|
||||
LineItems =
|
||||
[
|
||||
new SessionLineItemOptions { Price = priceId, Quantity = 1 }
|
||||
],
|
||||
Mode = "subscription",
|
||||
SubscriptionData = new SessionSubscriptionDataOptions
|
||||
{
|
||||
ApplicationFeePercent = stripeOptions.Value.HutopyRate,
|
||||
TransferData =
|
||||
new SessionSubscriptionDataTransferDataOptions
|
||||
{
|
||||
Destination = creatorReference.StripeAccountId
|
||||
}
|
||||
},
|
||||
SuccessUrl = successUrl, // Redirect after successful payment
|
||||
CancelUrl = cancelUrl, // Redirect after canceled payment
|
||||
Metadata = new Dictionary<string, string>
|
||||
{
|
||||
{ "userId", userId.ToString() },
|
||||
{ "creatorId", creatorReference.Id.ToString() },
|
||||
{ "creatorName", creatorReference.Name },
|
||||
{ "tierId", tierId.ToString() }
|
||||
}
|
||||
});
|
||||
|
||||
return new MembershipCheckoutSession(
|
||||
session.Id,
|
||||
session.Url);
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
using Hutopy.Infrastructure.Payments.Stripe.Configuration;
|
||||
using Hutopy.Modules.Memberships.Contracts;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Stripe;
|
||||
|
||||
namespace Hutopy.Infrastructure.Payments.Stripe.Services;
|
||||
|
||||
public sealed class MembershipTierProcessor(
|
||||
IOptions<StripeOptions> stripeOptions)
|
||||
: IMembershipTierProcessor
|
||||
{
|
||||
public async Task<string> CreateAsync(
|
||||
Guid creatorId,
|
||||
Guid tierId,
|
||||
string productName,
|
||||
string currencyCode,
|
||||
decimal amount)
|
||||
{
|
||||
StripeConfiguration.ApiKey = stripeOptions.Value.SecretKey;
|
||||
|
||||
// Create the product
|
||||
ProductService productService = new();
|
||||
Product? product = await productService.CreateAsync(
|
||||
new ProductCreateOptions
|
||||
{
|
||||
Name = productName,
|
||||
Metadata = { { "creatorId", creatorId.ToString() }, { "tierId", tierId.ToString() } }
|
||||
});
|
||||
|
||||
// Create the price for the product
|
||||
PriceService priceService = new();
|
||||
await priceService.CreateAsync(
|
||||
new PriceCreateOptions
|
||||
{
|
||||
Product = product.Id,
|
||||
UnitAmountDecimal = amount * 100, // Convert amount to cents
|
||||
Currency = currencyCode,
|
||||
Recurring = new PriceRecurringOptions { Interval = "month" }
|
||||
});
|
||||
|
||||
return product.Id;
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
using Hutopy.Infrastructure.Payments.Stripe.Configuration;
|
||||
using Hutopy.Modules.Creators.Contracts;
|
||||
using Hutopy.Modules.Tipping.Contracts;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Stripe;
|
||||
using Stripe.Checkout;
|
||||
|
||||
namespace Hutopy.Infrastructure.Payments.Stripe.Services;
|
||||
|
||||
internal class StripeTipProcessor(
|
||||
IOptions<StripeOptions> stripeOptions)
|
||||
: ITipProcessor
|
||||
{
|
||||
public async Task<TipCheckoutSession> CreateCheckoutSessionAsync(
|
||||
Guid tipId,
|
||||
CreatorReference creator,
|
||||
decimal amount,
|
||||
string currency,
|
||||
string message,
|
||||
Uri successUrl,
|
||||
Uri cancelUrl,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
var applicationFeeAmount = Convert.ToInt64(amount * stripeOptions.Value.HutopyRate);
|
||||
|
||||
StripeConfiguration.ApiKey = stripeOptions.Value.SecretKey;
|
||||
|
||||
var sessionService = new SessionService();
|
||||
|
||||
var options = new SessionCreateOptions
|
||||
{
|
||||
ClientReferenceId = tipId.ToString(),
|
||||
Mode = "payment",
|
||||
LineItems =
|
||||
[
|
||||
new SessionLineItemOptions
|
||||
{
|
||||
PriceData = new SessionLineItemPriceDataOptions
|
||||
{
|
||||
Currency = currency,
|
||||
UnitAmountDecimal = amount, // Amount in cents
|
||||
ProductData = new SessionLineItemPriceDataProductDataOptions
|
||||
{
|
||||
Name = $"Tip for {creator.Name}",
|
||||
Metadata = new Dictionary<string, string> { { "creatorId", creator.Id.ToString() } }
|
||||
}
|
||||
},
|
||||
Quantity = 1
|
||||
}
|
||||
],
|
||||
PaymentIntentData = new SessionPaymentIntentDataOptions { ApplicationFeeAmount = applicationFeeAmount },
|
||||
Metadata = new Dictionary<string, string>
|
||||
{
|
||||
{ "creatorId", creator.Id.ToString() }, { "creatorName", creator.Name }, { "message", message }
|
||||
},
|
||||
SuccessUrl = successUrl.ToString(), // Redirect after successful payment
|
||||
CancelUrl = cancelUrl.ToString(), // Redirect after canceled payment
|
||||
};
|
||||
|
||||
var requestOptions = new RequestOptions { StripeAccount = creator.StripeAccountId };
|
||||
|
||||
var session = await sessionService.CreateAsync(
|
||||
options,
|
||||
requestOptions,
|
||||
cancellationToken: ct)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return new TipCheckoutSession(session.Id, session.Url);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user