domingo, 28 de noviembre de 2010

Lo peor de la sociedad

Estoy impresionado desde hace varias horas con un documental de TVE2 que me he tragado. No porque no supiera algunos datos, sino por la impresionante facilidad con la que la gente deja que sus hijos sean pasto de publicistas y sean inducidos a convertirse en otro borrego que solo ve televisión.

Y es sabido por todos que es así, "somos lo que compramos"... que ya decía alguien más interesante que yo, pero no tenía consciencia de el punto en el que nos encontramos hasta haber visto el dichoso documental.

Ha sido impresionante ver hasta que punto llega esa obsesión y ahora si que me preocupa tanto programa del corazón, reality show, y en concreto tantos gimnasios llenos de gente que tiene su mundo en la pantalla de la televisión y tantos telediarios con noticias de estrenos de películas (que antes simplemente criticaba conformado).

El problema es que no veo la televisión, y si lo hago, intento ver poca, por eso no soy consciente de ello. Ya se sabe que la prensa está totalmente contaminada con campañas de marketing, las películas con publicidad de los gobiernos... y de empresas privadas, etc. y que todo forma parte de una enorme campaña de publicidad que corroe las vidas de las personas, y las hace convertirse en máquinas de comprar sin necesidad real, lo que en muchas ocasiones no se puede pagar.

Pero ahora me doy cuenta de la magnitud del peligro real, y de la cantidad de personas que realmente viven en un programa de televisión constante, y creen que el estreno de la ultima película de vampiros adolescentes es la noticia importante del día. Pensaba que en realidad el mundo era más inteligente.

Y el pronóstico no es muy alentador, teniendo en cuenta las campañas de marketing más caras y que mejor resultado dan, las campañas políticas.

Es un largometraje documental británico de 2009 titulado "Fábrica de Famosos", dirigido por Chris Atkins y producida por S2S Productions.

Integrar el pago electrónico con paypal en java

Es increíble lo complicado que a veces puede resultar encontrar información sencilla sobre algo concreto. A la hora de la integración de una aplicación con sistemas de pago electrónico puedes encontrar algunos de los mejores ejemplos. Lo que voy a explicar es producto de un número demasiado elevado de horas buscando, leyendo, consultando y quebrándome la cabeza.

Y no solo con el caso específico de PayPal, sino con el resto de plataformas de pago con las que me he encontrado. Estoy pensando seriamente en crear un grupo en facebook "En contra de las explicaciones ambiguas para integrar plataformas de pago".

Bueno pues lo primero es saber si es complicado lo que tienes que hacer, porque lo que voy a contar es un pago estandar, es decir, una vez que en tu app ya sabes la cantidad que hay que pagar, quieres que se haga. Si quieres hacer pagos o gestionar tus cobros, o cosas más complejas con la interfaz SOAP, no es este tu artículo, jeje... Lo que vas a encontrar es lo que llaman:

  • Pago Express
  • Interfaz para NVP (abreviado de name-value pair)
  • Pago Estándar

Siempre hay un entorno de pruebas, como ya esperabas, y que funcionará exactamente igual que en el entorno real. Esta es una de las diferencias (entre otras) con plataformas con las que he trabajado y PayPal.

En esta última, el proceso que en principio creemos sencillo, que es el de obtener un número de tarjeta ficticio que sea aceptado por la validación de la tarjeta en la plataforma de pruebas, me implicó crear una cuenta ficticia de cliente en Paypal Sandbox y asociarle tarjetas.

Después de mucho clickar y urgar por el sandbox, trás intentar comprender que tipo de pago quiero realizar (..ufff) o ver mil veces el esquema de pago, tienes que tener una cuenta de empresa (o también llamado comerciante) e ir al menú "Perfil" para encontrar lo que buscas.
  • Preferencias de notificación de pago instantánea (IPN)
  • Configuración de pago codificado

1. Preferencias de notificación de pago instantánea IPN

En la primera opción tienes que indicar la url a la que se notifica el pago mediante petición POST. Esto quiere decir que cuando el pago se confirma, desde paypal se hará una solicitud a esa url que pongas, e incluirá además de una copia de los valores en la petición que mandamos desde nuestra web (desde el navegador del usuario) algunos parámetros más como el identificador de operación, que es el que a ti te interesa. ¿Problemas con el IPN? Se pueden deber a varios factores:

  • El pago no se confirma: Esto ocurre con cantidades elevadas, paypal desde hace poco está obligado a retener las cantidades elevadas (no recuerdo ahora el intervalo exacto) y las contrasta. Tu tendrás que acceder a tu cuenta de paypal (del sandbox) y confirmar el pago manualmente. Probablemente ya te habrá caducado la sesión, y tendrás que tirarte un rato logeandote de nuevo, pero de tanto hacerlo, tienes la contraseña grabada a fuego en tu cerebro... ¿verdad? :P
  • La url de respuesta no es correcta: Claro suele pasar... cámbiala

2. Configuración de pago codificado

En la segunda opción, configuras el certificado que vas a usar para "firmar un botón". Esta impresionante acción, como todas, al final no es para tanto y no es más que tomar una cadena con la información del pago, firmarla, y añadir el texto de la firma (...en PEM) a un formulario que se dirija a Paypal y que los navegantes presionan en tu página cuando quieren realizar el pago. Y con esto pues ya está, ahora:
  • Te descargas El SDK para java, descomprimes e incluyes las librerías en tu aplicación en /WEB-INF/lib
  • Descárgate todos los jars de las librerías criptográficas bouncycastle latest releases e incluyes las librerías en tu aplicación en /WEB-INF/lib
  • Creas tus certificados para firmar e identificarte con paypal: Para esto necesitas instalar OpenSSL (en ubuntu con "sudo apt-get install openssl"... en windows... no lo sé...) y ejecutar:

    #Generas la clave privada, el CSR
    openssl genrsa -out prvkey.pem 1024
    #La auto firmas y obtienes un certificado público
    openssl req -new -key prvkey.pem -x509 -days 365 -out pubcert.pem
    #Generas un almacen de certificados pkcs12 con ellos
    openssl pkcs12 -export -inkey prvkey.pem -in pubcert.pem -out prvkey.p12


    Después de todo esto te aparecen un montón de ficheros de los cuales solo te hace falta el almacén de certificados prvkey.p12 y el certificado de paypal que debes descargarlo desde paypal en la opción de "Configuración de pago codificado".

Pues nada, ten a buen recaudo la contraseña para el acceso al almacen de certificados y el archivo p12 por que ahora viene cuando se usa.

Realización del pago, datos del pago y firma

Bueno pues ya estás en tu aplicación y estás desarrollando la parte en la que se realiza el pago, entonces, tu objetivo va a ser crear una página donde se indique al cliente lo que va a pagar y se muestre un botón que ponga "Pagar con Paypal". El código HTML del formulario lo pones tú, pero asegúrate de que tienes dos campos:

<input type="hidden" name="cmd" value="_s-xclick" />
<input type="hidden" name="encrypted" value="<%= signedPaymentStr %>" />


que se envían a la url que te pasan desde paypal (algo de documentación tendrás que leer).

Los datos del pago van en la cadena firmada del campo encrypted, y básicamente tendrás que rellenarlos creando una cadena con algunos parámetros. Aquí os dejo el código de un metodito que devuelve directamente la cadena que buscamos. Cópialo, pégalo y míra el Javadoc, te resultará fácil. Ten en cuenta que el pago está configurado para EUROS!!...



import com.paypal.wpstoolkit.util.PPCrypto;
import java.util.Properties;
import org.apache.log4j.Logger;

.....
.....



/**
*
* Obtiene la cadena del botón encriptada para una compra. Una cadena de
* ejemplo sería:
*
* cert_id=...
* cmd=_xclick
* business=....
* item_name=Lorem Ipsum Dolor sit amet...
* item_number=1234
* custom=sc-id-789
* amount=500.00
* currency_code=EUR
* tax=41.25
* shipping=20.00
* address_override=1
* address1=Calle inventada
* city=Ciudad
* state=Estado
* zip=23452345
* country=ES
* no_note=1
* cancel_return=http://url.de.retorno
* @param paymentData Variables adicionales que se quieran adjuntar.
* @param concepto Descripción de concepto por el que se va a pagar.
* @param codigoVenta Identificador de la venta
* @param cantidad Cantidad en euros que se va a cobrar
* @param impuesto Cantidad que se va a cobrar de impuestos
* @param direccion Dirección del pagador
* @param numero numero de la direccion postal
* @param cp Codigo postal
* @param localidad Localidad de la dirección postal
* @param pais País de la dirección postal
* @param nombre Nombre del pagador
* @param apellidos Apellidos del pagador
* @param pruebas Booleano que indica si se dirigirá al entorno de pruebas o no
* @return cadena de la firma de los datos.
* @throws Exception
*/
public String getButtonEncryptionValue(String paymentData,
String concepto, String codigoVenta, Float cantidad, Float impuesto,
String direccion, String numero, String piso, String puerta,
String cp, String localidad, String pais, String nombre,
String apellidos, String email, Boolean pruebas) throws Exception {

Properties oProps = new Properties();
ClassLoader oCL = Thread.currentThread().getContextClassLoader();

InputStream oIStr = oCL.
getResourceAsStream("archivodeconfiguracionenclasspathquesiempreexiste.properties");
oProperties.load(oIStr);
oIStr.close();

String env = ".sandbox";
if (!pruebas) {
env = "";
}

String signedStr = null;

String _keyPass = "password_que_tienes_que_poner_bien";
String user = "userquetienesqueponerbien";
String certId = oProps.getProperty("propiedad_con_el_valor_que_te_da_paypal_al_registrarte");
String returnURL = oProps.getProperty("propiedad_url_de_vuelta_en_navegador_despues_de_pagar");
String returnCURL = oProps.getProperty("propieda_de_la_url_si_cancela_el_pago");
if (piso == null) {
piso = "";
}
if (puerta == null) {
puerta = "";
}
if (_data == null) {
_data = "";
}
if (numero != null && numero.length() > 0) {
direccion += " nº " + numero;
}
if (piso != null && piso.length() > 0) {
direccion += " - " + piso + "º";
}
if (puerta != null && puerta.length() > 0) {
direccion += " " + puerta;
}

paymentData += "cert_id=" + certId + ","
+"item_name=" + concepto.replaceAll(",", "") + ","
+"item_number=" + codigoVenta + ","
+"amount=" + String.format("%1.2f", cantidad).replaceAll(",", ".") + ","
+"tax=" + String.format("%1.2f", impuesto).replaceAll(",", ".") + ","
+"address_override=1,"
+"address1=" + direccion.replaceAll(",", "") + ","
+"city=" + localidad + ","
+"zip=" + cp + ","
+"country=" + pais + ","
+"first_name=" + nombre + ","
+"last_name=" + apellidos + ","
+"payer_email=" + email + ","
+"cmd=_xclick,"
+"business=" + user + ","
+"currency_code=EUR,"
+"lc=" + pais + ","
+"cbt=Volver a la página,"
+"return=" + returnURL + ","
+"cancel_return=" + returnCURL + "";

logger.info("Encoding data: " + paymentData);

paymentData = paymentData.replace(',', '\n');
try {
signedStr = new String(PPCrypto.getButtonEncryptionValue(paymentData.getBytes("UTF-8"),
oProps.getProperty("ruta_al_archivo_p12"),
oProps.getProperty("ruta_al_certificado_de_paypal"),
_keyPass));
} catch (Exception ex) {
logger.error("Excepcion firmando: " + ex.getMessage());
}
return signedStr;
}