Cannot use Paypal API on SSL website

I have an SSL site with Paypal API integration using cURL.

This is my PHP class contains the file:

class paypalApi { public $username; public $password; public $signature; function post($method, $params, $mode) { // Method: Required // Parameters: An array containing the requested parameters // The request URL $url = "https://api-3t".$mode.".paypal.com/nvp"; // Version of the API $version = '116.0'; // Construct the query params // Set the API method, version, and API credentials. $credentials = array('METHOD' => $method, 'VERSION' => $version, 'USER' => $this->username, 'PWD' => $this->password, 'SIGNATURE' => $this->signature); $params = array_merge($credentials, $params); // Set the curl parameters. if(function_exists('curl_exec')) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_VERBOSE, 1); // Turn off the server and peer verification (TrustManager Concept). curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params)); $response = curl_exec($ch); } if(empty($response)) { $opts = array('http' => array( 'protocol_version' => '1.1', 'method' => 'POST', 'header' => 'Content-type: application/x-www-form-urlencoded', 'content' => http_build_query($params) ) ); $context = stream_context_create($opts); $response = file_get_contents($url, false, $context); } // Parse the response parse_str($response, $responseArr); // If the request fails if(empty($responseArr) || !array_key_exists('ACK', $responseArr)) { global $LNG; // Mimic a fake response return array('L_SHORTMESSAGE0' => $LNG['error'], 'L_LONGMESSAGE0' => $LNG['payment_error_0'], 'ACK' => 'REQUEST_FAILED'); } return $responseArr; } } 

For some reason this does not work, clicking on the payment button leads the user to Paypal, but after the process is completed, he returns the user to the site, the URL seems to be correct (for example, https://example.com/pro&type=successful?token=EC-8BB04791XJ708490K&PayerID=QL54Q696KZCLA ), but without make payment.

I tried the sandbox too, but I don't see an error in the Apache log file, so I need to debug $response , so I tried to add echo var_dump($response); before parsing the answer.

But I don’t have much experience in debugging, and in Chrome I don’t know where to check the answer. (on the JS console I do not see it)

How can I debug an API response to check why paypal does not allow payments for my site? (website already verified)

UPDATE

For authentication, I use the NVP format of the API signature using the SetExpressCheckout method.

This is the code for my answer:

  // Execute SetExpressCheckOut method to create the payment token and PayerID $paypalResponse = $paypal->post('SetExpressCheckout', $params, $PayPalMode); //Respond according to message we receive from Paypal if(strtoupper($paypalResponse["ACK"]) == "SUCCESS") { // Generat the PayPal payment url with the response Token $paypalurl = 'https://www'.$PayPalMode.'.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token='.$paypalResponse["TOKEN"].''; // Redirect to PayPal payment page header('Location: '.$paypalurl); // Execute DoExpressCheckoutPayment to receive the payment from the user $paypalResponse = $paypal->post('DoExpressCheckoutPayment', $params, $PayPalMode); // Check if the payment was successful if(strtoupper($paypalResponse["ACK"]) == "SUCCESS") { // Verify if the payment is Completed if($paypalResponse["PAYMENTINFO_0_PAYMENTSTATUS"] == 'Completed') { // Execute GetExpressCheckoutDetails to retrieve the transaction details $params = array('TOKEN' => $token); $paypalResponse = $paypal->post('GetExpressCheckoutDetails', $params, $PayPalMode); // If the GetExpressCheckoutDetails was successful if(strtoupper($paypalResponse["ACK"]) == "SUCCESS") { $date = date("Ymd H:m:s", strtotime(($_SESSION['SelectedPlan'] == 1 ? "+1 year" : "+1 month"))); $stmt = $db->prepare(sprintf("INSERT INTO `payments` (`by`, `payer_id`, `payer_first_name`, `payer_last_name`, `payer_email`, `payer_country`, `txn_id`, `amount`, `currency`, `type`, `status`, `valid`, `time`) VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s','%s', '%s', '%s', '%s')", $db->real_escape_string($feed->id), $db->real_escape_string($paypalResponse['PAYERID']), $db->real_escape_string($paypalResponse['FIRSTNAME']), $db->real_escape_string($paypalResponse['LASTNAME']), $db->real_escape_string($paypalResponse['EMAIL']), $db->real_escape_string($paypalResponse['SHIPTOCOUNTRYNAME']), $db->real_escape_string($paypalResponse['PAYMENTREQUEST_0_TRANSACTIONID']), $db->real_escape_string($paypalResponse['AMT']), $settings['currency'], $_SESSION['SelectedPlan'], 1, $date, date("Ymd H:m:s"))); // Execute the statement $stmt->execute(); // Check the affected rows $affected = $stmt->affected_rows; // Close the statement $stmt->close(); // If the pro status has been added if($affected) { // Set the pro account to valid $proAccount = 2; } } else { $TMPL['error'] = notificationBox('error', '<strong>'.urldecode($paypalResponse['L_SHORTMESSAGE0'].'</strong>: '.$paypalResponse['L_LONGMESSAGE0'])); } } else { $TMPL['error'] = notificationBox('error', '<strong>'.urldecode($paypalResponse['L_SHORTMESSAGE0'].'</strong>: '.$paypalResponse['L_LONGMESSAGE0'])); } } else { $TMPL['error'] = notificationBox('error', '<strong>'.urldecode($paypalResponse['L_SHORTMESSAGE0'].'</strong>: '.$paypalResponse['L_LONGMESSAGE0'])); } } 

EDIT

This is my error.log file:

 * Hostname was NOT found in DNS cache * Trying 173.0.82.83... * Connected to api-3t.sandbox.paypal.com (173.0.82.83) port 443 (#0) * successfully set certificate verify locations: * CAfile: none CApath: /etc/ssl/certs * SSL connection using *********************** * Server certificate: * subject: C=US; ST=California; L=San Jose; O=PayPal, Inc.; OU=PayPal Production; CN=api-3t.sandbox.paypal.com * start date: 2015-09-16 00:00:00 GMT * expire date: 2016-10-31 23:59:59 GMT * issuer: C=US; O=VeriSign, Inc.; OU=VeriSign Trust Network; OU=Terms of use at https://www.verisign.com/rpa (c)10; CN=VeriSign Class 3 Secure Server CA - G3 * SSL certificate verify ok. > POST /nvp HTTP/1.1 Host: api-3t.sandbox.paypal.com Accept: */* Content-Length: 862 Content-Type: application/x-www-form-urlencoded * upload completely sent off: 862 out of 862 bytes < HTTP/1.1 200 OK < Date: Wed, 30 Dec 2015 09:49:59 GMT * Server Apache is not blacklisted < Server: Apache < X-PAYPAL-OPERATION-NAME: SetExpressCheckout < X-PAYPAL-API-RC: < Connection: close < Content-Length: 138 < Paypal-Debug-Id: 7d9949c818525 < Set-Cookie: X-PP-SILOVER=name%3DSANDBOX3.API.1%26silo_version%3D880%26app%3Dappdispatcher_apit%26TIME%3D3349709654; domain=.paypal.com; path=/; Secure; HttpOnly < Set-Cookie: X-PP-SILOVER=; Expires=Thu, 01 Jan 1970 00:00:01 GMT < Content-Type: text/plain; charset=utf-8 * Closing connection 0 

2nd EDIT

Finally, I was able to debug the response (there was a redirect problem)

 TOKEN=EC-9F8624569H0752611 BILLINGAGREEMENTACCEPTEDSTATUS=0 CHECKOUTSTATUS=PaymentActionCompleted TIMESTAMP=2015-12-30T15:41:54Z CORRELATIONID=19204729b140 ACK=Success VERSION=116.0 BUILD=18308778 EMAIL=info-buyer@example.org PAYERID=QL54Q696KZCLA PAYERSTATUS=verified FIRSTNAME=test LASTNAME=buyer COUNTRYCODE=IT SHIPTONAME=test buyer SHIPTOSTREET=Via Unit? d\'Italia, 5783296 SHIPTOCITY=Napoli SHIPTOSTATE=NAPOLI SHIPTOZIP=80127 SHIPTOCOUNTRYCODE=IT SHIPTOCOUNTRYNAME=Italy ADDRESSSTATUS=Unconfirmed CURRENCYCODE=EUR AMT=4.00 ITEMAMT=4.00 SHIPPINGAMT=0.00 HANDLINGAMT=0.00 TAXAMT=0.00 INSURANCEAMT=0.00 SHIPDISCAMT=0.00 L_NAME0=Monthly Pro Plan - example subdirectory L_NUMBER0=cfcd208495d565ef66e7dff9f98764da L_QTY0=1 L_TAXAMT0=0.00 L_AMT0=4.00 L_DESC0=Monthly Pro Plan - example subdirectory L_ITEMWEIGHTVALUE0= 0.00000 L_ITEMLENGTHVALUE0= 0.00000 L_ITEMWIDTHVALUE0= 0.00000 L_ITEMHEIGHTVALUE0= 0.00000 PAYMENTREQUEST_0_CURRENCYCODE=EUR PAYMENTREQUEST_0_AMT=4.00 PAYMENTREQUEST_0_ITEMAMT=4.00 PAYMENTREQUEST_0_SHIPPINGAMT=0.00 PAYMENTREQUEST_0_HANDLINGAMT=0.00 PAYMENTREQUEST_0_TAXAMT=0.00 PAYMENTREQUEST_0_INSURANCEAMT=0.00 PAYMENTREQUEST_0_SHIPDISCAMT=0.00 PAYMENTREQUEST_0_TRANSACTIONID=61M42051UB346361T PAYMENTREQUEST_0_INSURANCEOPTIONOFFERED=false PAYMENTREQUEST_0_SHIPTONAME=test buyer PAYMENTREQUEST_0_SHIPTOSTREET=Via Unit? d\'Italia, 5783296 PAYMENTREQUEST_0_SHIPTOCITY=Napoli PAYMENTREQUEST_0_SHIPTOSTATE=NAPOLI PAYMENTREQUEST_0_SHIPTOZIP=80127 PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE=IT PAYMENTREQUEST_0_SHIPTOCOUNTRYNAME=Italy PAYMENTREQUEST_0_ADDRESSSTATUS=Unconfirmed PAYMENTREQUEST_0_ADDRESSNORMALIZATIONSTATUS=None L_PAYMENTREQUEST_0_NAME0=Monthly Pro Plan - example subdirectory L_PAYMENTREQUEST_0_NUMBER0=cfcd208495d565ef66e7dff9f98764da L_PAYMENTREQUEST_0_QTY0=1 L_PAYMENTREQUEST_0_TAXAMT0=0.00 L_PAYMENTREQUEST_0_AMT0=4.00 L_PAYMENTREQUEST_0_DESC0=Monthly Pro Plan - example subdirectory L_PAYMENTREQUEST_0_ITEMWEIGHTVALUE0= 0.00000 L_PAYMENTREQUEST_0_ITEMLENGTHVALUE0= 0.00000 L_PAYMENTREQUEST_0_ITEMWIDTHVALUE0= 0.00000 L_PAYMENTREQUEST_0_ITEMHEIGHTVALUE0= 0.00000 PAYMENTREQUESTINFO_0_TRANSACTIONID=61M42051UB346361T PAYMENTREQUESTINFO_0_ERRORCODE=0 

So, for its part, everything works right now, but I do not see transactions on the Paypal sandbox. What's wrong?

+7
php curl ssl paypal paypal-sandbox
source share
1 answer

Your process seems extremely confusing. Let me break it down

 // Execute SetExpressCheckOut method to create the payment token and PayerID $paypalResponse = $paypal->post('SetExpressCheckout', $params, $PayPalMode); //Respond according to message we receive from Paypal if(strtoupper($paypalResponse["ACK"]) == "SUCCESS") { // Generat the PayPal payment url with the response Token $paypalurl = 'https://www'.$PayPalMode.'.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token='.$paypalResponse["TOKEN"].''; // Redirect to PayPal payment page header('Location: '.$paypalurl); 

So far so good. You make your SEC call, get your token and transfer the user to PayPal. But then this next part is confusing

 // Execute DoExpressCheckoutPayment to receive the payment from the user $paypalResponse = $paypal->post('DoExpressCheckoutPayment', $params, $PayPalMode); // Check if the payment was successful if(strtoupper($paypalResponse["ACK"]) == "SUCCESS") { 

That doesn't make any sense. You just pushed the user to PayPal using the header , and we call it with what appears to be the same data that we passed to the SEC call. DoExpressCheckoutPayment requires that you transfer the token, and the user simply leaves the site to authorize it. I expect to see your code looking for $_GET['TOKEN'] (which means the user has returned from PayPal), and then create a new request for it. Right now, when your code is written, it just catches all 3 calls in one giant chain.

Here the process should look like

  • SetExpressCheckout - Opt out of a user at PayPal. Processing stop
  • GetExpressCheckoutDetails - The user returned from PayPal because we have TOKEN in the query string. Making this call now allows us to make sure that Token is indeed
  • DoExpressCheckoutPayment - If the TOKEN is valid, let me complete the sale.

And last but not least, you cannot just look for Success . Read the docs at ACK . You can also get SuccessWithWarning . Change the success condition to

  if(stripos($paypalResponse["ACK"], "SUCCESS") !== false) { 
+5
source share

All Articles