using System.Threading.Tasks; using ManagerService.Data; using ManagerService.Helpers; using Microsoft.Extensions.Options; using Stripe; using Stripe.Checkout; namespace ManagerService.Services { /// /// Stripe integration for the Essentiel plan self-service subscription (customer creation, /// Checkout Session, Billing Portal Session, webhook signature verification). Both Checkout /// and the Billing Portal are hosted by Stripe — no card form is built in any of our own apps. /// public class StripeService { private readonly StripeSettings _settings; private readonly CustomerService _customerService; private readonly SessionService _checkoutSessionService; private readonly Stripe.BillingPortal.SessionService _billingPortalSessionService; public StripeService(IOptions settings) { _settings = settings.Value; StripeConfiguration.ApiKey = _settings.SecretKey; _customerService = new CustomerService(); _checkoutSessionService = new SessionService(); _billingPortalSessionService = new Stripe.BillingPortal.SessionService(); } public async Task CreateCustomerAsync(Instance instance) { var customer = await _customerService.CreateAsync(new CustomerCreateOptions { Name = instance.Name, Metadata = new System.Collections.Generic.Dictionary { { "instanceId", instance.Id }, }, }); return customer.Id; } /// /// Create a Stripe Checkout Session for the Essentiel plan subscription. /// Stripe Tax is applied automatically based on the customer's billing details. /// public async Task CreateCheckoutSessionAsync(Instance instance, string successUrl, string cancelUrl) { var options = new SessionCreateOptions { Mode = "subscription", Customer = instance.StripeCustomerId, LineItems = new System.Collections.Generic.List { new SessionLineItemOptions { Price = _settings.EssentielPriceId, Quantity = 1, }, }, AutomaticTax = new SessionAutomaticTaxOptions { Enabled = true }, SuccessUrl = successUrl, CancelUrl = cancelUrl, Metadata = new System.Collections.Generic.Dictionary { { "instanceId", instance.Id }, }, }; var session = await _checkoutSessionService.CreateAsync(options); return session.Url; } /// /// Create a Stripe Billing Portal Session: the customer manages card, invoices and /// cancellation on Stripe's own pages. Nothing to build on our side beyond the redirect. /// public async Task CreateBillingPortalSessionAsync(Instance instance, string returnUrl) { var session = await _billingPortalSessionService.CreateAsync( new Stripe.BillingPortal.SessionCreateOptions { Customer = instance.StripeCustomerId, ReturnUrl = returnUrl, }); return session.Url; } public Event ConstructWebhookEvent(string json, string stripeSignatureHeader) { return EventUtility.ConstructEvent(json, stripeSignatureHeader, _settings.WebhookSecret); } } }