For the last couple of days, I have been working on realising a payment integration using the PayPal SDK for PHP (which uses the REST API). However, I have been experiencing some issues.
When a payer is redirected to the PayPal site for approving his payment and redirected back to the return URL, PayPal returns a HTTP 400 status code upon executing the approved payment. The code for executing the payment is as follows. Note that $paymentId is the ID returned after creating the payment and $payerId is the PayerID sent along with the approval.
$payment = Payment::get($paymentId);
$paymentExecution = new PaymentExecution();
$paymentExecution->setPayer_id($payerId);
$payment->execute($paymentExecution);
It says the payment is invalid:
{"name":"PAYMENT_STATE_INVALID","message":"This request is invalid due to the current state of the payment","information_link":"https://developer.paypal.com/docs/api/#PAYMENT_STATE_INVALID","debug_id":"223647e6e42fb"}
While figuring out where all goes wrong (note that the samples included with the API also give the same error), I stumbled across the following line in my log files:
PPHttpConnection: Invalid or no certificate authority found - Retrying using bundled CA certs file
I checked to make sure that the SDK locates the certificate included with the SDK. So my guess is that it's an invalid certificate. I'm kind of lost now about what to do. Does anybody have an idea how to fix this issue?
You should always check your payments state before running an execute. The error indicates that the payment already was executed
Payment state. Must be set to one of the one of the following:
created; approved; failed; canceled; expired; pending. Value assigned
by PayPal.
You probably ran the method Create on your payment, and the Create method executes the same submethods as Execute.
Related
Since few days the adaptive payments (both preapprovals and chained) seems to be broken.
When we send the user to paypal to complete the order (chained) or to authorize the preapproval (preapprovals), they get a generic "invalid transaction" error. Tested the flow, we get the same error and looking to the console we can see this error on the checkout.js file in the paypal object directory:
Uncaught TypeError: PAYPAL.AP.Subflow is not a constructor
at checkout.js:11
(anonymous) # checkout.js:11
Seems something has broken on paypal side.
Anyone with the same issue? Workarounds?
Cheers, Fil
We've finally figured out what was wrong.
Trying the complete debugging of the call to the svcs endpoint we've discovered that since few days (first time from 2013), we started getting an odd response from the paypal server to our SOAP request as:
{"faultstring":"Unknown Content-Encoding","faultcode":"HTTP"}
We've then thought to some issue in the "transportation" of the call to paypal servers and we've tryed to add something in the headers.
First, we discovered that in our http header request some line that we've never used before was missing, for example:
"X-PAYPAL-DEVICE-IPADDRESS: " . $_SERVER['REMOTE_ADDR'] . "\r\n" ;
But this didn't solve the issue.
Then we've added a new line in the soap client array:
'compression' => SOAP_COMPRESSION_ACCEPT,
Adding this solved the issue but no one ever adviced us about the requirement of this part of the code. Probably, this is a linux issue, maybe paypal has changed some server with a newer one and while the older accepted the SOAP request even if it was not with this "compression" parameter, in the newer environment it seems required.
Anyway, everything is back to normality adding this line, we just still have an odd time response (long) for the Pay operation while everyting is smooth for the Preapproval operation but this might depend on different paypal servers managing one or the other operation.
I spent the last day and a half researching this problem to no avail. I found many similar problems, but none that exactly address my issue. I am attempting to integrate Payflow Pro with transparent redirect, but cannot successfully complete a transaction. I am using the test environment with a test Payflow Gateway account.
I can successfully retrieve a secure token by posting the following from my test server to https://pilot-payflowpro.paypal.com:
PARTNER=[hidden]&VENDOR=[hidden]&USER=[hidden]&PWD=[hidden]&TRXTYPE=S&TENDER=C&CREATESECURETOKEN=Y&SECURETOKENID=20180916085333999&URLMETHOD=POST&SILENTTRAN=TRUE&AMT=2&BILLTOFIRSTNAME=John&BILLTOLASTNAME=Doe&BILLTOADDRESS=123TestDr.&BILLTOCITY=Testcity&BILLTOSTATE=TN&BILLTOZIP=55511&BILLTOEMAIL=johndoe#test.com&USER1=3&USER2=&USER3=0&USER4=2
to which I receive the following response:
RESULT=0&SECURETOKEN=[hidden]&SECURETOKENID=20180916085333999&RESPMSG=Approved
NOTE: I have configured a Return URL using PayPal Manager, which is why RETURNURL is not included in the secure token request. However, I also have tried with RETURNURL specified, and I have obtained the same end result.
I use the results from the secure token request to create a cc collection form. I input test credit card details using acct# 5105105105105100, then post the following from the browser directly to https://pilot-payflowlink.paypal.com:
fund_id=3&ACCT=5105105105105100&CVV2=555&EXPMONTH=01&EXPYEAR=20&EXPDATE=0120&SECURETOKENID=20180916085333581&SECURETOKEN=[hidden]&feeTokenID=20180916085333999&feeToken=[hidden]
The response is properly redirected to the Hosted Page error URL I have specified in my Payflow Manager Service Settings. My problem is that I do not understand why it is redirecting to the error url with the following message:
RESPMSG=Failed to connect to host Input Server Uri = https://pilot-payflowpro.paypal.com:443
NOTE: The value above is only one part of the response sent to the error page. The rest of the return values include information from my original secure token request, which I would assume could only be returned if a successful connection had been established with the link in the error message??
To clearly state the problem:
I have already successfully connected from my test server to the link specified in the error message, when first I obtained the secure token.
The post that results in the error message was sent from the browser (in this case, on the same physical box as my test server) to https://pilot-payflowlink.paypal.com, which is not the URL specified in the error message.
Finally, the error seemingly occurs during the Payflow process - to my understanding, there should not be a call from my server or the browser to the link in the error message at this point during the process. I mention this specifically to address the many search results I found relating this particular error message to PayPal's requirement for TLS1.2, which is already properly configured on my server (I should mention for the sake of completeness, I do still have TLS1.0 enabled on my test server, but cannot disable it for unrelated reasons. Nonetheless, I was able to successfully connect to obtain a secure token, and my server passes PayPal's own TLS test at https://tlstest.paypal.com/).
I should mention that I also have tried to complete this same transaction on our production server, still using test credentials and test endpoints at PayPal, with exactly the same results. The test server is also set up for TLS1.2 with TLS1.0 enabled, and also passes PayPal's test.
This problem may be the one that pushes me full-on into insanity, so any help really would be appreciated!!
Disabling TLS1.0 has helped others with this issue. If you keep having problems, contact PayPal's support
For anyone who might find this question and be similarly frustrated, I want to share that I was able to solve the problem by creating a new Payflow Gateway test account.
I spent a great deal of time on trial and error solutions with no success, and PayPal Merchant Technical Services was able to duplicate the problem but was also unable to find a solution. Finally, after simplifying my test app as much as possible (two bare-bones HTML forms filled in and submitted manually), I came to the conclusion that there might be something wrong with my test account. Upon creating a new account with new credentials, then inserting them back into my original code, everything worked perfectly.
As of this morning, PayPal MTS is continuing to research the problem, since others have reported similar issues.
For others with similar problems, it is worth noting that I am now able to complete transactions while TLS 1.0 remains enabled.
I am attempting a SetExpressCheckout transaction in LIVE, but it always fails with "We are unable to complete your request at this time." In the sandbox it works perfectly every time, so I believe my API call is correct.
Here is the full request:
VERSION=97.0
&METHOD=SetExpressCheckout
&RETURNURL=http://www.foo.com/
&CANCELURL=http://www.foo.com/
&PAYMENTREQUEST_0_PAYMENTACTION=Sale
&PAYMENTREQUEST_0_AMT=1.00
&PAYMENTREQUEST_0_CURRENCYCODE=USD
&PAYMENTREQUEST_0_ITEMAMT=1.00
&L_PAYMENTREQUEST_0_NAME0=Test+Payment
&L_PAYMENTREQUEST_0_NUMBER0=TestPayment
&L_PAYMENTREQUEST_0_AMT0=1.00
&L_PAYMENTREQUEST_0_QTY0=1
&L_PAYMENTREQUEST_0_ITEMCATEGORY0=Digital
&SOLUTIONTYPE=Sole
&REQCONFIRMSHIPPING=0
&NOSHIPPING=1
&USER=*************************
&PWD=*************************
&SIGNATURE=********************
I have a ticket open with Paypal Merchant Support, but they have no clue why it's failing, which amazes me. I have called paypal customer service twice, and they definitely have no clue.
What am I doing wrong? Thank you.
I figured it out. It was my mistake. Although I was pointed at the live environment for the SetExpressCheckout call, the subsequent redirect was still going to the sandbox.
My fault...BUT...why can't the paypal developers put a little line of code in there so that when you go to the wrong environment (the system knows EITHER that I had just made the call to Live, then redirected to sandbox, OR at a minimum that the Live environment didn't have a matching token for what I was calling) a concise message is thrown such as "No token found in sandbox environment" or "API call made to Live, but redirected to Sandbox". A message like that would have enabled me to fix my own problem in seconds instead of hours.
My application uses the SetExpressCheckout paypal classic API method. It is working fine when I use real accounts in a live environment.
It used to work fine using test accounts, but some weeks ago it has stopped working right. At some point, my application calls the "SetExpressCheckout" API method using curl in PHP. When I use the test seller account that I've always used for my tests, I always get the following error:
SetExpressCheckout API call failed.
Detailed Error Message: Security header is not valid
Short Error Message: Security error
Error Code: 10002
Error Severity Code: Error
I know that paypal has recently restructured its "developer network", and the issue seems to be caused by this but I have no proof of that. The API I used is now called the "classic" API.
I've read the documentation, and it says that I now have to create a new "real" paypal account, and then use it to log to https://developer.paypal.com. I did that.
Once logged to the developer website, there is a feature allowing us to import all the test buyer and seller accounts used in an old sandbox account. I did that, and my old test accounts appeared in a list.
One of them is the test seller account I used to test. When I check the details of this account, the username, password and signature used to authenticate to the paypal API are there. If I use them, it still returns the previous error.
There is also a feature allowing me to create test accounts. I've created a new seller, and still, I get the same error message.
When I search on google about this issue, most answers says that the username, password or signature are wrong or have hidden white spaces in them. That's not my case.
I don't know how to solve that problem. I am wondering if the API endpoint has changed. I currently use "https://api-3t.paypal.com/nvp" for tests. I am using the NVP API, version 64.
To make it short:
1) My test account used to work
2) The code has not been modified
3) Real accounts used to work and still work.
4) But test buyer account has stopped working
5) The issue chronologically coincide with paypal "developer network" restructuring.
6) I don't know what has changed exactly and might cause this.
7) Does anyone know what has changed and might has caused this (a new parameter in the query string? Endpoint URL changed?)?
8) According to my previous description, do I seem to have misunderstood something, and what?
I currently use "https://api-3t.paypal.com/nvp" for tests.
That's your problem. You're using test credentials, but the live API endpoint.
Change your endpoint to https://api-3t.sandbox.paypal.com/nvp and all should be fine.
Security header is not valid means that your credentials are incorrect. I've never once seen that error where this wasn't the case.
You need to make sure that if you're using sandbox credentials for testing that you're hitting the correct endpoint and using the correct credentials.
Lots of times people accidentally have sandbox credentials set but then send them to the live endpoint or visa versa. If you're hitting the correct endpoint and your credentials are indeed correct you won't get this error.
I'd like to think I'm just missing something obvious here, but I can't seem to get a chained payment to complete (using the PHP SDK in the sandbox). I am able to get a successful response, and when I redirect the user to PayPal the transaction details show up fine, but when the user attempts to complete the payment they get the dreaded error:
Your payment can't be completed. Please return to the participating website and try again.
What's frustrating is that I've dumped the request data that is being sent, and compared it to the data in the example given in the documentation and tweaked my request until they were effectively identical, and still no dice. I'm also not seeing anything at all on any of the accounts to indicate that payment was attempted, pending or failed.
This is what's being sent:
requestEnvelope.errorLanguage=en_US
&clientDetails.ipAddress=127.0.0.1
&clientDetails.applicationId=APP-80W284485P519543T
&actionType=PAY
&cancelUrl=http%3A%2F%2Fdomain.com%2Fpaypal%2Fcancel
¤cyCode=USD
&feesPayer=EACHRECEIVER
&memo=Test+Payment
&receiverList.receiver(0).amount=3.25
&receiverList.receiver(0).email=merchant%40domain.com
&receiverList.receiver(0).primary=1
&receiverList.receiver(1).amount=1.5
&receiverList.receiver(1).email=seller%40domain.com
&senderEmail=buyer%40domain.com
&returnUrl=http%3A%2F%2Fdomain.com%2Fpaypal%2Freturn
And the response looks fine to me:
PayPal\Types\AP\PayResponse Object
(
[responseEnvelope] => PayPal\Types\Common\ResponseEnvelope Object
(
[timestamp] => 2013-07-28T23:25:52.676-07:00
[ack] => Success
[correlationId] => bf1ba2c8a50d4
[build] => 6941298
)
[payKey] => AP-XXXXXXXXXXXXXXXXC
[paymentExecStatus] => CREATED
[payErrorList] =>
[paymentInfoList] =>
[sender] =>
[defaultFundingPlan] =>
[warningDataList] =>
[error] =>
)
I also tried setting the action type to PAY_PRIMARY since I am specifying a primary recipient, and that's ideally what I'm after anyways.
UPDATE: Seeing as I still have not received a response on the ticket I opened with PayPal regarding this, and nobody has commented on this question, I did some further testing. If I generate the same request with the API explorer, the transaction completes normally. But the exact same request fails through the API. I have verified (by copying and pasting the generated headers and request body) that the only differences between the request generated by the API Explorer and the SDK code are as follows:
The headers created by the explorer have a space between the name and values
The API Explorer does not include the application ID
My API call does include the application ID in both the header and request body
The SDK API call still does not work if I remove the application ID reference, which was added in an attempt to solve this issue to begin with.
I do not understand why the payment generated by the SDK (which is provided by PayPal) fails to complete, yet the exact call works fine when the explorer calls it. Any help or advice would be appreciated.
So after nearly a month of fighting this issue with PayPal's merchant technical support (most of the time not getting any responses at all) and waiting nearly two weeks for a response on an escalation, it turns out the issue stems from the SDK configuration.
Although throughout the API docs and SDK code the Application ID is referenced as applicationId, apparently the SDK requires it to be entered in the config file as acct1.AppId instead. I only discovered this after coming across this wiki page on configuring the SDK, which didn't even exist 24 hours ago.
Once I updated my config, I was able to authorize the payment without error.
I encountered another cause that can cause this exact problem with Chained Payments.
Here's how my chained payment was setup.
Main account received 100%.
Referring account got 50% from that.
Partner 1 account got 10%.
Partner 2 account got 10%.
Partner 3 account got 10%.
Partner 4 account got 10%.
10% remained in main account and paying the transaction fee.
This worked perfectly in sandbox (with normal prices), absolutely perfect, but I got this error in Live.
What was happening was a final, pre-announcement, test of Live, we were using a transaction amount of $1.00 and sending $.50, $.10, $.10, $.10, $.10 and leaving $.10 to pay the $.33 fee. (At time of writing, paypal charges 2.9% + $.30). All the answers around the internet were not solving the problem in our case, but this did. Changing the transaction amount to $5 (for testing) worked fine because it left $.50 to pay the $.45 fee ($.45 fee for $5).