No mostrar más este mensaje

ecommerce

Recepción XML

 

Como respuesta a la petición realitzada en el apartado 10, el SIS devolverá al comercio un documento XML con el resultado de la petición.

Este documento de respuesta (NOTIFICACIONXML) se introducirá de igual manera en un formulario, dentro de un campo denominado datos después de haberlo pasado a formato x-www-form-urlencoded

Los campos que puede tener este documento son los siguientes:

3_2_a

El TPV Virtual por defecto puede comunicar a los puertos 80, 443, 8080 y 8081 del comercio. Otros puertos deberán ser consultados.

Una vez que el comercio recibe el formulario, el código de respuesta (Ds_Response) tendrá los siguientes valores posibles:

3_2_b

Nota: solo en el caso de las preautenticaciones (preautorizaciones separadas), se devuelve un 0 si está autorizada y el titular se autentica y, un 1 si está autorizada y el titular no se autentica.

El TPV Virtual efectúa el envío de las notificaciones on-line para las operaciones de compra autorizadas y denegadas por la entidad emisora de la tarjeta, así como en aquellas situaciones en las que el proceso de compra ha sido interrumpido al haberse producido uno de los siguientes errores:
SIS0051 -> Pedido repetido. Se envía notificación con código 913.
SIS0078 -> Método de pago no disponible para su tarjeta. Se envía notificación con código 118
SIS0093 -> Tarjeta no válida. Se envía notificación con código 180.
SIS0094 -> Error en la llamada al MPI sin controlar. Se envía notificación con código 184

Para recibir la notificación HTTP montaremos un Servlet que se encargará de leer los parámetros enviados por la pasarela de pago. Este Servlet no implementa ninguna lógica de negocio, simplemente vuelca el contenido en el log del servidor. En un entorno real esos datos se explotarán de la manera más conveniente en cada caso.

package es.lacaixa.redsys.servlet;

import java.io.IOException;
import java.io.StringReader;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathExpressionException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class RespuestaXMLServlet extends HttpServlet {

    private static final long    serialVersionUID    = -8991452242470541541L;

    /**
     * @see HttpServlet#HttpServlet()
     */

    public RespuestaXMLServlet() {
        super();
    }

    /*
     * En el método doGet redirigimos al doPost. En principio no debería
     * entrarnos ninguna petición por aquí pero lo dejamos así por si acaso
     * algún día cambian la operativa
     */

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
                                                                                              IOException {
        doPost(request, response);
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
     *      response)
     */

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
                                                                                               IOException {

        System.out.println("Request (redsys): ");

        try {

            // Recuperamos el parámetro "datos" donde nos llegará el XML de
            // notificación
            String datos = request.getParameter("datos");

            // Parseamos el XML para obtener un mapa de valores
            Map<String, String> responseMap = parseXML(datos);

            // Y los imprimimos en la consola del servidor
            for (Entry<String, String> entry : responseMap.entrySet()) {

                System.out.println(entry.getKey() + ": " + entry.getValue());
            }
        } catch (XPathExpressionException e) {
            e.printStackTrace();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        }

    }

    private static Map<String, String> parseXML(String xml) throws ParserConfigurationException, 
                                                                       SAXException, 
                                                                       IOException, 
                                                                       XPathExpressionException {

        InputSource source = new InputSource(new StringReader(xml));

        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();

        Document doc = db.parse(source);
        NodeList nodeList = doc.getElementsByTagName("NOTIFICACIONXML");

        Element elementOperacion = (Element) nodeList.item(0);

        String Ds_Version = getChildValue(elementOperacion, "Ds_Version");
        String Ds_Amount = getChildValue(elementOperacion, "Ds_Amount");
        String Ds_Currency = getChildValue(elementOperacion, "Ds_Currency");
        String Ds_Order = getChildValue(elementOperacion, "Ds_Order");
        String Ds_MerchantCode = getChildValue(elementOperacion, "Ds_MerchantCode");
        String Ds_Terminal = getChildValue(elementOperacion, "Ds_Terminal");
        String Ds_Signature = getChildValue(elementOperacion, "Ds_Signature");
        String Ds_Response = getChildValue(elementOperacion, "Ds_Response");
        String Ds_MerchantData = getChildValue(elementOperacion, "Ds_MerchantData");
        String Ds_SecurePayment = getChildValue(elementOperacion, "Ds_SecurePayment");
        String Ds_TransactionType = getChildValue(elementOperacion, "Ds_TransactionType");
        String Ds_Card_Number = getChildValue(elementOperacion, "Ds_Card_Number");
        String Ds_ExpiryDate = getChildValue(elementOperacion, "Ds_ExpiryDate");
        String Ds_Card_Country = getChildValue(elementOperacion, "Ds_Card_Country");
        String Ds_AuthorisationCode = getChildValue(elementOperacion, "Ds_AuthorisationCode");

        Map<String, String> responseMap = new HashMap<String, String>();

        responseMap.put("Ds_Version", Ds_Version);
        responseMap.put("Ds_Amount", Ds_Amount);
        responseMap.put("Ds_Currency", Ds_Currency);
        responseMap.put("Ds_Order", Ds_Order);
        responseMap.put("Ds_Signature", Ds_Signature);
        responseMap.put("Ds_MerchantCode", Ds_MerchantCode);
        responseMap.put("Ds_Terminal", Ds_Terminal);
        responseMap.put("Ds_Response", Ds_Response);
        responseMap.put("Ds_AuthorisationCode", Ds_AuthorisationCode);
        responseMap.put("Ds_TransactionType", Ds_TransactionType);
        responseMap.put("Ds_Card_Number", Ds_Card_Number);
        responseMap.put("Ds_ExpiryDate", Ds_ExpiryDate);
        responseMap.put("Ds_SecurePayment", Ds_SecurePayment);
        responseMap.put("Ds_MerchantData", Ds_MerchantData);
        responseMap.put("Ds_Card_Country", Ds_Card_Country);

        return responseMap;
    }

    private static String getChildValue(Element element, String childName) {

        NodeList nlsNombre = element.getElementsByTagName(childName);
        Element eleNombre = (Element) nlsNombre.item(0);

if (eleNombre == null || eleNombre.getFirstChild() == null) {
            return "";
        }
        return eleNombre.getFirstChild().getNodeValue();
    }

En el fichero web.xml añadiremos la configuración de este servlet:

  
  <servlet>
    <description></description>
    <display-name>RespuestaXMLServlet</display-name>
    <servlet-name>RespuestaXMLServlet</servlet-name>
    <servlet-class>es.lacaixa.redsys.servlet.RespuestaXMLServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>RespuestaXMLServlet</servlet-name>
    <url-pattern>/RespuestaXMLServlet</url-pattern>
  </servlet-mapping>

Una vez hayamos desplegado el servlet en el servidor probaríamos de nuevo el Envío XML descrito en el apartado 10. En los logs del servidor donde tenemos instalado el Servlet deberíamos ver las siguientes trazas correspondientes a la notificación:

3_2_c

Para poder usar la notificación sobre este servlet necesitaremos instalarlo bajo algún dominio público. Es decir, no podemos probarlo en local ni en una red privada. Esto es porqué la pasarela no hace la petición a través del navegador como en el caso de las URL’s de OK y KO. En este caso la pasarela lanza una petición directamente desde su servidor al nuestro. Si nuestro servidor no es visible para la pasarela nunca nos llegará la modificación.

Esto solo afecta a la notificación, con lo que podríamos tener nuestra aplicación en local realizando pruebas y el servlet instalado en algún entorno de pruebas (siempre que sea visible para el exterior). De esta manera la notificación la recibiríamos en el entorno de pruebas pero el resto de proceso lo llevaríamos a cabo desde nuestro entorno local.