• Cómo usar el SDK
  • Creación de un cliente
  • Servicio para crear una nueva suscripción
  • Servicio para consulta de suscripción
  • Servicio para realizar un pago automático
  • Servicio para Validar pago

Consumo del API de Suscripciones en Java o Android

Cómo usar el SDK

Para poder consumir el API de Suscripciones de Nequi en su proyecto Java debe agregar el SDK como una dependencia de maven, el id del artefacto cambia según si el ambiente es QA o producción.

Por favor incluya en la parte de dependencias de su pom.xml lo siguiente:

  • Ambiente de pruebas o QA:
    
        <dependency>
            <groupId>com.nequi</groupId>
            <artifactId>nequi-subscriptions-api-sdk-qa</artifactId>
            <version>1.0.2</version>
        </dependency>
    
  • Ambiente de producción:
    
        <dependency>
            <groupId>com.nequi</groupId>
            <artifactId>nequi-subscriptions-api-sdk</artifactId>
            <version>1.0.2</version>
        </dependency>
    

 

Si no va a usar el artefacto de maven sino que el equipo de NEQUI le entregó los jars requeridos, agregue estos al classpath de su proyecto; o en caso que  tenga las fuentes del SDK de Java en un .zip, descomprímalo y en la raíz donde se encuentra el archivo pom.xml ejecute el comando mvn install para instalar el paquete en su repositorio local de maven.

Creación de un cliente

Ya teniendo el SDK integrado en nuestro proyecto, lo siguiente para consumir el API de NEQUI es instanciar un nuevo cliente mediante el objeto ApiClientFactory y la interfaz NequiSubscriptionsGatewayClient que representa el contrato de servicio con las operaciones que se pueden hacer sobre el API de suscripciones de Nequi.

Para este proceso va a necesitar el apiKey, accessKey y secretKey que le ha suministrado el equipo de Nequi como sus credenciales de acceso al API para poder configurar la autorización mediante alguno de los múltiples proveedores que ofrece AWS (mediante Variables de entorno, archivos de propiedades, AWS Security Token Service, etc.) o alguna estrategia que usted desee crear. Para este ejemplo vamos a utilizar un proveedor que nos expone el SDK de Nequi llamado BasicAWSCredentialsProvider.

En el siguiente código en java podemos ver un ejemplo de cómo instanciar un cliente del API:


//Se inicializa la fábrica de clientes
ApiClientFactory factory = new ApiClientFactory();
//Se instancia el proveedor de credenciales
AWSCredentialsProvider credenetialsProvider = new BasicAWSCredentialsProvider(ACCESS_KEY,SECRET_KEY);
//Se setea el api key
factory.apiKey(API_KEY);
//Se asigna el proveedor de credenciales a la fábrica de clientes
factory.credentialsProvider(credenetialsProvider);
//Se instancia un nuevo cliente del api a partir del contrato establecido por 
//NequiSubscriptionsGatewayClient
NequiSubscriptionsGatewayClient apiClient = factory.build(NequiSubscriptionsGatewayClient.class);

 

Ya con el contrato o interfaz NequiSubscriptionsGatewayClient instanciada podemos ejecutar de manera sincrónica cualquiera de los siguientes métodos:


public interface NequiSubscriptionsGatewayClient {    
  JsonObject servicesSubscriptionpaymentserviceAutomaticpaymentPost(JsonObject body);
  JsonObject servicesSubscriptionpaymentserviceGetsubscriptionPost(JsonObject body);
  JsonObject servicesSubscriptionpaymentserviceNewsubscriptionPost(JsonObject body);
  JsonObject servicesSubscriptionpaymentserviceGetstatuspaymentPost(JsonObject body);
}

 

Como se puede ver en la anterior imagen, cada método o servicio del API recibe un JsonObject que representa el cuerpo de la petición que requiere el servicio y retorna un JsonObject que representa la respuesta del servicio.

Servicio para crear una nueva suscripción

El servicio para crear una nueva suscripción envía una solicitud a un cliente Nequi mediante una notificación PUSH para suscribirse a un comercio con el objetivo de permitirle a éste realizar pagos o débitos automáticos de esa cuenta Nequi. El usuario cuenta con la posibilidad de aprobarla o rechazarla.

De los métodos que ofrece el NequiNotificationGateWayClient vamos a utilizar servicesSubscriptionpaymentserviceNewsubscriptionPost para consumir el servicio para crear una nueva suscripción.

En código Java sería de la siguiente forma:


//Inicialización del cliente API
ApiClientFactory factory = new ApiClientFactory();
AWSCredentialsProvider credenetialsProvider = new BasicAWSCredentialsProvider(ACCESS_KEY, SECRET_KEY);
factory.apiKey(_API_KEY);
factory.credentialsProvider(credenetialsProvider);
NequiSubscriptionsGatewayClient apiClient = factory.build(NequiSubscriptionsGatewayClient.class);
String phone_number =”3996581361”;
String code =”123456789”;
String name =”Prueba”; 
//Consumo del servicio, retorna un JsonObject con la respuesta del servicio
JsonObject response = apiClient.servicesSubscriptionpaymentserviceNewsubscriptionPost(BodyUtils. getNewSubscription(phone_number, code, name));

 

Si analizamos el anterior código primero se inicializa el cliente y luego se invoca el servicio. Además, en este ejemplo también se usa un método estático, BodyUtils.getNewSubscription, para generar el cuerpo de la petición, este método debería retornar un JsonObject con la siguiente estructura:


{
  "RequestMessage": {
    "RequestHeader": {
      "Channel": CONSUMER_ID, //ID o canal del consumidor para trazabilidad
      "RequestDate": DATE, //Timestamp completo, con milisegundos precisión 3
      "MessageID": ID, //Identificador único de la transacción, timestamp o alguno único
      "ClientID": NUMBER //Identificador de la terminal, nodo o servidor
          "Destination": {
        "ServiceName": "SubscriptionPaymentService", //Servicio que se quiere consumir
        "ServiceOperation": "newSubscription", //Operación del servicio a consumir
        "ServiceRegion": "C001", //Región a la que pertenece el servicio, para panamá P001
        "ServiceVersion": "1.0.0" //Versión del servicio
      }
    },
    "RequestBody": {
      "any": {
        "newSubscriptionRQ": {
          "phoneNumber": STRING, //Número de celular del cliente Nequi 
          "code": STRING, //Combinación del tipo y número de identificación del comercio
          "name": STRING //Nombre del comercio con el cual se desea aparezca en el PUSH
        }
      }
    }
  }
}

 

Para construir las cabeceras del cuerpo de la petición o  RequestHeader va a necesitar el Channel que le ha sido suministrado por Nequi, generar un datestamp a partir de la fecha en que se realiza la petición para la propiedad RequestDate y definir una forma única de identificar la transacción mediante un alfanumérico de 10 para asignar al campo MessageID. Un ejemplo de la codificación del método sería:


//Canal para pagos con suscripciones
public static final String CHANNEL = "PDA05-C001";
//Construye a partir del celular, tipo y número de identificación del comercio y nombre el mensaje de entrada del servicio de nueva
//suscripción
public static JsonObject getNewSubscription(String phoneNumber, String code, String name) {
  //Fecha de la petición
  Date d = new Date();
  String date = new SimpleDateFormat("yyyy-MM-dd:HH-mm-ss").format(d);
  String miliseconds = Long.toString(System.currentTimeMillis());
  String input = 
    "{\"RequestMessage\":{"
      + "\"RequestHeader\":{"
        //Canal
        + "\"Channel\":\""+CHANNEL+"\","
        //Fecha de la petición
        + "\"RequestDate\":\""+date+"\","
        //Identificador único de la transacción
          + "\"MessageID\":\""+miliseconds.substring(miliseconds.length()-9)+"\","
        //identificador de la terminal o servidor
        + "\"ClientID\":\"123\""
        + ", \"Destination\": {"                    
          +"\"ServiceName\":\"SubscriptionPaymentService\""
          +  ", \"ServiceOperation\": \"newSubscription\""
          +  ", \"ServiceRegion\": \"C001\""
          +  ", \"ServiceVersion\": \"1.0.0\""
        + "}"
      + "},"
      + "\"RequestBody\":{"
        + "\"any\":{"
          + "\"newSubscriptionRQ\":{"
            + "\"phoneNumber\":\""+ phoneNumber + "\","
            + "\"code\":\"" + code + "\","
            + "\"name\":\"" + name + "\""
          + "}"
        + "}"
      + "}"
    + "}}";
  return gson.fromJson(input, JsonObject.class);
}

 

Llegado el caso que el consumo del servicio sea exitoso, el JsonObject que retorna el método trae internamente el token requerido para poder usar por primera vez el servicio de pago automático, el token debería ser almacenado porque no hay ningún otro servicio que lo retorne nuevamente por temas de seguridad, si lo pierde tendría que consumir de nuevo este servicio y esperar que el usuario apruebe la suscripción. La estructura de la respuesta del servicio es similar a la siguiente:


{
  "ResponseMessage": {
    "ResponseHeader": {
      "Channel": CONSUMER_ID, //ID del consumidor para trazabilidad
      "ResponseDate": DATE, //Fecha de respuesta
      "Status": {
        "StatusCode": "0",
        "StatusDesc": "SUCCESS"
      },
      "MessageID": ID, //Identificador único de la transacción, timestamp o alguno único
      "ClientID": NUMBER, //Identificador de la terminal o servidor
      //Datos técnicos que no deberían ser procesados o almacenados
      "Destination": {
        "ServiceName": "SubscriptionPaymentService", //Nombre del Servicio
        "ServiceOperation": "newSubscription" //Nombre de la operación
              "ServiceRegion": "C001", //Región del servicio
        "ServiceVersion": "1.0.0" //Versión del servicio    
      }
    },
    "ResponseBody": {
      "any": {
        //Presente solo cuando StatusCode es igual a cero
        "newSubscriptionRS": {
          "token": STRING //Esta es la variable que nos interesa
        }
      }
    }
  }
}

 

Cuando la operación del servicio falla, no el consumo HTTP del servicio REST, sino la operación de negocio, el campo StatusCode será diferente de cero y por consiguiente en ResponseBody.any no vendrá el objeto  newSubscriptionRS sino que any  será un elemento o cadena vacía.

Servicio para consulta de suscripción

El servicio para consulta de suscripción permite a partir de un celular de un usuario Nequi, el tipo y número de identificación de un comercio y el último token que se tenga de esa suscripción, consultar los datos de dicha suscripción principalmente el estado que define si ya fue aprobada, rechazada, expirada o si sigue pendiente.

De los métodos que ofrece el NequiSubscriptionsGatewayClient vamos a utilizar servicesSubscriptionpaymentserviceGetsubscriptionPost para consultar una suscrpción.

En código Java seria de la siguiente forma:


//Inicialización del cliente API
ApiClientFactory factory = new ApiClientFactory();
AWSCredentialsProvider credenetialsProvider = new BasicAWSCredentialsProvider(ACCESS_KEY, SECRET_KEY);
factory.apiKey(_API_KEY);
factory.credentialsProvider(credenetialsProvider);
NequiSubscriptionsGatewayClient apiClient = factory.build(NequiSubscriptionsGatewayClient.class);
String phone_number =”3993457689”;
String token =”AWSDERRGTTGFD”;
String code = “12345”; 
//Consumo del servicio, retorna un JsonObject con la respuesta del servicio
JsonObject response = apiClient.servicesSubscriptionpaymentserviceGetsubscriptionPost(BodyUtils.getBodyGetSubscription(phone_number, code, token));

 

Si analizamos el anterior código primero se inicializa el cliente y luego se invoca el servicio. Además, en este ejemplo también se usa un método estático, BodyUtils.getBodyGetSubscription, para generar el cuerpo de la petición, este método debería retornar un JsonObject con la siguiente estructura:


{
  "RequestMessage": {
    "RequestHeader": {
      "Channel": CONSUMER_ID, //ID del consumidor para trazabilidad
      "RequestDate": DATE, //Timestamp completo, con milisegundos precisión 3
      "MessageID": ID, //Identificador único de la transacción, timestamp o alguno único
      "ClientID": NUMBER //Identificador de la terminal o servidor
          "Destination": {
        "ServiceName": " SubscriptionPaymentService", //Servicio que se quiere consumir
        "ServiceOperation": "getSubscription", //Operación del servicio a consumir
        "ServiceRegion": "C001", //Región a la que pertenece el servicio, para panamá P001
        "ServiceVersion": "1.0.0" //Versión del servicio
      }
    },
    "RequestBody": {
      "any": {
        "getSubscriptionRQ": {
          "phoneNumber": STRING, //Número de celular del cliente
          "code": STRING, //Combinación del tipo y número de identificación del comercio
          "token": STRING //Último token retornado por el servicio de nueva suscripción 
        }
      }
    }
  }
}

 

Para construir las cabeceras del cuerpo de la petición o  RequestHeader va a necesitar el Channel que le ha sido suministrado por Nequi, generar un datestamp a partir de la fecha en que se realiza la petición para la propiedad RequestDate y definir una forma única de identificar la transacción mediante un alfanumérico de 10 para asignar al campo MessageID. Un ejemplo de la codificación del método sería:


//Canal para pagos con suscripciones
public static final String CHANNEL = "PDA05-C001";
public static JsonObject getBodyGetSubscription(String phone, String code, String token) {
  //Fecha de la petición
  Date d = new Date();
  String date = new SimpleDateFormat("yyyy-MM-dd:HH-mm-ss").format(d);
  String miliseconds = Long.toString(System.currentTimeMillis());
  String input = 
    "{\"RequestMessage\":{"
      + "\"RequestHeader\":{"
        //Canal
        + "\"Channel\":\""+CHANNEL+"\","
        //Fecha de la petición
        + "\"RequestDate\":\""+date+"\","
        //Identificador único de la transacción
        + "\"MessageID\":\""+miliseconds.substring(miliseconds.length()-9)+"\","
        //Identificador de la terminal
        + "\"ClientID\":\"12345\""
        + ", \"Destination\": {"                    
          +     "\"ServiceName\": \"SubscriptionPaymentService\""
          +", \"ServiceOperation\": \"getSubscription\""
          +    ", \"ServiceRegion\": \"C001\""
          +    ", \"ServiceVersion\": \"1.0.0\""
        + "}"
      + "},"
      + "\"RequestBody\":{"
        + "\"any\":{"
          + "\"getSubscriptionRQ\":{"
            + "\"phoneNumber\":\""+ phone + "\","
            + "\"code\":\""+ code + "\","    
            + "\"token\":\"" + token + "\""
          + "}"
        + "}"
      + "}"
    + "}}";
  return gson.fromJson(input, JsonObject.class);
}

 

Llegado el caso que el consumo del servicio sea exitoso, el JsonObject que retorna el método trae los datos de la suscripción, la estructura de la respuesta es similar a la siguiente:


{
  "ResponseMessage": {
    "ResponseHeader": {
      "Channel": CONSUMER_ID, //ID del consumidor para trazabilidad
      "ResponseDate": DATE, //Fecha de respuesta
      "Status": {
        "StatusCode": "0",
        "StatusDesc": "SUCCESS"
      },
      "MessageID": ID, //Identificador único de la transacción, timestamp o alguno único
      "ClientID": NUMBER, //Identificador de la terminal o servidor
      //Datos técnicos que no deberían ser procesados o almacenados
      "Destination": {
        "ServiceName": "SubscriptionPaymentService", //Nombre del Servicio
        "ServiceOperation": "getSubscription" //Nombre de la operación
              "ServiceRegion": "C001", //Región del servicio
        "ServiceVersion": "1.0.0" //Versión del servicio
      }
    },
    "ResponseBody": {
      "any": {
        //Presente solo cuando StatusCode es igual a cero
        "getSubscriptionRS": {
          "dateCreated": STRING, //Fecha de generación de la suscripción,
          "name": STRING, //Nombre del comercio asociado a la suscripción
          "status": STRING //Estado de la suscripción
        }
      }
    }
  }
}

 

Cuando la operación del servicio falla, no el consumo HTTP del servicio REST, sino la operación de negocio, el campo StatusCode será diferente de cero y por consiguiente en ResponseBody.any no vendrá el objeto  getSubscriptionRS sino que any  será un elemento o cadena vacía.

Los posibles estados que puede tener una suscripción son los siguientes:

  • 0 = Pendiente
  • 1 = Aceptada
  • 2 = Rechazada
  • 3 = Expirada

Solo cuando es aceptada el servicio de pago automático podrá funcionar.

Servicio para realizar un pago automático

El servicio para realizar un pago automático permite a partir de un celular de un usuario Nequi, el tipo y número de identificación de un comercio, un valor a pagar y el último token que se tenga de esa suscripción, realizar un pago o débito automático o en línea de la cuenta del usuario Nequi.

El método que vamos a utilizar para los pagos automáticos es servicesSubscriptionpaymentserviceAutomaticpaymentPost.

En código Java seria de la siguiente forma:


//Inicialización del cliente API
ApiClientFactory factory = new ApiClientFactory();
AWSCredentialsProvider credenetialsProvider = new BasicAWSCredentialsProvider(ACCESS_KEY, SECRET_KEY);
factory.apiKey(_API_KEY);
factory.credentialsProvider(credenetialsProvider);
NequiSubscriptionsGatewayClient apiClient = factory.build(NequiSubscriptionsGatewayClient.class);
String phone_number =”3993457689”;
String token =”AWSDERRGTTGFD”;
String code = “12345”;
String value = “1”; 
//Consumo del servicio, retorna un JsonObject con la respuesta del servicio
JsonObject response = apiClient.servicesSubscriptionpaymentserviceAutomaticpaymentPost (BodyUtils.getBodyAutomaticPayment(phone_number, code, token, value));

 

Si analizamos el anterior código primero se inicializa el cliente y luego se invoca el servicio. Además, en este ejemplo también se usa un método estático, BodyUtils.getBodyAutomaticPayment, para generar el cuerpo de la petición, este método debería retornar un JsonObject con la siguiente estructura:


{
  "RequestMessage": {
    "RequestHeader": {
      "Channel": CONSUMER_ID, //ID del consumidor para trazabilidad
      "RequestDate": DATE, //Timestamp completo, con milisegundos precisión 3
      "MessageID": ID, //Identificador único de la transacción, timestamp o alguno único
      "ClientID": NUMBER //Identificador de la terminal o servidor
          "Destination": {
        "ServiceName": " SubscriptionPaymentService", //Servicio que se quiere consumir
        "ServiceOperation": "automaticPayment", //Operación del servicio a consumir
        "ServiceRegion": "C001", //Región a la que pertenece el servicio, para panamá P001
        "ServiceVersion": "1.0.0" //Versión del servicio
      }
    },
    "RequestBody": {
      "any": {
        "automaticPaymentRQ": {
          "phoneNumber": STRING, //Número de celular del cliente
          "code": STRING, //Combinación del tipo y número de identificación del comercio
          "valor": STRING, //Valor a cobrar
          "token": STRING, //Último token de la suscripción
          "reference1": "reference1",
          "reference2": "reference2",
          "reference3": "reference3"
        }
      }
    }
  }
}

 

Para construir las cabeceras del cuerpo de la petición o  RequestHeader va a necesitar el Channel que le ha sido suministrado por Nequi, generar un datestamp a partir de la fecha en que se realiza la petición para la propiedad RequestDate y definir una forma única de identificar la transacción mediante un alfanumérico de 10 para asignar al campo MessageID. Un ejemplo de la codificación del método sería:


//Canal para pagos con suscripciones
public static final String CHANNEL = "PDA05-C001";
public static JsonObject getBodyAutomaticPayment(String phone, String code, String value, String token,String reference1,String reference2,String reference3) {
  //Fecha de la petición
  Date d = new Date();
  String date = new SimpleDateFormat("yyyy-MM-dd:HH-mm-ss").format(d);
  String miliseconds = Long.toString(System.currentTimeMillis());
  String input = 
    "{\"RequestMessage\":{"
      + "\"RequestHeader\":{"
        //Canal
        + "\"Channel\":\""+CHANNEL+"\","
        //Fecha de la petición
        + "\"RequestDate\":\""+date+"\","
        //Identificador único de la transacción
        + "\"MessageID\":\""+miliseconds.substring(miliseconds.length()-9)+"\","
        //Identificador de la terminal
        + "\"ClientID\":\"12345\""
        + ", \"Destination\": {"                    
          +     "\"ServiceName\": \"SubscriptionPaymentService\""
          +", \"ServiceOperation\": \"automaticPayment\""
          +    ", \"ServiceRegion\": \"C001\""
          +    ", \"ServiceVersion\": \"1.0.0\""
        + "}"
      + "},"
      + "\"RequestBody\":{"
        + "\"any\":{"
          + "\"automaticPaymentRQ\":{"
            + "\"phoneNumber\":\""+ phone + "\","
            + "\"code\":\""+ code + "\","    
            + "\"value\":\""+ value + "\","            
            + "\"token\":\"" + token + "\"," 
​            + "\"reference1\":\"" + reference1+ "\"," 
​            + "\"reference2\":\"" + reference2+ "\"," 
            ​+ "\"reference3\":\"" + reference3+ "\"" 
          + "}"
        + "}"
      + "}"
    + "}}";
  return gson.fromJson(input, JsonObject.class);
}

 

Llegado el caso que el consumo del servicio sea exitoso, el JsonObject que retorna el método trae los datos de la suscripción, la estructura de la respuesta es similar a la siguiente:


{
  "ResponseMessage": {
    "ResponseHeader": {
      "Channel": CONSUMER_ID, //ID del consumidor para trazabilidad
      "ResponseDate": DATE, //Fecha de respuesta
      "Status": {
        "StatusCode": "0",
        "StatusDesc": "SUCCESS"
      },
      "MessageID": ID, //Identificador único de la transacción, timestamp o alguno único
      "ClientID": NUMBER, //Identificador de la terminal o servidor
      //Datos técnicos que no deberían ser procesados o almacenados
      "Destination": {
        "ServiceName": "SubscriptionPaymentService", //Nombre del Servicio
        "ServiceOperation": "automaticPayment" //Nombre de la operación
              "ServiceRegion": "C001", //Región del servicio
        "ServiceVersion": "1.0.0" //Versión del servicio
      }
    },
    "ResponseBody": {
      "any": {
        //Presente solo cuando StatusCode es igual a cero
        "automaticPaymentRS": {
          "transactionId ": STRING, //Identificador de la transacción que se usa en el 
          //servicio de validación o consulta de estado de pago,
          "token": STRING, //Nuevo token para usar en los servicios que lo requieren   
        }
      }
    }
  }
}

 

Cuando la operación del servicio falla, no el consumo HTTP del servicio REST, sino la operación de negocio, el campo StatusCode será diferente de cero y por consiguiente en ResponseBody.any no vendrá el objeto  automaticPaymentRS sino que any  será un elemento o cadena vacía.

Servicio para Validar pago

El servicio para validar pagos, expuesto en el api permite a partir del transactionId que retorna el servicio de pago automático validar si el pago ya fue realizado desde la cuenta NEQUI. Este servicio es útil por si se necesita verificar si el pago fue correcto o no, aunque el servicio de pago automático ya retorna si fue exitoso o no, este es una opción adicional para verificar el pago.

De las funciones que ofrece el NequiSubscriptionsGatewayClient usaremos servicesSubscriptionpaymentserviceGetstatuspaymentPost para consumir el servicio que valida el estado de un pago.

En código Java seria de la siguiente forma:


//Inicialización del cliente API
ApiClientFactory factory = new ApiClientFactory();
AWSCredentialsProvider credenetialsProvider = new BasicAWSCredentialsProvider(ACCESS_KEY, SECRET_KEY);
factory.apiKey(_API_KEY);
factory.credentialsProvider(credenetialsProvider);
NequiSubscriptionsGatewayClient apiClient = factory.build(NequiSubscriptionsGatewayClient.class);
String code = “1234”;
//Consumo del servicio, retorna un JsonObject con la respuesta del servicio
JsonObject response = apiClient. servicesSubscriptionpaymentserviceGetstatuspaymentPost(BodyUtils. getBodyGetStatusPayment(code));

 

En el anterior ejemplo primero se inicializa el cliente y luego se invoca el servicio, si la respuesta es exitosa y el estado del pago es igual a 35, significa que el pago ya está realizado, si es 34 fue rechazado y si es 33 ya expiró.

 

Además, en este ejemplo también se usa un método que no está implementado en el ejemplo, BodyUtils.getBodyGetStatusPayment, para generar el cuerpo de la petición, esta función debería retornar un JsonObject  con la siguiente estructura:


{
  "RequestMessage": {
    "RequestHeader": {
      "Channel": CONSUMER_ID, //ID del consumidor para trazabilidad
      "RequestDate": DATE, //Timestamp completo, con milisegundos precisión 3
      "MessageID": ID, //Identificador único de la transacción, timestamp o alguno único
      "ClientID": NUMBER, //Identificador de la terminal
      "Destination": {
        "ServiceName": "PaymentsService", //Servicio que se quiere consumir
        "ServiceOperation": "getStatusPayment", //Operación del servicio a consumir
        "ServiceRegion": "C001", //Región a la que pertenece el servicio, para panamá P001
        "ServiceVersion": "1.0.0" //Versión del servicio
      }
    },
    "RequestBody": {
      "any": {
        "getStatusPaymentRQ": {
          " codeQR ": STRING //transactionId retornado por el servicio de pago automático
        }
      }
    }
  }
}

 

Al igual que en los servicios anteriores para construir las cabeceras del cuerpo de la petición o  RequestHeader va a necesitar el Channel que le ha sido suministrado por Nequi, generar un datestamp a partir de la fecha en que se realiza la petición para la propiedad RequestDate y definir una forma única de identificar la mediante un alfanumérico de 10 para asignar al campo MessageID. Un ejemplo de la codificación del método sería:


//Canal para pagos con suscripciones
public static final String CHANNEL = "PDA05-C001";
//Construye a partir de un transactionId el mensaje de entrada del
//servicio de validación de pago
public static JsonObject getBodyGetStatusPayment(String code) {
  Date d = new Date();
  String date = new SimpleDateFormat("yyyy-MM-dd:HH-mm-ss").format(d);
  String miliseconds = Long.toString(System.currentTimeMillis());
  String input = 
    "{\"RequestMessage\":{"
      + "\"RequestHeader\":{"
        //Canal
        + "\"Channel\":\""+CHANNEL+"\","
        //Feha de la petición
        + "\"RequestDate\":\""+date+"\","
        //Identificador único de la transacción
        + "\"MessageID\":\""+miliseconds.substring(miliseconds.length()-9)+"\"," 
        + "\"ClientID\":\"12345\""
        + ", \"Destination\": {"                    
          + "\"ServiceName\": \"PaymentsService\""
          + ", \"ServiceOperation\": \"getStatusPayment\""
          + ", \"ServiceRegion\": \"C001\""
          + ", \"ServiceVersion\": \"1.0.0\""
        + "}"
      + "},"
      + "\"RequestBody\":{"
        + "\"any\":{"
          + "\"getStatusPaymentRQ\":{"
            + "\"codeQR\":\"" + code + "\""
          + "}"
        + "}"
      + "}"
    + "}}";
  return gson.fromJson(input, JsonObject.class);
}

 

Llegado el caso que el consumo del servicio sea exitoso, el response de la petición o el retorno del método trae internamente el estado del pago, el cual es igual a 35 cuando ya se realizó el pago por parte de algún cliente NEQUI. El estado es un atributo con nombre status y  la estructura de la respuesta es similar a la siguiente:


{
  "ResponseMessage": {
    "ResponseHeader": {
      "Channel": CONSUMER_ID, //ID del consumidor para trazabilidad
      "ResponseDate": DATE, //Fecha de respuesta
      "Status": {
        "StatusCode": "0",
        "StatusDesc": "SUCCESS"
      },
      "MessageID": ID, //Identificador único de la transacción, timestamp o alguno único
      "ClientID": NUMBER, //Identificador de la terminal
      //Datos técnicos que no deberían ser procesados o almacenados
      "Destination": {
        "ServiceName": "PaymentsService",
        "ServiceOperation": "getStatusPayment",
        "ServiceRegion": "C001",
        "ServiceVersion": "1.0.0"
      }
    },
    "ResponseBody": {
      "any": {
        //Presente solo cuando StatusCode es igual a cero
        "getStatusPaymentRS": {
          "status": STATUS, //Estado del pago, si es igual a 35 es porque esta completo
          "phoneNumber": CEL, //Numero del cliente que pago
          "date": DATE, //Fecha del pago
          "name": NAME, //Nombre del cliente merchant o comercio
          "trnId": ID, //Id de la transacción
          "value": VALUE, //Valor pagado
          "originMoney": [
            {
              "name": NAME, //Nombre del origen o bolsillo de dónde provino el dinero
              "value": VALUE, //Valor debitado
              "pocketType": POCKET, //Tipo de bolsillo
            }
          ]
        }
      }
    }
  }
}

 

Cuando la operación del servicio falla, no el consumo HTTP del servicio REST, sino la operación de negocio, el campo StatusCode será diferente de cero y por consiguiente en ResponseBody.any no vendrá el objeto  getStatusPaymentRS sino que any  será un elemento o cadena vacía.

Para consumir este servicio recomendamos las siguientes dos estrategias:

  • Por demanda: donde el usuario del aplicativo que se integre con el API lance el consumo para verificar el pago cuando desee.
  • Por sonda: donde el sistema integrado con el API lanza cada 30 segundos durante 15 minutos una petición para verificar el estado del pago y cuando el estado sea diferente de 33, que es pendiente, pare la sonda.

 

Si tiene dudas técnicas sobre la implementación y uso del API de NEQUI para notificaciones revise el código de la aplicación de ejemplo que se le entregó con esta guía o póngase en contacto con el equipo de NEQUI.