El apartado describe el uso del parámetro notification_url dentro de los pagos y suscripciones.
Al momento de registrar un pago o una suscripción en la plataforma de Pay per TIC se tiene la posibilidad de utilizar el parámetro url_notification, este permite la recepción de notificaciones de cambio de dicho pago o suscripción.
Al momento de enviar una notificación el sistema realiza un POST a la url informada con un modelo de dato como el siguiente
Notificación de un pago:
{ "type" : "debit", "validation" : false, "review" : false, "id" : "554ecb4a-aec5-439f-b506-9a22215e0746", "external_transaction_id" : "c189ad3d-f5e7-4d33-a92e-09adcb9273ed", "collector_id" : "999", "collector_detail" : { "name" : "PRUEBA" }, "notification_url" : "http://127.0.0.1:9999/notifications", "form_url" : "http://localhost:8180/formularios/v2/pagos/554ecb4a-aec5-439f-b506-9a22215e0746", "details" : [ { "amount" : 1.0, "external_reference" : "123", "concept_id" : "prueba", "concept_description" : "Concepto de prueba" } ], "currency_id" : "ARS", "payment_methods" : [ { "amount" : 1.0, "media_payment_id" : 9, "media_payment_detail" : "VISA CREDIT", "last_four_digits" : "0010", "first_six_digits" : "450799", "installments" : 1, "authorization_code" : "191780", "gateway" : { "establishment_number" : "PRUEBA", "transaction_id" : "4021606", "batch_number" : "1", "ticket_number" : "1533", "ppt_owner" : false }, "payment_method_id" : 0 } ], "final_amount" : 1.0, "status" : "approved", "status_detail" : "APROBADA - Autorizada - MOP GPAY: -1 - Aprobada", "request_date" : "2019-08-06T14:58:25-0300", "due_date" : "2019-08-06T14:58:25-0300", "last_due_date" : "2019-08-06T14:58:25-0300", "process_date" : "2019-08-06T14:58:25-0300", "paid_date" : "2019-08-06T14:58:25-0300", "accreditation_date" : "2019-08-06T14:58:25-0300", "last_update_date" : "2019-08-06T14:58:25-0300", "metadata" : { "parametro_1" : "valor_de_prueba" }, "source" : { "id" : "ee84ca67-5f90-4ca9-b587-37afce6ecc14", "name" : "system-test", "type" : "system" } } |
Notificación de una suscripción:
{ "type" : "subscription", "validation" : false, "review" : false, "source" : { "id" : "4450b7c2-58c6-4f38-b8ab-69b8d4761a7f", "name" : "system-test", "type" : "collector" }, "id" : "a16d59ca-b974-4f9c-a17a-37721705688d", "collector_id" : "999", "collector_detail" : { "name" : "PRUEBA" }, "notification_url" : "http://127.0.0.1:9980/notifications", "detail" : { "amount" : 1.0, "external_reference" : "344", "concept_id" : "44", "concept_description" : "Concepto de prueba" }, "currency_id" : "ARS", "payment_method" : { "media_payment_id" : 9, "media_payment_detail" : "VISA CREDIT", "last_four_digits" : "0010", "first_six_digits" : "450799" }, "payer" : { "name" : "Prueba", "email" : "prueba@paypertic.com", "external_reference" : "664", "identification" : { "type" : "DNI_ARG", "number" : "99999999", "country" : "ARG" } }, "amount" : 1.0, "status" : "active", "request_date" : "2019-08-06T15:35:04-0300", "due_day" : 25, "last_update_date" : "2019-08-06T15:35:05-0300", "recurrence" : "monthly", "periods" : 30 } |
Es posible enviar notificaciones en forma encriptada. Para esto se usaran tres tipos de llaves, una simétrica, una privada y una pública.
La notificación se encriptara con la llave simétrica. La llave simétrica se encriptara con la llave privada. Se envía al cliente la notificación junto con la llave simétrica, ambos encriptados.
El cliente deberá desencriptar primero la lleve simétrica utilizando la llave publica, y luego con esta deberá desencriptar la notificación.
Se recibirá un body en el request como el siguiente:
El secret_key es la llave simétrica encriptada por la llave privada configurada en el comercio.
El payload es la notificación encriptada con la llave simétrica.
{ secret_key:"ka8lPU+YudBbupb8UsjIviBBU2aQWHyLKZcOCjb9ENFNbftyfI50LrxroqwEixvSH97ZnN53yeUqd/LyGpaTuwna1aZQLQgKWg+G/Y3eKE0iRH1IyVNUdomndoKTlGY27w+5VoMpDlhWiQ3o8aDHzb5rVTNgz+dbUZsD5ot/vqeZmNv1Z4y6eEjpebc6X6wmHOkRUA+qVNak10oFRVycdapU0JzbaNGTFP9OzeCXDa/jMSxnBvqsmnv57PNhVKKd6T2jvMI01tPHj7iqqI+uNXRKuS7t47rFrLkG6YBwmr8FnWcryTiEE1LzoIMIgX9xBSPoYV3IodRw9dJ6BFvySw==", payload:"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" } |
Para desencriptar la notificación se deberá seguir el siguiente ejemplo (código en lenguaje java):
public String decryptNotification(String body){ // Convierto el body a un objeto PayloadNotification payloadNotification = JacksonConfigurationProvider.JacksonObjectMapper.get().readValue(body, PayloadNotification.class); String secretKey = payloadNotification.getSecretKey(); String payload = payloadNotification.getPayload(); // Obtengo la llave publica String publicKey = getPublicKey(); // Desencripto la llave simétrica con la llave publica String simetricKey = decryptWithPublicKey(secretKey,publicKey); // Desencripto la notificación con la llave simétrica String notificationDecrypt = decryptSymmetric(payload,simetricKey); return notificationDecrypt; } private String decryptWithPublicKey(String inputStr, String publicKey) { try { PublicKey pKey = getPublicKey(publicKey); Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, pKey); return new String(cipher.doFinal(Base64.getDecoder().decode(inputStr.getBytes()))); } catch (NoSuchAlgorithmException | InvalidKeySpecException | BadPaddingException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | IOException | ArrayIndexOutOfBoundsException e) { //error } } private PublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException { publicKey = publicKey.replaceAll("\\n", "").replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", ""); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKey)); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); return keyFactory.generatePublic(keySpec); } private String decryptSymmetric(String value,String secretKey) { try { Cipher c = Cipher.getInstance("AES"); c.init(Cipher.DECRYPT_MODE, generateSecretKey(secretKey)); return new String(c.doFinal(Base64.getDecoder().decode(value))); } catch(Exception e) { //error } } private Key generateSecretKey(String secKey) { return new SecretKeySpec(secKey.getBytes(), "AES"); } |
Para el ejemplo se usaron los siguientes datos:
Llave simétrica: 5q0++mJ1AJZdzHzSkfV2+VtGg9u9BFmq
Llave publica:
-----BEGIN PUBLIC KEY----- |
Llave privada:
-----BEGIN PRIVATE KEY----- |
Pago de prueba:
{ "type" : "debit", "validation" : false, "review" : false, "id" : "554ecb4a-aec5-439f-b506-9a22215e0746", "external_transaction_id" : "c189ad3d-f5e7-4d33-a92e-09adcb9273ed", "collector_id" : "999", "collector_detail" : { "name" : "PRUEBA" }, "notification_url" : "http://127.0.0.1:9999/notifications", "form_url" : "http://localhost:8180/formularios/v2/pagos/554ecb4a-aec5-439f-b506-9a22215e0746", "details" : [ { "amount" : 1.0, "external_reference" : "123", "concept_id" : "prueba", "concept_description" : "Concepto de prueba" } ], "currency_id" : "ARS", "payment_methods" : [ { "amount" : 1.0, "media_payment_id" : 9, "media_payment_detail" : "VISA CREDIT", "last_four_digits" : "0010", "first_six_digits" : "450799", "installments" : 1, "authorization_code" : "191780", "gateway" : { "establishment_number" : "PRUEBA", "transaction_id" : "4021606", "batch_number" : "1", "ticket_number" : "1533", "ppt_owner" : false }, "payment_method_id" : 0 } ], "final_amount" : 1.0, "status" : "approved", "status_detail" : "APROBADA - Autorizada - MOP GPAY: -1 - Aprobada", "request_date" : "2019-08-06T14:58:25-0300", "due_date" : "2019-08-06T14:58:25-0300", "last_due_date" : "2019-08-06T14:58:25-0300", "process_date" : "2019-08-06T14:58:25-0300", "paid_date" : "2019-08-06T14:58:25-0300", "accreditation_date" : "2019-08-06T14:58:25-0300", "last_update_date" : "2019-08-06T14:58:25-0300", "metadata" : { "parametro_1" : "valor_de_prueba" }, "source" : { "id" : "ee84ca67-5f90-4ca9-b587-37afce6ecc14", "name" : "system-test", "type" : "system" } } |