php mysql laravel-5 paypal paypal-ipn

php - Paypal IPN, no obteniendo todas las respuestas de las transacciones después de cambiar la URL ipn en la cuenta



mysql laravel-5 (3)

En primer lugar, escriba un registro como la primera fila del servicio web, para que sepa cuándo recibe una solicitud.

Luego, a veces no tiene todos los parámetros de solicitud establecidos, por lo que es posible que su sql cometa un error cuando no se encuentran los parámetros.

En mi formulario de PayPal, por ejemplo, envío el número de factura. Luego, cuando recibo una solicitud de IPN, verificaré el número de factura para vincular el pago con la factura. Pero recibo el pago en la misma cuenta de PayPal también de otra fuente, por lo que en el otro caso, no se establece el número de factura.

Puede escribir un registro con todos los parámetros encontrados en la llamada de IPN para que pueda verificar lo que falta.

Estoy implementando ipnlistner dentro de mi proyecto. Puse el ipn url dentro de mi cuenta de paypal. Pero no estoy recibiendo todas las respuestas ipn de transacción a esa url. Pero cuando estoy revisando el historial de ipn en mi cuenta, muestra que todo el ipn ha sido enviado. Por ejemplo ayer está mostrando todos los 112 ipn que había enviado. pero estoy consiguiendo solo 7 en mi db. Aquí está mi código para ipn listner. Estoy insertando todos los datos que estoy recibiendo en la base de datos solo en la primera línea.

<?php namespace App/Http/Controllers; use Illuminate/Support/Facades/DB; use Illuminate/Support/Facades/Response; class PaypalIPN extends Controller { private $use_sandbox = null; const VALID = ''VERIFIED''; const INVALID = ''INVALID''; public function useSandbox() { $this->use_sandbox = env( ''USE_SANDBOX'' ); } public function getPaypalUri() { if ( $this->use_sandbox ) { return env( ''SANDBOX_VERIFY_URI'' ); } else { return env( ''VERIFY_URI'' ); } } public function verifyIPN() { try { DB::table( ''ipn_response'' )->insert( [ ''data'' => json_encode( $_POST, true ) ] ); if ( ! count( $_POST ) ) { throw new /Exception( "Missing POST Data" ); } $raw_post_data = file_get_contents( ''php://input'' ); $raw_post_array = explode( ''&'', $raw_post_data ); $myPost = array(); foreach ( $raw_post_array as $keyval ) { $keyval = explode( ''='', $keyval ); if ( count( $keyval ) == 2 ) { // Since we do not want the plus in the datetime string to be encoded to a space, we manually encode it. if ( $keyval[0] === ''payment_date'' ) { if ( substr_count( $keyval[1], ''+'' ) === 1 ) { $keyval[1] = str_replace( ''+'', ''%2B'', $keyval[1] ); } } $myPost[ $keyval[0] ] = urldecode( $keyval[1] ); } } // Build the body of the verification post request, adding the _notify-validate command. $req = ''cmd=_notify-validate''; $get_magic_quotes_exists = false; if ( function_exists( ''get_magic_quotes_gpc'' ) ) { $get_magic_quotes_exists = true; } foreach ( $myPost as $key => $value ) { if ( $get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1 ) { $value = urlencode( stripslashes( $value ) ); } else { $value = urlencode( $value ); } $req .= "&$key=$value"; } // Use the sandbox endpoint during testing. $this->useSandbox(); // Post the data back to PayPal, using curl. Throw exceptions if errors occur. $ch = curl_init( $this->getPaypalUri() ); curl_setopt( $ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1 ); curl_setopt( $ch, CURLOPT_POST, 1 ); curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); curl_setopt( $ch, CURLOPT_POSTFIELDS, $req ); curl_setopt( $ch, CURLOPT_SSLVERSION, 6 ); curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, 1 ); curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, 2 ); curl_setopt( $ch, CURLOPT_FORBID_REUSE, 1 ); curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, 30 ); curl_setopt( $ch, CURLOPT_HTTPHEADER, array( ''Connection: Close'' ) ); $res = curl_exec( $ch ); if ( ! ( $res ) ) { $errno = curl_errno( $ch ); $errstr = curl_error( $ch ); curl_close( $ch ); throw new /Exception( "cURL error: [$errno] $errstr" ); } $info = curl_getinfo( $ch ); $http_code = $info[''http_code'']; if ( $http_code != 200 ) { throw new /Exception( "PayPal responded with http code $http_code" ); } curl_close( $ch ); // Check if PayPal verifies the IPN data, and if so, return true. if ( $res == self::VALID ) { DB::table( ''ipn_response'' )->insert( [ ''data'' => json_encode( $res, true ) ] ); } else { DB::table( ''ipn_response'' )->insert( [ ''data'' => json_encode( $res, true ) ] ); } // Reply with an empty 200 response to indicate to paypal the IPN was received correctly. header( "HTTP/1.1 200 OK" ); }catch (/Exception $e){ DB::table( ''ipn_response'' )->insert( [ ''data'' => json_encode( ["Exception"=>$e->getMessage()]) ] ); } } }

Estoy muy satisfecho IPN en este url

https://ipnpb.paypal.com/cgi-bin/webscr

y mi ipn url es

https://www.myproject.com/api/verify-ipn

Nota: anteriormente creé algunos botones de PayPal en esta cuenta, no obtengo las respuestas de ipn para los pagos de ese botón.

Por favor ayuda o guía que hacer para esto ..


Parece que puede haber un error en su código. Sería necesaria una mayor depuración. Cuando me encuentro con algo como esto, por lo general reviso los registros de error para ver qué está pasando.

PayPal seguirá intentando enviar solicitudes hasta que reciba una respuesta de estado HTTP 200 OK sin contenido en el cuerpo. Si PayPal muestra una recepción exitosa por parte del punto final, es probable que el lugar donde la base de datos no ingrese los datos sea justo antes de que se llame a su función de header .

Mi próximo paso a la depuración sería tratar de averiguar si mis inserciones de base de datos estaban fallando debido a algún tipo de error / advertencia de integridad de datos.

Podría ser útil detectar errores en la base de datos y desencadenar algún tipo de respuesta que no pase, por lo que PayPal vuelve a enviar hasta que haya resuelto el problema de las secuencias de comandos.

También:

  • Intente agregar un registro adicional usando algo como Monolog o incluso error_log para llegar al final de donde termina su script o lo que no funciona como se esperaba.

Debo tener en cuenta que también estoy implementando PayPal IPN ahora y que esta biblioteca fue difícil de usar. Hice mi propio giro con un patrón de suscriptor. Todavía no está listo para ser público, pero fue en gran medida para separar la lógica de la verificación para una mejor prueba y legibilidad.


Por favor, cree la siguiente función en su controlador y en su cuenta de Paypal agregue en la URL de IPN y verifique cada golpe de IPN.

<?php function paymentIpnlistener(){ $req = ''cmd=_notify-validate''; foreach ($_POST as $key => $value) { $value = urlencode(stripslashes($value)); $req .= "&$key=$value"; } // post back to PayPal system to validate $header = "POST /cgi-bin/webscr HTTP/1.0/r/n"; // If testing on Sandbox use: $header .= "Host: www.sandbox.paypal.com:443/r/n"; //$header .= "Host: ipnpb.paypal.com:443/r/n"; $header .= "Content-Type: application/x-www-form-urlencoded/r/n"; $header .= "Content-Length: " . strlen($req) . "/r/n/r/n"; if (strpos(''ssl://www.sandbox.paypal.com'', ''sandbox'') !== FALSE && function_exists(''openssl_open'')) { $fp = fsockopen(''ssl://www.sandbox.paypal.com'', 443, $errno, $errstr, 30); } else{ // The old "normal" way of validating an IPN. $fp = fsockopen(''ssl://www.sandbox.paypal.com'', 80, $errno, $errstr, 30); } // If testing on Sandbox use: //$fp = fsockopen (''ssl://www.sandbox.paypal.com'', 443, $errno, $errstr, 30); //$fp = fsockopen (''ssl://ipnpb.paypal.com'', 443, $errno, $errstr, 30); // assign posted variables to local variables $item_name = $_POST[''item_name'']; $item_number = $_POST[''item_number'']; $payment_status = $_POST[''payment_status'']; $payment_amount = $_POST[''mc_gross'']; $payment_currency = $_POST[''mc_currency'']; $txn_id = $_POST[''txn_id'']; $receiver_email = $_POST[''receiver_email'']; $payer_email = $_POST[''payer_email'']; if (!$fp) { // HTTP ERROR } else { fputs ($fp, $header . $req); while (!feof($fp)) { $res = fgets ($fp, 1024); if (strcmp ($res, "VERIFIED") == 0) { // check the payment_status is Completed // check that txn_id has not been previously processed // check that receiver_email is your Primary PayPal email // check that payment_amount/payment_currency are correct // process payment // Add your live email address $mail_From = "From: [email protected]"; // Add your live email address $mail_To = "[email protected]"; $mail_Subject = "VERIFIED IPN"; $mail_Body = $req; foreach ($_POST as $key => $value){ $emailtext .= $key . " = " .$value ."/n/n"; } mail($mail_To, $mail_Subject, $emailtext . "/n/n" . $mail_Body, $mail_From); } else if (strcmp ($res, "INVALID") == 0) { // log for manual investigation $mail_From = "From: [email protected]"; $mail_To = "[email protected]"; $mail_Subject = "INVALID IPN"; $mail_Body = $req; foreach ($_POST as $key => $value){ $emailtext .= $key . " = " .$value ."/n/n"; } mail($mail_To, $mail_Subject, $emailtext . "/n/n" . $mail_Body, $mail_From); } } // while end fclose ($fp); } } ?>

La función anterior le enviará un correo electrónico cada vez que se active el servicio de escucha de IPN. Simplemente si está funcionando, puede administrarlo según sus necesidades. Intenta y házmelo saber.