Paypal Security header is not valid error - solved!

After spending two days figuring out how to cleanly call PayPal's SOAP API in the sandbox environment, I was pretty much gutted when I couldn't get the same code working against the production environment.

I just kept getting the same error:

[Errors] => stdClass Object
        [ShortMessage] => Security error
        [LongMessage] => Security header is not valid
        [ErrorCode] => 10002
        [SeverityCode] => Error

If you've hit this issue yourself then you're probably sick and tired by now of reading forum post after forum post telling people that this error only occurs when you use the wrong credentials or try to use the right credentials to access the wrong endpoint. Blah blah blah blah blah... yeah, read it a million times... got sick of reading it!

In my case I was following all the rules (or so I thought). I was definitely instantiating my SOAPClient with the URL for the production WSDL and I was definitely using production credentials. I even tried dropping the credentials and re-creating them, as suggested in one or two forum posts, but that didn't help.

I also whipped up some code to do a GetBalance() request in the production environment using the NVP API and that worked, proving beyond a skeric of doubt that my credentials were, indeed, correct.

And I did RTFM too, which, in hindsight, possibly contributed to the problem, because the PHP manual clearly states that you only need to provide the location of the endpoint as one of the options to the SOAPClient constructor if you're running in non-WSDL mode. I guess this makes sense, because the WSDL should contain the correct URL for the endpoint, right?


Let me repeat that...


The breakthrough came when, in desperation, I read through all of the comments on the SOAPClient page and discovered a hint in the second last comment, made by a Mr Jim Plush all the way back in 2005. The comment was this:

As of version 5.0.4 you can now dynamically change your location even if you're using a wsdl

So I thought to myself, "What the hell, I'll just explicitly set the location of the endpoint and see if that solves the problem".

And guess what? IT WORKED!!!!

You are not going to believe this, but at the time of writing, the endpoints, as defined in the PRODUCTION Paypal WSDL, are:

<wsdl:service name="PayPalAPIInterfaceService">
    <wsdl:port name="PayPalAPI" binding="ns:PayPalAPISoapBinding">
        <wsdlsoap:address location=""/>
    <wsdl:port name="PayPalAPIAA" binding="ns:PayPalAPIAASoapBinding">
        <wsdlsoap:address location=""/>

Yeah, it says "sandbox" in there. D'oh...

So if you are hitting this issue and you are using the more common signature-type authentication (as opposed to certificate authentication), the code to instantiate your SOAPClient object should look something like this:

= new SoapClient( '',
'location' => '',
'soap_version' => SOAP_1_1 ));

I guess the big lesson in all this - again - is to always double check all assumptions, even those that you wouldn't normally question, when trying to resolve an issue.

I gotta tell you, the idea of lurking on StackOverflow until somebody asked this question again so that I could post the answer and get, like, a bazillion rep points did occur to me, but then I thought to myself, "I was only able to solve this problem due to a hint I got from somebody who was generous enough with their time to post their thoughts on Therefore, the right thing to do would be to make this information available ASAP so that others can benefit". So I did.

But I'm still going for those rep points if I spot this issue on StackOverflow. :-)


Nickfranko (visitor) says:

I really appreciate this post and who written this. This is the best solution for the Paypal security header error. The clarity in your post is simply spectacular and I can assume you are an expert on this field. Keep up the good work.

car diagnostic tool (visitor) says:

Please let me know if you’re looking for a author for your weblog. You have some really great articles and I feel I would be a good asset. If you ever want to take some of the load off, I’d love to write some material for your blog in exchange for a link back to mine. Please send me an email if interested. Kudos!

Anonymous (visitor) says:

nice helping post

brad (visitor) says:

you'll also get this error if your signature is wrong (ie bad username, password or signature). I just had the same issue happen when I pasted in my info to a config file, and had extra characters at the end of my signature by mistake.

brad (visitor) says:

for me, the problem was that i was reading my API username,password and signature from a config file, and there was a trailing space at the end of my username. I got rid of it and it started working fine.... So PayPal isn't trimming username/password or signature in the login request... FYI!

Andy Travis (visitor) says:

I returned after a relaxing weekend break to set the paypal live first thing this Monday morning only to discover the above problem. As you, I have been looking through post after post saying the same thing, but after reading yours I thought I best go through all the code line by line rather than just the variables at the top. Guess What, the sandbox api was hard coded as you mentioned. Thank you for saving my sanity on this Monday morning.

Arun (visitor) says:

This was a helpful hint. Thanks for posting the info.

Rohit (visitor) says:

Many thanks for the post Mr.James.I really like it..!!

Moc53 (visitor) says:

AS you said : "IT WORKED!!!"
Many thanks for this post Mr James :)

Hannes (visitor) says:

With this post you have worn my eternal gratitude and my heart :) BTW it still says sandbox in the WSDL

Dinesh Karki (visitor) says:

like it