Kasper Juner
Kasper Juner

Reputation: 952

Stripe webhook signature is not present

I'm trying to integrate stripe webhooks on my website. Initially the application was using only basic stripe and then i've changed it to Stripe Connect, when i was using the basic stripe all webhooks was working well but after changing the usage to Stripe Connect (that actually only adds the connected user ID to the payments) the webhooks stopped to work by returning the following error:

Stripe.StripeException: The signature for the webhook is not present in the Stripe-Signature header.
   at Stripe.EventUtility.ValidateSignature(String json, String stripeSignatureHeader, String secret, Int64 tolerance, Int64 utcNow)
   at Stripe.EventUtility.ConstructEvent(String json, String stripeSignatureHeader, String secret, Int64 tolerance, Int64 utcNow, Boolean throwOnApiVersionMismatch)
   at Stripe.EventUtility.ConstructEvent(String json, String stripeSignatureHeader, String secret, Int64 tolerance, Boolean throwOnApiVersionMismatch)
   at VisualOrder.Controllers.WebhookController.Stripe() in E:\VS2019\ccc\Controllers\WebhookController.cs:line 22
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

I've yet changed the webhook key to Connect one, but all sent webhooks return the same error...

Here is my c# code for webhook

const string secret = "whsec_kgyb....";
    [HttpPost]
    public async Task<IActionResult> Stripe()
    {
        
        var json = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync();


        var stripeEvent = EventUtility.ConstructEvent(json,
            Request.Headers["Stripe-Signature"], secret);

        try
        {
            if (stripeEvent.Type == Events.ChargeSucceeded)
            {
                var charge = (Charge)stripeEvent.Data.Object;
                charge.Metadata.TryGetValue("Piva", out string piva);
                charge.Metadata.TryGetValue("OrderId", out string orderID);
                charge.Metadata.TryGetValue("PaymentId", out string paymentID);
                OrdineHelper.ConfirmOrder(piva, orderID, (double)charge.Amount / 100, charge.PaymentIntentId, paymentID);
                return Ok();
            }
            else
            {
                return BadRequest();
            }
        }
        catch (Exception)
        {
            // Invalid Signature
            return BadRequest();
        }
    }

Upvotes: 1

Views: 3091

Answers (1)

Nolan H
Nolan H

Reputation: 7469

This error is actually telling you that the expected signature is not found, not that no signature is found.

Be aware that Account and Connect webhooks are two different webhook endpoint and therefore have distinct signing secrets. You either need separate handlers for these or you need to carefully manage which secret you use for each received event. Connect-related events will have an account attribute, if you are using a mixed handler.

Upvotes: 2

Related Questions