Stripe-dotnet: Question: .NET Core and Receiving Events from Stripe (Handlers -> Middleware)

Created on 28 Mar 2017  路  6Comments  路  Source: stripe/stripe-dotnet

I haven't fully implemented this library, so I haven't tested it yet.

But, I know that HTTP Handler's have been replaced with .NET Core Middleware (https://docs.microsoft.com/en-us/aspnet/core/migration/http-modules) classes.

Does this completely prevent event handling from working with .NET Core, or is there some sort of backwards compatibility?

Thanks!

Most helpful comment

This is the code I use in my Webhook Handler in .Net Core 1.1.2. You are welcome to adapt it as necessary:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using System.IO;
using Stripe;
using Microsoft.Extensions.Logging;
using WebApp.Data;
using Entities;

namespace WebApp.Middleware
{
    public class StripeWebhookHandler
    {
        private readonly ILogger _log;
        private readonly ApplicationDataContext _ctx;

        public StripeWebhookHandler(RequestDelegate next, ILoggerFactory logger, ApplicationDataContext ctx)
        {
            _log = logger.CreateLogger<StripeWebhookHandler>();
            _ctx = ctx;
        }

        public async Task Invoke(HttpContext httpContext)
        {            
            bool handled = true;

            var json = await new StreamReader(httpContext.Request.Body).ReadToEndAsync();

            var stripeEvent = StripeEventUtility.ParseEvent(json);

            if (!_ctx.ServiceEvents.Any(evt => evt.ServiceEventId == stripeEvent.Id))
            {
                switch (stripeEvent.Type)
                {

                    case StripeEvents.AccountApplicationDeauthorized:
                    case StripeEvents.AccountExternalAccountCreated:
                    case StripeEvents.AccountExternalAccountDeleted:
                    case StripeEvents.AccountExternalAccountUpdated:
                    case StripeEvents.AccountUpdated:
                        var stripeAccount = Stripe.Mapper<StripeAccount>.MapFromJson(stripeEvent.Data.Object.ToString());
                        break;
                    case StripeEvents.ApplicationFeeCreated:
                    case StripeEvents.ApplicationFeeRefunded:
                    case StripeEvents.ApplicationFeeRefundUpdated:
                        var fee = Stripe.Mapper<StripeApplicationFee>.MapFromJson(stripeEvent.Data.Object.ToString());
                        break;
                    case StripeEvents.BalanceAvailable:
                        var bal = Stripe.Mapper<StripeBalance>.MapFromJson(stripeEvent.Data.Object.ToString());
                        break;
                    case StripeEvents.BitcoinReceiverCreated:
                    case StripeEvents.BitcoinReceiverFilled:
                    case StripeEvents.BitcoinReceiverTransactionUpdated:
                    case StripeEvents.BitcoinReceiverUpdated:
                        var btcrcv = Stripe.Mapper<StripeReceiver>.MapFromJson(stripeEvent.Data.Object.ToString());
                        break;
                    case StripeEvents.ChargeCaptured:
                    case StripeEvents.ChargeFailed:
                    case StripeEvents.ChargePending:
                    case StripeEvents.ChargeRefunded:
                    case StripeEvents.ChargeSucceeded:
                    case StripeEvents.ChargeUpdated:
                        var charge = Stripe.Mapper<StripeCharge>.MapFromJson(stripeEvent.Data.Object.ToString());
                        break;
                    case StripeEvents.ChargeDisputeClosed:
                    case StripeEvents.ChargeDisputeCreated:
                    case StripeEvents.ChargeDisputeFundsReinstated:
                    case StripeEvents.ChargeDisputeFundsWithdrawn:
                        var dispute = Stripe.Mapper<StripeDispute>.MapFromJson(stripeEvent.Data.Object.ToString());
                        break;
                    case StripeEvents.CouponCreated:
                    case StripeEvents.CouponDeleted:
                    case StripeEvents.CouponUpdated:
                        var cpn = Stripe.Mapper<StripeCoupon>.MapFromJson(stripeEvent.Data.Object.ToString());
                        break;
                    case StripeEvents.CustomerCreated:
                    case StripeEvents.CustomerDeleted:
                    case StripeEvents.CustomerUpdated:
                        var cst = Stripe.Mapper<StripeCustomer>.MapFromJson(stripeEvent.Data.Object.ToString());
                        break;
                    case StripeEvents.CustomerDiscountCreated:
                    case StripeEvents.CustomerDiscountDeleted:
                    case StripeEvents.CustomerDiscountUpdated:
                        var dsc = Stripe.Mapper<StripeDiscount>.MapFromJson(stripeEvent.Data.Object.ToString());
                        break;
                    case StripeEvents.CustomerSourceCreated:
                        var src = Stripe.Mapper<StripeSource>.MapFromJson(stripeEvent.Data.Object.ToString());
                        break;
                    case StripeEvents.CustomerSubscriptionCreated:
                        break;
                    case StripeEvents.InvoiceCreated:
                        break;
                    case StripeEvents.InvoicePaymentSucceeded:
                        break;
                    case StripeEvents.InvoicePaymentFailed:
                        break;
                    case StripeEvents.Ping:
                        break;
                    case StripeEvents.PlanCreated:
                        break;
                    case StripeEvents.PayoutCreated:
                        break;
                    case StripeEvents.PayoutPaid:
                        break;
                    default:
                        _log.LogWarning("Received unhandled webhook: {0}", json);
                        handled = false;
                        break;
                }

                if (handled)
                {
                    WebhookEvent evt = new WebhookEvent()
                    {
                        ServiceName = "Stripe",
                        ServiceEventType = stripeEvent.Type.ToString(),
                        ServiceEventId = stripeEvent.Id,
                        Processed = DateTime.Now,
                        EventText = json
                    };

                    await _ctx.ServiceEvents.AddAsync(evt);

                    await _ctx.SaveChangesAsync();

                    httpContext.Response.StatusCode = 200;
                }
                else
                    httpContext.Response.StatusCode = 400;
            }
            else
                httpContext.Response.StatusCode = 200;
        }
    }

    // Extension method used to add the middleware to the HTTP request pipeline.
    public static class StripeWebhookHandlerExtensions
    {
        public static IApplicationBuilder UseStripeWebhookHandler(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<StripeWebhookHandler>();
        }
    }
}

Then in the Startup.cs, I add the following line to the Configure method:

app.Map(new PathString("/webhooks/stripe"), a => a.UseStripeWebhookHandler());

All 6 comments

Good question!

The example in the mspec test project could be converted to use middleware (i think). This is something that needs to be figured out. I'll leave this open - someone out there has probably done it. If not, it's worth some investigation. Thanks!

This is the code I use in my Webhook Handler in .Net Core 1.1.2. You are welcome to adapt it as necessary:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using System.IO;
using Stripe;
using Microsoft.Extensions.Logging;
using WebApp.Data;
using Entities;

namespace WebApp.Middleware
{
    public class StripeWebhookHandler
    {
        private readonly ILogger _log;
        private readonly ApplicationDataContext _ctx;

        public StripeWebhookHandler(RequestDelegate next, ILoggerFactory logger, ApplicationDataContext ctx)
        {
            _log = logger.CreateLogger<StripeWebhookHandler>();
            _ctx = ctx;
        }

        public async Task Invoke(HttpContext httpContext)
        {            
            bool handled = true;

            var json = await new StreamReader(httpContext.Request.Body).ReadToEndAsync();

            var stripeEvent = StripeEventUtility.ParseEvent(json);

            if (!_ctx.ServiceEvents.Any(evt => evt.ServiceEventId == stripeEvent.Id))
            {
                switch (stripeEvent.Type)
                {

                    case StripeEvents.AccountApplicationDeauthorized:
                    case StripeEvents.AccountExternalAccountCreated:
                    case StripeEvents.AccountExternalAccountDeleted:
                    case StripeEvents.AccountExternalAccountUpdated:
                    case StripeEvents.AccountUpdated:
                        var stripeAccount = Stripe.Mapper<StripeAccount>.MapFromJson(stripeEvent.Data.Object.ToString());
                        break;
                    case StripeEvents.ApplicationFeeCreated:
                    case StripeEvents.ApplicationFeeRefunded:
                    case StripeEvents.ApplicationFeeRefundUpdated:
                        var fee = Stripe.Mapper<StripeApplicationFee>.MapFromJson(stripeEvent.Data.Object.ToString());
                        break;
                    case StripeEvents.BalanceAvailable:
                        var bal = Stripe.Mapper<StripeBalance>.MapFromJson(stripeEvent.Data.Object.ToString());
                        break;
                    case StripeEvents.BitcoinReceiverCreated:
                    case StripeEvents.BitcoinReceiverFilled:
                    case StripeEvents.BitcoinReceiverTransactionUpdated:
                    case StripeEvents.BitcoinReceiverUpdated:
                        var btcrcv = Stripe.Mapper<StripeReceiver>.MapFromJson(stripeEvent.Data.Object.ToString());
                        break;
                    case StripeEvents.ChargeCaptured:
                    case StripeEvents.ChargeFailed:
                    case StripeEvents.ChargePending:
                    case StripeEvents.ChargeRefunded:
                    case StripeEvents.ChargeSucceeded:
                    case StripeEvents.ChargeUpdated:
                        var charge = Stripe.Mapper<StripeCharge>.MapFromJson(stripeEvent.Data.Object.ToString());
                        break;
                    case StripeEvents.ChargeDisputeClosed:
                    case StripeEvents.ChargeDisputeCreated:
                    case StripeEvents.ChargeDisputeFundsReinstated:
                    case StripeEvents.ChargeDisputeFundsWithdrawn:
                        var dispute = Stripe.Mapper<StripeDispute>.MapFromJson(stripeEvent.Data.Object.ToString());
                        break;
                    case StripeEvents.CouponCreated:
                    case StripeEvents.CouponDeleted:
                    case StripeEvents.CouponUpdated:
                        var cpn = Stripe.Mapper<StripeCoupon>.MapFromJson(stripeEvent.Data.Object.ToString());
                        break;
                    case StripeEvents.CustomerCreated:
                    case StripeEvents.CustomerDeleted:
                    case StripeEvents.CustomerUpdated:
                        var cst = Stripe.Mapper<StripeCustomer>.MapFromJson(stripeEvent.Data.Object.ToString());
                        break;
                    case StripeEvents.CustomerDiscountCreated:
                    case StripeEvents.CustomerDiscountDeleted:
                    case StripeEvents.CustomerDiscountUpdated:
                        var dsc = Stripe.Mapper<StripeDiscount>.MapFromJson(stripeEvent.Data.Object.ToString());
                        break;
                    case StripeEvents.CustomerSourceCreated:
                        var src = Stripe.Mapper<StripeSource>.MapFromJson(stripeEvent.Data.Object.ToString());
                        break;
                    case StripeEvents.CustomerSubscriptionCreated:
                        break;
                    case StripeEvents.InvoiceCreated:
                        break;
                    case StripeEvents.InvoicePaymentSucceeded:
                        break;
                    case StripeEvents.InvoicePaymentFailed:
                        break;
                    case StripeEvents.Ping:
                        break;
                    case StripeEvents.PlanCreated:
                        break;
                    case StripeEvents.PayoutCreated:
                        break;
                    case StripeEvents.PayoutPaid:
                        break;
                    default:
                        _log.LogWarning("Received unhandled webhook: {0}", json);
                        handled = false;
                        break;
                }

                if (handled)
                {
                    WebhookEvent evt = new WebhookEvent()
                    {
                        ServiceName = "Stripe",
                        ServiceEventType = stripeEvent.Type.ToString(),
                        ServiceEventId = stripeEvent.Id,
                        Processed = DateTime.Now,
                        EventText = json
                    };

                    await _ctx.ServiceEvents.AddAsync(evt);

                    await _ctx.SaveChangesAsync();

                    httpContext.Response.StatusCode = 200;
                }
                else
                    httpContext.Response.StatusCode = 400;
            }
            else
                httpContext.Response.StatusCode = 200;
        }
    }

    // Extension method used to add the middleware to the HTTP request pipeline.
    public static class StripeWebhookHandlerExtensions
    {
        public static IApplicationBuilder UseStripeWebhookHandler(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<StripeWebhookHandler>();
        }
    }
}

Then in the Startup.cs, I add the following line to the Configure method:

app.Map(new PathString("/webhooks/stripe"), a => a.UseStripeWebhookHandler());

this is awesome @txdotnetdev! I edited your comment a little just for formatting. thanks!

how to get customerID from StripeEvents if ChargeSucceeded in C#

@afollestad This is a really old issue I would recommend contacting our support team directly: https://support.stripe.com/contact?email=true

@remi-stripe well it's so old it's not really relevant anymore. 馃檪

Was this page helpful?
0 / 5 - 0 ratings

Related issues

DanWM picture DanWM  路  15Comments

bzbetty picture bzbetty  路  5Comments

Jagadeesh-Govindaraj picture Jagadeesh-Govindaraj  路  11Comments

wize1 picture wize1  路  5Comments

MatteoMichelotti picture MatteoMichelotti  路  14Comments