Stripe.NET Create Stripe Webhooks Receiver

USING STRIPE.NET: CREATE A STRIPE WEBHOOKS RECEIVER

by

In this tutorial, you will create an ASP.NET controller that will act as a listener for Stripe webhooks. This controller can respond to events related to your Stripe customers or connected accounts.

Source Code

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

Getting Started

If you will be following along with other tutorials in this series, I will be working with a server-side Blazor project. If not, the same principles will apply to MVC or Razor pages projects, so use whichever you prefer.

Get started by installing the Stripe.Net Nuget package for use in your project.

Install-Package Stripe.net

Configure Stripe.Net

There are a number of global configuration settings for Stripe.Net. The one you will need to set for this tutorial is your Stripe API Key. Don't forget to use the Test key if your project is not yet live. Remember, you should never store secrets in your project's source code. Using ASP.NET's Secret Manager, add your API key. I also added my webhook endpoint signing key.

"Stripe": {
    "ApiKey": "sk_test_xxxx",
    "WebhookSigningKey": "whsec_xxxx"
}

Now, open the project's Startup.cs file and start by importing the Stripe namespace.

using Stripe;

Still in Startup.cs, locate the Configure() method. Here, you will set the global API Key parameter for Stripe.Net.

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

We will be using the webhook signing key to verify that events sent to our webhook receiver were actually sent by Stripe. To do this, use ASP.NET's Options pattern. Create a class called StripeOptions that looks like the following. The name WebhookSigningKey should match the key name you configured in secrets.json.

public class StripeOptions
{
    public string WebhookSigningKey { get; set; }
}

Back in Startup.cs, locate the ConfigureServices() method. Here, you will bind the values from secret manager to the StripeOptions class and add it as a type that can be injected into your controller.

services.AddOptions();
services.Configure<StripeOptions>(Configuration.GetSection("Stripe"));

Create Webhook Receiver

Your webhook listener simply be a controller with a single HttpPost endpoint. Stripe will send POST requests to this endpoint containing details related to a Stripe event. Your controller will determine which type of event it has received and take the appropriate action based on the event.

Create a Controllers folder in your project. Within that folder, create a class called StripeWebhook. You will make this a controller class that will be able to respond to any event received from Stripe's webhooks.

In projects where I am receiving payments from customers and paying out to connected Stripe accounts, I like to create two separate webhook receiver controllers. One controller will respond to customer events and the other will respond to Stripe Connect events. This is not strictly necessary, as a single controller can respond to both events. I just do this to help me manage my controller code!

Now, inject any services you will need in the controller using C# dependency injection. Also inject the StripeOptions interface so you will be able to access your unique webhook signing key.

[Route("[controller]")]
public class StripeWebhook : ControllerBase
{
	private readonly string _webhookSecret;
	private readonly StripeService _stripeService;
	private readonly ApiService _apiService;
	
	public StripeWebhook(IOptions<StripeConfig> options,
		StripeService stripeService,
		ApiService apiService)
	{
		_webhookSecret = options.Value.WebhookSigningKey;
		_stripeService = stripeService;
		_apiService = apiService;
	}
}

In my constructor example above, I have extracted the WebhookSigningKey value from the Options interface and assigned it to a private variable _webhookSecret. I also injected two service instances. One to handle any API calls dealing with my local database, and another for interfacing with Stripe.

Next, add a single HttpPost endpoint for your controller.

[HttpPost]
public async Task<IActionResult> Index()
{
	
}

This is where you will respond to events sent by Stripe. When you are designing your webhook receiver, please remember that Stripe expects your application to send an Http success response code every time an event is received.

Stripe will notify your webhook receiver for any numbers of events. For example, your application might respond when a customer updates their payment information, when a customer's payment method will soon expire, or when a charge fails. Your controller should determine which type of event it has received and then take the appropriate action.

[HttpPost]
public async Task<IActionResult> Index()
{
	string json = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync();
            
	try
	{
		var stripeEvent = EventUtility.ConstructEvent(json,
			Request.Headers["Stripe-Signature"], _webhookSecret);
		switch (stripeEvent.Type)
		{
			case Events.CustomerSourceUpdated:
				//make sure payment info is valid
				break;
			case Events.CustomerSourceExpiring:
				//send reminder email to update payment method
				break;
			case Events.ChargeFailed:
				//do something
				break;
		}
		return Ok();
	}
	catch (StripeException e)
	{
		return BadRequest();
	}
}

The controller action above starts by parsing the body of the request received and saving it as a string json. Then, the controller verifies that the event was sent by Stripe by comparing the value of the Stripe-Signature with our unique webhook secret. Finally, we determine the type of event and perform the appropriate action based on the event. In this case, we might have some code that will verify that a customer's payment method is still valid and update our database records accordingly when a customer.source.updated event is received. Similarly, we might send a friendly reminder email in response to the customer.source.expiring event when a customer's payment method is set to expire.

Once your controller is finished, don't forget to tell Stripe which endpoint to send webhook events to by updating your Stripe developer dashboard.

The Bottom Line

In this tutorial, you learned how to create a webhook receiver that will respond to Stripe events. You can use the same technique if you wish to set up a listener that responds to webhook events sent out by any other platform, such as Github. Hopefully this was a practical tutorial that will help you monetize your next startup! In subsequent tutorials, you will learn more about working with the Stripe API in server-side Blazor applications.


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