Ver Mensaje Individual
  #2 (permalink)  
Antiguo 14/01/2013, 13:39
Avatar de zalito12
zalito12
 
Fecha de Ingreso: noviembre-2011
Ubicación: Coruña, España
Mensajes: 430
Antigüedad: 13 años, 1 mes
Puntos: 67
Respuesta: Tutorial: Saca provecho a tu Web (PayPal y más)

2. IPN:
Como veo que me estoy extendiendo bastante voy a intentar ser lo más claro y conciso posible. En esta parte nos encargamos de recibir la notificación de PayPal de que alguien compró nuestro producto, pero hay que hacer más comprobaciones para asegurarnos que la transacción fue de la manera esperada.

Debemos crear un archivo PHP, lo llamaremos como queramos (en este caso notify.php) pero debe ser igual que el notify_url de nuestro botón.
Si queremos configurar una url para IPN por defecto podéis ir a Perfil->Notificación de pago instantánea (IPN)->Escoger Configurarción... Escribis la url y activais Recibir mensajes IPN

notify.php:
Código PHP:
<?php                                    
$ip_remote 
$_SERVER['REMOTE_ADDR'];    //Guardo la IP desde la que se realiza la petición, no es necesario
$comentario '';

// Primera comprobación. Comprobamos que haya variables pasadas por POST (como nos las pasa PayPal)
    
if($_POST){
    
        
//************TRATAMIENTO DE INFO
        // Obtenemos los datos en formato variable1=valor1&variable2=valor2&...
        
$raw_post_data file_get_contents('php://input');

        
// Los separamos en un array
        
$raw_post_array explode('&',$raw_post_data);

        
// Separamos cada uno en un array de variable y valor
        
$myPost = array();
        foreach(
$raw_post_array as $keyval){
            
$keyval explode("=",$keyval);
            if(
count($keyval) == 2)
                
$myPost[$keyval[0]] = urldecode($keyval[1]);
        }

        
//Nos comunicaremos con PayPal para verificar que la información es suya 
       //para ello nuestro string debe comenzar con cmd=_notify-validate
        
$req 'cmd=_notify-validate';
        if(
function_exists('get_magic_quotes_gpc')){
            
$get_magic_quotes_exists true;
        }
        foreach(
$myPost as $key => $value){
            
// Cada valor se trata con urlencode para poder pasarlo por GET
            
if($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) {
                
$value urlencode(stripslashes($value)); 
            } else {
                
$value urlencode($value);
            }

            
//Añadimos cada variable y cada valor
            
$req .= "&$key=$value";
        }
        
        
//********ENVIO DE INFO
        // Esta URL debe variar dependiendo si usamos SandBox o no. Si no lo usamos, se queda así.
        
$ch curl_init('https://www.paypal.com/cgi-bin/webscr');   
        
curl_setopt($chCURLOPT_HTTP_VERSIONCURL_HTTP_VERSION_1_1);
        
curl_setopt($chCURLOPT_POST1);
        
curl_setopt($chCURLOPT_RETURNTRANSFER,1);
        
curl_setopt($chCURLOPT_POSTFIELDS$req);
        
curl_setopt($chCURLOPT_SSL_VERIFYPEER1);
        
curl_setopt($chCURLOPT_SSL_VERIFYHOST2);
        
curl_setopt($chCURLOPT_FORBID_REUSE1);
        
curl_setopt($chCURLOPT_HTTPHEADER, array('Connection: Close'));

        if( !(
$res curl_exec($ch)) ) {
            
// Error con la petición de Curl.
            
curl_close($ch);
            
$comentario "Error Curl IPN";
            
//Guardo datos y $comentario en el Log de la DB
            
exit; //Paramos la ejecución
        
}
        
curl_close($ch);
         
        
//******RECIBIDA CONTESTACION
        
if (strcmp ($res"VERIFIED") == 0) { //PayPal nos verifica que la Info es correcta
        
            
$item_name $_POST['item_name'];
            
$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'];
            
$date date('Y-m-d H:i:s',strtotime($_POST['payment_date'])); //Fecha en formato MySQL
            
$custom$_POST['custom'];

            
/**Hacemos algunas comprobaciones extraordinarias
             * * Comprobar que $_POST["payment_status"] tenga el valor "Completed", que nos confirma el pago como completado.
             * * Tambien podemos aceptar Processed
             **/
            
if($payment_status=='Completed' || $payment_status=='Processed' ) {
            
/**
             * *Comprobar que el email al que va dirigido el pago sea nuestro email principal de PayPal
             **/
                
if($receiver_email == '[email protected]'){
                
/**
                 * *Ahora podríamos hacer otras comprobaciones como
                 * * Comprobar que no hemos tratado antes la misma id de transacción (txd_id)
                 * * Comprobar que la cantidad y la divisa son correctas
                 */
                
                /**Después de las comprobaciones, toca el procesamiento de los datos.
                 * En este punto tratamos la información.
                 * Podemos hacer con ella muchas cosas:
                 * 
                 * * Guardarla en una base de datos.
                 * * Guardar cada linea del pedido en una linea diferente en la base de datos.
                 * * Guardar un log.
                 * * Restar las cantidades de los artículos del stock.
                 * * Enviar un mensaje de confirmcaión al cliente.
                 * * Enviar un mensaje al encargado de pedidos para que lo prepare.
                 * * etc
                 */            
                
}else{
                    
$comentario "Reciever email manipulado (".$receiver_email.")"
                
}
            }else{
              
$comentario "Payment_status inválido (".$payment_status.")/".$comentario;
            }
        }elseif(
strcmp ($res"INVALID") == 0){
            
// El estado que devuelve es INVALIDO, la información no ha sido enviada por PayPal. 
            
$comentario "INVALID, informacion no enviada por PayPal/".$comentario;
        } 
    }else{    
         
// Si no hay datos $_POST podría tratarse de un acceso directo, para eso la IP
        
$comentario "Acceso sin variables POST/".$comentario;
    }
    if(
$comentario != ''){ 
        
//Si comentario tiene contenido es que hubo un error
        //Guardamos el comentario, la IP y toda la info que queramos en un log en la DB
        
if(!$_POST )echo '<meta http-equiv="Refresh" content="0;url=index.html" />';
    }         
?>
El contenido de este archivo no es 100% de mi autoría, he copiado partes, modificado otras y añadido otras.

Bueno, está casi todo el código explicado en los comentarios. Lo que falta es comunicación con la DB que eso ya es de vuestra parte.
Podéis encontrar mucha más información sobre IPN en el enlace (3) de las fuentes.