# Plataforma de pagos
<!--
Version del documento
-->
## Control de Versiones
| Versión | Fecha | Autor | Revisor | Descripción del Cambio |
|--|--|--|--|--|
|1.0|20210407|luis.arismendi / francisco.higuera / Sergio Ñ|Jed Horne|Emisión|
## 1. Introducción
<!--
párrafo corto que explica qué estas proponiendo
-->
La implementación de un Microservicio para el proceso de pago con los servicios de terceros de **MercadoPago**, **Tpaga** y **Billetera Davivienda (wip)**.
## 2. Motivación
<!--
¿qué motiva esta decisión y por qué es importante?
¿Por que construirlo?
el propósito de esta sección es articular de una manera sencilla el valor de la decision que vamos a tomar
-->
* La motivación de implementar este feature como un Microservicio es para su fácil mantenimiento, descentralización, tiempo de despliegue, facilidad de pruebas y facil experimentación, que también podemos reutilizar para otros sistemas o funcionalidades.
* La posibilidad de poder agregar a futuro de manera sencilla otros métodos de pago en el Microservicio, sin afectar las aplicaciones conectadas.
* Mejorar performance y reducción de costos en infraestructura.
* Utilizar Micrositio favorece el desacople en sistemas más pequeños y con responsabilidades específicas, facilitando el matenimiento y la sencillez del sistema.
## 2.1 Lluvia de Ideas
* Crear una plataforma independiente para realizar pagos, que nos permita integrar diversas aplicaciones, no solo el ecommerce. A su vez, también nos permita agregar y switchear pasarelas de pagos fácilmente sin necesidad de cambiar la integración con los clientes.
* Garantizar un buen esquema de seguridad.
* Validar muy bien las integraciones específicas para no tener reprocesos.
* Ideas sobre microservicios:
* **Principios:**
* Modelar entorno a conceptos de negocios.
* Adoptar la cultura de automatización.
* Esconder detalles internos de implementación.
* Descentralizar todas las cosas.
* Despliegue independiente.
* Aislar las fallas.
* Altamente observable.
* **Ventajas:**
* Tecnología Heterogénea.
* Resistencia a fallos.
* Escalabilidad.
* Facilidad de desplegar.
* Alineamiento con la organización, equipos pequeños con códigos pequeños.
* **Desventajas:**
* Distribución: rendimiento y confiabilidad, son elementos que se deben considerar evitando grandes cantidades llamadas de funciones asincrónicamente y ajustando el manejo de fallos.
* Consistencia eventual: se deben emplear mecanismos para detectar antes que ocasione estos problemas.
* Complejidad operacional: al multiplicarse el uso de microservicios aumenta la necesidad de monitoreo de cada uno.
## 3. Propuesta de implementación
<!--
Este es el núcleo de tu propuesta, y su proposito es ayudarte a pensar en la solución. Esto debe ser un wireframe, no un documento perfecto con todos los detalles.
Escribir es pensar https://medium.learningbyshipping.com/writing-is-thinking-an-annotated-twitter-thread-2a75fe07fade
- Usa diagramas para ilustrar tus ideas o flujos.
- Inluye ejemplos de código si estas proponiendo una interfaz o contrato de sistemas nuevo.
- Agrega links con las especificaciones de proyectos.
- Competidores e inspiración de productos.
- Mockups.
El proposito de esta sección se resume en:
"Esta es la dirección en la que los voy a llevar, alguién ve huecos en mi propuesta o tiene comentarios sobre cómo mejorarla?
-->
La siguiente propuesta está dividida en una propuesta para backend y otra propuesta para frontend/mobile.
- Propuesta Frontend: está basada en la creación de un micrositio, el cuál se encarga de abstraer todas las complejidades específicas de las pasarales de pago que tiene configurado el cliente.
- Propuesta mobile: en principio, la idea es hacer uso de webviews y tener una implementación similar a web. Sin embargo, algunas pasarelas piden integrar SDKs específicos en las aplicaciones, y en ese escenario, la aplicación mobile haría consumo directamente de los servicios.
- Propuesta Backend: está basada en arquitectura de microservicios, en la cuál las consideraciones técnicas específicas como lenguaje, protocolo de comunicación, estilos arquitectónicos, frameworks, se pueden consultar en el siguiente documento: [Arquitectura Backend Plataforma de Pagos](/HAvw3iSJSxuMa-x-46PqSA)
En las siguientes secciones se especifican ambas propuestas:
### 3.1 Micrositio para implementación frontend:
Un microsito es un sitio web que extiende o amplía la información y funcionalidades de un sitio web principal. Normalmente un micrositio está vinculado al sitio web principal pero se centra en solo algunos puntos específicos.
En este proyecto en particular el propósito del micrositio es permitir que el frontend haga el llamado al mismo, y éste se encargue del procesamiento del pago según las pasarelas y medios de pago.
El micrositio consiste en dos páginas:
- Una página que puede ser consumida vía iframe o vía redirección que contiene formularios para agregar tarjetas de crédito.
- Una página que funciona vía redirección, la cuál se encarga de procesar los que no son de tarjeta de crédito, como pagos en tiendas específicas del país, transacciones bancarias, etc.
Comunicación de las páginas con la aplicación cliente:
- Vía Iframe:
- Este recibe vía parámetros en la URL, las credenciales públicas de la aplicación y el ambiente que se va a utilizar
- Por seguridad el iframe aplica restricciones de seguridad para el dominio(s) configurados para la aplicación.
- La comunicación entre el iframe y la web se hace utilizando el API postMessage de Javascript.
- Vía página
- Este recibe vía parámetros en la URL, las credenciales públicas de la aplicación, datos del usuario, información del pago entre otros.
- A su vez, se debe enviar el tipo de pago seleccionado por el usuario cuando este no corresponda a pago con tarjeta.
- También se debe especificar dos urls de redirección para cuando el proceso de pago ha concluido en la plataforma, en los que se puede devolver un mensaje de error si hubo un fallo o un mensaje exitoso, en el cuál el pago queda pendiente de validación.
- En el caso de la integración de Android e iOS se debe capturar la redirección de la página y parsear los parámetros.
- **Seguridad**: no se debe tener en cuenta el acceso a la página de respuesta como una confirmación de pagos realizados, el uso de esta es meramente informativo para el usuario. El estado final y real es transmitido vía webhook al servidor.
### 3.1.1 Flujos para cada tipo pasarela de pagos:
#### 3.1.1.1 Flujo agregar tarjeta vía iframe web
| Usuario | Aplicación | Backend | Micrositio | Microservicio |
| --- | --- | --- | --- | --- |
|<sub>**1.** Entra al checkout| | | | | | | |
| |<sub>**2.** Consulta los métodos de pagos disponibles | | | |
| | |<sub>**3.** Llama al servicio **Payment.getAvailableMethods** | | | |
| | | | |<sub>**4.** Consulta métodos de pago disponibles para la aplicación desde la base de datos y retorna los datos.
| | |<sub>**5.** Retorna los métodos de pago al front + credenciales para cargar iframe | | |
| |<sub>**6.** Muestra formulario al usuario con los métodos de pagos disponibles | | | |
|<sub>**7.** Selecciona la opción agregar tarjeta | | | | |
| |<sub>**8.** Utiliza las credenciales para cargar el iframe ej: /add-card-mercadopagos en un modal | | | |
| | | |<sub>**9.** Retorna página de agregar tarjeta de crédito correspondiente a la paserela de pagos seleccionada.| |
| | | |<sub>**10.** Esta página carga los recursos necesarios por la pasarela y abstrae la complejidad de la implementación. Muestra el formulario. | |
| | | |<sub>**11.** Llama al servicio **Payment.getPaymentGatewayKeys** | |
| | | | |<sub>**12.** Retorna las keys necesarias por la pasarela de pagos para realizar la integración | |
|<sub>**13.** Da click en guardar | | | | |
| | | |<sub>**14.** LLama al servicio **Payment.saveCard** | |
| | | | |<sub>**15.** Guarda en la BD la tarjeta |
| | | |<sub>**16.** Utilizando la API postMessage notifica al front que ha guardado y envía tokens. | |
| |<sub>**17.** Cierra el modal y envía la información al backend | | | |
| | |<sub>**18.** Guarda la información de la tarjeta en la base de datos | | |
**Consideraciones:**
**5.** Seguridad: el servicio debe retornar las llaves públicas. Y el id de la aplicación.
**6.** UX: se aconseja que a este punto se realice una carga en segundo plano de dicho iframe para no afectar la experiencia del usuario. Después de guardar una tarjeta se debe realizar de nuevo la carga para no tener datos previamente cargados.
**8.** La url a la que se debe redirigir debe ser devuelta por el microservicio, y debe ser específica para cada método de pago.
**8.** Parámetros adicionales para la url:
* userName
* email
* userId
**16.** Envía la siguiente información:
```json
{
"franchise": "VISA",
"lastDigits": "1111",
"firstDigits": "123456",
"id": "uuid-uuid-uuid-uuidv4"
}
```
#### 3.1.1.2 Flujo agregar tarjeta vía webview apps
| Usuario | Aplicación | Backend | Micrositio | Microservicio |
| --- | --- | --- | --- | --- |
|<sub>**1.** Entra al checkout | | | | | | | |
| |<sub> **2.** Consulta los métodos de pagos disponibles | | | |
| | |<sub> **3.** Llama al servicio **Payment.getAvailableMethods** | | | |
| | | | |<sub> **4.** Consulta métodos de pago disponibles para la aplicación desde la base de datos y retorna los datos.
| | |<sub> **5.** Retorna los métodos de pago al front + credenciales para cargar iframes o redirigir | | |
| |<sub> **6.** muestra formulario al usuario con los métodos de pagos disponibles | | | |
|<sub> **7.** Selecciona la opción agregar tarjeta | | | | |
| |<sub> **8.** Utiliza las credenciales para cargar el webview ej: /add-card-mercadopagos en un modal | | | |
| | | |<sub>**9.** Retorna página de agregar tarjeta de crédito correspondiente a la paserela de pagos seleccionada.| |
| | | |<sub> **10.** Esta página carga los recursos necesarios por la pasarela y abstrae la complejidad de la implementación. Muestra el formulario. | |
| | | |<sub> **11.** Llama al servicio **Payment.getPaymentGatewayKeys** | |
| | | | |<sub> **12.** Retorna las keys necesarias por la pasarela de pagos para realizar la integración | |
|<sub> **13.** Da click en guardar | | | | |
| | | |<sub> **14.** LLama al servicio **Payment.saveCard** | |
| | | | |<sub> **15.** Guarda en la BD la tarjeta |
| | | |<sub> **16.** Realiza redirección a la url especificada en paso **8** y agrega en dicha url un parámetro en la url ?json={data} | |
| |<sub> **17.** Cierra el webview y envía la información al backend | | | |
| | |<sub> **18.** Guarda la información de la tarjeta en la base de datos | | |
**Consideraciones:**
**5.** Seguridad: el servicio debe retornar las llaves públicas. Y el id de la aplicación.
**6.** UX: se aconseja que a este punto se realice una carga en segundo plano de dicho webview para no afectar la experiencia del usuario. Después de guardar una tarjeta se debe realizar de nuevo la carga para no tener datos previamente cargados.
**8.** La url a la que se debe redirigir debe ser devuelta por el microservicio, y debe ser específica para cada método de pago.
**8.** Parámetros adicionales para la url:
* userName
* email
* userId
* redirectUrl = esta URL es importante pues es la que el webview va a estar escuchando para recibir los datos.
**16.** Envía la siguiente información:
```json
{
"franchise": "VISA",
"lastDigits": "1111",
"firstDigits": "123456",
"id": "uuid-uuid-uuid-uuidv4"
}
```
#### 3.1.1.3 Flujo pagar con tarjeta
| Usuario | Aplicación | Backend | Micrositio | Microservicio |
| --- | --- | --- | --- | --- |
|<sub>**1.** Da click en pagar | | | | | | | |
| |<sub> **2.** Envía datos de pago al servidor | | | |
| | |<sub> **3.** Llama al servicio **Payment.charge** | | | |
| | | | |<sub> **4.** Realiza la transacción con la pasarela de pagos
| | |<sub> **5.** Guarda datos de la transacción en la base de datos | | |
#### 3.1.1.4 Flujo pago con redireccionamiento de página
Este flujo aplica para todos los pagos que requieren salir de la aplicación.
Como PSE:
| Usuario | Aplicación | Backend | Micrositio | Microservicio |
| --- | --- | --- | --- | --- |
|<sub>**1.** Entra al checkout | | | | | | | |
| |<sub> **2.** Consulta los métodos de pagos disponibles | | | |
| | |<sub> **3.** Llama al servicio **Payment.getAvailableMethods** | | | |
| | | | |<sub> **4.** Consulta métodos de pago disponibles para la aplicación desde la base de datos y retorna los datos.
| | |<sub> **5.** Retorna los métodos de pago al front + credenciales para cargar iframes o redirigir | | |
| |<sub> **6.** Muestra formulario al usuario con los métodos de pagos disponibles | | | |
|<sub> **7.** Selecciona un método de pago con redirección | | | | |
| |<sub> **8.** Redirecciona a la página para el método de pago elegido /pse | | | |
| | | |<sub>**9.** Retorna página del método de pagos | |
|<sub> **10.** Esta página carga los recursos necesarios por la pasarela y abstrae la complejidad de la implementación. **Muestra el formulario**. | | | | |
| | | |<sub> **11.** Llama al servicio **Payment.getPaymentGatewayKeys** | |
| | | | |<sub> **12.** Retorna las keys necesarias por la pasarela de pagos para realizar la integración | |
|<sub> **13.** Interactúa con el flujo conforme el método de pago | | | | |
| | | |<sub> **14.** LLama al servicio **Payment.charge** | |
| | | | |<sub> **15.** Guarda en la BD la transacción |
| | | |<sub> **16.** Realiza redirección a la url especificada en paso **8** y agrega en dicha url un parámetro en la url ?json={data} | |
| | | | |<sub> **17.** Consume webhook del backend notificando estado final de la transacción |
| | |<sub> **18.** Guarda la información de la transacción en la base de datos | | |
#### 3.1.1.5 Pagos con Tpaga:
| Usuario | Aplicación | Backend | Micrositio | Microservicio |
| --- | --- | --- | --- | --- |
|<sub>**1.** Entra al checkout | | | | | | | |
| |<sub> **2.** Consulta los métodos de pagos disponibles | | | |
| | |<sub> **3.** Llama al servicio **Payment.getAvailableMethods** | | | |
| | | | |<sub> **4.** Consulta métodos de pago disponibles para la aplicación desde la base de datos y retorna los datos.
| | |<sub> **5.** Retorna los métodos de pago al front + credenciales para cargar iframes o redirigir | | |
| |<sub> **6.** Muestra formulario al usuario con los métodos de pagos disponibles | | | |
|<sub> **7.** Selecciona un método de pago con redirección | | | | |
| |<sub> **8.** Redirecciona a la página para el método de pago elegido /tpaga | | | |
| | | |<sub>**9.** Retorna página del método de pagos | |
|<sub> **10.** Esta página carga los recursos necesarios por la pasarela y abstrae la complejidad de la implementación. **Muestra el widget de pago y oprime pagar**. | | | | |
| | | | |<sub> **11.** Recibe la notificación de fin de compra y confirma el pago para reportar la entrega del producto
| | |<sub> **12.** Guarda la información de la transacción en la base de datos | | |
**Consideraciones:**
- **11.** Por medio de un servicio síncrono se recibirá la notificación vía webhook por parte de la billetera de Tpaga informando la finalización del proceso de compra, esto dispara una consulta del estado del pago y se obtendrá de Tpaga Api la confirmación del mismo, por último se reporta la entrega del producto de manera asíncrona.
- **12.** Este paso podría hacerlo microservicio.
#### 3.1.1.6 Flujos de Pago offline: Baloto y Efecty
Este flujo es para los pagos con Baloto y Efecty desde los métodos de pagos ofrecidos por Mercado Pago.
| Usuario | Aplicación | Backend | Micrositio | Microservicio |
| --- | --- | --- | --- | --- |
|<sub>**1.** Entra al checkout
| |<sub>**2.** Consulta los métodos de pagos disponibles
| | |<sub>**3.** Llama al servicio **Payment getAvailableMethods**
| | | | |<sub>**4.** Consulta métodos de pago disponibles para la aplicación incluyendo los métodos de ticket de Mercado Pago y retorna los datos
| | |<sub>**5.** Retorna los métodos de pago al frontend + credenciales para cargar iframes o redirigir
| |<sub>**6.** Muestra formulario al usuario con los métodos de pagos disponibles
|<sub> **7.** Selecciona un método de pago **Baloto/Efecty** para pago en efectivo
| | | |<sub> **8.** Captura los datos para el pago usando la librería MercadoPago.js para más seguridad
| | | | |<sub>**9.** Envía el pago a Mercado Pago
| | | | |<sub>**10.** Guarda la respuesta de Mercado Pago con el estado pendiente hasta que el comprador realice el pago. El ID del cupón de pago es igual al ID de la transacción de Mercado Pago
| | | |<sub>**11.** Muestra el resultado y la información del ticket de pago
#### 3.1.1.7 Flujo de Billetera Davivienda
Pendiente de información del cliente.
### 3.1.2 Micrositio:
Para desarrollar el Micrositio podemos utilizar el Framework **Nuxt.js** en **Vue.js** el cual es simple y poderoso, y se ha utilizado en otros proyectos Frontend en **Mi Águila**.
### 3.2 Implementación Microservicio para Plataformas de Pago
El microservicio es un tipo de arquitectura que tiene como idea principal dividir el software en servicios que sean los más independientes posibles entre ellos distribuidos en diferentes lugares, dichos servicios se comunican con mecanismos ligeros generalmente usando un recurso API basado en HTTP.

Fuente: [Microservicios](https://microservices.io/patterns/microservices.html)
#### 3.2.1 Especificación de microservicios
**Función para listar métodos de pagos en el proceso agregar tarjeta**
```proto3
syntax = "proto3";
service Payment{
rpc getAvailableMethods(AvailableMethodsRequest) returns (AvailableMethodsReply) {}
}
message AvailableMethodsRequest {
string applicationId = 1;
string environment = 2;
}
message AvailableMethodsReply {
repeated Method methods = 1;
}
message Method {
string id = 1;
string name = 2;
string url = 3;
}
```
**Función para generar token en el proceso agregar tarjeta**
```proto3
syntax = "proto3";
service Payment {
rpc getPaymentGatewayKeys(PaymentGatewayKeysRequest) returns (PaymentGatewayKeysReply) {}
}
message PaymentGatewayKeysRequest {
string applicationId = 1;
string environment = 2;
}
message PaymentGatewayKeysReply {
string clientPublic = 1;
string clientSecret = 2;
repeated KeyPair options = 3;
}
message KeyPair {
string key = 1;
string name = 2;
}
```
**Función para guardar tarjeta de crédito en el proceso agregar tarjeta**
```proto3
syntax = "proto3";
service Payment {
rpc saveCard(SaveCardRequest) returns (EmptyResponse) {}
}
message SaveCardRequest {
string id = 1;
string token = 2;
string lastDigits = 3;
string firstDigits = 4;
string userId = 5;
}
message EmptyResponse {
}
```
**Función para procesar pago**
```proto3
syntax = "proto3";
service Payment{
rpc charge(ChargeRequest) returns (ChargeReply) {}
}
message ChargeRequest {
string cardToken = 1;
repeated Item items = 2;
float total = 3;
float subtotal = 4;
float taxes1 = 5;
float taxes2 = 6;
float shippingCost = 7;
string orderId = 8;
repeated Shipment shipments = 9;
Payer payer = 10;
}
message Payer {
string id;
string firstName = 1;
string lastName = 2;
string phone = 3;
Address address = 5;
string identification = 6;
string typeIdentification = 7;
}
message chargeReply {
string transactionId = 1;
float transactionAmount = 2;
enum Status {
APPROVED = 0;
PENDING = 1;
ERROR = 2;
}
Status status = 3;
string message = 4;
}
message Item {
string id = 1;
string name = 2;
float quantity = 6;
float unitPrice = 7;
}
message Shipment {
string id = 1;
string zipCode = 2;
string stateName = 3;
string cityName = 4;
string address1 = 5;
string address2 = 6;
}
```
**Función para procesar pago con redireccionamiento**
```proto3
syntax = "proto3";
service Payment{
rpc charge(ChargeRequest) returns (ChargeReply) {}
}
message ChargeRequest {
string cardToken = 1;
repeated Item items = 2;
float total = 3;
float subtotal = 4;
float taxes1 = 5;
float taxes2 = 6;
float shippingCost = 7;
string orderId = 8;
repeated Shipment shipments = 9;
Payer payer = 10;
}
message Payer {
string id;
string firstName = 1;
string lastName = 2;
string phone = 3;
Address address = 5;
string identification = 6;
string typeIdentification = 7;
}
message chargeReply {
string transactionId = 1;
float transactionAmount = 2;
enum Status {
APPROVED = 0;
PENDING = 1;
ERROR = 2;
}
Status status = 3;
string message = 4;
}
message Item {
string id = 1;
string name = 2;
float quantity = 6;
float unitPrice = 7;
}
message Shipment {
string id = 1;
string zipCode = 2;
string stateName = 3;
string cityName = 4;
string address1 = 5;
string address2 = 6;
}
```
### 3.3 Documentación Tpaga
#### 3.3.1 Glosario:
Los roles que interactúan en la integración con Tpaga son: El comprador, El comercio, El API de Tpaga y la Billetera de Tpaga.
**Billetera Tpaga** es una Aplicación móvil de ingresos y pagos que se encarga de intermediar los cobros que se requiere por parte del comercio.
**Comercio** es la empresa que realiza la integración con la **Billetera Tpaga**.
**Comprador** es el usuario de la Billetera Tpaga que está realizando la compra en el Comercio.
**Tpaga API** es la Interfaces de programación de aplicaciones de Tpaga y sirve para establecer la comunicación entre el sistema del comercio y la Billetera Tpaga.
**Solicitud de pago** es el registro dentro de la Tpaga API que corresponde a una compra en el Comercio. La solicitud de pago contiene la información del valor, la descripción de la compra, el número de orden y otros datos, provistos por el Comercio, y el estado de pago, realizado por el Comprador.
#### 3.3.2 Flujo de pago
El flujo de pago que recomendaría sería donde el cliente no requiera confirmar al comercio que realizo el pago.

Cada petición que el Comercio envía a Tpaga API debe tener el encabezado de la autenticación de acceso básica (Basic Authentication), que es basada en nombre de usuario y contraseña asignados al Comercio por Tpaga y que están codificados en Base64.
Para crear una Solicitud de pago se debe hacer una petición POST a la Tpaga API desde el servidor del comercio, no desde el navegador o webview.
Tpaga ofrece el servicio de realizar una devolución de dinero al Comprador.
Estados para una solicitud de pago:
* Created: Solicitud de pago creada y disponible para pagar.
* Paid: Pagada por el Comprador.
* Failed: El pago no fue exitoso.
* Expired: Solicitud de pago se expiró y no está disponible para pagar.
* Delivered: Los productos comprados fueron entregados.
* Reverted: El dinero fue reembolsado.

**BASE URL:**
`http://stag.wallet.tpaga.co/merchants/api/v1/payment_requests`
**Seguridad:**
UserAuth (HTTP Basic Authentication)
#### 3.3.2.1 El cliente inicia el proceso de pago
Este proceso se inicia desde la web de La14 hacia el Api Gateway.
#### 3.3.2.2 El Api Gateway recibe la petición
El Api Gateway se encarga de redirijir la petición al servicio que corresponda, en este caso Payment Service.
#### 3.3.2.3 Payment Service crea la petición de pago
A continuación se realiza la petición del pago a Tpaga API:
`POST /create`
Request Body:
```
{
"cost": 1,
"expires_at": "2015-01-01T15:00:00.000Z",
"idempotency_token": "somestring",
"merchant_user_id": "somestring",
"miniapp_user_token": "somestring",
"order_id": "somestring",
"purchase_description": "somestring",
"purchase_details_url": "somestring",
"purchase_items": {},
"terminal_id": "somestring",
"user_ip_address": "somestring",
"voucher_url": "somestring"
}
```
Response 201:
```
{
"cancelled_at": "somestring",
"cost": "somestring",
"expires_at": "somestring",
"idempotency_token": "somestring",
"merchant_user_id": "somestring",
"miniapp_user_token": "somestring",
"order_id": "somestring",
"purchase_description": "somestring",
"purchase_details_url": "somestring",
"purchase_items": {},
"status": "created",
"terminal_id": "somestring",
"token": "somestring",
"tpaga_payment_url": "somestring",
"user_ip_address": "somestring",
"voucher_url": "somestring"
}
```
Finalizado este proceso se envía un link al cliente para el siguiente paso.
#### 3.3.2.4 Link de pago en la billetera de Tpaga
En esta parte, el cliente luego de hacer clic en el link recibido se abre la aplicación de pago.

#### 3.3.2.5 Recibimos la notificación de pago por parte de Tpaga Api
Luego de que la Billetera Tpaga solicita el pago a Tpaga Api y esta devuelve la finalización del proceso, se envía una notificación via WebHook a nuestro servicio Payment Service con la confirmación del pago.
Una alternativa a utilizar WebHook seria consultar directamente a Tapa Api como se explica a continuación:
En el momento que el Comprador llegue al Link de finalización de compra el Comercio debe confirmar con la Tpaga API el estado de la Solicitud de pago para determinar si el Comprador pudo pagar o no, antes de decidir entregar el producto.
Para esto, el sistema del Comercio debe hacer una petición al servicio de consulta de estado de pago, especificando el identificador de la solicitud de pago, que obtuvo al momento de la creación (el campo token):
```
curl -X GET \
https://stag.wallet.tpaga.co/merchants/api/v1/payment_requests/pr-3d6a2289193bec5adb5080dc2e91cadeba29b58f06ebbba1aba4c9eb85c6777e76811dcd/info \
-H 'Authorization: Basic bWluaWFwcG1hLW1pbmltYWw6YWJjMTIz' \
-H 'Cache-Control: no-cache' \
-H 'Content-Type: application/json'
```
La Tpaga API devolverá los datos de la solicitud de pago con el estado (status) actualizado:
```
{
"miniapp_user_token": null,
"cost": "12000.0",
"purchase_details_url": "https://example.com/compra/348820",
"voucher_url": "https://example.com/comprobante/348820",
"idempotency_token": "ea0c78c5-e85a-48c4-b7f9-24a9014a2339",
"order_id": "348820",
"terminal_id": "sede_45",
"purchase_description": "Compra en Tienda X",
"purchase_items": [
{
"name": "Aceite de girasol",
"value": "13.390"
},
{
"name": "Arroz X 80g",
"value": "4.190"
}
],
"user_ip_address": "61.1.224.56",
"merchant_user_id": null,
"token": "pr-3d6a2289193bec5adb5080dc2e91cadeba29b58f06ebbba1aba4c9eb85c6777e76811dcd",
"tpaga_payment_url": "https://w.tpaga.co/eyJtIjp7Im8iOiJQUiJ9LCJkIjp7InMiOiJtaW5pbWFsLW1hIiwicHJ0IjoicHItM2Q2YTIyODkxOTNiZWM1YWRiNTA4MGRjMmU5MWNhZGViYTI5YjU4ZjA2ZWJiYmExYWJhNGM5ZWI4NWM2Nzc3ZTc2ODExZGNkIn19",
"status": "paid",
"expires_at": "2018-11-05T15:10:57.549-05:00",
"cancelled_at": null,
"checked_by_merchant_at": "2018-10-22T11:26:16.964-05:00",
"delivery_notification_at": "2018-10-22T11:26:16.980-05:00"
}
```
#### 3.2.2.6 Reportar la entrega del producto
El comercio debe reportar a Tpaga que entrego el producto de manera explicita, de lo contrario será devuelto el dinero a la billetera del cliente.
Esto se hace por medio de un request como el siguiente:
```
curl -X POST \
https://stag.wallet.tpaga.co/merchants/api/v1/payment_requests/confirm_delivery \
-H 'Authorization: Basic bWluaWFwcG1hLW1pbmltYWw6YWJjMTIz' \
-H 'Cache-Control: no-cache' \
-H 'Content-Type: application/json' \
-d '{
"payment_request_token":"pr-3d6a2289193bec5adb5080dc2e91cadeba29b58f06ebbba1aba4c9eb85c6777e76811dcd"
}'
```
La Tpaga API devuelve los datos de la solicitud de pago con el estado (status) actualizado:
```
{
"miniapp_user_token": null,
"cost": "12000.0",
"purchase_details_url": "https://example.com/compra/348820",
"voucher_url": "https://example.com/comprobante/348820",
"idempotency_token": "ea0c78c5-e85a-48c4-b7f9-24a9014a2339",
"order_id": "348820",
"terminal_id": "sede_45",
"purchase_description": "Compra en Tienda X",
"purchase_items": [
{
"name": "Aceite de girasol",
"value": "13.390"
},
{
"name": "Arroz X 80g",
"value": "4.190"
}
],
"user_ip_address": "61.1.224.56",
"merchant_user_id": null,
"token": "pr-3d6a2289193bec5adb5080dc2e91cadeba29b58f06ebbba1aba4c9eb85c6777e76811dcd",
"tpaga_payment_url": "https://w.tpaga.co/eyJtIjp7Im8iOiJQUiJ9LCJkIjp7InMiOiJtaW5pbWFsLW1hIiwicHJ0IjoicHItM2Q2YTIyODkxOTNiZWM1YWRiNTA4MGRjMmU5MWNhZGViYTI5YjU4ZjA2ZWJiYmExYWJhNGM5ZWI4NWM2Nzc3ZTc2ODExZGNkIn19",
"status": "delivered",
"expires_at": "2018-11-05T15:10:57.549-05:00",
"cancelled_at": null,
"checked_by_merchant_at": "2018-10-22T11:26:16.964-05:00",
"delivery_notification_at": "2018-10-22T11:29:36.017-05:00"
}
```
#### 3.3.2.7 Revertir el pago.
Por último, un flujo alternativo al camino feliz sería si se necesita cancelar la compra, para esto Tpaga ofrece el servicio de realizar una devolución de dinero al Comprador.
Para solicitar una devolución se debe enviar una petición a la Tpaga API con el identificador de la solicitud de pago, cuyo valor hay que reembolsar:
```
curl -X POST \
https://stag.wallet.tpaga.co/merchants/api/v1/payment_requests/refund \
-H 'Authorization: Basic bWluaWFwcG1hLW1pbmltYWw6YWJjMTIz' \
-H 'Cache-Control: no-cache' \
-H 'Content-Type: application/json' \
-d '{
"payment_request_token":"pr-3d6a2289193bec5adb5080dc2e91cadeba29b58f06ebbba1aba4c9eb85c6777e76811dcd"
}'
```
La Tpaga API devuelve los datos de la solicitud de pago con el estado (status) actualizado:
```
{
"miniapp_user_token": null,
"cost": "12000.0",
"purchase_details_url": "https://example.com/compra/348820",
"voucher_url": "https://example.com/comprobante/348820",
"idempotency_token": "ea0c78c5-e85a-48c4-b7f9-24a9014a2339",
"order_id": "348820",
"terminal_id": "sede_45",
"purchase_description": "Compra en Tienda X",
"purchase_items": [
{
"name": "Aceite de girasol",
"value": "13.390"
},
{
"name": "Arroz X 80g",
"value": "4.190"
}
],
"user_ip_address": "61.1.224.56",
"merchant_user_id": null,
"token": "pr-3d6a2289193bec5adb5080dc2e91cadeba29b58f06ebbba1aba4c9eb85c6777e76811dcd",
"tpaga_payment_url": "https://w.tpaga.co/eyJtIjp7Im8iOiJQUiJ9LCJkIjp7InMiOiJtaW5pbWFsLW1hIiwicHJ0IjoicHItM2Q2YTIyODkxOTNiZWM1YWRiNTA4MGRjMmU5MWNhZGViYTI5YjU4ZjA2ZWJiYmExYWJhNGM5ZWI4NWM2Nzc3ZTc2ODExZGNkIn19",
"status": "reverted",
"expires_at": "2018-11-05T15:10:57.549-05:00",
"cancelled_at": null,
"checked_by_merchant_at": "2018-10-22T11:26:16.964-05:00",
"delivery_notification_at": "2018-10-22T11:29:36.017-05:00"
}
```
### 3.4. Documentación Mercadopago:
[Documentación Online](https://www.mercadopago.com.co/developers/es/guides)
#### 3.4.1. Integración Checkout API:
Los Tipos de integración de mercadopago son: Checkout Pro y Checkout API. Checkout Pro es la integración que permite cobrar a través de un formulario web predeterminado de mercadopago que se puede llamar desde cualquier dispositivo de manera simple, rápida y segura. Sin embargo para efectos de esta propuesta se utilizará Checkout API, que consiste en la interacción de las APIS de mercadopago lo cual permite un control total del proceso de pago.
* Requisitos:
- Acceder a una cuenta:
Para poder comenzar la integración, es necesario contar con una cuenta de Mercado Pago o Mercado Libre.
- Credenciales
Las credenciales son las claves que se proporcionan para poder configurar la integración.
* Referencias APIs:
https://www.mercadopago.com.co/developers/es/reference
¿Cómo Funciona?

Al usar Checkout API de Mercado Pago, es importante tener en cuenta dos instancias: la de la captura de datos y la del envío de confirmación del pago.
1. Primero, es necesario un frontend para que recolecte los datos de la tarjeta y que genere un token de seguridad con la información para poder crear el pago.
2. Segundo, un backend que tome el token generado y los datos del pago, como por ejemplo monto e ítem, pueda confirmar y efectuar el pago.
#### 3.4.1.1. Integración Pagos con Tarjeta:
**Captura de los datos:**
**a. Incluir librería MercdoPago.js:**
Se debe utilizar la librería oficial de API de MercadoPago desde la aplicación para recolectar los datos de forma segura:
```
<script src="https://secure.mlstatic.com/sdk/javascript/v1/mercadopago.js"></script>
```
La información de la tarjeta se convierte en un token para enviar los datos a los servidores en modo seguro.
**b. Agregar el formulario de pago:**
Para realizar la captura de datos sensibles de las tarjetas de los clientes, es muy importante utilizar formulario de ejemplo de mercado pago con los atributos correspondientes para garantizar la seguridad de la información y la correcta generación del token. Por ejemplo, se debe respetar los atributos data-checkout y no colocar el atributo name en los campos que tienen datos sensibles, de esta forma nunca llegarán a los servidores.
Se puede agregar todo lo que se necesita, modificar el atributo label sugerido y sumarle estilo personalizado sin problemas.
En el siguiente ejemplo se asume que los datos transactionAmount y description se obtuvieron en el paso previo donde el cliente seleccionó el producto o servicio que desea pagar.
```
<form action="/process_payment" method="post" id="paymentForm">
<h3>Detalles del comprador</h3>
<div>
<div>
<label for="email">E-mail</label>
<input id="email" name="email" type="text" value="test@test.com"/>
</div>
<div>
<label for="docType">Tipo de documento</label>
<select id="docType" name="docType" data-checkout="docType" type="text"></select>
</div>
<div>
<label for="docNumber">Número de documento</label>
<input id="docNumber" name="docNumber" data-checkout="docNumber" type="text"/>
</div>
</div>
<h3>Detalles de la tarjeta</h3>
<div>
<div>
<label for="cardholderName">Titular de la tarjeta</label>
<input id="cardholderName" data-checkout="cardholderName" type="text">
</div>
<div>
<label for="">Fecha de vencimiento</label>
<div>
<input type="text" placeholder="MM" id="cardExpirationMonth" data-checkout="cardExpirationMonth"
onselectstart="return false" onpaste="return false"
oncopy="return false" oncut="return false"
ondrag="return false" ondrop="return false" autocomplete=off>
<span class="date-separator">/</span>
<input type="text" placeholder="YY" id="cardExpirationYear" data-checkout="cardExpirationYear"
onselectstart="return false" onpaste="return false"
oncopy="return false" oncut="return false"
ondrag="return false" ondrop="return false" autocomplete=off>
</div>
</div>
<div>
<label for="cardNumber">Número de la tarjeta</label>
<input type="text" id="cardNumber" data-checkout="cardNumber"
onselectstart="return false" onpaste="return false"
oncopy="return false" oncut="return false"
ondrag="return false" ondrop="return false" autocomplete=off>
</div>
<div>
<label for="securityCode">Código de seguridad</label>
<input id="securityCode" data-checkout="securityCode" type="text"
onselectstart="return false" onpaste="return false"
oncopy="return false" oncut="return false"
ondrag="return false" ondrop="return false" autocomplete=off>
</div>
<div id="issuerInput">
<label for="issuer">Banco emisor</label>
<select id="issuer" name="issuer" data-checkout="issuer"></select>
</div>
<div>
<label for="installments">Cuotas</label>
<select type="text" id="installments" name="installments"></select>
</div>
<div>
<input type="hidden" name="transactionAmount" id="transactionAmount" value="100" />
<input type="hidden" name="paymentMethodId" id="paymentMethodId" />
<input type="hidden" name="description" id="description" />
<br>
<button type="submit">Pagar</button>
<br>
</div>
</div>
</form>
```
**c. Configurar Clave Pública:**
Incluir la [clave pública](https://www.mercadopago.com.co/developers/panel/credentials) de la siguiente manera:
```
window.Mercadopago.setPublishableKey("YOUR_PUBLIC_KEY");
```
**d. Obtener los datos para formulario:**
**Obtener tipos de documentos:**
Uno de los campos obligatorios es el tipo de número de documento. Se utiliza la lista de documentos al momento de completar los datos.
Incluyendo el elemento de tipo select con id = docType que se encuentra en el formulario, MercadoPago.js completará automáticamente las opciones disponibles cuando se llame a la siguiente función:
```
window.Mercadopago.getIdentificationTypes();
```
Más detalle en la sección de [Tipos de documentos](https://www.mercadopago.com.co/developers/es/guides/resources/localization/identification-types).
**Obtener Método de Pago de la tarjeta:**
Se Valida los datos de los clientes mientras los completan para evitar errores y ofrecer correctamente las cuotas disponibles. Se debe usar el siguiente código de ejemplo para identificar el medio de pago con los primeros 6 dígitos de la tarjeta.
```
document.getElementById('cardNumber').addEventListener('change', guessPaymentMethod);
function guessPaymentMethod(event) {
let cardnumber = document.getElementById("cardNumber").value;
if (cardnumber.length >= 6) {
let bin = cardnumber.substring(0,6);
window.Mercadopago.getPaymentMethod({
"bin": bin
}, setPaymentMethod);
}
};
function setPaymentMethod(status, response) {
if (status == 200) {
let paymentMethod = response[0];
document.getElementById('paymentMethodId').value = paymentMethod.id;
getIssuers(paymentMethod.id);
} else {
alert(`payment method info error: ${response}`);
}
}
```
**Obtener banco emisor:**
Al completar los datos, es importante identificar el banco emisor de la tarjeta para evitar conflictos entre los distintos emisores y poder ofrecer las opciones de pago en cuotas correctas.
Se debe agregar el siguiente código para obtener el issuer_id:
```
function getIssuers(paymentMethodId) {
window.Mercadopago.getIssuers(
paymentMethodId,
setIssuers
);
}
function setIssuers(status, response) {
if (status == 200) {
let issuerSelect = document.getElementById('issuer');
response.forEach( issuer => {
let opt = document.createElement('option');
opt.text = issuer.name;
opt.value = issuer.id;
issuerSelect.appendChild(opt);
});
getInstallments(
document.getElementById('paymentMethodId').value,
document.getElementById('transactionAmount').value,
issuerSelect.value
);
} else {
alert(`issuers method info error: ${response}`);
}
}
```
**Obtener cantidad de cuotas:**
Otro de los campos obligatorios para pagos con tarjetas es la cantidad de cuotas. Para obtener las cuotas disponibles, se puede utilizar la siguiente función de ejemplo para completar el campo sugerido de tipo select denominado installments.
```
function getInstallments(paymentMethodId, transactionAmount, issuerId){
window.Mercadopago.getInstallments({
"payment_method_id": paymentMethodId,
"amount": parseFloat(transactionAmount),
"issuer_id": parseInt(issuerId)
}, setInstallments);
}
function setInstallments(status, response){
if (status == 200) {
document.getElementById('installments').options.length = 0;
response[0].payer_costs.forEach( payerCost => {
let opt = document.createElement('option');
opt.text = payerCost.recommended_message;
opt.value = payerCost.installments;
document.getElementById('installments').appendChild(opt);
});
} else {
alert(`installments method info error: ${response}`);
}
}
```
**e. Crea el token de la tarjeta:**
Antes de enviar el pago, se debe crear el token que contendrá de manera segura toda la información de la tarjeta. Se tiene que generar de la siguiente manera:
```
doSubmit = false;
document.getElementById('paymentForm').addEventListener('submit', getCardToken);
function getCardToken(event){
event.preventDefault();
if(!doSubmit){
let $form = document.getElementById('paymentForm');
window.Mercadopago.createToken($form, setCardTokenAndPay);
return false;
}
};
function setCardTokenAndPay(status, response) {
if (status == 200 || status == 201) {
let form = document.getElementById('paymentForm');
let card = document.createElement('input');
card.setAttribute('name', 'token');
card.setAttribute('type', 'hidden');
card.setAttribute('value', response.id);
form.appendChild(card);
doSubmit=true;
form.submit();
} else {
alert("Verify filled data!\n"+JSON.stringify(response, null, 4));
}
};
```
El método createToken devolverá un card_token con la representación segura de la tarjeta. El segundo campo del método createToken es la función de callback que procesará la respuesta (en este caso usamos la función setCardTokenAndPay). Allí se tomará el ID de la respuesta y se guarda en un atributo oculto que se llamará token, para luego enviar el formulario a los servidores.
**Importante:**
Se debe tener en cuenta que el token tiene una validez de 7 días y solo se puede usar una vez.
**Enviar el pago a Mercado Pago**
El backend debe contar con un endpoint para recibir la respuesta, para elo ejemplo se cuenta con el endpoint /process_payment, definido en el atributo action del formulario, para recibir allí todos los datos luego de realizar la acción submit.
Ya estando en el backend toda la información recolectada, es momento de enviar la solicitud a Mercado Pago a través de las APIs. Los campos mínimos requeridos a enviar son: token, transaction_amount, installments, payment_method_id y el payer.email.
Nota: Configurar la clave privada y que para interactuar con las APIs de mercado pago.
Se puede encontrar el estado del pago en el valor status.
```
curl -X POST \
-H 'accept: application/json' \
-H 'content-type: application/json' \
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
'https://api.mercadopago.com/v1/payments' \
-d '{
"transaction_amount": 100,
"token": "ff8080814c11e237014c1ff593b57b4d",
"description": "Blue shirt",
"installments": 1,
"payment_method_id": "visa",
"issuer_id": 310,
"payer": {
"email": "test@test.com"
}
}'
```
Respuesta
```
{
"status": "approved",
"status_detail": "accredited",
"id": 3055677,
"date_approved": "2019-02-23T00:01:10.000-04:00",
"payer": {
...
},
"payment_method_id": "visa",
"payment_type_id": "credit_card",
"refunds": [],
...
}
```
Todos los campos disponibles para realizar un pago completo se encuentran e [Referencias de API](https://www.mercadopago.com.co/developers/es/reference/payments/_payments/post).
**Mensajes de respuestas**

Para ayudar a mejorar la aprobación de los pagos, es fundamental que se pueda comunicar correctamente a los clientes los resultados al realizar o crear un pago.
[Recomendaciones para mejorar la aprobación de los pagos](https://www.mercadopago.com.co/developers/es/guides/manage-account/account/payment-rejections).
**Recibir notificaciones de pago**
Es importante que estar siempre informado sobre la creación de nuevos pagos y las actualizaciones de sus estados. Por ejemplo si fueron aprobados, rechazados o si se encuentran pendientes.
[Configuración notificaciones webhooks](https://www.mercadopago.com.co/developers/es/guides/notifications/webhooks) o [notificaciones IPN](https://www.mercadopago.com.co/developers/es/guides/notifications/ipn).
**Ejemplos descargables:**
[Ejemplos completos de integración](http://github.com/mercadopago/card-payment-sample)
[Ejemplos completo de formulario de pago](https://github.com/mercadopago/card-payment-sample/tree/master/client)
#### 3.4.1.2. Integración de otros medios de pago
Con el Checkout API de Mercado Pago se pueden sumar otras alternativas de medios de pago para ofrecer a los clientes a la hora de realizar el pago.
Para recibir otros medios de pago, tienes que tener en cuenta dos instancias:
1. Primero, es necesario un frontend para que recolecte el e-mail y documento de tu cliente y el método de pago y detalle del monto.
2. Segundo, un backend que tome los datos del pago y pueda confirmar y efectuar el pago.
Tanto para el frontend como para el backend, Mercado Pago provee librerías para poder recolectar los datos sensibles de los usuarios de manera segura.
Además de tarjetas, también existen otras opciones de pago que se pueden ofrecer en el sitio.
| Tipo de medio de pago | Medio de pago |
| -------- | -------- |
| ticket | Efecty |
| ticket | Baloto |
| bank_transfer | Efecty |
**Obtener los medios de pago disponibles:**
Se puede consultar los medios de pago disponibles siempre que se necesite con:
```
curl -X GET \
-H 'accept: application/json' \
-H 'content-type: application/json' \
-H 'Authorization: Bearer ENV_ACCESS_TOKEN' \
'https://api.mercadopago.com/v1/payment_methods' \
```
El resultado será un listado con los medios de pago y sus propiedades. Por ejemplo, los medios de pago del payment_type_id que tienen como valor ticket refieren a medio de pago en efectivo.
La respuesta devolverá todos los medios de pago. Por eso, se puede filtrar los medios que se desee ofrecer según la lista de medios de pago disponibles.
```
[
{
"id": "efecty",
"name": "Efecty",
"payment_type_id": "ticket",
"status": "active",
"secure_thumbnail": "https://www.mercadopago.com/org-img/MP3/API/logos/efecty.gif",
"thumbnail": "http://img.mlstatic.com/org-img/MP3/API/logos/efecty.gif",
"deferred_capture": "does_not_apply",
"settings": [],
"additional_info_needed": [],
"min_allowed_amount": 5000,
"max_allowed_amount": 4000000,
"accreditation_time": 0,
"financial_institutions": [],
"processing_modes": [
"aggregator"
]
},
{
"id": "baloto",
"name": "Baloto",
"payment_type_id": "ticket",
"status": "active",
"secure_thumbnail": "https://www.mercadopago.com/org-img/MP3/API/logos/baloto.gif",
"thumbnail": "http://img.mlstatic.com/org-img/MP3/API/logos/baloto.gif",
"deferred_capture": "supported",
"settings": [],
"additional_info_needed": [],
"min_allowed_amount": 1500,
"max_allowed_amount": 1000000,
"accreditation_time": 0,
"financial_institutions": [],
"processing_modes": [
"aggregator"
]
},
{
"id": "pse",
"name": "PSE",
"payment_type_id": "bank_transfer",
"status": "active",
"secure_thumbnail": "https://www.mercadopago.com/org-img/MP3/API/logos/pse.gif",
"thumbnail": "http://img.mlstatic.com/org-img/MP3/API/logos/pse.gif",
"deferred_capture": "does_not_apply",
"settings": [],
"additional_info_needed": [
"entity_type"
],
"min_allowed_amount": 1600,
"max_allowed_amount": 30000000,
"accreditation_time": 30,
"financial_institutions": [
…,
],
"processing_modes": [
"aggregator"
]
}
]
```
Puedes obtener más información en la [Referencias de API](https://www.mercadopago.com.co/developers/es/reference).
**Capturar los datos para el pago:**
**Integrar Checkout API con MercadoPago.js V2:**
**a. Usar la librería MercadoPago.js:**
Utilizar la librería oficial para acceder a la API de Mercado Pago desde la aplicación y recolectar los datos de forma segura.
```
<script src="https://secure.mlstatic.com/sdk/javascript/v1/mercadopago.js"></script>
```
**b. Agrega el formulario de pago:**
Para realizar la captura de datos sensibles de los clientes, es muy importante que se utilice formulario con los atributos correspondientes para garantizar la seguridad de la información según ejemplo.
Se puedes agregar todo lo que se necesite y sumarle el estilo que se desee sin problemas.
Se debe utilizar la lista que se consultó de medios de pago disponibles para crear las opciones de pagos que se quiera ofrecer.
```
<form action="/process_payment" method="post" id="paymentForm">
<h3>Medio de pago</h3>
<div>
<select class="form-control" id="paymentMethod" name="paymentMethod">
<option>Seleccione un medio de pago</option>
<!-- Create an option for each payment method with their name and complete the ID in the attribute 'value'. -->
<option value="--PaymentTypeId--">--PaymentTypeName--</option>
</select>
</div>
<h3>Detalles del comprador</h3>
<div>
<div>
<label for="payerFirstName">Nombre</label>
<input id="payerFirstName" name="payerFirstName" type="text" value="Nome"></select>
</div>
<div>
<label for="payerLastName">Apellido</label>
<input id="payerLastName" name="payerLastName" type="text" value="Sobrenome"></select>
</div>
<div>
<label for="payerEmail">E-mail</label>
<input id="payerEmail" name="payerEmail" type="text" value="test@test.com"></select>
</div>
<div>
<label for="docType">Tipo de documento</label>
<select id="docType" name="docType" data-checkout="docType" type="text"></select>
</div>
<div>
<label for="docNumber">Número de documento</label>
<input id="docNumber" name="docNumber" data-checkout="docNumber" type="text"/>
</div>
</div>
<div>
<div>
<input type="hidden" name="transactionAmount" id="transactionAmount" value="100" />
<input type="hidden" name="productDescription" id="productDescription" value="Nombre del Producto" />
<br>
<button type="submit">Pagar</button>
<br>
</div>
</div>
</form>
```
**c. Configurar clave pública:**
Agrega tu clave pública de la siguiente manera:
```
window.Mercadopago.setPublishableKey("YOUR_PUBLIC_KEY");
```
Si aún no tienes cuenta para ver tus credenciales, regístrate.
**d. Obtén los datos para tu formulario:**
**Obtener tipos de documentos**
Uno de los campos obligatorios es el tipo de número de documento. Utiliza la lista de documentos al momento de completar los datos.
Incluyendo el elemento de tipo select con id = docType que se encuentra en el formulario, MercadoPago.js completará automáticamente las opciones disponibles cuando llames a la siguiente función:
```
window.Mercadopago.getIdentificationTypes();
```
Más detalle en la sección de [Tipos de documentos](https://www.mercadopago.com.co/developers/es/guides/resources/localization/identification-types).
**Envía el pago a Mercado Pago**
Para recibir pagos en efectivo se debe enviar el e-mail y documento del cliente y el método de pago y detalle del monto.
En el backend con toda la información recolectada, es momento de enviar la solicitud a Mercado Pago a través de las APIs.
Se debe configurar la clave privada.
```
curl -X POST \
'https://api.mercadopago.com/v1/payments' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer ENV_ACCESS_TOKEN' \
-d '{
transaction_amount: 5000,
description: "Título del producto",
payment_method_id: "efecty",
payer: { email: "test_user_19549678@testuser.com" }
}'
```
La respuesta va a mostrar el estado pendiente hasta que el comprador realice el pago. El ID del cupón de pago es igual al ID de la transacción de Mercado Pago.
```
[
{
...,
"id": 5466310457,
"status": "pending",
"status_detail": "pending_waiting_payment",
...,
"transaction_details": {
"payment_method_reference_id": "24308386",
"verification_code": "24308386",
"net_received_amount": 0,
"total_paid_amount": 5000,
"overpaid_amount": 0,
"external_resource_url": "https://www.mercadopago.com/mco/payments/sandbox/ticket/helper?payment_id=1234&payment_method_reference_id=12345678&caller_id=1234&hash=aaaaaa-bbb-cccc-dddd-eeeeeeee",
"installment_amount": 0,
"financial_institution": "",
"payable_deferral_period": null,
"acquirer_reference": null
}
}
]
```
En el campo external_resource_url se va encontrar una dirección que contiene las instrucciones para que el comprador pueda pagar.
Se puede redirigirlo o enviarle el enlace para que ingrese.
**Nota:**
El cliente tiene entre 3 a 5 días para pagar según el medio de pago. Luego de este tiempo, debes cancelarlo.
**Fecha de vencimiento para pagos en efectivo:**
Se puede cambiar la fecha de vencimiento por defecto de un pago en efectivo enviando el campo date_of_expiration en la solicitud de creación de pago. La fecha configurada debe ser entre 1 y 30 días a partir de la fecha de emisión.
La fecha usa el formato ISO 8601: yyyy-MM-dd'T'HH:mm:ssz
```
"date_of_expiration": "2020-05-30T23:59:59.000-04:00",
```
El período de acreditación es de 1 y 2 días hábiles según el medio de pago. Por lo tanto, se recomienda establecer la fecha de vencimiento con al menos 3 días para asegurarse de que se realice el pago.
Mas detalles [tiempos de acreditación por medio de pago](https://www.mercadopago.com.co/ayuda/Medios-de-pago-y-acreditaci-n_221) para realizar la configuración.
**Importante:**
Si el pago se realiza después de la fecha de vencimiento, el monto se devolverá a la cuenta de Mercado Pago del pagador.
**Recibir pagos con PSE:**
Para poder recibir pagos con PSE, también tienes que enviar la institución financiera que procesa el pago.
```
curl -X POST \
'https://api.mercadopago.com/v1/payments' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer _ACCESS_TOKEN' \
-d '{
transaction_amount: 5000,
description: "Título del producto",
payment_method_id: "pse",
payer: { email: "test_user_19549678@testuser.com" },
transaction_details: { financial_institution: 1234 }
}'
```
La respuesta va a mostrar el estado pendiente hasta que el comprador realice el pago.
```
[
{
...,
"status": "pending",
"status_detail": "pending_waiting_transfer"
...,
"transaction_details": {
...,
"external_resource_url": "https://www.mercadopago.com/mco/payments/bank_transfer/sandbox/helper/commerce?id=3692089&caller_id=1234&hash=aaaaaa-bbb-cccc-dddd-eeeeeeee",
"installment_amount": 0,
"financial_institution": "1234",
"payment_method_reference_id": null
}
}
]
```
En el campo external_resource_url vas a encontrar una dirección que contiene las instrucciones para que tu comprador pueda pagar. Puedes redirigirlo o enviarle el enlace para que ingrese.
Al finalizar el pago, el cliente va a ser redirigido a la callback_url que indiques.
**Cancelar un pago:**
Es importante que se pueda cancelar los pagos luego de su vencimiento para evitar problemas con el cobro. Los pagos de medios en efectivo deben ser pagados entre los 3 a 5 días hábiles según el tiempo de cada uno.
Solo se puede cancelar los pagos que se encuentren en estado pendiente o en proceso. Si la expiración de un pago se produce a los 30 días, la cancelación es automática y el estado final será de cancelado o expirado.
Puedes encontrar toda la información en la sección Devoluciones y cancelaciones.
Tiempos de acreditación del pago
Cada medio de pago tiene su propia fecha de acreditación, en algunos casos es inmediata y en otros puede demorar hasta 3 días hábiles.
Revisa los tiempos de acreditación por medio de pago siempre que lo necesites.
## 4. Métricas
<!--
Que métricas debemos vamos a instrumentar, o monitorear para observar las implicaciónes de esta decisiòn?
Por ejemplo, cuando interactuamos con un sistema externo que tipo de latencia esperariamos o si agregamos una tabla nueva que tan rápido se llenaría?
-->
* Velocidad de la transacción.
* Performance.
* Número de peticiones.
## 5. Riesgos e inconvenientes
<!--
¿Hay razones por las que no deberiamos hacer esto?
¿Qué riesgos estamos tomando? Por ejemplo, no tenemos experiencia con esta tecnología nueva o no entendemos la escala aún.
-->
Para la implementación de las plataformas de pagos a pesar de poseer gran cantidad de documentación se debe tomar en cuenta la curva de aprendizaje de dichos documentos, lo que debe considerarse en el tiempo de ejecución.
Se debería analizar la propuesta desde varios puntos de vista, empezando con los servicios de terceros que vamos a incluir por parte de Ingeniería, así como a nivel de infraestructura la implementación de eventos como cambios de estados del pago por medio del un webhook, entre otros.
## 6. Alternativas
<!--
¿Hay otras formas de resolver éste problema?
-->
- Sobre microservicios: La alternativa que se tiene es desarrollar este feature en OrdersApi, la desventaja es una implementación monolítica como la que tenemos actualmente.
- Sobre micrositio: Implicaría que cada ecommerce a nivel de ramas o de configuración tuviera una integración de cada pasarela de pagos.
- Sobre iframe en mobile: en el caso de mobile es la integración más práctica y nos ayudaría a no tener dentro de las apps, sdks pesados de la pasarela de pagos que se vaya a usar. Sin embargo, por restricciones de seguridad en dicho caso habría que hacer uso de los sdks que estos proveen. En el caso de mercado pagos, ellos proveen un sdk que hace todo por debajo.
- En cuanto a la integración con Tpaga, tenemos la alternativa de síncrona de finalización del proceso de pago del usuario en vez de la selecciona con webhook para recibirla asíncronamente.
## 7. Impacto potencial y dependencias
<!--
¿Qué otros sistemas se verán afectados con esta propuesta?
¿Qué consideraciones de seguridad debemos tener?¿Como pueden explotar esta parte del sistema?
¿Que impacto tiene esta decision sobre soporte al cliente?
Aquí buscamos ser concientes del ambiente en el que operamos y generar empatía hacia otros que pueden verse afectados por nuestra decisión.
-->
* El checking de las ordenes.
* Siempre hay implicaciones de seguridad.
## 8. Preguntas sin resolver
<!--
¿ Qué preguntas no hemos resuelto?
-->
## 9. Ideas futuras
<!--
¿ Qué preguntas no hemos resuelto?
-->
- Integrar OpenPay
- Integrar Kushki
## 10. Conclusión
Incorporar las funcionalidades para procesar plataformas de pagos a través de Microservicios, trae como beneficio mayor escalabilidad y modulos independientes, facilitando el tiempo de despliegue así como la rapidez del desarrollo de la aplicación.
Se pueden tener equipos de trabajo mínimo gracias al desarrollo modular.
Igualmente este proceso permitirá la flexibilidad de incorporar nuevos medios de pagos y nuevas pasarelas de pagos, consolidando nuevas implementaciones en un solo servicio.
## 11. Estimaciones:
- Hacer como un listado de tareas de implementar esta propuesta:
| Tarea | Puntos | Equipo |
| --- | --- | --- |
| Configurar EKS | 8 | Infra
| Configurar CI microservicios | 5 | Infra
| Configurar CI micrositio | 5 | Infra
| Configurar Kubernetes | 13 | Backend - Microservicios
| Configurar Linkerd | 5 | Backend - Microservicios
| Configurar gRPC | 5 | Backend - Microservicios
| Crear repo de Microservicios | 3 | Backend - Microservicios
| Crear el modelo datos | 5 | Backend - Microservicios
| Crear las migraciones de datos | 3 | Backend - Microservicios
| Crear el servicio Payment.getAvailableMethods | 5 | Backend - Microservicios
| Crear el servicio Payment.getPaymentGatewayKeys | 5 | Backend - Microservicios
| Crear el servicio Payment.charge | 13 | Backend - Microservicios
| Crear el servicio Payment.saveCard | 8 | Backend - Microservicios
| Crear el servicio Payment.webhook | 5 | Backend - Microservicios
| Ajustar Emails con pagos tpaga, baloto, efecty | 5 | Backend - OrdersApi
| Integración con Microservicios | 8 | Backend - OrdersApi
| Ajuste endpoints orders api para La14 y microservicios | 3 | Backend - OrdersApi
| Crear repo de Micrositio | 3 | Frontend - Micrositio
| Construir página de pago con PSE | 8 | Frontend - Micrositio
| Construir página de agregar tarjeta de credito | 8 | Frontend - Micrositio
| Ajustar lógica de tarjeta de credito | 5 | Frontend - Ecommerce
| Ajustar lógica de métodos de pago | 5 | Frontend - Ecommerce
| Integrar SDK device session id | 3 | Mobile
| Ajustar lógica de tarjeta de crédito | 5 | Mobile
| Ajustar lógica de métodos de pago | 5 | Mobile
| **Total** (2 weeks 1 engineer) | 18 | Infra
| **Total** (4 weeks 2 senior engineer) | 86 | Backend
| **Total** (3 weeks 2 senior engineer) | 29 | Frontend
| **Total** (2 weeks 1 ios engineer + 1 android engineer) *Puede subirse a 3 semanas si mercadopagos nos obliga a utilizar el SDK en la integración custom y no el iframe| 13* | Mobile
En Total tenemos **4 semanas de desarrollo**.
Adicional a esto sumamos **1 semana de QA** para probar todos los métodos de pago.
Esta estimación No incluye la integración de billetera davivienda pues a la fecha no hemos recibido documentación. Pero consideramos no debería