#oranges13-php-missingkey

1 messages ยท Page 1 of 1 (latest)

narrow merlinBOT
opal ridge
#

That error really just means that you never provided an API key to us

#

it's fairly easy to debug. Step 1: hardcode your key right before the call and confirm it just works

bold trout
#

I have. It still fails.

opal ridge
#
  'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
);
$stripe->customers->create([
  'description' => 'My First Test Customer (created for API docs at https://www.stripe.com/docs/api)',
]);```
#

try that exact code

#

nothing else, no laravel, nothing. Just pure PHP

bold trout
#

I have tried it, it works in tinker but even with the API key hard coded into the file, it fails

#

It's not letting me post the request headers but I confirmed it says bearer and has our correct key

opal ridge
#

I don't know what "it works in tinker" means

#

API headers don't really matter honestly

bold trout
#

The request headers containing the API key don't matter?

#

Showing the request was sent with the correct key?

opal ridge
#

Right now they don't. I don't know how you go and access them but I don't think that's the issue

#

oranges13-php-missingkey

bold trout
#

Tinker is like laravel CLI. It loads everything about your app just like a controller would, for example

opal ridge
#

ah gotcha

#

okay so it works in Tinker, that's good

#

Can you make a request in Tinker for me with my name in the parameter?

#

I want to go and find that request and then compare it to your other request

#

(I work for Stripe I have access to internal logs)

bold trout
#

Which is why I'm confused the API key hard coded into the client as you describe, but also included as a parameter in the invoice->retrieve call itself, same result

#

Yes one moment. Use that test key?

#

The other odd thing is that it is only the invoice->retrieve method. Everything else is working fine

opal ridge
#

hum

#

that is even weirder ๐Ÿ˜…

#

Just do an API request in Test mode on your account and put koopajah somewhere and then tell me what you did

#

I can look up that query

#

and then we can work backwards from that

bold trout
#

ok!

#

OK I retrieved an invoice and used your name as the idempotency key I have no idea if that works

#

oh woops taht was in live mode

opal ridge
#

oh boy

#

I was hoping a real parameter, that's why I couldn't find anything

#

let me have a look

bold trout
#

it was just a retrieve ๐Ÿ™‚

#

Do you have a suggestion on how to include that with Invoice->retrieve?

#

That seems to be the only method with this issue. ๐Ÿ˜ฆ

opal ridge
#

what Invoice did you retrieve, like what's the id? I can't find a retrieve with koopajah anywhere in the idempotency key

#

cc @bold trout

bold trout
#

ok, let me try test then

#

in_1LpHWlILkkcOmYXlgeFhCTZS on our test key

#

here's the requst ID req_foUITMNZQbI2yQ

opal ridge
#

perfect. Okay, now try to retrieve the Invoice in your normal environment where it doesn't work. Just try once and then give me the Invoice id

bold trout
#

I'll need to wait for an organic request, it may take a few moments

opal ridge
#

I thought you said you could reproduce this error

bold trout
#

I can, but when I do it manually, it always works, so I gotta wait for a request to come through -- but I am manually triggering them so it should be soon

#

OK we just attempted to request in_1LpHjSILkkcOmYXl9yxfErNX

#

and received the error:

{
  "params": [],
  "response": {
    "error": {
      "message": "You did not provide an API key. You need to provide your API key in the Authorization header, using Bearer auth (e.g. 'Authorization: Bearer YOUR_SECRET_KEY'). See https://stripe.com/docs/api#authentication for details, or we can help at https://support.stripe.com/.",
      "type": "invalid_request_error"
    }
  },
  "responseCode": 401
}

That is the response in full

opal ridge
#

(looking)

#

Okay, so in the past 15 minutes I see 3 separate requests to retrieve that Invoice

#

1 failed with a 401 and 2 others succeeded

#

the request with a 401 comes from a different IP address than the other 2

bold trout
#

I modified the code to work around this error but it's not ideal, so those successes may be from that

opal ridge
#

the ones that succeed also use a completely different version of our stripe-php library

bold trout
#

yeah, we are in the middle of an upgrade >_>

opal ridge
#

lol

#

you're holding out a ton of crucial details here ๐Ÿ˜…

bold trout
#

We have a load balancer. The new system is the problem

#

Well it works on the old system but it's going away!

#

I need the new system to work ๐Ÿ˜ข

#

The key information remains the same -- I AM providing the api key ๐Ÿ˜•

#

but it says I am not ๐Ÿ˜ฆ

#

Are you receiving the API key? Is it a formatting issue or something?

opal ridge
#

that part I can't know

#

I have access to things, but not raw input requests

bold trout
#

ah I see.

opal ridge
#

I definitely see the request come in and one of our earliest systems is like "yeah no sorry there's no key"

#

And so you have direct access to that new infra and you can add whatever code you want to it right?

bold trout
#

correct

opal ridge
#

So you could totally have code that goes, creates a customer, then retrieves an invoice, sequentially

bold trout
#

In this case we're responding to webhooks

#

We are consuming an invoice.created webhook, this is a process in a stack of processes - so we need to ensure the invoice is up to date pending the previous tasks. (If you're wondirng why we can't just use the invoice included in the event)

#

Maybe there's a better way to refresh it?

opal ridge
#

let's ignore that for now

#

all I am asking is if you can make one-off code in your system

#

because waiting for real live events is really not scalable

bold trout
#

Yeah I think so. I'd prefer to do that with a test key if possible tho

opal ridge
#

So how easy/hard is it for you to add a custom logic that can trigger a request to Stripe from that environment

#

sure me too

#

So step 1:
Add code in that system that will try to retrieve the Invoice id in_koopajah

bold trout
#

ok, let me fiddle with this a little bit. Scary writing code on the fly on prod ๐Ÿ˜“

#

ok, have the code locally -- going to copy to the affected system.

#

No such invoice: 'in_koopajah'

opal ridge
#

cool let me look now

bold trout
#

You should see a request from the problematic IP

#

_> that's not the api error though wtf

opal ridge
#

okay so that request worked totally fine lol

bold trout
#

indeed it did.

#

but why???

opal ridge
#

what did you do to the code. did you hardcode the API key?

bold trout
#

No, I used our original method which should use the app-loaded config variable, which stores the api key (the way it SHOULD be working)

#

But that code and the code I just executed, except for it's location, are exactly the same

opal ridge
#

hum

bold trout
#

I am trying something else, I am pointing my webhook code at that code instead

#

to see what happens.

opal ridge
#

yeah

#

you could just curl it too I assume

#

At this point I really think this is an initialization issue somewhere

bold trout
#

it must be ๐Ÿ™ƒ but I swear to god I have no idea how

#

because I have literally hard coded the api key in there and it still failed

#

and that should override anything else that came before you'd think?

opal ridge
#

Can you share your exact code and just redact the API key part

bold trout
#

it's kind of all over the place.

opal ridge
#

ack

#

that kinda makes my point a bit. It's highly likely you have something not initialized properly

bold trout
#

Well like, we are initializing Stripe in the AppServiceProvider for Laravel, using Stripe::setApiKey and that works globally for most everything else

#

it's just this one area being weird.

#

But yeah, earlier, where the Invoice->retrieve is called, I overrode it with

$stripe = new \Stripe\StripeClient(config('services.stripe.secret'));
        return $stripe->invoices->retrieve($invoiceId);

right in the code where this error happens

#

and I even replaced the call to config with the API string directly

#

so I'm stumped

opal ridge
#

hum

#

and I even replaced the call to config with the API string directly
what did you do exactly?

#

because it feels like Laravel is using the old PHP way with global API key

#

and you're suddenly using the new client/service infra

#

and so they differ completely in behaviour

bold trout
#

$stripe = new \Stripe\StripeClient("APIKEYHERE");
return $stripe->invoices->retrieve($invoiceId);

#

Ah yeah, I noticed the documentation was different. I also tried
\Stripe\Invoice::retrieve("invoice_id", [], ['api_key' => "APIKEY"]);

#

That also failed ๐Ÿ˜ญ

opal ridge
#

did you really try that?

#

because that is impossible :p

#

the old way to do retrieve was super annoyingly confusing

#

\Stripe\Invoice::retrieve(["id" =>"invoice_id"],['api_key' => "APIKEY"]);

#

that's how yu used to have to do it. The second array in your code example is just plain ignored I think

bold trout
#

oh? huh

opal ridge
#

$stripe->invoices->retrieve($invoiceId, [], ['api_key' => "APIKEY"]) that would work

bold trout
#

Well, we are still using Stripe v8

opal ridge
#

that's irrelevant

#

sorry you're mixing up a lot of things ๐Ÿ˜…

#

Client/service infra, the new StripeClient was shipped in 7.33.0, so it is in v8 too.
But if you mix both coding styles, you have to understand the subtle differences in shapes

bold trout
#

let me check something -- we use the Object::retrieve signature a lot, maybe this one is just written wrong

opal ridge
bold trout
#

My attempt to use StripeClient was purely because that's what the documentation said to do it was kind of a last ditch effort

#

Since this was recently upgraded from 6 -> 8, we are still using the old format for the most part, example e.g: Customer::retrieve($customerId, ['expand' => ['default_source']]); That works just fine

opal ridge
#

yes

#

I'd recommend ignoring the new way entirely for now

#

(and later migrating all your code to the new way)

#

so really to me it still boils down to "at that point, the API key is not set properly. Either a part of your code elsewhere "unsets it" and it's a global so it breaks, or there's something else you're misunderstanding

#

I'm sorry I have to run, but @zealous meteor on my team can help if needed. I really think at this point you need to add detailed logs to your whole code everywhere the API key is set globally to log what it's set to and confirm it's correct.
Also make super sure you don't have any trailing space, new line character and such in your logic that loads the key.
It's almost 100% sure this is a bug like that, and not a bug with the library itself or your own code at this point

bold trout
#

I appreciate you

#

If I figure this out I will be sure to let you know

opal ridge
#

sounds good!

zealous meteor
#

Hi @bold trout I'm taking over, let me know if you have any follow-up question

bold trout
#

Thanks Jack -- at this point it is late and I hate to fiddle with prod in the middle of the night, but I have things to think about. I will report in the morning with more information as I have it. I appreciate you both!!

#

Well actually, shoot -- this is the even weirder part

#

I just had 2 successes and 2 failures from the same box, theoretically the same code wtf is going on ๐Ÿ˜ฆ

zealous meteor
#

This is a long chat, give me a sec to catch up the previous discussions.

bold trout
#

Would hte 401 provide a request ID?

#

req_T8GgFiiFFbjZI7 succeeded

#

Same box, same code

zealous meteor
#

401 means No valid API key provided., can you check if a valid API is provided in your app?

bold trout
#

Yeah, we are using stripe throughout our app, it's just this one instance that is failing for some reason. I have modified my code to set the api key immediately before calling Invoice::retrieve too and it still fails -- and the stupid thing is that it's intermittent

#

The 401 doesn't appear in our Stripe Dashboard logs, so I don't believe there is a request ID

zealous meteor
#

Hmm, can you put a log to print out the API key right before the Invoice::retrieve, so that we can make sure the API key is valid? Remember to remove this log before deploying to production.

bold trout
#

I am hesitatnt to do so but yeah

#

Yeah frustratingly this is only happening on prod.

#

OK, I added a debug IMMEDIATELY before the call and teh api key is present and was printed

zealous meteor
#

OK, was the API request succeeded or failed?

bold trout
#

We got two 401's in a row

zealous meteor
#

Can you share with me the exact code?

bold trout
#

we are including Stripe\Invoice further up the page, but essentially

    /**
     * Retrieve Stripe Invoice
     * @param string $invoiceId Stripe Invoice ID
     * @return Invoice
     */
    public function retrieve($invoiceId)
    {
        // Added apikey debug here and it printed
        return Invoice::retrieve(['id' => $invoiceId]);
    }
zealous meteor
#

And how do you pass the API key to \Stripe\Stripe::setApiKey() ?

bold trout
#

That is in the AppServiceProvider which is global to laravel

#

I printed out the configuration value immediately before this though

zealous meteor
#

Is there a possibility that the \Stripe\Stripe::setApiKey() was called with a different API key somewhere else in your code?

bold trout
#

When we initially noticed this issue, we were setting it in various places across the code, but I have removed those and it is only set once

zealous meteor
bold trout
#

No, we only have stripe\stripephp

#

We were initially using the most recent version v9. I downgraded this afternoon to v8 and the issue persists ๐Ÿ˜ฆ

zealous meteor
#

OK. The SDK recommends using Client/service pattern (e.g., StripeClient) since version 7.33.0, and I notice you are still using the legacy pattern

bold trout
#

Yeah, our current system was using v6 -- this is all part of an upgrade project.

#

So I guess we need to rewrite everything to avoid depreceations

#

Everything is working except this one thing and it's mindboggling

#

Like.. I just watched 2 requests work, and 2 requests fail. Same box, same code. I do not understand ๐Ÿ˜ฆ

zealous meteor
#

It's suboptimal but can you try hardcoding the API key in your application? so that we can rule out the cases where the API key variable is altered by something else

bold trout
#

I have done that earlier today and received the same sort of mixed result

#

I just added the setApiKey directly before wehre this code is called and got those 2 failures.

zealous meteor
#

And you call setApiKey with the hard coded API key string?

bold trout
#

not in this moment, but I had done so eariler yeah -- also logged the api key directly ahead of the line where it's failing

#

Unfortunately I have to go to sleep ๐Ÿ˜ฆ I will catch back up in the morning

zealous meteor
#

Sure, have a good rest

bold trout
#

I appreciate your help