Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: simple client using rsa #4

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/

### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr

### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache

### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/

### VS Code ###
.vscode/

### Mac OS ###
.DS_Store

.idea/
88 changes: 87 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,88 @@
# iugu_rsa_java
Lib em Java para RSA

Client de exemplo em Java, utilizando Feign (https://github.com/OpenFeign/feign), para consumo das APIs da iugu.

## Métodos suportados

Esta é uma versão demonstrativa e tem suporte apenas para alguns métodos que utilizam a nova autenticação com chave RSA,
que são:

- /v1/signature/validate
- /v1/accounts/{accountId}/request_withdraw
- /v1/transfers

## Como utilizar

### Criação das chaves pública e privada

Para criação e configuração das chaves público e privada, siga as recomendações dos
links:

- https://dev.iugu.com/reference/autentica%C3%A7%C3%A3o
- https://www.youtube.com/watch?v=oY9-8cVQzvo

### Utilizando a chave privada no seu projeto

Existem várias abordagens para utilização de variáveis no ambiente num projeto Java. Como sugestão, podemos fazer
o encode, em Base64, do conteúdo do arquivo da chave privada e utilizar um "gerenciador de segredos", como
o Secrets Manager da AWS ou GCP, ou qualquer outro gerenciador para armazená-lo.

Essa abordagem facilitará a troca do segredo caso necessária e facilitará sua utilização, tornando desnecessária
a manipulação de arquivos em tempo de execução.

Supondo que o valor está definido como uma variável de ambiente, podemos criar um método para recuperá-lo da seguinte
forma:

```java
public String getPrivateKey() {
final String privateKeyInBase64 = System.getenv("IUGU_PRIVATE_KEY");
return new String(Base64.getDecoder().decode(privateKeyInBase64));
}
```

Neste caso, o nome da variável de ambiente utilizada foi "IUGU_PRIVATE_KEY", mas, isso vai depender de como a variável
foi definida anteriormente.

### Utilizando o client Iugu

Com o valor da chave privada em mãos, agora podemos utilizar a implementação do client Iugu. Para tal, precisamos
instanciar o client:

```java
final IuguClient iuguClient = IuguClient.getProductionInstance();
```

Apenas para exemplo, vamos criar uma requisição de transferência de R$10 para a conta "12345":

```java
final TransferRequest transferRequest = new TransferRequest();
transferRequest.setReceiverId("12345");
transferRequest.setAmountCents(BigInteger.valueOf(10));
```

Como o objetivo aqui é testar a chave, vamos chamar o método "/v1/signature/validate" utilizando essa request:

```java
final Object response = iuguClient
.withApiToken(apiToken)
.withPrivateKey(privateKey)
.validateSignature(transferRequest);
```

Perceba que aqui estamos utilizando 2 métodos de segurança:

- withApiToken: esse método inclui o "apiToken" no header da requisição;
- withPrivateKey: esse método inclui a assinatura, utilizando a chave RSA, no header da requisição.

Se tudo foi configurado corretamente, o método "/v1/signature/validate" vai retornar um 200.

### Exemplo completo

A classe "IuguClientTest" possui um exemplo funcional, sendo apenas necessário definir o valor do "apiToken" e do "
privateKey".

## Disclaimer

Criei esse projeto de exemplo apenas para facilitar a utilização da chave RSA num ambiente real, sem necessidade da
manipulação de arquivos e tentando abstrair o máximo possível da complexidade do fluxo, trazendo complexidade apenas
para o client.
45 changes: 45 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.iugu</groupId>
<artifactId>iugu_rsa_java</artifactId>
<version>0.0.1</version>

<properties>
<java.version>17</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId>
<version>13.2.1</version>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-jackson</artifactId>
<version>13.2.1</version>
</dependency>
</dependencies>

<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
28 changes: 28 additions & 0 deletions src/main/java/com/iugu/Iugu.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.iugu;

import com.iugu.domain.request.RequestWithdrawRequest;
import com.iugu.domain.request.TransferRequest;
import com.iugu.domain.response.RequestWithdrawResponse;
import com.iugu.domain.response.TransferResponse;
import feign.Headers;
import feign.Param;
import feign.RequestLine;

import java.security.SignatureException;

/**
* @author italobrunos
*/
@Headers("Content-Type: application/json")
public interface Iugu {

@RequestLine("POST /v1/signature/validate")
Object validateSignature(Object body) throws SignatureException;

@RequestLine("POST /v1/accounts/{accountId}/request_withdraw")
RequestWithdrawResponse requestWithdraw(RequestWithdrawRequest request,
@Param("accountId") String accountId) throws SignatureException;

@RequestLine("POST /v1/transfers")
TransferResponse transfer(TransferRequest transferRequest) throws SignatureException;
}
Loading