php ssl curl paypal paypal-sandbox

php - No se puede usar la API de Paypal en un sitio web SSL



curl paypal-sandbox (1)

Tengo un sitio web SSL con integración de Paypal API usando cURL.

Esta es mi clase en PHP incluye archivo:

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; } }

Por alguna razón, no funciona, al hacer clic en el botón de pago se lleva al usuario a Paypal, pero después de finalizar el proceso, el usuario regresa al sitio web, la URL parece correcta (por ejemplo, https://example.com/pro&type=successful?token=EC-8BB04791XJ708490K&PayerID=QL54Q696KZCLA ) pero sin realizar el pago.

Probé la caja de arena también, pero no puedo ver ningún error en el archivo de registro de Apache, así que tengo que depurar $response , por esta razón intenté agregar echo var_dump($response); antes de analizar la respuesta.

Pero no tengo mucha experiencia en la depuración, y en Chrome no sé dónde verificar la respuesta (en la consola JS no puedo verla)

¿Cómo podría depurar esta respuesta de API para verificar por qué PayPal no permite pagos para mi sitio web? (el sitio web ya está verificado)

ACTUALIZAR

Como autenticación, estoy usando el formato NVP de la firma API con el método SetExpressCheckout .

Este es el código de mi respuesta:

// 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("Y-m-d 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("Y-m-d 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''])); } }

EDITAR

Este es mi archivo error.log:

* 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

Finalmente pude depurar la respuesta (hubo un problema de redirección)

TOKEN=EC-9F8624569H0752611 BILLINGAGREEMENTACCEPTEDSTATUS=0 CHECKOUTSTATUS=PaymentActionCompleted TIMESTAMP=2015-12-30T15:41:54Z CORRELATIONID=19204729b140 ACK=Success VERSION=116.0 BUILD=18308778 [email protected] 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

Entonces, por mi parte, todo funciona ahora, pero no veo transacciones en Sandbox Paypal. ¿Qué pasa?


Tu proceso parece muy intrincado. Vamos a romper esto

// 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);

Hasta aquí todo bien. Usted hace su llamada SEC, obtiene su token y pasa el usuario a PayPal. Pero luego esta siguiente parte es confusa

// 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") {

Esto no tiene ningún sentido. Acabas de devolver al usuario a PayPal con un header y estamos llamando a esto con lo que parece ser los mismos datos que pasamos a la llamada SEC. DoExpressCheckoutPayment requiere que devuelva el token y el usuario acaba de abandonar el sitio para autorizarlo. Esperaría ver su código buscar $_GET[''TOKEN''] (es decir, el usuario devuelto desde PayPal) y luego crear una nueva solicitud para eso. En este momento, como está escrito su código, solo está encadenando las 3 llamadas en una cadena gigante.

Esto es lo que debería parecer el proceso

  • SetExpressCheckout - Rebote al usuario a PayPal. Detener el procesamiento
  • GetExpressCheckoutDetails : el usuario ha regresado de PayPal porque tenemos un TOKEN en la cadena de consulta. Ejecutar esta llamada ahora nos permite asegurarnos de que TOKEN sea válido
  • DoExpressCheckoutPayment : si DoExpressCheckoutPayment es válido, completemos la venta.

Por último, pero no menos importante, no puedes simplemente buscar el éxito . Lea los documentos en ACK . También puede obtener SuccessWithWarning . Cambie su condición de éxito a

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