diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..ec99bfae --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,42 @@ +name: Java CI + +on: + push: + branches: + - master + - develop + pull_request: + types: [synchronize, opened, reopened] + +jobs: + sonar-cloud-check: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up JDK 8 + uses: actions/setup-java@v4 + with: + java-version: '8' + distribution: 'temurin' + + - name: Cache SonarCloud packages + uses: actions/cache@v3 + with: + path: ~/.sonar/cache + key: ${{ runner.os }}-sonar + restore-keys: ${{ runner.os }}-sonar + + - name: Install dependencies and run tests with coverage + run: mvn clean install verify -P no-gpg --no-transfer-progress + + - name: SonarQube Scan + uses: SonarSource/sonarqube-scan-action@master + with: + projectBaseDir: . + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml deleted file mode 100644 index 4e07c8dc..00000000 --- a/.github/workflows/codeql-analysis.yml +++ /dev/null @@ -1,50 +0,0 @@ -name: "Code scanning - action" -on: - push: - pull_request: - schedule: - - cron: '0 10 1,15 * *' - -jobs: - CodeQL-Build: - - runs-on: ubuntu-latest - - steps: - - name: Checkout repository - uses: actions/checkout@v2 - with: - # We must fetch at least the immediate parents so that if this is - # a pull request then we can checkout the head. - fetch-depth: 2 - - # If this run was triggered by a pull request event, then checkout - # the head of the pull request instead of the merge commit. - - run: git checkout HEAD^2 - if: ${{ github.event_name == 'pull_request' }} - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v1 - # Override language selection by uncommenting this and choosing your languages - # with: - # languages: go, javascript, csharp, python, cpp, java - - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v1 - - # 鈩癸笍 Command-line programs to run using the OS shell. - # 馃摎 https://git.io/JvXDl - - # 鉁忥笍 If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language - - #- run: | - # make bootstrap - # make release - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 diff --git a/CHANGELOG.md b/CHANGELOG.md index bd523ab6..af1dd8f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,19 @@ Todos los cambios notables a este proyecto ser谩n documentados en este archivo. El formato est谩 basado en [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) y este proyecto adhiere a [Semantic Versioning](http://semver.org/spec/v2.0.0.html). + +## [6.1.0] - 2025-06-25 + +Esta versi贸n agrega una clase para la nueva funcionalidad de la API de OneClick. Los m茅todos existentes no tienen cambios. + +### Agrega: + +- Se agrega la clase OneclickMallBinInfo, la cual contiene el m茅todo queryBin para la consulta de informaci贸n de una tarjeta registrada en OneClick. + +### Actualiza: + +- Se actualizan las dependencias necesarias para construir el proyecto. + ## [6.0.0] - 2025-05-05 Esta versi贸n no tiene cambios en el comportamiento de las funcionalidades de la API. diff --git a/README.md b/README.md index 0a575ecf..173a42dc 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,13 @@ Ahora, si gestionas las dependencias manualmente 馃槺 te quedan las siguientes o (Por eso te recomendamos fuertemente que uses maven u otra herramienta que gestione las dependencias por t铆) +## Ejecutar Test + +```bash +mvn test -P no-gpg +``` + + ## Documentaci贸n Puedes encontrar toda la documentaci贸n de c贸mo usar este SDK en el sitio https://www.transbankdevelopers.cl. @@ -45,146 +52,78 @@ La documentaci贸n relevante para usar este SDK es: - Primeros pasos con [Webpay](https://www.transbankdevelopers.cl/documentacion/webpay). - Referencia detallada sobre [Webpay](https://www.transbankdevelopers.cl/referencia/webpay). -## Informaci贸n para contribuir y desarrollar este SDK -Esta librer铆a usa [Project Lombok][lombok] en su desarrollo. Si bien no es necesario podr铆as querer instalar el [plugin][lombok-plugins] -para tu IDE favorito con el fin de evitar que veas errores marcados por la herramienta de desarrollo. +## Informaci贸n para contribuir a este proyecto -Se recomienda usar Java 8 para compilar este SDK. En Java 9 o superior la generaci贸n de Javadocs falla debido a la introducci贸n de m贸dulos (y a que varias clases de JavaEE en el paquete javax.* han sido movidas a m贸dulos separados). +### Forma de trabajo -### Standares +- Para los mensajes de commits, nos basamos en las [Git Commit Guidelines de Angular](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#commits). +- Usamos ingl茅s para los nombres de ramas y mensajes de commit. +- Los mensajes de commit no deben llevar punto final. +- Los mensajes de commit deben usar un lenguaje imperativo y estar en tiempo presente, por ejemplo, usar "change" en lugar de "changed" o "changes". +- Los nombres de las ramas deben estar en min煤sculas y las palabras deben separarse con guiones (-). +- Todas las fusiones a la rama principal se deben realizar mediante solicitudes de Pull Request(PR). 猬囷笍 +- Se debe emplear tokens como "WIP" en el encabezado de un commit, separados por dos puntos (:), por ejemplo, "WIP: this is a useful commit message". +- Una rama con nuevas funcionalidades que no tenga un PR, se considera que est谩 en desarrollo. +- Los nombres de las ramas deben comenzar con uno de los tokens definidos. Por ejemplo: "feat/tokens-configurations". -- Para los commits respetamos las siguientes normas: https://chris.beams.io/posts/git-commit/ -- Usamos ingles, para los mensajes de commit. -- Se pueden usar tokens como WIP, en el subject de un commit, separando el token con `:`, por ejemplo: -`WIP: This is a useful commit message` -- Para los nombres de ramas tambi茅n usamos ingles. -- Se asume, que una rama de feature no mezclada, es un feature no terminado. -- El nombre de las ramas va en min煤sculas. -- Las palabras se separan con `-`. -- Las ramas comienzan con alguno de los short lead tokens definidos, por ejemplo: `feat/tokens-configuration` - -#### Short lead tokens -##### Commits -- WIP = Trabajo en progreso. -##### Ramas -- feat = Nuevos features -- chore = Tareas, que no son visibles al usuario. -- bug = Resoluci贸n de bugs. - -### Todas las mezclas a master se hacen mediante Pull Request. - -### Construir el proyecto localmente -```bash -mvn clean compile -``` -### Correr los test localmente -```bash -mvn test -``` +### Short lead tokens permitidos -### Generar un reporte de los test ejecutados localmente -```bash -mvn surefire-report:report -``` +`WIP` = En progreso. -### Generar un jar local +`feat` = Nuevos features. -````bash -mvn package -```` +`fix` = Correcci贸n de un bug. -#### Instalar jar local +`docs` = Cambios solo de documentaci贸n. -````bash -mvn clean install -```` +`style` = Cambios que no afectan el significado del c贸digo. (espaciado, formateo de c贸digo, comillas faltantes, etc) -Si te encuentras con un error como +`refactor` = Un cambio en el c贸digo que no arregla un bug ni agrega una funcionalidad. -````bash -[INFO] --- maven-gpg-plugin:1.6:sign (sign-artifacts) @ transbank-sdk-java --- -gpg: signing failed: Timeout -```` +`perf` = Cambio que mejora el rendimiento. -tienes que exportar la siguiente variable de entorno: +`test` = Agregar test faltantes o los corrige. -````bash -export GPG_TTY=$(tty) -```` +`chore` = Cambios en el build o herramientas auxiliares y librer铆as. -Luego, se te pedira una frase para desbloquear la firma (puedes encontrar m谩s informacion en 1Password) +`revert` = Revierte un commit. -### Generar una nueva versi贸n (con deploy autom谩tico a maven) +`release` = Para liberar una nueva versi贸n. -Para generar una nueva versi贸n, se debe crear un PR (con un t铆tulo "Prepare release X.Y.Z" con los valores que correspondan para `X`, `Y` y `Z`). Se debe seguir el est谩ndar semver para determinar si se incrementa el valor de `X` (si hay cambios no retrocompatibles), `Y` (para mejoras retrocompatibles) o `Z` (si s贸lo hubo correcciones a bugs). +### Creaci贸n de un Pull Request -En ese PR deben incluirse los siguientes cambios: +- El PR debe estar enfocado en un cambio en concreto, por ejemplo, agregar una nueva funcionalidad o solucionar un error, pero un solo PR no puede agregar una nueva funcionalidad y arreglar un error. +- El t铆tulo del los PR y mensajes de commit no debe comenzar con una letra may煤scula. +- No se debe usar punto final en los t铆tulos. +- El t铆tulo del PR debe comenzar con el short lead token definido para la rama, seguido de ":"" y una breve descripci贸n del cambio. +- La descripci贸n del PR debe detallar los cambios que se est谩n incorporando. +- La descripci贸n del PR debe incluir evidencias de que los test se ejecutan de forma correcta o incluir evidencias de que los cambios funcionan y no afectan la funcionalidad previa del proyecto. +- Se pueden agregar capturas, gif o videos para complementar la descripci贸n o demostrar el funcionamiento del PR. -1. Modificar el archivo `CHANGELOG.md` para incluir una nueva entrada (al comienzo) para `X.Y.Z` que explique en espa帽ol los cambios **de cara al usuario del SDK**. -2. Modificar este `README.md` para que los ejemplos usen la nueva versi贸n `X.Y.Z` -3. Modificar el archivo `pom.xml` para que la versi贸n snapshot sea `X.Y.{Z+1}` (de manera que los snapshots que se generen despu茅s del release sean de la siguiente versi贸n). +#### Flujo de trabajo -Luego de obtener aprobaci贸n del pull request, debe mezclarse a master e inmediatamente generar un release en GitHub con el tag `vX.Y.Z`. En la descripci贸n del release debes poner lo mismo que agregaste al changelog. +1. Crea tu rama desde develop. +2. Haz un push de los commits y publica la nueva rama. +3. Abre un Pull Request apuntando tus cambios a develop. +4. Espera a la revisi贸n de los dem谩s integrantes del equipo. +5. Para poder mezclar los cambios se debe contar con 2 aprobaciones de los revisores y no tener alertas por parte de las herramientas de inspecci贸n. -Con eso Travis CI generar谩 autom谩ticamente una nueva versi贸n de la librer铆a y la publicar谩 en Maven Central. +### Esquema de flujo con git -### Deploy manual a maven central +![gitflow](https://wac-cdn.atlassian.com/dam/jcr:cc0b526e-adb7-4d45-874e-9bcea9898b4a/04%20Hotfix%20branches.svg?cdnVersion=1324) -El deploy de una nueva version ocurre autom谩ticamente, en Travis CI, cuando una nueva tag de git es creada. -Los tag de git deben respetar el standard de [SemVer](https://semver.org/). Adem谩s si el commit (o PR) a master no tiene un tag asociada, se generara una version snapshot. -Si de todas maneras necesitas hacer el release manualmente a MavenCentral ya sea de un snapshot o una nueva version, entonces debes configurar lo siguiente en tu archivo settings de maven, com煤nmente ubicado en `~/.m2/settings.xml` +## Generar una nueva versi贸n -```xml - - - - ossrh - your-jira-id - your-jira-pwd - - - - - ossrh - - true - - - gpg - your-gpg-pwd - - - - -``` +Para generar una nueva versi贸n, se debe crear un PR (con un t铆tulo "release: prepare release X.Y.Z" con los valores que correspondan para `X`, `Y` y `Z`). Se debe seguir el est谩ndar [SemVer](https://semver.org/lang/es/) para determinar si se incrementa el valor de `X` (si hay cambios no retrocompatibles), `Y` (para mejoras retrocompatibles) o `Z` (si s贸lo hubo correcciones a bugs). -- `your-jira-id`: Usuario de Jira del repositorio Nexus. -- `your-jira-pwd`: Password del usuario Jira de Nexus. -- `your-gpg-pwd`: Frase para la el certificado de firma gpg. +En ese PR deben incluirse los siguientes cambios: -_*Nota*: para subir codigo a MavenCentral, este debe estar firmado._ [Mas informaci贸n](https://dracoblue.net/dev/uploading-snapshots-and-releases-to-maven-central-with-travis/) +1. Modificar el archivo `CHANGELOG.md` para incluir una nueva entrada (al comienzo) para `X.Y.Z` que explique en espa帽ol los cambios. +2. Modificar el archivo `pom.xml` y modificar la versi贸n. -Si quieres probar el snapshot que se genera en MavenCentral, debes agregar el repositorio de snapshots de Sonatype, a continuaci贸n -esta la configuraci贸n que debes agregar a tu settings `~/.m2/settings.xml` -```xml - - - allow-snapshots - true - - - snapshots-repo - https://oss.sonatype.org/content/repositories/snapshots - false - true - - - - -``` +Luego de obtener aprobaci贸n del PR, debe mezclarse a master e inmediatamente generar un release en GitHub con el tag `vX.Y.Z`. En la descripci贸n del release debes poner lo mismo que agregaste al changelog. - +Con eso Github Actions generar谩 autom谩ticamente una nueva versi贸n de la librer铆a y la publicar谩 en Maven Central. +Posterior a la liberaci贸n debes mezclar la rama release en develop, finalmente realizar un rebase de la rama develop utilizando como base la rama main. diff --git a/pom.xml b/pom.xml index 12889f15..e6d3003c 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ com.github.transbankdevelopers transbank-sdk-java - 6.0.0 + 6.1.0 Transbank Java SDK 2018 @@ -103,13 +103,13 @@ com.google.code.gson gson - 2.12.1 + 2.13.1 org.slf4j slf4j-api - 1.7.32 + 1.7.36 test @@ -131,7 +131,7 @@ org.mockito mockito-core - 4.0.0 + 5.18.0 test @@ -221,52 +221,55 @@ - + org.jacoco jacoco-maven-plugin - 0.8.2 + 0.8.11 + prepare-agent prepare-agent jacoco-report - test + verify report - - - jacoco-check - - check - - - - - PACKAGE - - - LINE - COVEREDRATIO - 0.0 - - - - - - - + + + no-gpg + + + skipGpg + true + + + + + + org.apache.maven.plugins + maven-gpg-plugin + + + sign-artifacts + none + + + + + + release diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 00000000..e3092c03 --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,10 @@ +sonar.organization=transbankdevelopers +sonar.projectKey=TransbankDevelopers_transbank-sdk-java +sonar.language=java +sonar.projectVersion=1.0.0 +sonar.sourceEncoding=UTF-8 +sonar.sources=src/main/java +sonar.tests=src/test/java +sonar.java.binaries=target/classes +sonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml +sonar.exclusions=**/model/**,**/requests/**,**/responses/**,**/exception/** diff --git a/src/main/java/cl/transbank/common/BaseTransaction.java b/src/main/java/cl/transbank/common/BaseTransaction.java index 6a428c6c..857a2a35 100644 --- a/src/main/java/cl/transbank/common/BaseTransaction.java +++ b/src/main/java/cl/transbank/common/BaseTransaction.java @@ -1,10 +1,12 @@ package cl.transbank.common; import cl.transbank.model.Options; +import lombok.Getter; /** * This abstract class represents a base transaction with common properties and methods. */ +@Getter public abstract class BaseTransaction { /** diff --git a/src/main/java/cl/transbank/webpay/exception/QueryBinException.java b/src/main/java/cl/transbank/webpay/exception/QueryBinException.java new file mode 100644 index 00000000..6f056278 --- /dev/null +++ b/src/main/java/cl/transbank/webpay/exception/QueryBinException.java @@ -0,0 +1,33 @@ +package cl.transbank.webpay.exception; + +/** + * This class represents an exception that is thrown when a query bin operation + * fails. + */ +public class QueryBinException extends WebpayException { + + /** + * Constructs a new QueryBinException with no detail message. + */ + public QueryBinException() { + super(); + } + + /** + * Constructs a new QueryBinException with the specified cause. + * + * @param e The cause of the exception. + */ + public QueryBinException(Exception e) { + super(e); + } + + /** + * Constructs a new QueryBinException with the specified detail message. + * + * @param message The detail message. + */ + public QueryBinException(String message) { + super(message); + } +} diff --git a/src/main/java/cl/transbank/webpay/oneclick/Oneclick.java b/src/main/java/cl/transbank/webpay/oneclick/Oneclick.java index 9f9b68cc..8f028a1a 100644 --- a/src/main/java/cl/transbank/webpay/oneclick/Oneclick.java +++ b/src/main/java/cl/transbank/webpay/oneclick/Oneclick.java @@ -5,7 +5,8 @@ import cl.transbank.webpay.common.WebpayOptions; /** - * This class provides methods to configure and perform transactions with the Oneclick service. + * This class provides methods to configure and perform transactions with the + * Oneclick service. */ public class Oneclick { @@ -19,26 +20,28 @@ public MallInscription(Options options) { } /** - * Creates and returns an instance of `MallInscription` configured for the integration environment. + * Creates and returns an instance of `MallInscription` configured for the + * integration environment. * * @param commerceCode The commerce code. - * @param apiKey The API key used for authentication. - * @return A new instance of `MallInscription` configured for the test environment (IntegrationType.TEST). + * @param apiKey The API key used for authentication. + * @return A new instance of `MallInscription` configured for the test + * environment (IntegrationType.TEST). */ - public static MallInscription buildForIntegration(String commerceCode, String apiKey) - { + public static MallInscription buildForIntegration(String commerceCode, String apiKey) { return new Oneclick.MallInscription(new WebpayOptions(commerceCode, apiKey, IntegrationType.TEST)); } /** - * Creates and returns an instance of `MallInscription` configured for the production environment. + * Creates and returns an instance of `MallInscription` configured for the + * production environment. * * @param commerceCode The commerce code. - * @param apiKey The API key used for authentication. - * @return A new instance of `MallInscription` configured for the production environment (IntegrationType.LIVE). + * @param apiKey The API key used for authentication. + * @return A new instance of `MallInscription` configured for the production + * environment (IntegrationType.LIVE). */ - public static MallInscription buildForProduction(String commerceCode, String apiKey) - { + public static MallInscription buildForProduction(String commerceCode, String apiKey) { return new Oneclick.MallInscription(new WebpayOptions(commerceCode, apiKey, IntegrationType.LIVE)); } } @@ -53,28 +56,66 @@ public MallTransaction(Options options) { } /** - * Creates and returns an instance of `MallTransaction` configured for the integration environment. + * Creates and returns an instance of `MallTransaction` configured for the + * integration environment. * * @param commerceCode The commerce code. - * @param apiKey The API key used for authentication. - * @return A new instance of `MallTransaction` configured for the test environment (IntegrationType.TEST). + * @param apiKey The API key used for authentication. + * @return A new instance of `MallTransaction` configured for the test + * environment (IntegrationType.TEST). */ - public static MallTransaction buildForIntegration(String commerceCode, String apiKey) - { + public static MallTransaction buildForIntegration(String commerceCode, String apiKey) { return new Oneclick.MallTransaction(new WebpayOptions(commerceCode, apiKey, IntegrationType.TEST)); } /** - * Creates and returns an instance of `MallTransaction` configured for the production environment. + * Creates and returns an instance of `MallTransaction` configured for the + * production environment. * * @param commerceCode The commerce code. - * @param apiKey The API key used for authentication. - * @return A new instance of `MallTransaction` configured for the production environment (IntegrationType.LIVE). + * @param apiKey The API key used for authentication. + * @return A new instance of `MallTransaction` configured for the production + * environment (IntegrationType.LIVE). */ - public static MallTransaction buildForProduction(String commerceCode, String apiKey) - { + public static MallTransaction buildForProduction(String commerceCode, String apiKey) { return new Oneclick.MallTransaction(new WebpayOptions(commerceCode, apiKey, IntegrationType.LIVE)); } } + /** + * Default constructor. Uses default options if none are provided. + */ + public static class MallBinInfo extends OneclickMallBinInfo { + + public MallBinInfo(Options options) { + super(options); + } + + /** + * Creates and returns an instance of `MallBinInfo` configured for the + * integration environment. + * + * @param commerceCode The commerce code. + * @param apiKey The API key used for authentication. + * @return A new instance of `MallBinInfo` configured for the test + * environment (IntegrationType.TEST). + */ + public static MallBinInfo buildForIntegration(String commerceCode, String apiKey) { + return new Oneclick.MallBinInfo(new WebpayOptions(commerceCode, apiKey, IntegrationType.TEST)); + } + + /** + * Creates and returns an instance of `MallBinInfo` configured for the + * production environment. + * + * @param commerceCode The commerce code. + * @param apiKey The API key used for authentication. + * @return A new instance of `MallBinInfo` configured for the production + * environment (IntegrationType.LIVE). + */ + public static MallBinInfo buildForProduction(String commerceCode, String apiKey) { + return new Oneclick.MallBinInfo(new WebpayOptions(commerceCode, apiKey, IntegrationType.LIVE)); + } + } + } diff --git a/src/main/java/cl/transbank/webpay/oneclick/OneclickMallBinInfo.java b/src/main/java/cl/transbank/webpay/oneclick/OneclickMallBinInfo.java new file mode 100644 index 00000000..ff6aa646 --- /dev/null +++ b/src/main/java/cl/transbank/webpay/oneclick/OneclickMallBinInfo.java @@ -0,0 +1,59 @@ +package cl.transbank.webpay.oneclick; + +import java.io.IOException; + +import cl.transbank.common.ApiConstants; +import cl.transbank.common.BaseTransaction; +import cl.transbank.exception.TransbankException; +import cl.transbank.model.Options; +import cl.transbank.model.WebpayApiRequest; +import cl.transbank.util.HttpUtil; +import cl.transbank.util.ValidationUtil; +import cl.transbank.util.WebpayApiResource; +import cl.transbank.webpay.exception.QueryBinException; +import cl.transbank.webpay.oneclick.requests.QueryBinRequest; +import cl.transbank.webpay.oneclick.responses.OneclickMallQueryBinResponse; + +abstract class OneclickMallBinInfo extends BaseTransaction { + /** + * This abstract class represents the OneclickMallBinInfo and provides methods + * to handle Oneclick Mall Bin Info. + */ + protected OneclickMallBinInfo(Options options) { + super(options); + } + + /** + * Query for BIN information. + * + * @param tbkUser The inscription id of the user. + * + * @return The response from the query BIN request. + * @throws IOException If there is an error during the execution of the + * request. + * @throws QueryBinException If there is an error during the query of the + * BIN. + */ + public OneclickMallQueryBinResponse queryBin( + String tbkUser) throws IOException, QueryBinException { + ValidationUtil.hasTextTrimWithMaxLength( + tbkUser, + ApiConstants.TBK_USER_LENGTH, + "tbkUser"); + + final WebpayApiRequest request = new QueryBinRequest(tbkUser); + String endpoint = String.format( + "%s/bin_info", + ApiConstants.ONECLICK_ENDPOINT); + try { + return WebpayApiResource.execute( + endpoint, + HttpUtil.RequestMethod.POST, + request, + options, + OneclickMallQueryBinResponse.class); + } catch (TransbankException e) { + throw new QueryBinException(e); + } + } +} diff --git a/src/main/java/cl/transbank/webpay/oneclick/requests/QueryBinRequest.java b/src/main/java/cl/transbank/webpay/oneclick/requests/QueryBinRequest.java new file mode 100644 index 00000000..186f7a28 --- /dev/null +++ b/src/main/java/cl/transbank/webpay/oneclick/requests/QueryBinRequest.java @@ -0,0 +1,16 @@ +package cl.transbank.webpay.oneclick.requests; + +import cl.transbank.model.WebpayApiRequest; +import lombok.*; + +/** + * This class represents a request to query a BIN. + */ +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Setter +@ToString +public class QueryBinRequest extends WebpayApiRequest { + private String tbkUser; +} diff --git a/src/main/java/cl/transbank/webpay/oneclick/responses/OneclickMallQueryBinResponse.java b/src/main/java/cl/transbank/webpay/oneclick/responses/OneclickMallQueryBinResponse.java new file mode 100644 index 00000000..2ef6e6d6 --- /dev/null +++ b/src/main/java/cl/transbank/webpay/oneclick/responses/OneclickMallQueryBinResponse.java @@ -0,0 +1,18 @@ +package cl.transbank.webpay.oneclick.responses; + +import lombok.*; + +/** + * This class represents the response from the OneclickMallBinInfo + * query bin request. + */ +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Setter +@ToString +public class OneclickMallQueryBinResponse { + private String binIssuer; + private String binPaymentType; + private String binBrand; +} diff --git a/src/test/java/webpayplus/OneclickMallTest.java b/src/test/java/webpayplus/OneclickMallTest.java index 57452826..a873a48b 100644 --- a/src/test/java/webpayplus/OneclickMallTest.java +++ b/src/test/java/webpayplus/OneclickMallTest.java @@ -24,7 +24,7 @@ import static org.junit.jupiter.api.Assertions.*; import static org.mockserver.integration.ClientAndServer.startClientAndServer; -class OneclickMallTest extends OneclickMallTestBase { +class OneclickMallTest extends OneclickMallTestBase { private static String apiUrl = ApiConstants.ONECLICK_ENDPOINT; private static Options option = new WebpayOptions(IntegrationCommerceCodes.ONECLICK_MALL, @@ -53,7 +53,7 @@ void resetMockServer() { @Test void start() throws IOException, InscriptionStartException { - String url = String.format("/%s/inscriptions",apiUrl); + String url = String.format("/%s/inscriptions", apiUrl); String urlResponse = "https://webpay3gint.transbank.cl/webpayserver/bp_multicode_inscription.cgi"; Map mapResponse = new HashMap(); @@ -66,7 +66,8 @@ void start() throws IOException, InscriptionStartException { String returnUrl = "http://localhost:8081/oneclick-mall/finish"; - final OneclickMallInscriptionStartResponse response = (new Oneclick.MallInscription(option)).start(username, email, returnUrl); + final OneclickMallInscriptionStartResponse response = (new Oneclick.MallInscription(option)).start(username, + email, returnUrl); assertEquals(response.getToken(), testToken); assertEquals(response.getUrlWebpay(), urlResponse); } @@ -124,7 +125,7 @@ void deleteNotFound() throws IOException { @Test void authorize() throws IOException, TransactionAuthorizeException { OneclickMallTransactionStatusResponse expectedResponse = generateStatusResponse(); - String url = String.format("/%s/transactions",apiUrl); + String url = String.format("/%s/transactions", apiUrl); setResponsePost(url, generateJsonResponse()); String tbkUserReq = "aaaaaaaaaaaaa-bbbbbbbb-cccccc"; @@ -140,13 +141,14 @@ void authorize() throws IOException, TransactionAuthorizeException { .add(amountMallOne, commerceCode1, buyOrderMallOne, installmentsNumberMallOne) .add(amountMallTwo, commerceCode2, buyOrderMallTwo, installmentsNumberMallTwo); - final OneclickMallTransactionAuthorizeResponse response = (new Oneclick.MallTransaction(option)).authorize(username, tbkUserReq, buyOrderReq, details); + final OneclickMallTransactionAuthorizeResponse response = (new Oneclick.MallTransaction(option)) + .authorize(username, tbkUserReq, buyOrderReq, details); assertEquals(response.getBuyOrder(), expectedResponse.getBuyOrder()); assertEquals(response.getCardDetail().getCardNumber(), expectedResponse.getCardDetail().getCardNumber()); assertEquals(response.getAccountingDate(), expectedResponse.getAccountingDate()); assertEquals(response.getTransactionDate(), expectedResponse.getTransactionDate()); - //details1 + // details1 OneclickMallTransactionStatusResponse.Detail expectedDetail1 = expectedResponse.getDetails().get(0); OneclickMallTransactionAuthorizeResponse.Detail detail1 = response.getDetails().get(0); assertEquals(detail1.getAmount(), expectedDetail1.getAmount()); @@ -157,7 +159,7 @@ void authorize() throws IOException, TransactionAuthorizeException { assertEquals(detail1.getInstallmentsNumber(), expectedDetail1.getInstallmentsNumber()); assertEquals(detail1.getCommerceCode(), expectedDetail1.getCommerceCode()); assertEquals(detail1.getBuyOrder(), expectedDetail1.getBuyOrder()); - //details2 + // details2 OneclickMallTransactionStatusResponse.Detail expectedDetail2 = expectedResponse.getDetails().get(1); OneclickMallTransactionAuthorizeResponse.Detail detail2 = response.getDetails().get(1); assertEquals(detail2.getAmount(), expectedDetail2.getAmount()); @@ -187,7 +189,8 @@ void refund() throws IOException, TransactionRefundException { String childCommerceCode = "597055555542"; String childBuyOrder = "2019439134"; double amount = 1000d; - final OneclickMallTransactionRefundResponse response = (new Oneclick.MallTransaction(option)).refund(buyOrder, childCommerceCode, childBuyOrder, amount); + final OneclickMallTransactionRefundResponse response = (new Oneclick.MallTransaction(option)).refund(buyOrder, + childCommerceCode, childBuyOrder, amount); assertEquals(response.getType(), type); } @@ -198,13 +201,14 @@ void status() throws IOException, TransactionStatusException { String url = String.format("/%s/transactions/%s", apiUrl, expectedResponse.getBuyOrder()); setResponseGet(url, generateJsonResponse()); - final OneclickMallTransactionStatusResponse response = (new Oneclick.MallTransaction(option)).status(expectedResponse.getBuyOrder()); + final OneclickMallTransactionStatusResponse response = (new Oneclick.MallTransaction(option)) + .status(expectedResponse.getBuyOrder()); assertEquals(response.getBuyOrder(), expectedResponse.getBuyOrder()); assertEquals(response.getCardDetail().getCardNumber(), expectedResponse.getCardDetail().getCardNumber()); assertEquals(response.getAccountingDate(), expectedResponse.getAccountingDate()); assertEquals(response.getTransactionDate(), expectedResponse.getTransactionDate()); - //details1 + // details1 OneclickMallTransactionStatusResponse.Detail expectedDetail1 = expectedResponse.getDetails().get(0); OneclickMallTransactionStatusResponse.Detail detail1 = response.getDetails().get(0); assertEquals(detail1.getAmount(), expectedDetail1.getAmount()); @@ -215,7 +219,7 @@ void status() throws IOException, TransactionStatusException { assertEquals(detail1.getInstallmentsNumber(), expectedDetail1.getInstallmentsNumber()); assertEquals(detail1.getCommerceCode(), expectedDetail1.getCommerceCode()); assertEquals(detail1.getBuyOrder(), expectedDetail1.getBuyOrder()); - //details2 + // details2 OneclickMallTransactionStatusResponse.Detail expectedDetail2 = expectedResponse.getDetails().get(1); OneclickMallTransactionStatusResponse.Detail detail2 = response.getDetails().get(1); assertEquals(detail2.getAmount(), expectedDetail2.getAmount()); @@ -228,6 +232,26 @@ void status() throws IOException, TransactionStatusException { assertEquals(detail2.getBuyOrder(), expectedDetail2.getBuyOrder()); } + @Test + void queryBin() throws IOException, QueryBinException { + String url = String.format("/%s/bin_info", apiUrl); + String binIssuer = "BANCO TEST"; + String binPaymentType = "Prepago"; + String binBrand = "VISA"; + Map mapResponse = new HashMap(); + mapResponse.put("bin_issuer", binIssuer); + mapResponse.put("bin_payment_type", binPaymentType); + mapResponse.put("bin_brand", binBrand); + + Gson gson = new GsonBuilder().create(); + String jsonResponse = gson.toJson(mapResponse); + setResponsePost(url, jsonResponse); + + final OneclickMallQueryBinResponse response = (new Oneclick.MallBinInfo(option)).queryBin("fakeTbkUser"); + assertEquals(response.getBinIssuer(), binIssuer); + assertEquals(response.getBinPaymentType(), binPaymentType); + assertEquals(response.getBinBrand(), binBrand); + } } diff --git a/src/test/java/webpayplus/OneclickTest.java b/src/test/java/webpayplus/OneclickTest.java new file mode 100644 index 00000000..714a4d8f --- /dev/null +++ b/src/test/java/webpayplus/OneclickTest.java @@ -0,0 +1,70 @@ +package webpayplus; + +import cl.transbank.common.IntegrationType; +import cl.transbank.model.Options; +import cl.transbank.webpay.common.WebpayOptions; +import cl.transbank.webpay.oneclick.Oneclick; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +public class OneclickTest { + + private static final String COMMERCE_CODE = "123456789"; + private static final String API_KEY = "test_api_key"; + + @Test + public void testMallInscriptionBuildForIntegration() { + Oneclick.MallInscription inscription = Oneclick.MallInscription.buildForIntegration(COMMERCE_CODE, API_KEY); + + assertNotNull(inscription); + + Options options = inscription.getOptions(); + assertTrue(options instanceof WebpayOptions); + WebpayOptions webpayOptions = (WebpayOptions) options; + + assertEquals(COMMERCE_CODE, webpayOptions.getCommerceCode()); + assertEquals(API_KEY, webpayOptions.getApiKey()); + assertEquals(IntegrationType.TEST, webpayOptions.getIntegrationType()); + } + + @Test + public void testMallInscriptionBuildForProduction() { + Oneclick.MallInscription inscription = Oneclick.MallInscription.buildForProduction(COMMERCE_CODE, API_KEY); + + assertNotNull(inscription); + assertEquals(IntegrationType.LIVE, ((WebpayOptions) inscription.getOptions()).getIntegrationType()); + } + + @Test + public void testMallTransactionBuildForIntegration() { + Oneclick.MallTransaction transaction = Oneclick.MallTransaction.buildForIntegration(COMMERCE_CODE, API_KEY); + + assertNotNull(transaction); + assertEquals(IntegrationType.TEST, ((WebpayOptions) transaction.getOptions()).getIntegrationType()); + } + + @Test + public void testMallTransactionBuildForProduction() { + Oneclick.MallTransaction transaction = Oneclick.MallTransaction.buildForProduction(COMMERCE_CODE, API_KEY); + + assertNotNull(transaction); + assertEquals(IntegrationType.LIVE, ((WebpayOptions) transaction.getOptions()).getIntegrationType()); + } + + @Test + public void testMallBinInfoBuildForIntegration() { + Oneclick.MallBinInfo binInfo = Oneclick.MallBinInfo.buildForIntegration(COMMERCE_CODE, API_KEY); + + assertNotNull(binInfo); + assertEquals(IntegrationType.TEST, ((WebpayOptions) binInfo.getOptions()).getIntegrationType()); + } + + @Test + public void testMallBinInfoBuildForProduction() { + Oneclick.MallBinInfo binInfo = Oneclick.MallBinInfo.buildForProduction(COMMERCE_CODE, API_KEY); + + assertNotNull(binInfo); + assertEquals(IntegrationType.LIVE, ((WebpayOptions) binInfo.getOptions()).getIntegrationType()); + } +}