LinkedIn: linkedin.com/in/fsalom
Mobile: +34 660406625
Skype: fdosalom
E-mail: hello@fernandosalom.es
www: fernandosalom.es

Como crear una pasarela de pago con PayPal


Escrito por fernando! | 14-02-2010 23:42

Ultimamente he estado implicado en un proyecto que requería hacer una pasarela de pago con PayPal de modo que me puse a buscar información al respecto y me he dado cuenta que resulta complicado obtener ejemplos funcionales por lo que he decidido hacer esta pequeña entrada para aquellos que se encuentren en mi misma situación lo tengan un poco más fácil.

Existen muchas forma de realizar un pago mediante paypal : Pago express , carro de la compra , pago estándar ... Dentro de cada uno de estos formatos existen muchos otras formas de realizar el pago. El más tradicional y el cual seguramente muchos de vosotros habréis usado es el pago estándar ya sea para pagar algún producto de una tienda online o para realizar una donación en los muchos sitios web que piden donaciones , de modo que este va a ser nuestro caso de estudio.

Pero antes de nada para aquellos que todavía no sepan que es Paypal os añado la definición propia de wikipedia :

PayPal es una empresa estadounidense perteneciente al sector del comercio electrónico por Internet que permite la transferencia de dinero entre usuarios que tengan correo electrónico, una alternativa al tradicional método en papel como los cheques o giros postales. PayPal también procesa peticiones de pago en comercio electrónico y otros servicios webs, por los que cobra un porcentaje. La mayor parte de su clientela proviene del sitio de subastas en línea eBay.

Primero hay que entender como funciona el flujo de datos en este tipo de transacciones para ello no hay nada mejor que una imagen procedente de PayPal : 

En la imagen podemos observar como partiendo de nuestro sitio web mediante un formulario que tendrá una serie de campos ocultos podemos acceder a paypal donde se realizará el pago , una vez se realiza el pago PayPal envía una notificación mediante su protocolo IPN (Instant Payment Notification o notificación instantánea de pago) a través de ella conoceremos el estado que ha tenido la transacción así como una serie de datos añadidos que permitirán que podemos tener un control absoluto sobre el estado del pago.

Ya que no puedo concentrar todas las posibilidades que tiene este método de pago voy a explicarlo a través de un pequeño código de ejemplo para que podáis tener más información de la que aparece en la documentación de paypal.

Algo que tenéis que tener en cuenta a la hora de desarrollar una pasarela de pago con PayPal es que debéis conocer el sandbox o entorno de prueba (https://www.sandbox.paypal.com/) , para poder utilizar la DEMO o modificar/usar estos scripts tenéis que daros de alta y crear compradores y vendedores ficticios.

Formulario.html

#GALLETAS5 ; Nombre: Galletas ; Valor : 5.00 , Cantidad : 2 #PIRULETAS3 ; Nombre: Piruletas ; Valor : 3.00 , Cantidad : 5

Como podréis observar el campo action del formulario nos lleva al sandbox de PayPal , es decir , al sitio de pruebas donde podremos testear nuestro script , en caso de querer realizar el testeo directamente con PayPal deberemos de eleminar el subdominio sandbox dejándolo como : https://www.paypal.com/cgi-bin/webscr.

Repecto a los demás campos:

  • cmd > indica el tipo de fichero que va a recoger PayPal 
    _cart : varios items
    _donations : donaciones
    _xclick : boton de compra
  • business > indica el identificador del negocio registrado en paypal. Ejemplo : buyer_1265883185_biz@gmail.com
  • shopping_url > la dirección de nuestra tienda online . Ejemplo : http://www.fernandosalom.es
  • currency_code > el tipo de moneda (USD , EUR ...)
  • return > sera el enlace de vuelta a nuestro negocio que ofrece paypal
  • notify_url > en esta pagina es donde recogeremos el estado del pago y un gran numeros de variables con informacion adicional en nuestro caso lo hemos llamado paypal_ipn.php
  • rm > Indica el método que se va a utilizar para enviar la información de vuelta a nuestro sitio. RM=1 información enviada por GET , RM=2 información enviada por POST (En este caso usamos este método porque es un script php el que recoge los datos) . (Gracias Miguel)
  • item_number_X > identificador del producto
  • item_name_X > nombre del producto
  • amount_X > precio del producto
  • quantity_X > cantidad del producto

Paypal_ipn.php

 
<\?php

//Leer POST del sistema de PayPal y añadir 'cmd'
$req = 'cmd=_notify-validate';
foreach ($_POST as $key => $value) {
$value = urlencode(stripslashes($value));
$req .= "&$key=$value";
}
//header para el sistema de paypal
$header  = "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
//header para el correo
$headers = 'From: webmaster@ejemplo.com' . "\r\n" .
           'Reply-To: webmaster@ejemplo.com' . "\r\n" .
           'X-Mailer: PHP/' . phpversion();
//Si estamos usando el testeo de paypal:
$fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);
//En caso de querer usar PayPal oficialmente:
//$fp = fsockopen ('ssl://www.paypal.com', 443, $errno, $errstr, 30);
if (!$fp) {
// ERROR DE HTTP
}else{
fputs ($fp, $header . $req);
while (!feof($fp)) {
$res = fgets ($fp, 1024);
if (strcmp ($res, "VERIFIED") == 0) {

//Almacenamos todos los valores recibidos por $_POST.
foreach($_POST as $key => $value){
        $recibido.= $key." = ". $value."\r\n";
}
//Enviamos por correo todos los datos , esto es solo para que veáis como funciona
//En un caso real accederíamos a una BBDD y almacenaríamos los datos.
// > Comprobando que payment_status es Completed
// > Comprobando que txn_id no ha sido previamente procesado
// > Comprobando que receiver_email es tu email primario de paypal
// > Comprobando que payment_amount/payment_currency son procesos de pago correctos

mail("micorreo", "NOTIFICACION DE PAGO", $recibido , $headers);
}else if (strcmp ($res, "INVALID") == 0) {
mail("micorreo", "NOTIFICACION DE PAGO INVALIDA", "invalido",$headers);
}
}fclose ($fp);
}
?>

Este script no se visualiza ya que no hacemos un acceso directo a él sino que es PayPal el que lo ejecuta para notificarnos los datos de la transacción , es por ello que en este script he hecho que nos envíe un correo con los datos de la operación si han sido válidos o no. Para ello lo único que debemos modificar es el texto micorreo por nuestro correo electrónico.

Este no es el procedimiento adecuado para recoger estos datos ya que lo que deberíamos de hacer es crear un script con su correspondiente BBDD que comprobará los datos y los insertará para tener un registro de todas las transacciones.

Si deseáis preguntar algo comentarlo y lo contestaré conforme tenga tiempo , a continuación os dejo una serie de enlaces de interés sobre este tema.

> DEMO de este ejemplo en funcionamiento Recordar que debéis de daros de alta en el SANDBOX y crear un comprador ficticio para que os funcione

> Documentación para pagos estándares


Iván dice :
15-02-2010 12:58
Es muy buen artículo, me ha gustado. Y también el blog está muy bien
Adrian dice :
05-03-2010 08:44
Con este tutorial (que es excelente, sobre todo por el ejemplo), es posible recibir el ID del usuario, a fin de saber quien fue el usuario que me compro, que fue lo que compro. Agradezco tu respuesta. Saludos
Fernando! dice :
14-03-2010 16:15
Hola Adrian , no se que tipo de compra estas desarrollando pero una forma que se me ocurre de poder hacer lo que dices es hacer el formulario con php y de esa forma puedas modificar dinámicamente el campo notify_url de modo que cuando se realice la compra puedas obtener valores por GET por ejemplo : http://mipagina.com/paypal_ipn.php?idusuario=10 y almacenar la cesta que ha seleccionado el usuario en la bbdd de modo que con id de usuario puedas obtener los datos que necesitas , esto es una explicacion rapida , pero espero que te valga la idea ;)
Miguel dice :
15-03-2010 13:16
Gracias por este magnifico manual, era justo lo que necesitaba para aclararme algunas dudas.
Miguel dice :
15-03-2010 13:43
Por cierto una cosa que si me ha resultado dudosa es la variable rm dices que es el numero de items, pero en la página de PayPal hablan sobre:
rm=2:" El método POST redirige el navegador del pagador a la URL de devolución y también se envían todas las variables de transacción."
cuando se refieren a la variable rm.
Fernando! dice :
15-03-2010 17:51
Hola Miguel , tienes razón fue un error por hacer las cosas rápidas - como puedes ver en https://www.x.com/docs/DOC-1552

la variable rm hace referencia al método que se va a utilizar para enviar la información a devolver , en nuestro caso al ser un script el que recogerá la información vamos a utilizar rm=2 ya que la información se enviará por POST , rm=1 lo utilizaríamos en caso de querer enviar la información por GET . Voy a cambiarlo en el post.

Muchas gracias;)
Adrian dice :
21-03-2010 19:36
Gracias Fernando por la respuesta, ya estoy realizando algunas cosas, mas que nada pruebas, al final si no surgen mas dudas, posteare el link a la pagina en donde lo implemente. Saludos.
Jose L. Guerrero dice :
29-04-2010 19:22
Muchas gracias por tus explicaciones, lo cierto es que llevaba mucho tiempo intentando encontar una explicacion documentada y sencilla como la que propones.
Y puedes estar seguro de que al menos a mi me has ayudado muchisimo.
Un saludo y muchas gracias.
09-06-2010 11:20
Muy bueno el articulo, solo que si añadieras unas capturas estaria mejor
18-06-2010 11:17
Hola Fernando, como sería para añadir campos de información opcionales??

Lo he intentado buscar en la
Sara dice :
24-06-2010 16:39
Hola Fernando, muy buen artículo. Sólo tengo un problema, que a mí no me funciona.
No sé donde tengo que activar el ipn.
Si me identifico en Sandbox con mi usuario y contraseña y voy a "Test Tools" me aparece lo de ipn y relleno los siguientes campos con los datos:
IPN handler URL: http://localhost/prueba/paypal_ipn.php
Transaction type: Web accept
No sé si están bien los valores.

Por favor, una ayudita.

Muchas Gracias
Fernando dice :
28-06-2010 11:00
Hola Sara , perdona por el retraso. No estoy muy seguro de lo que te pasa pero creo que por lo que me has puesto el problema es el IPN handler URL ya que estas usando una dirección local para recibir la petición y el sandbox de paypal no te puede hacer llegar los datos.

Deberías de tener un dominio en internet para que tu dirección sea visible por el sandbox , por ejemplo : http://www.mipaginaweb.com/prueba/paypal_ipn.php , no te sirve hacerlo en local.

Espero que te sea de ayuda
Sara dice :
29-06-2010 11:40
Gracias Fernando por tu respuesta, ya lo conseguí hacer funcionar.
Ahora tengo otro problema, y es que cuando paso a sandbox y me tienen que mostrar los artículos que he comprado, me aparece un "Error detectado: Ha escrito caracteres no admitidos en este cuadro. Los tipos de caracteres actualmente disponibles son: europeo, chino, coreano, japonés y tailandés. Inténtelo de nuevo."

Muchísimas gracias por contestar.

Un saludo.
dayer dice :
09-07-2010 03:10
¡Gran explicación! Ya no creía posible el hecho de transferir el típico carrito de la compra hecho en PHP a PayPal para que quedara más serio que el cobrar una cantidad por un único producto a ojos de PayPal.

Un saludo.
carlos dice :
12-07-2010 17:11
Gracias Fernando, cuando tuve que ponerme con el carrito de Paypal pensé que sería más sencillo al haber hecho ya el de Servired, pero no me imaginaba que iba a ser tan complicado y que iba a haber tan poca documentación (y tan poco clara) sobre el tema.
Luego apareciste tú... y se hizo la luz ;)
Lo dicho: 1000 GRACIAS :)
Fernando dice :
13-07-2010 21:08
Comentarios como los vuestros hacen que uno tenga ganas de seguir escribiendo este tipo de artículos , gracias ;)
Jose francisco dice :
14-07-2010 14:30
Buenas Fernando, excelente información la que nos has plasmado alli. Me pasa igual que a Sara, al tratar de pagar en PayPal me aparece el mensaje: Ha escrito caracteres no admitidos en este cuadro. Los tipos de caracteres actualmente disponibles son: europeo, chino, coreano, japonés y tailandés. Inténtelo de nuevo. ¿A que se debe o como lo soluciono?
Gracias Fernando.
RM dice :
16-10-2010 14:27
Hola Fernando, tengo el siguiente problema. Estoy trabajando en un sitio de subastas de a centavos donde los usuarios compran "bids", lo hacen a traves de paypal. Luego del pago, los usuarios regresan a mi sitio donde se carga la página success.php q se encarga de ingresar en la DB los "bids" comprados por el usuario. El problema es que si un usuario recarga (actualiza F5) la página (o sea se carga el mismo success.php?orderid=MTM=) se vuelven a cargar los "bids" comprados. Quizas puedas darme una pista o guiarme para encontrar una solución. Te Agradezco y felicito por tu dedicación a ayudar a los demas. Muchas gracias.
RM dice :
16-10-2010 14:37
Fernando, ya encontre la solución. Volvi a decirtelo para q no desperdicies tiempo. Gracias y mucha suerte en el IMBA.
paul dice :
09-11-2010 23:23
Gracias por el aporte fernando, me salvaste de mucha investigacion :D, como dicen varios un buen articulo y otra vez mil gracias.
Imanol dice :
29-12-2010 15:20
Muy bueno el aporte! y la página está genial!
Pero me surge una duda,
Cuando creamos ese formulario con un botón enviar, podríamos hacer con el firebug, por ejemplo, una modificación de los precios y así lograr otro total...
Saludos!
fiuz dice :
16-02-2011 16:40
Genial. 3 días leyendo documentacion en ingles de como implementar un simple boton, y cada pdf que encontraba era más largo y más complicado. He buscado mil webs y tu guia ha sido la mejor, decisiva para que me funcione lo que buscaba :)
gracias.
Encarna dice :
15-03-2011 11:50
Hola a todos:

Me encuentro con un problema. Estoy intentando poner la pasarela de pago de la caixa. El post funciona correctamente,pero uno de los parámetros que me exigen (la caixa claro) es un sitio web donde poner las transacciones. ¿como debo configurar esto? ¿alguna sugerencia?

Gracias mil
jose dice :
15-03-2011 22:11
Hola a todos y muchas gracias Fernando.

El ejemplo es tremendo y se sigue muy bien pero lo he puesto en practica y no consigo que me llegue el correo,no es que llegue al spam ni nada de eso, es que no se envia.

alguna idea?

muchas gracias
fiuz dice :
16-03-2011 13:35
hola jose, para comprobar si envia emails sin tener que hacer la transaccion por paypal, carga la pagina directamente (www.tudominio.com/paypal_ipn.php) deberia enviarte un correo de NOTIFICACION DE PAGO INVALIDA, si no te llega puedes probar algo como:
if(mail("micorreo", "NOTIFICACION DE PAGO INVALIDA", "invalido",$headers)) { echo "email enviado"; } else { echo "email enviado"; }
pero si no envia puede ser problema de tu servidor, y no recuredo como capturar los errores de email() creo que no era sencillo. Busca "php mail error handling" en google a ver si puedes encontrar algo.
27-03-2011 13:24
Muy buen artículo.
Yo estoy teniendo ciertas dificultadas. Tengo creadas y funcionando las cuentas de vendedor y comprador en el Sandbox de Pyapal y el formulario de las galletas va bien. La problemática la tengo en el fichero paypal_ipn.php. En este fichero de primeras no me funcionaba el tema del correo, después he incorporado lo mismo pero escribiéndolo en un fichero de texto y nada, por último estoy poniendo echos que tampoco me pinta. He incorporado un filtro cuando recoge las variables de Paypal por el post por si era esa bucle el que se quedaba colgado, aún así nada. No sé qué puedo estar haciendo mal, pero el tema es que necesitaría recoger el resultado de la transacción para, como tú muy bien dices, registrarlo en una BBDD. ¿Alguna sugerencia?

Gracias de ante mano.
02-04-2011 01:04
Te felicito por este gran articulo. Muy interesante y esclarecedor.

Un saludo.
Victor dice :
09-04-2011 10:51
Un artículo genial. Solo una pregunta, ¿Hay alguna forma de mostrar las opciones de que pague con tarjeta de crédito por defecto abierta y el desglose del artículo abierto?

Muchas gracias :)
06-07-2011 12:45
Muchísimas gracias. La documentación de Paypal puede ser realmente farragosa. Un saludo y gracias por compartir tu trabajo!!!
06-07-2011 13:20
Hola! He intentado el ejemplo y sólo consigo que paypal me deje comprar galletas y piruletas, jeje. ¿Cómo puedo hacer para que reconozca los ítems que hay en el carro de la compra de mi web?, almacenados en una base de datos? Muchas gracias de nuevo!!!
Flavio dice :
14-07-2011 03:47
Excelente tutorial. Tengo un sitio desarrollado íntegramente en ASP y no conozco absolutamente nada de PHP. ¿Cómo sería el codigo de la página "Paypal_ipn.php" traducido a ASP? De esta manera sabría cómo almacenar los datos en una base de datos que ya tengo creada en Access.
Alberto dice :
21-07-2011 12:37
Muchas Gracias esta genial!
Yeison dice :
26-08-2011 22:17
Fernando gran tutorial.

Tengo la siguiente duda, cuando le doy clic al boton de paypal me abre una pagina en ttps://www.sandbox.paypal.com/us/cgi-bin/webscr muy distinta a la que abre en tu ejemplo. Ingreso los datos y hago clic en iniciar sesion pero la pagina me muestra al lado izquierdo los valores de la compra pero no hace nada más. Sabes por qué?. Hay alguna forma de mostrarle al usuario el número de la factura cuando hay realizado el pago directamente en Paypal. Gracias
Iván IaS dice :
20-10-2011 17:15
Hola buenas,

He creado un botón de suscripción parecido al que tu tienes y me he encontrado con un error muy gordo, ya que cualquier usuario con algo de conocimiento puede modificar las variables hidden del botón del formulario y modificar la cuenta destino y la cantidad a pagar (por ejemplo).

Había pensado en comprobar eso nada más llegar al IPN antes de reenviarle los datos para evitar dicho problema, pero veo que nadie lo implementa así.

No se si es por desconocimiento o por qué se me está pasando algo...

¿alguna idea?
20-10-2011 19:57
gracias, por la información ;).!! Fernando y a todos ustedes.
GRAILS dice :
23-10-2011 13:19
Hola Fernando,

¿Para el pago express de paypal el usuario que va a comprar necesita una cuenta de paypal o puede poner directamente la tarjeta de credito/debito? .

Saludos
31-10-2011 04:56
Hola nuevamente, tenía un problemita con actualizar mi BD, y encontré esto que es de muy buena utilidad para reforzar conocimientos, y pues no podía dejar de ponerlo aquí, gracias nuevamente a todos.
LINK: https://www.paypalobjects.com/WEBSCR-640-20111007-1/es_ES/ES/pdf/PP_OrderManagement_IntegrationGuide.pdf
31-10-2011 04:58
específicamente pasar mis variables de esta manera:
Por ejemplo, el valor de la variable notify_url puede ser así:
notify_url=https://www.mysite.com/PP-IPN-Validate.cfm?secret=shhhhhhh
maurioasis dice :
17-11-2011 17:50
una duda, si yo antes de enviar a la pasarlea paypal el carrito, quiero insertar en mi bbdd el id pedido y luego una vez el usuario haya hecho el pago, ¿hay alguna maaner de mandar el idpedido y que luego me lo retorne para saber que idpedido tengo que actualizar en mi base de datos???
Gabriel dice :
20-11-2011 01:23
Estimado Fernando, quiero saber porque cuando se usa _cart IPN no retorna las variables item_number y lo mismo para item_name

En cambio _xclick si las devuelve.

Esto ha impedido que pueda usar el carro de compras de paypal y responder de forma instantánea al cliente.

dichas variables retornan vacías. En cambio el resto de variables llegan completas como el amount, feed, etc.

Gracias por tu ayuda y orientación.
19-01-2012 19:09
Muy bueno el tutorial, XD

Siempre viene bien saber un poco mas sobre el codigo para el pago con paypal.

Gracias.

Añade tu comentario

Me reservo el derecho de eliminar y/o modificar aquellos comentarios que se salgan de esta temática , así como los promocionales (spam), susceptibles de afectar a derechos de terceros o de vulnerar las leyes.
Lenguaje HTML permitido : strong , em , a , ul , li , i , u

* :
* : * (no será publicado) : :