#stibbs-webhook

1 messages · Page 1 of 1 (latest)

shy knot
#

Hello, there could be many things leads to that error. It's a common one

#

What language are you using?

river bridge
#

Elixir

shy knot
#

Normally, something in your middleware could prevent your server to handle the raw request

river bridge
#

I can see the signature

#

I'm grabbing the raw body

shy knot
#

If you print out the raw body before goes in the signature checking, does it match exactly what Stripe sent out?

#

You can check the event in your Dashboard

#

Does the issue comes around these lines?

    signing_secret = Application.get_env(:stripity_stripe, :signing_secret)
    {:ok, body, _} = Plug.Conn.read_body(conn)
    [stripe_signature] = Plug.Conn.get_req_header(conn, "stripe-signature")

    {:ok, stripe_event} = Stripe.Webhook.construct_event(body, stripe_signature, signing_secret)
shy knot
#

In case you are back, I suggest to open a Github issue with Stripity Stripe since they own this checking logic

river bridge
#

This is the raw body

"{\n \"id\": \"evt_1KEnoJFSYzAEE2mTpWKCkZ6d\",\n \"object\": \"event\",\n \"api_version\": \"2020-08-27\",\n \"created\": 1641444167,\n \"data\": {\n \"object\": {\n \"id\": \"cs_test_a1JYSZJEhFCuS4UMmISCDqMdjC3n4XqV2Z9yRGHInGI9mQ8uryvi6MNJPp\",\n \"object\": \"checkout.session\",\n \"after_expiration\": null,\n \"allow_promotion_codes\": null,\n \"amount_subtotal\": 5000,\n \"amount_total\": 5000,\n \"automatic_tax\": {\n \"enabled\": false,\n \"status\": null\n },\n \"billing_address_collection\": null,\n \"cancel_url\": \"http://rafo.com.au:443/my-jobs\",\n \"client_reference_id\": null,\n \"consent\": null,\n \"consent_collection\": null,\n \"currency\": \"aud\",\n \"customer\": \"cus_Kud4zP2d4qOxYq\",\n \"customer_details\": {\n \"email\": \"joe@example.com\",\n \"phone\": null,\n \"tax_exempt\": \"none\",\n \"tax_ids\": [\n\n ]\n },\n \"customer_email\": null,\n \"expires_at\": 1641530553,\n \"livemode\": false,\n \"locale\": null,\n \"metadata\": {\n \"user_id\": \"ac4074f4-8a50-4f7e-ba69-6f072a27a49a\",\n \"job_id\": \"3f2ef9a8-7b18-49d0-b2a7-327174087ba8\"\n },\n \"mode\": \"payment\",\n \"payment_intent\": \"pi_3KEno5FSYzAEE2mT1NB92GZR\",\n \"payment_method_options\": {\n },\n \"payment_method_types\": [\n \"card\"\n ],\n \"payment_status\": \"paid\",\n \"phone_number_collection\": {\n \"enabled\": false\n },\n \"recovered_from\": null,\n \"setup_intent\": null,\n \"shipping\": null,\n \"shipping_address_collection\": null,\n \"shipping_options\": [\n\n ],\n \"shipping_rate\": null,\n \"status\": \"complete\",\n \"submit_type\": null,\n \"subscription\": null,\n \"success_url\": \"http://rafo.com.au:443/my-jobs\",\n \"total_details\": {\n \"amount_discount\": 0,\n \"amount_shipping\": 0,\n \"amount_tax\": 455\n },\n \"url\": null\n }\n },\n \"livemode\": false,\n \"pending_webhooks\": 3,\n \"request\": {\n \"id\": null,\n \"idempotency_key\": null\n },\n \"type\": \"checkout.session.completed\"\n}"
#

What Stripe sent

{
  "id": "evt_1KEnoJFSYzAEE2mTpWKCkZ6d",
  "object": "event",
  "api_version": "2020-08-27",
  "created": 1641444167,
  "data": {
    "object": {
      "id": "cs_test_a1JYSZJEhFCuS4UMmISCDqMdjC3n4XqV2Z9yRGHInGI9mQ8uryvi6MNJPp",
      "object": "checkout.session",
      "after_expiration": null,
      "allow_promotion_codes": null,
      "amount_subtotal": 5000,
      "amount_total": 5000,
      "automatic_tax": {
        "enabled": false,
        "status": null
      },
      "billing_address_collection": null,
      "cancel_url": "http://rafo.com.au:443/my-jobs",
      "client_reference_id": null,
      "consent": null,
      "consent_collection": null,
      "currency": "aud",
      "customer": "cus_Kud4zP2d4qOxYq",
      "customer_details": {
        "email": "joe@example.com",
        "phone": null,
        "tax_exempt": "none",
        "tax_ids": [
        ]
      },
      "customer_email": null,
      "expires_at": 1641530553,
      "livemode": false,
      "locale": null,
      "metadata": {
        "user_id": "ac4074f4-8a50-4f7e-ba69-6f072a27a49a",
        "job_id": "3f2ef9a8-7b18-49d0-b2a7-327174087ba8"
      },
      "mode": "payment",
      "payment_intent": "pi_3KEno5FSYzAEE2mT1NB92GZR",
      "payment_method_options": {
      },
      "payment_method_types": [
        "card"
      ],
      "payment_status": "paid",
      "phone_number_collection": {
        "enabled": false
      },
      "recovered_from": null,
      "setup_intent": null,
      "shipping": null,
      "shipping_address_collection": null,
      "shipping_options": [
      ],
#
      "shipping_rate": null,
      "status": "complete",
      "submit_type": null,
      "subscription": null,
      "success_url": "http://rafo.com.au:443/my-jobs",
      "total_details": {
        "amount_discount": 0,
        "amount_shipping": 0,
        "amount_tax": 455
      },
      "url": null
    }
  },
  "livemode": false,
  "pending_webhooks": 3,
  "request": {
    "id": null,
    "idempotency_key": null
  },
  "type": "checkout.session.completed"
}
#

It does match (if you discount escaped characters)

#

The issue is definitely one of these 3 lines. If the escaped characters are the issue, then the issue is the read_body(conn)

    {:ok, body, _} = Plug.Conn.read_body(conn)
    [stripe_signature] = Plug.Conn.get_req_header(conn, "stripe-signature")

    {:ok, stripe_event} = Stripe.Webhook.construct_event(body, stripe_signature, signing_secret)
shy knot
#

Yeah I guess so. We see a lot of similar asks in different programming languages. They all comes down to the raw body wasn't the same with what Stripe sent

#

Could you try to take the body without modification? Sorry I am not super familiar with Elixir and Phoenix (?)

river bridge
#

That's what the read_body does to my understanding. The body is normally parsed and the raw version discarded. Above is retaining the raw body purely for validating the stripe message