How to Integrate ASP.NET Core and Blazor App - Windows ASP.NET Core Hosting 2024 | Review and ComparisonWindows ASP.NET Core Hosting 2024 | Review and Comparison

Now that our app is complete, I must monetize it. Creating sponsored content was the first thing that came to mind: you post something, and we show it above the results in exchange.

I decided on Stripe for the payment because it looks like it would be simple to integrate (all server side work is done with a nuget package).

This blog post’s main goal is to demonstrate Blazor JS Interop’s functionality and ease of use.

Client Side

The way Stripe operates is that you call a JS method, which prompts a modal to appear and request payment information. Once Stripe has verified the payment details, you will receive your token back.

You simply call Stripe on the server side with this token and the amount, and you’re set to go.

The Blazor code to open the modal is the first thing. It happens when a button is clicked in my app:

@implements IStripeCallBack
//whatever
@function{
    protected async Task OnClick(UIEventArgs ev)
    {
       await JSRuntime.Current.InvokeAsync<string>("stripeCheckout",new DotNetObjectRef(stripeCallBack), amountInCts);
    }
    [JSInvokable]
    public async Task TokenReceived(string token)
    {       
       await GetCharge(token);
    }
}
  • I can reuse this code in another component because it implements IStripeCallBack in this component itself.
  • GetCharge is merely a method that uses the provided token to call the server.
  • To invoke this method from JS, you must have [JSInvokable].
  • We encapsulate the instance that JS (this) will call in a DotNetObjectRef. The object’s serialized JSON version will be sent to JS if we don’t do that.

Now the JS part

stripeCheckout = function (callBackInstance, amount) {
    var handler = StripeCheckout.configure({
        key: 'pk_test_IAEerhZ6JVmmcj9756zIZegI',
        image: 'https://stripe.com/img/documentation/checkout/marketplace.png',
        locale: 'auto',
        token: function (token) {
            callBackInstance.invokeMethodAsync('TokenReceived', token.id)
                .then(r => console.log(token));
        },
        currency: 'EUR'
    });
    // Open Checkout with further options:
    handler.open({
        name: 'Stripe.com',
        description: '2 widgets',
        zipCode: true,
        amount: amount
    });
    return Promise.resolve();
};
  • “key” is Stripe’s public key.
  • As every JSON interop needs to be asynchronous (not required by Blazor documentation, but I’ve seen bugs when I’m not doing it), I return Promise.resolve().
  • The JS interop call is “callBackInstance.invokeMethodAsync,” which will invoke the TokenReceived method on my component instance.

Server Side

The server side is now easy to use.

    public class StripeClient : IStripeClient
    {
        private readonly HttpClient httpClient = new HttpClient();
        public StripeClient(string stripeSecretKey)
        {
            StripeConfiguration.SetApiKey(stripeSecretKey);
        }
        public async Task<bool> Charge(string token, int amount, string description, string email)
        {
            var chargeOptions = new StripeChargeCreateOptions()
            {
                Amount = amount,
                Currency = "eur",
                Description = description,
                SourceTokenOrExistingSourceId = token,
                ReceiptEmail = email
            };
            var chargeService = new StripeChargeService();
            StripeCharge charge = chargeService.Create(chargeOptions);
            return charge.FailureMessage != null && charge.Paid;
        }
    }
  • Your secrets json is where the secret API key needs to be kept (a quick google search reveals that some people are unaware of this).
  • To ensure that the amount displayed is the amount charged, I should send the amount from the client to the server, compute the amount on the server side, and raise an exception if it doesn’t match.
  • It’s 100 times easier to use the Stripe Nuget package than to manually handle the HTTP request (I tried).

Conclusion

Once more, Blazor’s ease of use with other tools and API is evident. Once the client-side Blazor performance issues are resolved, I believe the current framework—minus the bugs—will be prepared for production use.