Stripe Webhooks

I’m trying to implement Stripe webhooks into my app to confirm subscription payment (payment_succeeded, payment failed, session completed).
Stripe is successfully sending the webhooks and I’m recieving them, but stripe sig verification is consistently failing:

Stripe webhook received!
Received Signature Header: t=1695558609,v1=c36992d950cebe0b9e35b921e7cc2eaf0ce05cc7f1aea54187ac21bbd4a997fc,v0=f297193f4723de1f69cfdc064de67425d8f05f57ddda0060ee63d1e9320d55d6
First 100 bytes of payload: b’{\n “id”: “evt_3NtrRqKx9mFp39qk1uFmceNP”,\n “object”: “event”,\n “api_version”: “2023-08-16”,\n "cre’
Error: Stripe signature verification failed

API secret key and Webhook signing secret are correct. The webhook URL is correct as I’m receiving the webhook.

Setting up the CLI to listen locally I’m seeing:
2023-09-24 13:30:11 ← [200] POST https://bqs3i7bzcsyzuawc.anvil.app/VHYXNWDFOTKW4JQ4ZEOI53SZ/_/api/webhook [evt_1NtrRsKx9mFp39qkuujklfWO]

Which suggests success.

I’m wondering if it’s something to do with how Anvil handles incoming headers for webhooks that is causing the problem.
I’ve looked at the Anvil documentation, but with regards to webhooks it mostly relates to Trello and I cant find anything relevant in the forum. I don’t know where to go from here to get to the bottom of it.

Here’s the relevant part of the function in my server module:

@anvil.server.http_endpoint(“/webhook”)
def handle_stripe_webhook(**kwargs):
print(“Stripe webhook received!”)

# Retrieve the Stripe signature header
sig_header = anvil.server.request.headers.get('stripe-signature', anvil.server.request.headers.get('STRIPE-SIGNATURE'))

print(f"Received Signature Header: {sig_header}") 
# Extract the payload as StreamingMedia
payload = anvil.server.request.body
# Convert the StreamingMedia payload to bytes
payload_bytes = payload.get_bytes()
print(f"First 100 bytes of payload: {payload_bytes[:100]}")

Please bear in mind I’m neither a coder or a developer when replying.

I should add I’m using a stripe payment link for taking payments (not sure if that’s relevant or not).

Thanks in adavance
Adam

Hello @mail,

I think this is the code you’re looking for.

import stripe
import json

stripe_secret_key = anvil.secrets.get_secret('stripe_secret_key')

@anvil.server.http_endpoint("/webhook_number_1")
def webhook_number_1():
  signing_secret = anvil.secrets.get_secret('webhook_number_1_signing_secret')
  payload = anvil.server.request.body.get_bytes()
  
  if stripe_secret_key:
    # Only verify the event if there is an endpoint secret defined
    # Otherwise use the basic event deserialized with json
    sig_header = anvil.server.request.headers.get("stripe-signature")
    try:
      event = stripe.Webhook.construct_event(
          payload, sig_header, signing_secret
      )
      print('Webhook signature verification succeeded.')
      return anvil.server.HttpResponse(status=200, body=json.dumps({'success':True}), headers=None)
    except stripe.error.SignatureVerificationError as e:
      print('⚠️  Webhook signature verification failed.' + str(e))
      return anvil.server.HttpResponse(status=400, body=json.dumps({'success':False}), headers=None)`
1 Like