Stripe Connect Express and Blazor

USING STRIPE.NET: STRIPE CONNECT EXPRESS AND SERVER-SIDE BLAZOR

by

In this tutorial, you will learn how to integrate Stripe Connect Express accounts with your server-side Blazor application.

Source Code

Source code for this project, and for others in the Blazor and Stripe series, are available on Github.

What is Stripe Connect

Stripe Connect allows you to develop marketplace and platform applications that can accept money and pay out to connected Stripe accounts. For example, a platform like Lyft has the ability to receive payments from a customer, retain a percentage as a platform fee, and then pay out the difference to the customer's driver. Those drivers would all be considered Stripe Connect accounts for the Lyft platform.

There are three ways to integrate with Stripe Connect. A Standard account is the easiest to integrate, but it has limitations with respect to branding and the type of charges it can handle. A Custom account offers the most control, but it requires significantly more integrations work. An Express account is a happy medium between the two alternatives, and it is the focus of this tutorial.

Configure Stripe.Net

Like the Stripe webhooks tutorial, this tutorial will rely on the Stripe.net Nuget package. Install it and add it to your server-side Blazor project.

Install-Package Stripe.net

To configure Stripe.net, load your project's Startup.cs file, locate the Configure() method, and add the following lines:

StripeConfiguration.ApiKey = Configuration.GetSection("Stripe")["ApiKey"];
StripeConfiguration.ClientId = Configuration.GetSection("Stripe")["ClientId"];  

The API key can be found in your Stripe developer dashboard. You can find your Client ID in the Stripe Connect Settings page. The above code is using the Secret Manager to store sensitive data. Please see the Secret Manager tutorial if you have questions about keeping secrets out of your source code.

Linking Stripe Connect Account

This tutorial assumed you are already using an identity provider like Azure AD B2C or IdentityServer to authenticate your application's users. In addition, you will likely be storing information in a database, as well. If I were designing a project that integrated with both Azure AD B2C and Stripe Connect, I would have an entry in a local table that included the user's Azure Object ID and their Stripe Connect ID.

To link a Stripe Connect Express account with the currently signed in user in a server-side Blazor application, simply add a button with an OnClick event handler to a page, such as an Edit Profile page.

<button class="btn btn-primary" @onclick="ConnectStripe">Setup Stripe Connect</button>

I suggest adding some logic so that the button only appears for signed in users who have not already linked their Stripe Connect account.

<h3>Edit Profile</h3>
@if (currentUser == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <AuthorizeView>
        <Authorized>
            <div>
                <h4>Stripe Connect</h4>
                <div>
                    @if (currentUser.StripeConnectId == null)
                    {
						<button class="btn btn-primary" @onclick="ConnectStripe">Setup Stripe Connect</button>
					}
				</div>
			</div>
		</Authorized>
	</AuthorizeView>
}

You will need to fetch the currently signed in user's information by overriding the page's OnInitializedAsync method.

Now, it is time to design the ConnectStripe method which is triggered by the button's OnClick event. This method will simply generate and navigate to an OAuth link based on your Stripe Connect ID and redirect URI.

If you have not already configured a redirect URI in your Stripe Connect Settings page, go ahead and create one that points to a page on your Blazor app, such as http://localhost:5000/VerifyStripeConnect. This could be a route for a specific controller action, but this tutorial will demonstrate that it can be done with a Blazor page. We will create this page later.

To protect against Cross-Site Request Forgery (CSRF) attacks, Stripe Connect allows you to attach a state parameter to the URL. This parameter will be passed back to the redirect URI, so you can verify that it corresponds to the current user's request.

You can generate a unique token to use as the value of the state parameter, and store it in the current user's browser session store using the Blazored.SessionStorage Nuget package. Once you have install the Nuget package, the following line will inject an instance onto your Blazor page.

@inject Blazored.SessionStorage.ISessionStorageService sessionStorage

Later, you will read the value from the session store and verify that it matches the state value passed back by Stripe Connect.

Following is a sample event handler method for generating a Stripe Connect OAuth link from a Blazor page.

private async Task ConnectStripe()
{
	var state = Guid.NewGuid();
	string baseUrl = "https://connect.stripe.com/express/oauth/authorize";
	string redirectUri = "http://localhost:5000/VerifyStripeConnect";

	string clientId = StripeConfiguration.ClientId;
	string businessType = "individual";

	await sessionStorage.SetItemAsync("stripeState", state.ToString());

	string stripeAuthUrl = $"{baseUrl}?" +
		$"redirect_uri={redirectUri}&" +
		$"client_id={clientId}&" +
		$"stripe_user[business_type]={businessType}&" +
		$"stripe_user[email]={currentUser.EmailAddress}&" +
		$"stripe_user[first_name]={currentUser.FirstName}&" +
		$"stripe_user[last_name]={currentUser.LastName}&" +
		$"state={state}";

	navMan.NavigateTo(stripeAuthUrl, true);
}

The above code generates a link and then navigates the current user to the link to complete the Stripe Connect onboarding process. I provided parameters based on my local user table to prefill some of the Stripe Connect form fields, such as email address, first name, and last name. This is optional.

After the user enters the required information for Stripe, they will be redirected to http://localhost:5000/VerifyStripeConnect.

Create Verification Page

You need to create a page whose route corresponds to the redirect URI you provided in your Stripe Connect Settings page. Create a new Blazor page and add the following route directive.

@page "/VerifyStripeConnect"

I want this page to automatically perform the verification and then redirect the user to the appropriate page based on whether verification succeeded.

Start by verifying that the state parameter of the incoming request matches the value of the token you created and stored in the session store. This must be done after the page has been rendered in the user's browser. Override the OnAfterRenderAsync method.

protected override async Task OnAfterRenderAsync(bool firstRender)
{

}

Next, validate the state parameter by fetching the expected state from the browser's session store and comparing it to the value received from state query parameter.

protected override async Task OnAfterRenderAsync(bool firstRender)
{
	var expectedState = await sessionStorage.GetItemAsync<string>("stripeState");
	var queryString = navMan.ToAbsoluteUri(navMan.Uri).Query;
	var query = QueryHelpers.ParseQuery(queryString);

	if (query.TryGetValue("state", out var state))
	{
		if (state == expectedState)
		{		
			//state values match
		}
	}
}

Finally, use the authorization code returned by Stripe to fetch the user's Stripe Connect ID.

protected override async Task OnAfterRenderAsync(bool firstRender)
{
	var expectedState = await sessionStorage.GetItemAsync<string>("stripeState");
	var queryString = navMan.ToAbsoluteUri(navMan.Uri).Query;
	var query = QueryHelpers.ParseQuery(queryString);

	if (query.TryGetValue("state", out var state))
	{
		if (state == expectedState)
		{		
			await sessionStorage.RemoveItemAsync("stripeState");
						  
			if (query.TryGetValue("code", out var code))
			{
				var stripeId = stripeService.GetStripeIdFromAuthCode(code);
				currentUser.StripeConnectId = stripeId;

				await apiService.EditUserAsync(currentUser);
				navMan.NavigateTo("/EditProfile");
			}
		}
	}
}

After successfully verifying the state and completing the user's Stripe Connect Express account connection, I update the Users table in my local database and redirect the user back to the Edit Profile page.

Get Stripe ID from Auth code

You may have noticed the GetStripeIdFromAuthCode() method called on line 54. This method is part of a StripeService class I created for interfacing with the Stripe API. This method takes the one-time use authorization code returned by Stripe and returns a string corresponding to the user's new Stripe Connect account.

public string GetStripeIdFromAuthCode(string authCode)
{
	var options = new OAuthTokenCreateOptions
	{
		GrantType = "authorization_code",
		Code = authCode,
	};

	var service = new OAuthTokenService();
	var response = service.Create(options);

	return response.StripeUserId;
}

The Bottom Line

This tutorial walked you through how to integrate Stripe Connect with an existing Blazor server-side application. I hope this tutorial has inspired you as you look to create a real-world applications. Maybe you will even consider using Blazor and Stripe for your next business startup! Let me know if you have any questions.


Don't stop learning!

There is so much to discover about C#. That's why I am making my favorite tips and tricks available for free. Enter your email address below to become a better .NET developer.


Did you know?

Our beautiful, multi-column C# reference guides contain more than 150 tips and examples to make it even easier to write better code.

Get your cheat sheets