stripe / stripe-dotnet

Stripe.net is a sync/async .NET 4.6.1+ client, and a portable class library for stripe.com.
Apache License 2.0
1.36k stars 571 forks source link

Provide Dependency injection support #1882

Open Bchir opened 4 years ago

Bchir commented 4 years ago

As a developer, I want to have an extension to IServiceCollection (Extensions.DependencyInjection.Abstractions) so that I can register all stripe services and inject them directly Expected Method

services.AddStripe(ApiKey);

Notice that for HTTP client it is recommended to use services.AddHttpClient

DanDepot commented 4 years ago

Agreed, this would be a nice feature for .NET core applications.

ob-stripe commented 4 years ago

Hi both. This seems like it would be an interesting addition to Stripe.net. I can't commit to an ETA, but I'll tag this as future for now and we will try to add support for this in a future version.

clement911 commented 4 years ago

One thing that would need to be sorted is how to inject services when different api keys are used. Probably a good model is how HttpClient does it with named clients and a factory.

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-3.1#named-clients

Bchir commented 4 years ago

@clement911 maybe for configuration as

services.AddStripeAccount(configuration, name);

and then two choices :

OR

Simonl9l commented 4 years ago

It's also important to ensure that one can control DI scopes. For example Blazor Server apps need services per session/circuit to be transient scoped, this also applied the the underlying HttpClient or one is likely to have severe issues.

Bchir commented 4 years ago

@Simonl9l it is possible to use ServiceDescriptor Describe method to implement this , and the user will just have to pass the scope from the ServiceLifetime enum

Simonl9l commented 3 years ago

@Bchir I create a wrapper service that wraps the Stripe Client creating a new one each time, an hence its underlying http client, so each blazer session has its own stripe client Http connection.

It would be better if there was an option to leverage the underlying HttpClient Factory, especially since DotNet 5 is now in production and DotNet Framework support per the current implementation will at some point sunset.

spencer741 commented 3 years ago

Currently I am doing it myself... sort of.

Can't attribute to what's going on under the hood with HttpClient in this library...

I assume HttpClientFactory is not being used in stripe-dotnet underneath... as such, the HttpClient used would be re-instantiated on every incoming request... but in reality, it was doing that anyway when I would instantiate a Stripe Service within a controller.

So, I guess you could say my code base is ready when DI is officially supported. Until then, when I use a stripe service, I just add it as transient to my extensions... not like it's doing anything different other than instantiating the service for me... haven't rigorously tested either.

using Stripe;

...

public static class BusinessServiceCollectionExtensions
{
    public static void AddStripeServices(this IServiceCollection services)
    {
        //https://github.com/stripe/stripe-dotnet/issues/1882
        services.AddTransient<CustomerService>();
        services.AddTransient<SubscriptionService>();
        services.AddTransient<InvoiceService>();
        services.AddTransient<PriceService>();
    }
}

Then in my Startup.cs, I just set the API key from appsettings.json, since the StripeConfiguration class is static.

StripeConfiguration.ApiKey = Configuration["Stripe:ApiKey"];

Makes it easy... only using one api key at the moment.

cecilphillip-stripe commented 2 years ago

@spencer741 I've been doing something similar.

Curious... Do you think all stripe services should be registered in the container?

jaymedavis commented 1 year ago

fwiw, I don't think this should be implemented. Interfaces for services belong in business logic, not as part of this library. You may not need all functions in a service in your application. Therefore create an interface in your business logic (with all your other interfaces) and wire it up that way.

My $0.02 :)

AraHaan commented 1 year ago

I think this would be great for the following targets only:

The following can be done for the below targets just by using netstandard2.1 as a target:

While the .NET Framework target (aka netstandard2.0) would need to stay the same as the Microsoft.AspNet.* packages are made specifically for .NET Framework which means no dependency injection support unless you manage to get AspNetCore to fully work in .NET Framework out of chance (yes, many colleges use framework and so that means no AspNetCore and likewise no DI and some of them might want to in the future require their students to learn how to use stripe's api (I feel like doing it should be a requirement as many companies love it when someone knows how to properly maintain their payment integrations)).