#MikeD-PHP

1 messages · Page 1 of 1 (latest)

zenith osprey
#

one sec

#

that's the header comes with the request from Stripe. We includes it when we send the event

#

you don't need to set it yourself

#

Invalid Signature is a common error

#

Have you correctly set the $endpoint_secret?

sly escarp
#

Yes from your documentation but yeahj

#

so I am doing it locally

#

and testing using ngrok

#

How do I find the webhook secret after I create the webhook just to verify

zenith osprey
#

In your dashboard, look at that webhook endpoint you setup

sly escarp
#

yeah didn't see it. but I created a new end point

#

should begin with whsec_ right?

zenith osprey
#

yes!

sly escarp
#

Ok. So I can access the header through laravel like the following

$headers = collect($request->header())->transform(function ($item) {
return $item[0];
})->toArray();

#

$headers['stripe-signature'];

zenith osprey
#

Click on "Reveal" when you are at the page of your endpoint

sly escarp
#

and I get something that looks like this

#

it's not letting me paste the photo

#

but like the documentation

t=1492774577,
v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd,
v0=6ffbb59b2300aae63f272406069a9788598b792a944a07aba816edb039989a39
#

without the "Stripe-Signature:"

zenith osprey
#

this is the Signature header

#

Just to verify, have you correctly set the Endpoint secret to your env('STRIPE_LOCAL_ENDPOINT') ?

sly escarp
#

That's my whsec_ code

zenith osprey
#

Yeah, but it looks for STRIPE_LOCAL_ENDPOINT in your environment variables

sly escarp
#

right it's there

zenith osprey
#

You have it? If you print out env('STRIPE_LOCAL_ENDPOINT') you have the whsec_xxx value, right?

sly escarp
#

yes

zenith osprey
#

awesome sound good

#

And then you also have payload and sig_header?

sly escarp
#

well I didn't do the payload that may be the problem.

#

let me try one thing

#

Ok. So how does it accept it?

#

Because In Laravel we typically do something like $request->all() $request is everything

#

So I have tried a couple different ways
If I do
$request all it complains about it being an array
if I do json_encode($request->all()) to basically get it back to the way it was. it doesn't like it either says "invalid signature"

#

In looking at the webhook I am returning it exactly as it is sent

zenith osprey
#

you are talking about the payload right?

sly escarp
#

Yes so I basically did this

return json_encode($request->all())

#

Then when I look at the WebHook the Response and the Request are exactly identical.

zenith osprey
#

It's okay as long as you are returning 200 to our request. Stripe only care if you well received it (we got 200/201)

sly escarp
#

tested with $payload = @file_get_contents('php://input');1 with same result

#

right right I understand it is going into success

#

Becasue I am returning 200

#

But if I do not return and it go through the rest of the code. it fails at signature

#

But you're saying that my signature is correct

zenith osprey
#

I see, so the issue is the signature code

#

let's figure it out

sly escarp
#

right but you said that my signature looked valid.

zenith osprey
#

so we have correct endpoint_secret, we have the header, we have the payload

#

still, it's failing

sly escarp
#

Can I share what the signature look slike ?

zenith osprey
#

Let me quick check

#

1 min

sly escarp
#

Is the signature even a "secret" without the "secret"

#

Also, it's test data so. Not really caring too much lol

#

Can I share what my signature extraction is coming out to?

#

f it
t=1645071548,v1=45c0d0eb757dc9a473af4202a5065bced4ea71e291ea020a048a3a47f175448e,v0=d2625482a145cb93fcbb56dbbfcb890b8f96ac1b00852d8d59911977743cecb5

#

That's the string output of my extraction. That looks normal yes?

zenith osprey
#
"t=1645071645,v1=153ec87a5ab59d9235660eb0148ddf2ac09292ef44d6056a0e39b3485c05c328,v0=f5c08aefe31bfb0453547cb8a3c4796cc2f2e890af5f0797b5ded76f7bf20772"
#

Mine

#

So it does look like correct format

sly escarp
#

Plot thickens lol

zenith osprey
#

I know you can echo your endpoint secret, but how about print it inside your program

#

maybe your program doesn't capture environment variables well...

sly escarp
#

i'll hard code it for a sec to see

zenith osprey
#

and printout payload as well

sly escarp
#

Well I printed out payload by responding and reading the payload in your web request response section.

#

So I hard coded the webhook_secret no change

zenith osprey
#

can you paste here how you payload looks like?

sly escarp
#
{"id":"evt_1KU1C0GHeMNtzjNmdLP9XAGv","object":"event","api_version":"2020-08-27","created":1645070528,"data":{"object":{"id":"in_1KHrzcGHeMNtzjNmVGodu0mx","object":"invoice","account_country":"US","account_name":"MyTekki, LLC","account_tax_ids":null,"amount_due":127500,"amount_paid":127500,"amount_remaining":0,"application_fee_amount":null,"attempt_count":1,"attempted":true,"auto_advance":false,"automatic_tax":{"enabled":false,"status":null},"billing_reason":"manual","charge":"ch_3KHrzdGHeMNtzjNm00jc97RI","collection_method":"send_invoice","created":1642175228,"currency":"usd","custom_fields":null,"customer":"cus_KW5ZjC1SjHhhJZ","customer_address":{"city":"Westford","country":"United States","line1":"70 Main Street","line2":null,"postal_code":"01886","state":"Massachusetts"},"customer_email":"mike@mytekki.com","customer_name":"Building Science Corporation","customer_phone":null,"customer_shipping":{"address":{"city":null,"country":null,"line1":null,"line2":null,"postal_code":null,"state":null},"name":"Betsy BSC Pettit","phone":null},"customer_tax_exempt":"none","customer_tax_ids":[],"default_payment_method":null,"default_source":null,"default_tax_rates":[],"description":null,"discount":null,"discounts":[],"due_date":1642222799,"ending_balance":0,"footer":null,"hosted_invoice_url":"https:\/\/invoice.stripe.com\/i\/acct_1JhwTvGHeMNtzjNm\/test_YWNjdF8xSmh3VHZHSGVNTnR6ak5tLF9LeG5hYnpSZXUyYmxYeHRyalFLcWkyekx0NUFrbWVYLDM1NjExMzI40200cozLv7yl?s=ap","invoice_pdf":"https:\/\/pay.stripe.com\/invoice\/acct_1JhwTvGHeMNtzjNm\/test_YWNjdF8xSmh3VHZHSGVNTnR6ak5tLF9LeG5hYnpSZXUyYmxYeHRyalFLcWkyekx0NUFrbWVYLDM1NjExMzI40200cozLv7yl\/pdf?s=ap","last_finalization_error":null,"lines":{"object":"list","data":[{"id":"il_1KHrzcGHeMNtzjNmn89Oph6R","object":"line_item","amount":127500,"currency":"usd","description":"$150\/ hr @ 8.50 Hours | test","discount_amounts":[],"discountable":true,"discounts":[],"invoice_item":"ii_1KHrzcGHeMNtzjNmNJ1kxQR7","livemode":false,"metadata":{"entry_type":"TimeEntry","billable_hours":"8.50","cost_rate":"0","bill_rate":"15000","description":"test","notes_public":"false","charge_amount":"127500","billable":"true","out_of_scope":"false","wuwd":"0","entry_date":"2022-01-20 00:00:00","item_id":"1","item_description":"Consulting Services","item_code":"CON150","project_id":"1","project_name":"Betsy  BSC Pettit","project_code":"0003"},"period":{"end":1642175228,"start":1642175228},"plan":null,"price":{"id":"price_1KHrzcGHeMNtzjNmUUqCbfH2","object":"price","active":false,"billing_scheme":"per_unit","created":1642175228,"currency":"usd","livemode":false,"lookup_key":null,"metadata":[],"nickname":null,"product":"prod_KxnaVkWkxnREHT","recurring":null,"tax_behavior":"unspecified","tiers_mode":null,"transform_quantity":null,"type":"one_time","unit_amount":127500,"unit_amount_decimal":"127500"},"proration":false,"quantity":1,"subscription":null,"tax_amounts":[],"tax_rates":[],"type":"invoiceitem"}],"has_more":false,"total_count":1,"url":"\/v1\/invoices\/in_1KHrzcGHeMNtzjNmVGodu0mx\/lines"},"livemode":false,"metadata":[],"next_payment_attempt":null,"number":"4D8F9B3B-0037","on_behalf_of":null,"paid":true,"paid_out_of_band":false,"payment_intent":"pi_3KHrzdGHeMNtzjNm0h0kvMzr","payment_settings":{"payment_method_options":null,"payment_method_types":null},"period_end":1642175228,"period_start":1642175228,"post_payment_credit_notes_amount":0,"pre_payment_credit_notes_amount":0,"quote":null,"receipt_number":null,"starting_balance":0,"statement_descriptor":null,"status":"paid","status_transitions":{"finalized_at":1642175229,"marked_uncollectible_at":null,"paid_at":1645070528,"voided_at":null},"subscription":null,"subtotal":127500,"tax":null,"total":127500,"total_discount_amounts":[],"total_tax_amounts":[],"transfer_data":null,"webhooks_delivered_at":1642175228}},"livemode":false,"pending_webhooks":1,"request":{"id":"req_XYSXEFmwbY6pdV","idempotency_key":"407564da-e9c4-41c0-afe9-07ba61f69a67"},"type":"invoice.payment_succeeded"}
zenith osprey
#

Umm looks normal to me

#

I had some \n

#

hmm, why didn't you have any \n. Is this how you get your payload?

$payload = @file_get_contents('php://input');
sly escarp
#

tried both ways

#

so if I do it the way you just said it comes out on the response screen formatted

#

if I do it the way I tried json_encoded($request->all())

#

comesout as one line string. but either way they both fail

#

So I am presuming your response screen is interpretting the \n

#

So it would be equivalent to your one that you had.

zenith osprey
#

From my experiences, we have received a lot of similar questions for Signature verification failed. It's normally some middleware tried to modify the request body. (Node.js frameworks is terrible, ie) It's possible that Laravel also has some

#

Do you have an idea of which Laravel middleware could have done some modification?

sly escarp
#

no. Because I don't have it blocked by a middleware

#

I found a video

#

Going to watch this real fast might explain.

zenith osprey
#

Choose PHP and click download

sly escarp
#

Looks like there is a package
composer require spatie/laravel-stripe-webhooks

#

Going to explore real quick

sly escarp
#

Which seems to be well used.

#

Maybe ngrok is changing something?

zenith osprey
#

No idea about ngrok but hard to think they have changed smth that could affect

#

So it didn't work with even that library?

#

Could you try the example PHP project above?

sly escarp
#

So I got it working. Looks like ngrok is modifying the request a bit. It would probably work without ngrok the way I was doing it. but I ended up using the library above anyways due to the fact that it handles the stripe webhook split out and assigns it to jobs. a little more cleaner then my solution if I want to expand.

#

Thanks for your time.

zenith osprey
#

Glad to hear it's working!