Controlar pagos de PayPal con php, ClassIPN

Iniciado por alexander1712, Octubre 10, 2013, 11:49:33 AM

Tema anterior - Siguiente tema

0 Miembros y 1 Visitante están viendo este tema.

Octubre 10, 2013, 11:49:33 AM Ultima modificación: Marzo 27, 2014, 05:22:31 PM por Expermicid
Hola, siguiendo con mi rutina de armar clases para manejar ciertas cosas y así no tener que escribirlas una y otra vez en cada sistema, hoy realizé una que controle pagos instantaneos de paypal, los IPN o instant payment notification de paypal, son notificaciones para cuando uno recibe un pago, imaginense que vendo productos chinos en mi página china, cuando alguien realiza un pago, paypal me envía la notificación de pago satisfactorio, y mi php automáticamente le dice al cliente que su pago fue realizado y todas esas boludeces, lo mismo pasa con hosting y etc.

Lo único que tienen que hacer para recibir esas notificaciones es ir a paypal, activar IPN y poner el link del php que controla las notificaciones.

Ese php se puede llamar por ejemplo IPN.php, las siguientes clases te pueden ayudar a controlar los IPN.

creamos un archivo php, que incluya mi property No tienes permitido ver los links. Registrarse o Entrar a mi cuenta, y la clase ClassIPNInterface.

ipn.php
Código: php

<?php
include('Property.php');
include('ClassIPNInterface.php');

// creamos el objeto, automáticamente la clase enviará una notificación a paypal de que recibimos la notificación y eso
$ipn = new ClassIPN();
// vemos si ubo un error al realizar el aviso a paypal
if($ipn->error == true)
{
    // mostramos el error
    echo $ipn->error_msg;
} else { // si no ocurrió ningún error

// aquí guardamos en la base de datos, y actualizamos la tabla que tenga los pagos y le damos la plata al cliente o le ponemos una notificación de que se realizó el pago.

// podemos usar las siguientes variables:

$ipn->item_name(); // nombre del producto
$ipn->payment_status(); // el estado del pago cuando se realizó esta notificacion
$ipn->payment_amount(); // el dinero que pagó por el producto
$ipn->transaction_id(); // el numero de transacción único, recomiendo que revisen en la db antes de hacer nada si ya había un pago con este numero de transacción para no tener duplicados.
$ipn->client_email(); // el email de la persona que pagó

}


para que esto funcione crean un archivo Property.php con el código del link que dejé más arriba, y dos archivos más:

ClassIPNInterface.php
Código: php
<?php 

interface IIPN
{

public function __construct();

public function get_item_name();
public function set_item_name($value);

public function get_payment_status();
public function set_payment_status($value);

public function get_payment_amount();
public function set_payment_amount($value);

public function get_payment_currency();
public function set_payment_currency($value);

public function get_transaction_id();
public function set_transaction_id($value);

public function get_receiver_email();
public function set_receiver_email($value);

public function get_client_email();
public function set_client_email($value);

}

include('ClassIPN.php');


y ClassIPN.php:

Código: php
<?php 

class IPN implements IIPN
{
// usamos mi trait Property
use Property;

// atributos privados
private $notify_validate_request_content = null;
private $notify_validate_request_header = null;

// variables.
private $item_name = null; // nombre del producto
private $payment_status = null; // estado del pago
private $payment_amount = null; // precio pagado
private $payment_currency = null; // ?
private $transaction_id = null; // id de transacción de paypal
private $receiver_email = null; // nuestro mail
private $client_email = null; // mail del que compró

private $error = false;
private $error_msg = null;


public function __construct()
{
$this->vars_extract();
$this->notify_validate_request_content = $this->request_content_generate();
$this->notify_validate_request_header = $this->request_header_generate();
$this->notify_validate_request();
}

private function request_content_generate()
{
$req = 'cmd=_notify-validate';
foreach ($_POST as $key => $value) {
$value = urlencode(stripslashes($value));
$req .= "&$key=$value";
}
return $req;
}

private function request_header_generate()
{
$header = null;
$header .= "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($this->notify_validate_request_content) . "\r\n\r\n";
return $header;
}

private function notify_validate_request()
{
try
{
$fp = fsockopen ('www.paypal.com', 80, $errno, $errstr, 30);
if(!$fp) throw new exception('No es posible conectar con www.paypal.com');
fputs ($fp, $this->notify_validate_request_header . $this->notify_validate_request_content);
while (!feof($fp))
{
$res = fgets ($fp, 1024);
if (strcmp ($res, "VERIFIED") == 0)
{
return true;
}
else
{
throw new exception('Ocurrió un error con la transaccion');
}
}
} catch(Exception $e)
{
$this->error = true;
$this->error_msg = $e->getMessage();
return false;
}
}

private function vars_extract()
{
$this->item_name = $_REQUEST['item_name'];
$this->payment_status = $_REQUEST['payment_status'];
$this->payment_amount = $_REQUEST['mc_gross'];
$this->payment_currency = $_REQUEST['mc_currency'];
$this->transaction_id = $_REQUEST['txn_id'];
$this->receiver_email =  $_REQUEST['receiver_email'];
$this->client_email = $_REQUEST['payer_email'];
}

public function get_item_name() { return $this->item_name; }
public function set_item_name($value) { ; }

public function get_payment_status() { return $this->payment_status; }
public function set_payment_status($value) { ; }

public function get_payment_amount() { return $this->payment_amount; }
public function set_payment_amount($value) { ; }

public function get_payment_currency() { return $this->payment_currency; }
public function set_payment_currency($value) { ; }

public function get_transaction_id() { return $this->transaction_id; }
public function set_transaction_id($value) { ; }

public function get_receiver_email() { return $this->receiver_email; }
public function set_receiver_email($value) { ; }

public function get_client_email() { return $this->client_email; }
public function set_client_email($value) { ; }
}


bueno eso es todo! saludos!

te hago una consulta aparte...

porque cuando creas una variable siempre le das valor null. En el caso de que no lo hagas y solamente lo cree, no va a tener ningun valor. Ademas de que las variables que usas son privadas, asi que no se va a poder utilizar en otro lado, de cualquier forma, las utilizas en la misma clase obviamente. Pero la pregunta es... les pones un valor nulo por algun motivo o porque te acostumbraste/te gusta asi?.

saludos

Octubre 15, 2013, 12:11:45 PM #2 Ultima modificación: Octubre 15, 2013, 01:15:09 PM por Harkonnen
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
te hago una consulta aparte...

porque cuando creas una variable siempre le das valor null. En el caso de que no lo hagas y solamente lo cree, no va a tener ningun valor. Ademas de que las variables que usas son privadas, asi que no se va a poder utilizar en otro lado, de cualquier forma, las utilizas en la misma clase obviamente. Pero la pregunta es... les pones un valor nulo por algun motivo o porque te acostumbraste/te gusta asi?.

saludos

es un tema que arrastro desde estructurada, si no definis una variable y la usas para por ejemplo concatenar ($variable .= 'hola';) te tirará un warning informando que la variable no existe (ya que quieres accesar para leer un recurso inexistente), por lo que me acostumbré a definir toda variable que voy a usar, así no hay warnings y está todo aclarado para php, eso por un lado.

en segundo lugar, porque defino el tipo también, si pongo Null es porque en general puede ser un string o un objeto lo que valla a meter en dicha variable, si pongo = 0, es porque voy a poner solo numeros, y si le pongo array(); es porque voy a poner un arreglo :P

en éste caso en específico, son todas null porque estoy trabajando con una api, por lo que no especifico el tipo que la api me retorna.

en otros lenguajes es de suma importancia definir variables, por lo que se me hizo una costumbre definirlas y darles un valor inicial yo mismo.

por lo que en realidad darle un valor inicial no es necesario como mencionas.

y sobre que son todas private, eso depende de la ocación, pero yo no uso public desde hace un tiempo, me limito solo a usar private o protected, no uso public por los principios de encapsulamiento y ocultamiento de información. por lo demas generalmente pongo private salvo que esté trabajando con herencia donde, aquellas cosas que no quiero que puedan ser redeclaradas uso protected (eso en funciones) y en variable si son clases abstractas no tiene sentido pero si son clases comunes me evita incidentes de acceso (o así le llamo yo).

saludos!

Entiendo...

como deciamos no hace falta declararlas, aunque tampoco esta de mas, de cualquier forma hay que estar atento con private, protected y public. Me paso que muchas veces puse private y al usar la clase y a su vez funcion en otro archivo no aparecia nada, no funcionaba, obviamente porque estaba privada, y buen.. hasta que te das cuenta puede pasar 1 segundo como 10 minutos o inclusive mas... si te toca un mal dia xD.

Buena explicacion.

Saludos!

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
Entiendo...

como deciamos no hace falta declararlas, aunque tampoco esta de mas, de cualquier forma hay que estar atento con private, protected y public. Me paso que muchas veces puse private y al usar la clase y a su vez funcion en otro archivo no aparecia nada, no funcionaba, obviamente porque estaba privada, y buen.. hasta que te das cuenta puede pasar 1 segundo como 10 minutos o inclusive mas... si te toca un mal dia xD.

Buena explicacion.

Saludos!

si al prin cipio se me complicaba más que nada entre private y protected luego fue bastante intuitivo si seguis la normativa te das cuenta en seguida las cosas que no deberías hacer xD
y si con un mal día te puede pasar cualquier cosa.

saludos!