Files
Moonlight/Moonlight/App/Services/BillingService.cs
2023-07-13 21:29:20 +02:00

127 lines
4.1 KiB
C#

using System.Globalization;
using Moonlight.App.Database.Entities;
using Moonlight.App.Events;
using Moonlight.App.Exceptions;
using Moonlight.App.Repositories;
using Moonlight.App.Services.Mail;
using Moonlight.App.Services.Sessions;
using Stripe.Checkout;
using Subscription = Moonlight.App.Database.Entities.Subscription;
namespace Moonlight.App.Services;
public class BillingService
{
private readonly ConfigService ConfigService;
private readonly SubscriptionService SubscriptionService;
private readonly Repository<Subscription> SubscriptionRepository;
private readonly SessionServerService SessionServerService;
private readonly EventSystem Event;
private readonly MailService MailService;
public BillingService(
ConfigService configService,
SubscriptionService subscriptionService,
Repository<Subscription> subscriptionRepository,
EventSystem eventSystem,
SessionServerService sessionServerService,
MailService mailService)
{
ConfigService = configService;
SubscriptionService = subscriptionService;
SubscriptionRepository = subscriptionRepository;
Event = eventSystem;
SessionServerService = sessionServerService;
MailService = mailService;
}
public async Task<string> StartCheckout(User user, Subscription subscription)
{
var appUrl = ConfigService.Get().Moonlight.AppUrl;
var controllerUrl = appUrl + "/api/moonlight/billing";
var options = new SessionCreateOptions()
{
LineItems = new()
{
new()
{
Price = subscription.StripePriceId,
Quantity = 1
}
},
Mode = "payment",
SuccessUrl = controllerUrl + "/success",
CancelUrl = controllerUrl + "/cancel",
AutomaticTax = new SessionAutomaticTaxOptions()
{
Enabled = true
},
CustomerEmail = user.Email.ToLower(),
Metadata = new()
{
{
"productId",
subscription.StripeProductId
}
}
};
var service = new SessionService();
var session = await service.CreateAsync(options);
return session.Url;
}
public async Task CompleteCheckout(User user)
{
var sessionService = new SessionService();
var sessionsPerUser = await sessionService.ListAsync(new SessionListOptions()
{
CustomerDetails = new()
{
Email = user.Email
}
});
var latestCompletedSession = sessionsPerUser
.Where(x => x.Status == "complete")
.Where(x => x.PaymentStatus == "paid")
.MaxBy(x => x.Created);
if (latestCompletedSession == null)
throw new DisplayException("No completed session found");
var productId = latestCompletedSession.Metadata["productId"];
var subscription = SubscriptionRepository
.Get()
.FirstOrDefault(x => x.StripeProductId == productId);
if (subscription == null)
throw new DisplayException("No subscription for this product found");
// if (await SubscriptionService.GetActiveSubscription(user) != null)
// {
// return;
// }
await SubscriptionService.SetActiveSubscription(user, subscription);
await MailService.SendMail(user, "checkoutComplete", values =>
{
values.Add("SubscriptionName", subscription.Name);
values.Add("SubscriptionPrice", subscription.Price
.ToString(CultureInfo.InvariantCulture));
values.Add("SubscriptionCurrency", subscription.Currency
.ToString());
values.Add("SubscriptionDuration", subscription.Duration
.ToString(CultureInfo.InvariantCulture));
});
await Event.Emit("billing.completed", user);
await SessionServerService.ReloadUserSessions(user);
}
}