Integración de Kotlin con Pasarela de Pago PayPal
Tags: kotlin, java, springboot, paypal
Published: 2023-10-21 20:31:55

## 1. Introducción
Hola amigos! En esta publicación, te mostraré cómo puedes integrar Kotlin en el lado backend con PayPal. La integración de PayPal en la parte trasera de tu aplicación Kotlin puede resultar extremadamente beneficiosa para procesar pagos y transacciones en línea.

Las transacciones de pago en un sitio web de comercio electrónico son cruciales para su funcionamiento, y PayPal es ampliamente reconocida como una de las pasarelas de pago en línea más populares y fiables en todo el mundo. Permite a los clientes adquirir productos o servicios utilizando tarjetas de crédito/débito o su saldo de PayPal.

Además, PayPal proporciona un Software Development Kit (SDK) que simplifica la tarea de integrar su solución de pago en un sitio web.

En este artículo, aprenderemos cómo integrar la API de PayPal Checkout con un backend desarrollado en Kotlin.

## 2. Entender el flujo de trabajo típico del proceso de pago
Para comprender mejor el proceso de pago en un sitio web de comercio electrónico, echemos un vistazo al siguiente diagrama:

![_**Figura #1: Proceso típico de un pago en un sitio web de comercio electrónico**_](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oex36130b241oio3we7t.png)_**Figura #1: Proceso típico de un pago en un sitio web de comercio electrónico**_

**- Selección del producto:** El cliente, desde el carrito de compras, se dirige a la página de pago. En esta página, se presentan los detalles del pedido, que incluyen el costo de los productos, impuestos, gastos de envío y el importe total a pagar.

**- Elección del método de pago:** Cuando el cliente hace clic en el botón de pago en la página de pago, es redirigido a una página de PayPal. Aquí, se le ofrece la opción de utilizar su saldo de PayPal o pagar con una tarjeta de crédito o débito. Una vez que el cliente hace su elección y se aprueba la transacción, se le redirige a la página de revisión.

**- Revisión del pedido:** En la página de revisión, el cliente tiene la oportunidad de verificar la información del comprador, que incluye datos como la dirección de envío.

**- Confirmación del pago:** Cuando el cliente hace clic en el botón "Pagar" en la página de revisión, se procesa el pago y se muestra la página de recibo, confirmando la transacción.
A lo largo de este tutorial, aprenderás cómo implementar la integración de pago de PayPal siguiendo este flujo de trabajo.

## 3. Crear nuevo proyecto de Kotlin
Una vez que hemos comprendido el proceso, el siguiente paso es crear un proyecto en Kotlin. Para ello, podemos utilizar Spring Initializr para generar un nuevo proyecto siguiendo los pasos que se muestran en la Figura #2.

![Figura #2: Configuración de un nuevo proyecto de Spring Boot con Kotlin y Thymeleaf**_](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rvcdh7t7j8gco0gkxfyj.png)_**Figura #2: Configuración de un nuevo proyecto de Spring Boot con Kotlin y Thymeleaf**_

La configuración mencionada es todo lo que necesitamos para crear un nuevo proyecto de Spring Boot con `Kotlin` y `Thymeleaf`. Una vez completado este paso, podemos hacer clic en el botón "Generar" e importar el proyecto en nuestro entorno de desarrollo, como IntelliJ IDEA.

## 4. Estructura del proyecto
La Figura #3 muestra cómo está estructurado el proyecto.

![_**Figura #3: Estructura del proyecto**_](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1xslthjbv941hs9r7bcm.png)_**Figura #3: Estructura del proyecto**_

## 5. Crear la cuenta en paypal developer
Antes de continuar con la integración de PayPal, necesitas una cuenta de PayPal Developer para gestionar aplicaciones relacionadas con pagos. Para ello, sigue estos pasos: 

**- Paso 1:** Accede al PayPal Developer Dashboard, donde podrás crear y gestionar aplicaciones para la integración de pagos. Inicia sesión con tu cuenta de PayPal y utiliza el botón "Apps & Credentials" para comenzar el proceso. Presiona "Create App" para crear una nueva aplicación. Si ya tienes una aplicación, simplemente haz clic en su nombre para acceder a tus credenciales.

Si necesitas crear una cuenta de PayPal Developer directamente, puedes hacerlo siguiendo este enlace: https://developer.paypal.com/dashboard/applications/sandbox

## 5.1 Ejemplo: Cuentas de PayPal Developer
La Figura #4 muestra dos aplicaciones en PayPal, una en modo Sandbox (pruebas) y otra en modo Live (producción). Para esta integración, utilizaremos credenciales de Sandbox, apropiadas para el desarrollo y las pruebas. Una vez que el proyecto funcione correctamente, podrás actualizar tus credenciales a modo Live para transacciones reales.

![Figura #4: Ejemplo de Cuentas de PayPal Developer](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ddj80x4a90o4a6b5tkyz.png)**_Figura #4: Ejemplo de Cuentas de PayPal Developer_**

**- Paso 2:** Crear una nueva aplicación seleccionando `"Create App"`. Esto te llevará a una página donde debes proporcionar un nombre para la aplicación, por ejemplo, `"app-demo-kotlin".` Además, selecciona el tipo de aplicación adecuado para tu proyecto, en este caso, "Merchant", como se muestra en la Figura #4.1.

![Figura #4.1: Creación de una nueva aplicación en PayPal Developer](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lrgbuv78dorts8thn83c.png)_**Figura #4.1: Creación de una nueva aplicación en PayPal Developer**_

**- Paso 3:** Una vez creada la aplicación, obtendrás tus credenciales de prueba. Estas credenciales son necesarias para que tu aplicación se comunique con PayPal y realice pruebas de pago. Las credenciales consisten en el `Client ID` y el `Secret`, como se muestra en la Figura #4.2.

![Figura #4.2: Credenciales de prueba de PayPal Developer](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0ypad7lagx2euysh18r7.png)_**Figura #4.2: Credenciales de prueba de PayPal Developer**_

## 5.3 Guardar las credenciales de PayPal
Después de obtener tus credenciales, es importante guardarlas en un lugar seguro. Más adelante, necesitarás utilizar estas credenciales en tu aplicación Kotlin para autenticarte con la API de PayPal.

## 6. Agregar dependencias de PayPal en el archivo build.gradle
PayPal ofrece a los desarrolladores un conjunto de herramientas conocido como Kit de Desarrollo de Software (SDK) que facilita la integración de los pagos de PayPal en sus aplicaciones. Este SDK es versátil y es compatible con una variedad de lenguajes de programación, incluyendo Java. La característica distintiva del SDK de PayPal es su capacidad para interactuar con los servidores de PayPal a través de servicios web RESTful, lo que le otorga el nombre de "SDK REST de PayPal".

Una de las ventajas notables de este SDK es que se trata de una API de alto nivel. Esto significa que los desarrolladores no tienen que lidiar directamente con los detalles complejos de los servicios web, como las solicitudes y respuestas HTTP. En lugar de eso, el SDK proporciona métodos y funciones que simplifican en gran medida la interacción con PayPal, permitiendo a los desarrolladores centrarse en la lógica de su aplicación en lugar de la comunicación con la pasarela de pago.

Para comenzar la integración, necesitas agregar las dependencias de PayPal en tu archivo de construcción Gradle. Abre tu archivo `build.gradle.kts` y agrega las siguientes dependencias:

```yaml
implementation("com.paypal.sdk:paypal-core:1.7.2")
implementation("com.paypal.sdk:rest-api-sdk:1.14.0")
```

## 7. Integración de Paypal 
Después de configurar el `SDK de PayPal`, es el momento de integrarlo en nuestro proyecto. Esta integración se realiza en varias etapas para que todo funcione de manera armoniosa. Aquí vamos a explorar estas etapas en detalle.

## 7.1 Crear el clase de configuración de Paypal:
La configuración de PayPal es fundamental para establecer una conexión efectiva entre tu aplicación y la pasarela de pago de PayPal. Esta configuración se realiza a través de una clase llamada "PaypalConfig". Dentro de esta clase, especificamos tres valores clave:

**- clientId:** Este valor representa el ID del cliente de PayPal que obtuviste al crear tu aplicación en el Panel de Desarrolladores de PayPal.

**- clientSecret:** Aquí debes proporcionar el secreto del cliente, que también se obtiene al crear la aplicación.

**- mode:** Este campo define si estás trabajando en el modo de prueba (sandbox) o en modo de producción (live). Para propósitos de desarrollo y pruebas, debes configurarlo en `"sandbox"`.

```kotlin
@Configuration
class PaypalConfig(
    @Value("\${paypal.client-id}")
    private val clientId: String,
    @Value("\${paypal.client-secret}")
    private val clientSecret: String,
    @Value("\${paypal.mode}")
    private val mode: String
){
    @Bean
    fun apiContext(): APIContext {
        return APIContext(clientId, clientSecret, mode)
    }
}
```

## 7.2 Generar Client-ID y Client-Secret de Paypal
**- Configurar las credenciales de PayPal:** Ahora, vamos a configurar las credenciales de PayPal que obtuviste anteriormente. En tu archivo `application.properties` para esta demo modificamos el nombre con su extensión, quedaría de esta forma `application.yml`. Agrega las siguientes propiedades con tus credenciales de PayPal Sandbox:

```yaml
# Configuración de PayPal (Sandbox)
paypal:
  client-id: CLIENT-ID
  client-secret: CLIENT-SECRET
  mode: sandbox
```
Reemplaza `CLIENT-ID` y `CLIENT-SECRET` con las credenciales que obtuviste de PayPal Developer.

## 8. Servicio Paypal
Una vez que hemos configurado la conexión, es el momento de crear un servicio que nos permita interactuar con la pasarela de PayPal de manera efectiva. Esto se realiza a través de la clase "PaypalService".

## 8.1 Creación de la data class Request de Payment:
Para llevar a cabo las operaciones de pago, necesitamos una estructura de datos que describa la solicitud de pago. Esta estructura se define como una `"data class"` llamada `"CreatePaymentRequest"`. Contiene información crucial sobre el pago, como el monto, la moneda, el método de pago, la intención, la descripción y las URL de redirección en caso de éxito o cancelación.

```kotlin
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonNaming(PropertyNamingStrategies.LowerCamelCaseStrategy::class)
@JsonInclude(JsonInclude.Include.NON_NULL)
data class CreatePaymentRequest(
    val total : BigDecimal,
    val currency: String,
    val method: String,
    val intent: String,
    val description: String,
    val cancelUrl: String,
    val successUrl: String
)
```

## 8.2 Crear servicio Paypal:
Dentro de nuestra aplicación, necesitamos un servicio dedicado para administrar todas las operaciones relacionadas con PayPal. Esta función se realiza en la clase `"PaypalService"`. El servicio actúa como un intermediario entre nuestra aplicación y la pasarela de PayPal, facilitando la creación y ejecución de pagos.

```kotlin
@Service
class PaypalService(private val apiContext: APIContext? = null) {}
```

## 8.3 Implementar el método de pago
En el proceso de integración con PayPal, uno de los componentes cruciales es la implementación del método de pago. En nuestra aplicación, este método recibe el nombre de "createPayment" y desempeña una función esencial.

**- Paso 1:** Creación de la solicitud de pago.
El método `"createPayment"`, contenido en la clase `"PaypalService"`, tiene la responsabilidad de reunir todos los detalles necesarios para llevar a cabo una transacción. Estos detalles son proporcionados por el cliente y pueden incluir información sobre el producto o servicio, el monto a pagar, la moneda utilizada y otros datos pertinentes.

**- Paso 2:** Envío de la solicitud a PayPal.
Una vez que se ha reunido toda la información esencial, el método "createPayment" envía una solicitud de pago a PayPal para su procesamiento. Esto implica que la pasarela de pago de PayPal valida la transacción y realiza todas las operaciones necesarias para completar el pago.

**- Resultados posibles:**
Si todo transcurre sin problemas y la solicitud de pago es aceptada, la transacción se confirma y se genera un recibo que sirve como prueba de la transacción exitosa. Este recibo es esencial para el seguimiento de la transacción y puede ser utilizado para futuras referencias.

Sin embargo, en el mundo de las transacciones en línea, pueden surgir complicaciones. Si algo no funciona como se esperaba, el método `"createPayment"` está preparado para manejar posibles errores y excepciones. Estos pueden incluir problemas de comunicación con PayPal, problemas con los datos proporcionados por el cliente o cualquier otro obstáculo que pueda surgir en el proceso de pago.

En resumen, la implementación del método de pago es un componente crucial en la integración de PayPal en tu aplicación. Este método garantiza que las transacciones se procesen de manera eficiente y que se manejan posibles problemas de manera adecuada para brindar una experiencia de compra segura y satisfactoria a los usuarios.

```kotlin
fun createPayment(request: CreatePaymentRequest): Payment {
       logger.info(LOG_INIT_CREATE_PAYMENT, request)
       try {
           return Payment().apply {
               intent = request.intent
               payer = Payer().apply {
                   paymentMethod = request.method
               }
               transactions = mutableListOf(Transaction().apply {
                   description = request.description
                   amount = Amount().apply {
                       currency = request.currency
                       total = String.format(Locale.forLanguageTag(request.currency), "%.2f", request.total)
                   }
               })
               redirectUrls = RedirectUrls().apply {
                   cancelUrl = request.cancelUrl
                   returnUrl = request.successUrl
               }
           }.run {
               create(apiContext).also {
                   logger.info(LOG_END_CREATE_PAYMENT,apiContext)
               }
           }
       } catch (ex: PayPalRESTException) {
           throw Exception(LOG_ERROR_CREATING_PAYMENT, ex)
       }
   }
```
Por otra parte hemos personalizado los mensajes de logs para un mejor control. Dentro del servicio de PayPal, hemos agregado mensajes de registro personalizados. Estos mensajes registran eventos clave, como el inicio de la creación de un pago, cualquier error que pueda surgir durante el proceso y la finalización exitosa de una transacción.

Estos mensajes ayudan a rastrear y depurar cualquier problema que pueda surgir en el proceso de pago, proporcionando un mayor control y visibilidad sobre lo que está ocurriendo en la aplicación.

```kotlin
companion object {
        private val logger = LoggerFactory.getLogger(PaypalService::class.java)
        private const val LOG_INIT_CREATE_PAYMENT = "PaypalService::createPayment -- INIT - request: [{}]"
        private const val LOG_ERROR_CREATING_PAYMENT = "Error creating payment - error: [{}]"
        private const val LOG_END_CREATE_PAYMENT = "PaypalService::createPayment -- END - response: [{}]"
}
```

## 8.4 Implementar el método de pago de ejecución
Una vez que hemos configurado la creación de pagos, es igualmente importante implementar la ejecución de pagos. El método "executePayment" en la clase "PaypalService" se encarga de esta tarea crucial.

**- Paso 1:** Inicialización del proceso de ejecución de pago.
Cuando un cliente decide pagar por un producto o servicio, se desencadena el proceso de ejecución del pago. En este punto, el método "executePayment" toma dos argumentos esenciales:

**paymentId:** Este identificador es único para cada transacción y se utiliza para identificar el pago que se va a ejecutar.

**payerId:** El `"payerId"` representa al pagador y se utiliza para asociar el pago con la persona que lo está realizando.

**- Paso 2:** Ejecución del pago
Una vez que se han proporcionado los valores adecuados para `"paymentId"` y `"payerId"`, el método `"executePayment"` realiza la ejecución real del pago. Esta ejecución implica la confirmación y autorización del pago a través de la pasarela de PayPal.

**Manejo de errores:**
Si, en algún momento, ocurre un error durante el proceso de ejecución del pago, el método `"executePayment"` se encarga de manejarlo adecuadamente. Esto puede incluir problemas de conexión, autenticación o problemas específicos relacionados con la pasarela de PayPal. Estos errores se capturan y se generan registros detallados, lo que facilita la identificación y resolución de problemas.

```kotlin
 fun executePayment(paymentId: String, payerId: String): Payment {
        logger.info(LOG_INIT_EXECUTE_PAYMENT, paymentId, payerId)
        try {
            return Payment().apply { id = paymentId }.run {
                val paymentExecution = PaymentExecution().apply { this.payerId = payerId }
                execute(apiContext, paymentExecution)
            }.also {
                logger.info(LOG_END_EXECUTE_PAYMENT, paymentId, payerId)
            }
        } catch (ex: PayPalRESTException) {
            throw Exception(LOG_ERROR_EXECUTE_PAYMENT, ex)
        }
    }
```

- **Continuando con la personalización de mensajes de registro o logs:**
Al igual que en otras partes de la implementación de PayPal, los mensajes de registro son personalizados para brindar un mayor control y visibilidad. Estos mensajes registran eventos clave, como el inicio de la ejecución del pago, cualquier error que pueda surgir durante el proceso y la finalización exitosa de una transacción. Esta funcionalidad facilita el seguimiento y la depuración de cualquier problema que pueda surgir durante el proceso de ejecución del pago.

```kotlin
companion object {
        private val logger = LoggerFactory.getLogger(PaypalService::class.java)
        private const val LOG_INIT_CREATE_PAYMENT = "PaypalService::createPayment -- INIT - request: [{}]"
        private const val LOG_ERROR_CREATING_PAYMENT = "Error creating payment - error: [{}]"
        private const val LOG_END_CREATE_PAYMENT = "PaypalService::createPayment -- END - response: [{}]"
        private const val LOG_ERROR_EXECUTE_PAYMENT = "Error when executing payment - error: [{}]"
        private const val LOG_INIT_EXECUTE_PAYMENT = "PaypalService::executePayment -- INIT - paymentId: [{}] - payerId: [{}]"
        private const val LOG_END_EXECUTE_PAYMENT = "PaypalService::executePayment -- END - paymentId: [{}] - payerId: [{}]"
    }
```

## 9. Controlador de Paypal
En el proceso de integración de PayPal, uno de los componentes clave es el controlador de PayPal. Este controlador, representado por la clase "PaypalController", actúa como un intermediario entre la pasarela de pago de PayPal y nuestra aplicación. Su función principal es gestionar las solicitudes y respuestas relacionadas con las transacciones de pago.

## 9.1 Crear el controlador de Paypal:
Para comenzar, creamos el controlador de PayPal utilizando la anotación @Controller. Este controlador se comunica con el servicio de PayPal, que hemos configurado previamente, para realizar las operaciones de pago.

## 9.2 Implementar el método de índice:
El método `"home"` dentro del controlador se utiliza para manejar las solicitudes en la ruta raíz `("/")`. En otras palabras, cuando los usuarios acceden a la página de inicio de nuestra aplicación, este método se ejecuta. Su función es simple: devuelve la vista `"index"` que se mostrará al usuario. La vista `"index"` contendrá un formulario que permitirá a los usuarios realizar pagos a través de PayPal.

```kotlin
@Controller
class PaypalController(private val paypalService: PaypalService){
    
    @GetMapping("/")
    fun home(): String {
        return "index"
    }
}
```

## 9.3 Creación del formulario index.html:
Para mejorar la experiencia visual de los usuarios al realizar pagos a través de PayPal, hemos creado un formulario denominado `"index.html"`. Este formulario se ha estilizado utilizando la biblioteca de diseño `Bootstrap` para que tenga un aspecto más atractivo y amigable. Incluye campos para seleccionar el método de pago, ingresar el monto, elegir la moneda, proporcionar una descripción y un botón que permite confirmar el pago a través de PayPal.

```html
<!DOCTYPE html>
<html xmlns:th="http://thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Paypal Integration</title>

    <!-- Bootstrap CSS -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">

    <!-- Bootstrap JavaScript -->
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.6/dist/umd/popper.min.js" integrity="sha384-oBqDVmMxFTKwzxwjkO+rz/8mB/4E4Jj59Tz0mzYzpsTnDQDxEJ2kGbpCLWg1I593" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.min.js" integrity="sha384-cn7l7gDp0eyniUwwAZgrzD06kc/tftFf19TOAs2zVinnD/C7E91j9yyk5//jjpt/" crossorigin="anonymous"></script>
</head>
<body>
<div class="container">
    <h1 class="text-center mt-5">Paypal Payment Integration</h1>
    <form method="post" action="/payment/create" class="mt-5 card p-3">
        <div class="mb-3">
            <label for="method" class="form-label">Payment method</label>
            <input id="method" type="text" class="form-control"
                   name="method" value="Paypal" readonly>
        </div>
        <div class="mb-3">
            <label for="amount" class="form-label">Amount</label>
            <input id="amount" type="number" class="form-control"
                   name="amount" value="10.0">
        </div>
        <div class="mb-3">
            <label for="currency" class="form-label">Amount</label>
            <select class="form-control" id="currency" name="currency">
                <option value="USD" selected>USD</option>
                <option value="EUR">EUR</option>
                <option value="GBP">GBP</option>
                <option value="COP">COP</option>
            </select>
        </div>
        <div class="mb-3">
            <label for="description" class="form-label">Description</label>
            <input id="description" type="text" class="form-control"
                   name="description">
        </div>
        <div class="d-flex justify-content-center">
            <button type="submit" class="btn btn-primary">
                Pay with Paypal
            </button>
        </div>
    </form>
</div>
</body>
</html>
```
En la figura #5 podemos observar como se visualiza la pagina _**Paypal Payment Integration**_.


![Figura #5: Pagina Index.html](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0tcns8of4fjoh9ip3x82.png)_**Figura #5: Pagina Index.html**_

## 9.4 Implementar crear método de pago:
Cuando un usuario completa el formulario y hace clic en el botón `"Pay with PayPal"`, se ejecuta el método `"createPayment"`. Este método se encarga de generar una solicitud de pago con todos los detalles proporcionados por el usuario, como el método de pago, el monto, la moneda y la descripción. Luego, envía esta solicitud a PayPal para su procesamiento. Si la solicitud es exitosa, se obtiene una URL de aprobación de PayPal y el usuario es redirigido a la página de PayPal para confirmar el pago.

```kotlin
@PostMapping("/payment/create")
    fun createPayment(
        @RequestParam("method") method: String,
        @RequestParam("amount") amount: String,
        @RequestParam("currency") currency: String,
        @RequestParam("description") description: String
    ): RedirectView {
        try {
            val cancelUrl = "http://localhost:8080/payment/cancel"
            val successUrl = "http://localhost:8080/payment/success"
            val request = CreatePaymentRequest(
                total = amount.toBigDecimal(),
                currency = currency,
                method = method,
                intent = "sale",
                description = description,
                cancelUrl = cancelUrl,
                successUrl = successUrl
            )
            val payment = paypalService.createPayment(request)
                for (links in payment.links ?: emptyList()) {
                    if (links.rel == "approval_url") {
                        return RedirectView(links.href)
                    }
                }
        } catch (ex: PayPalRESTException) {
            logger.error(LOG_ERROR_CREATE_PAYMENT, ex.message)
        }
        return RedirectView("/payment/error")
    }
```

## 9.5 Implementar método de pago exitoso:
Después de que el usuario completa el proceso de pago en PayPal y se redirige de vuelta a nuestra aplicación, el método `"paymentSuccess"` se encarga de verificar el estado del pago. Si el pago se aprueba con éxito, se muestra la página `"paymentSuccess.html"` al usuario.

```kotlin
@GetMapping("/payment/success")
    fun paymentSuccess(
        @RequestParam("paymentId") paymentId: String,
        @RequestParam("PayerID") payerId: String
    ): String {
        try {
            val payment = paypalService.executePayment(paymentId, payerId)
            if (payment.state == "approved") {
                return "paymentSuccess"
            }
        } catch (ex: PayPalRESTException) {
            logger.error(LOG_ERROR_SUCCESS_PAYMENT, ex.message)
        }
        return "paymentSuccess"
    }
```

## 9.5.1 Creación de la Página de pago exitoso (paymentSuccess.html):

Cuando un usuario completa con éxito el proceso de pago a través de PayPal, se le redirige a la página `"paymentSuccess.html"`. Esta página confirma que el pago se ha realizado con éxito y puede proporcionar detalles adicionales sobre la transacción, como un número de referencia o información de contacto para preguntas o problemas. El objetivo es brindar al usuario una sensación de confianza y satisfacción después de una transacción exitosa.

```html
<!DOCTYPE html>
<html xmlns:th="http://thymeleaf.org">
<head>
  <meta charset="UTF-8">
  <title>Paypal Integration</title>

  <!-- Bootstrap CSS -->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">

  <!-- Bootstrap JavaScript -->
  <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.6/dist/umd/popper.min.js" integrity="sha384-oBqDVmMxFTKwzxwjkO+rz/8mB/4E4Jj59Tz0mzYzpsTnDQDxEJ2kGbpCLWg1I593" crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.min.js" integrity="sha384-cn7l7gDp0eyniUwwAZgrzD06kc/tftFf19TOAs2zVinnD/C7E91j9yyk5//jjpt/" crossorigin="anonymous"></script>
</head>

<body>
<div class="container">
  <h1 class="text-center mt-5">Paypal Success</h1>
  <div class="d-flex justify-content-center mt-5">
    <a href="/" class="btn btn-primary">
      Back to Home
    </a>
  </div>
</div>
</body>

</html>
```
En la figura #5.1 podemos observar como se visualiza la pagina `Paypal Success`.

![Figura #5.1: Pagina PaymenSuccess.html](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eg3amgefkrh3zbj144i0.png)**_Figura #5.1: Pagina PaymenSuccess.html_**

## 9.6 Implementar método de pago cancelado:
En caso de que el usuario decida cancelar el pago durante el proceso en PayPal, el método `"paymentCancel"` muestra la página `"paymentCancel.html"`.

```kotlin
 @GetMapping("/payment/cancel")
    fun paymentCancel(): String {
        return "paymentCancel"
    }
```
**9.6.1 Creación de Página de pago cancelado (paymentCancel.html):**
Cuando un usuario decide cancelar el proceso de pago en cualquier etapa, se muestra una página especial denominada `"paymentCancel.html"`. Esta página ofrece un mensaje claro al usuario indicando que el pago se ha cancelado. Proporciona información adicional y posiblemente instrucciones sobre cómo proceder en caso de que el usuario desee intentar nuevamente o necesite asistencia adicional.

```html
<!DOCTYPE html>
<html xmlns:th="http://thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Paypal Integration</title>

    <!-- Bootstrap CSS -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">

    <!-- Bootstrap JavaScript -->
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.6/dist/umd/popper.min.js" integrity="sha384-oBqDVmMxFTKwzxwjkO+rz/8mB/4E4Jj59Tz0mzYzpsTnDQDxEJ2kGbpCLWg1I593" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.min.js" integrity="sha384-cn7l7gDp0eyniUwwAZgrzD06kc/tftFf19TOAs2zVinnD/C7E91j9yyk5//jjpt/" crossorigin="anonymous"></script>
</head>

<body>
<div class="container">
    <h1 class="text-center mt-5">Payment Cancelled</h1>
    <div class="d-flex justify-content-center mt-5">
        <a href="/" class="btn btn-primary">
            Back to Home
        </a>
    </div>
</div>
</body>

</html>
```
En la figura #5.2 podemos observar como se visualiza la pagina `Payment Cancel`.

![Figura #5.2: Pagina PaymenCancel.html](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q29s225xo0u6m8812fng.png) **_Figura #5.2: Pagina PaymenCancel.html_**

## 9.7 Implementar método de pago erróneo:
Si se produce un error durante el proceso de pago en PayPal, el método `"paymentError"` muestra la página `"paymentError.html"`. Esta página puede proporcionar información adicional o instrucciones para el usuario en caso de problemas con el pago.

```kotlin
 @GetMapping("/payment/error")
    fun paymentError(): String {
        return "paymentError"
    }
```

## 9.7.1 Creación de Página de error en el pago (paymentError.html):
Si ocurre un error durante el proceso de pago, se presenta una página de `"paymentError.html"` al usuario. Esta página puede incluir información sobre el error específico que ha ocurrido y proporcionar orientación sobre cómo abordar el problema. El objetivo es ayudar al usuario a comprender la situación y brindar una experiencia de usuario clara y útil incluso en situaciones de error.

```html
<!DOCTYPE html>
<html xmlns:th="http://thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Paypal Integration</title>

    <!-- Bootstrap CSS -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">

    <!-- Bootstrap JavaScript -->
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.6/dist/umd/popper.min.js" integrity="sha384-oBqDVmMxFTKwzxwjkO+rz/8mB/4E4Jj59Tz0mzYzpsTnDQDxEJ2kGbpCLWg1I593" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.min.js" integrity="sha384-cn7l7gDp0eyniUwwAZgrzD06kc/tftFf19TOAs2zVinnD/C7E91j9yyk5//jjpt/" crossorigin="anonymous"></script>
</head>

<body>
<div class="container">
    <h1 class="text-center mt-5 text-danger">Payment Error</h1>
    <p class="text-center mt-3">An error occurred during the payment. Please try again</p>
    <div class="d-flex justify-content-center mt-5">
        <a href="/" class="btn btn-primary">
            Back to Home
        </a>
    </div>
</div>
</body>

</html>
```
En la figura #5.3 podemos observar como se visualiza la pagina `Payment Error`.


![**_Figura #5.3: Pagina PaymenError.html_**](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wn4r4bwqtk171fr3re5g.png)**_Figura #5.3: Pagina PaymenError.html_**

En resumen cada uno de estos archivos HTML desempeña un papel crucial en la experiencia del usuario al interactuar con la pasarela de pago de PayPal a través de nuestra aplicación. Proporcionan información, orientación y confirmación en función del estado de la transacción, ya sea que se complete con éxito, se cancele o se produzca un error.

**- Mensajes personalizados para los registros:**
Hemos agregado mensajes de registro personalizados para facilitar el seguimiento y la depuración de posibles errores o problemas en cada uno de los métodos del controlador de PayPal. Estos mensajes de registro proporcionan información valiosa para identificar y resolver cualquier inconveniente que pueda surgir en el proceso de pago.
En resumen, el controlador de PayPal es el punto central para gestionar las interacciones entre los usuarios y la pasarela de pago de PayPal en nuestra aplicación. Cada método dentro del controlador desempeña un papel específico en el proceso de pago y proporciona una experiencia de usuario eficiente y amigable.

```kotlin
companion object {
        private val logger = LoggerFactory.getLogger(PaypalController::class.java)
        private const val LOG_ERROR_CREATE_PAYMENT = "PaypalController::createPayment Error occurred - error: [{}]"
        private const val LOG_ERROR_SUCCESS_PAYMENT = "PaypalController::paymentSuccess Error occurred - error: [{}]"
    }
```

## Conclusión
Hemos explorado cómo integrar la API de PayPal Checkout con una aplicación `Kotlin` de comercio electrónico. Desde la configuración de las credenciales de PayPal y la creación de una página de pago hasta la captura del pago y el manejo de la respuesta de PayPal, has aprendido los conceptos esenciales para implementar una pasarela de pago en línea con Kotlin.

Este artículo es una introducción, y hay muchas formas de personalizar y extender esta integración para adaptarla a las necesidades específicas de tu aplicación. Asegúrate de leer la documentación de PayPal para obtener más detalles y opciones avanzadas.


**- -[Descarga del Proyecto](https://github.com/Geovanny0401/kotlin-integration-paypal)**



## Referencias:

- [Libro Kotlin Developers de Marcin Moskała](https://leanpub.com/kotlin_developers)
- [Post de CodeJava](https://www.codejava.net/coding/how-to-integrate-paypal-payment-into-java-web-application)
- [Post de Vladimir Djurovic](https://bitshifted.co/blog/spring-boot-paypal-integration/)
- [Página de desarrolladores de PayPal ](https://developer.paypal.com/home/)
- [Documentación de PayPal Checkout](https://developer.paypal.com/docs/checkout/)
- [Curso de BOUALI Ali](https://www.udemy.com/course/spring-boot-paypal-payment-integration/)