Skip to content

Commit

Permalink
feat: 상품 호출 메소드 (requestProduct) (#6)
Browse files Browse the repository at this point in the history
* feat: requestProduct 초기 버전

* feat: EasyCodefResponse 파싱 버그 개선

* feat: EasyCodef 파라미터 단일화

* docs: update README.md

* docs: update README.md

* docs: update README.md

* docs: update README.md

* docs: update README.md

* release: 2.0.0-alpha-003
  • Loading branch information
h-beeen authored Nov 13, 2024
1 parent 72d395e commit db6fffa
Show file tree
Hide file tree
Showing 20 changed files with 363 additions and 60 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,4 @@ out
test-output
atlassian-ide-plugin.xml
.gradletasknamecache
/src/test/java/io/codef/api/EasyCodefTokenTest.java
55 changes: 42 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
<h1 align="center">EasyCodef Java V2</h1>
<br>
<p align="center">
<a title="코드에프" href="https://codef.io/">
<picture>
Expand All @@ -9,44 +11,71 @@

<br>

# easycodef-java-v2

`easycodef-java-v2`는 codef API를 더욱 더 편리하게 연동할 수 있도록 돕는 오픈소스 라이브러리입니다.
`easycodef-java-v2`는 codef API를 JDK 환경에서 더욱 더 편리하게 연동할 수 있도록 돕는 오픈소스 라이브러리입니다.

현재 알파 버전 개발중으로 v2.0.0-ALPHA-002 버전으로 Maven Central Repository를 통해 배포중입니다.

## Release
2024년 상반기 실제 고객사 대상으로 릴리즈 예정입니다.

<a href="https://central.sonatype.com/artifact/io.codef.api/easycodef-java-v2"/><img src=https://github.com/user-attachments/assets/91bc4d3d-c971-43d8-b6a1-2798c68d82eb width="100px"></a><br><br>
<br><br>

## Release

[![Build Status](https://img.shields.io/github/actions/workflow/status/codef-io/easycodef-java-v2/publish.yml?style=for-the-badge&logo=gradle&color=02303A)](https://github.com/codef-io/easycodef-java-v2/actions?query=branch%3Amaster)<br>
[![Last Commit](https://img.shields.io/github/last-commit/codef-io/easycodef-java-v2/master?style=for-the-badge&label=LAST%20BUILD&logo=Github&color=181717)](https://github.com/codef-io/easycodef-java-v2)<br>
[![Maven Central](https://img.shields.io/maven-central/v/io.codef.api/easycodef-java-v2.svg?style=for-the-badge&label=Maven%20Central&logo=apache-maven&color=C71A36)](https://central.sonatype.com/artifact/io.codef.api/easycodef-java-v2)<br>


### Snippets
## Snippets

- Gradle(Kotlin)
```gradle
implementation("io.codef.api:easycodef-java-v2:2.0.0-alpha-002")
implementation("io.codef.api:easycodef-java-v2:2.0.0-alpha-003")
```
- Gradle(short)
```gradle
implementation 'io.codef.api:easycodef-java-v2:2.0.0-alpha-002'
implementation 'io.codef.api:easycodef-java-v2:2.0.0-alpha-003'
```
- Maven
```xml
<dependency>
<groupId>io.codef.api</groupId>
<artifactId>easycodef-java-v2</artifactId>
<version>2.0.0-alpha-002</version>
<version>2.0.0-alpha-003</version>
</dependency>
```
## LISENCE
## Get It !
<img alt="헥토데이터" src="https://github.com/user-attachments/assets/ac6b7a7d-33f1-4b1e-9fbb-8231d56e7f33" width="100">
- 예제 코드
```java
EasyCodef easyCodef = EasyCodefBuilder.builder()
.clientType(CodefClientType.DEMO)
.clientId("your-client-id")
.clientSecret("your-client-secret")
.publicKey("your-public-key")
.build();
EasyCodefRequest request = EasyCodefRequestBuilder.builder()
.path("/v1/kr/public/hw/nip-cdc-list/my-vaccination")
.organization("0011")
.requestBody("loginType", "1")
.requestBody("userId", "your-nhis-id")
.secureRequestBody("userPassword", "your-nhis-password")
.secureWith(easyCodef)
.build();
EasyCodefResponse easyCodefResponse = easyCodef.requestProduct(request);
final EasyCodefResponse.Result result = easyCodefResponse.result();
final Object data = easyCodefResponse.data();
```

---

<p align="center">
<img alt="헥토데이터" src="https://github.com/user-attachments/assets/ac6b7a7d-33f1-4b1e-9fbb-8231d56e7f33" height="20"><br>
<span>MIT © | <a href="https://github.com/codef-io/easycodef-java-v2/blob/master/LICENSE" target="_blank">LICENSE</a></span>
</p>

MIT © Hectodata Co,. Ltd [LICENSE](https://github.com/codef-io/easycodef-java-v2/blob/master/LICENSE) 파일을 참고하세요.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ plugins {


group = "io.codef.api"
version = "2.0.0-alpha-002"
version = "2.0.0-alpha-003"

signing {
useInMemoryPgpKeys(
Expand Down
5 changes: 0 additions & 5 deletions src/main/java/io/codef/api/CodefUrl.java

This file was deleted.

3 changes: 3 additions & 0 deletions src/main/java/io/codef/api/CodefValidator.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package io.codef.api;

import io.codef.api.error.CodefError;
import io.codef.api.error.CodefException;

import java.util.Optional;
import java.util.UUID;

Expand Down
28 changes: 25 additions & 3 deletions src/main/java/io/codef/api/EasyCodef.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,38 @@
package io.codef.api;

import io.codef.api.constants.CodefClientType;
import io.codef.api.dto.EasyCodefRequest;
import io.codef.api.dto.EasyCodefResponse;
import io.codef.api.util.RsaUtil;

import java.security.PublicKey;

public class EasyCodef {
private final String publicKey;
private final EasyCodefClientType clientType;
private final PublicKey publicKey;
private final CodefClientType clientType;
private final EasyCodefToken easyCodefToken;

protected EasyCodef(
EasyCodefBuilder builder,
EasyCodefToken easyCodefToken
) {
this.publicKey = RsaUtil.generatePublicKey(builder.getPublicKey());
this.clientType = builder.getClientType();
this.publicKey = builder.getPublicKey();
this.easyCodefToken = easyCodefToken;
}

public EasyCodefResponse requestProduct(EasyCodefRequest request) {
final String requestUrl = generateRequestUrl(request);
easyCodefToken.validateAndRefreshToken();

return EasyCodefConnector.requestProduct(request, easyCodefToken, requestUrl);
}

private String generateRequestUrl(EasyCodefRequest request) {
return clientType.getHost() + request.path();
}

public PublicKey getPublicKey() {
return publicKey;
}
}
10 changes: 7 additions & 3 deletions src/main/java/io/codef/api/EasyCodefBuilder.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package io.codef.api;

import io.codef.api.constants.CodefClientType;
import io.codef.api.error.CodefError;
import io.codef.api.error.CodefException;

import java.util.UUID;

public class EasyCodefBuilder {
private String publicKey;
private UUID clientId;
private UUID clientSecret;
private EasyCodefClientType clientType;
private CodefClientType clientType;

public static EasyCodefBuilder builder() {
return new EasyCodefBuilder();
Expand All @@ -27,7 +31,7 @@ public EasyCodefBuilder clientSecret(String clientSecret) {
return this;
}

public EasyCodefBuilder clientType(EasyCodefClientType clientType) {
public EasyCodefBuilder clientType(CodefClientType clientType) {
this.clientType = clientType;
return this;
}
Expand Down Expand Up @@ -69,7 +73,7 @@ protected UUID getClientSecret() {
return clientSecret;
}

protected EasyCodefClientType getClientType() {
protected CodefClientType getClientType() {
return clientType;
}
}
12 changes: 0 additions & 12 deletions src/main/java/io/codef/api/EasyCodefClientType.java

This file was deleted.

45 changes: 44 additions & 1 deletion src/main/java/io/codef/api/EasyCodefConnector.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,34 @@
package io.codef.api;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import io.codef.api.constants.CodefHost;
import io.codef.api.constants.CodefPath;
import io.codef.api.dto.EasyCodefRequest;
import io.codef.api.dto.EasyCodefResponse;
import io.codef.api.error.CodefError;
import io.codef.api.error.CodefException;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.StringEntity;

import java.net.URLDecoder;

import static org.apache.hc.client5.http.auth.StandardAuthScheme.BASIC;
import static org.apache.hc.client5.http.auth.StandardAuthScheme.BEARER;
import static org.apache.hc.core5.http.HttpHeaders.AUTHORIZATION;

final class EasyCodefConnector {

static String issueToken(String codefOAuthToken) {
System.out.println("issue Token !!!\n\n");
final String BASIC_TOKEN_FORMAT = BASIC + " %s";
final String accessTokenParameter = "access_token";

try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {
HttpPost httpPost = new HttpPost(CodefUrl.CODEF_OAUTH_SERVER + CodefUri.ISSUE_TOKEN);
HttpPost httpPost = new HttpPost(CodefHost.CODEF_OAUTH_SERVER + CodefPath.ISSUE_TOKEN);
httpPost.addHeader(AUTHORIZATION, String.format(BASIC_TOKEN_FORMAT, codefOAuthToken));

return httpClient.execute(httpPost, response -> {
Expand All @@ -40,4 +52,35 @@ static String issueToken(String codefOAuthToken) {
throw CodefException.of(CodefError.OAUTH_CONNECTION_ERROR, exception);
}
}

static EasyCodefResponse requestProduct(
EasyCodefRequest request,
EasyCodefToken token,
String requestUrl
) {
final String BEARER_TOKEN_FORMAT = BEARER + " %s";

try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {
HttpPost httpPost = new HttpPost(requestUrl);
httpPost.addHeader(AUTHORIZATION, String.format(BEARER_TOKEN_FORMAT, token.getAccessToken()));
String rawRequest = JSON.toJSONString(request.requestParams());
httpPost.setEntity(new StringEntity(rawRequest));

return httpClient.execute(httpPost, response -> {
String httpResponse = EntityUtils.toString(response.getEntity());
String decodedResponse = URLDecoder.decode(httpResponse, "UTF-8");

// TODO {"error":"invalid_token","error_description":"Cannot convert access token to JSON","code":"CF-09990","message":"OAUTH2.0 토큰 에러입니다. 메시지를 확인하세요."}
JSONObject jsonResponseObject = JSON.parseObject(decodedResponse);

EasyCodefResponse.Result resultResponse = jsonResponseObject.getJSONObject("result").to(EasyCodefResponse.Result.class);
Object dataResponse = jsonResponseObject.getJSONObject("data").to(Object.class);
return new EasyCodefResponse(resultResponse, dataResponse);
});
} catch (CodefException exception) {
throw exception;
} catch (Exception exception) {
throw CodefException.of(CodefError.OAUTH_CONNECTION_ERROR, exception);
}
}
}
19 changes: 17 additions & 2 deletions src/main/java/io/codef/api/EasyCodefToken.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,24 @@ public class EasyCodefToken {
private LocalDateTime expiresAt;

protected EasyCodefToken(EasyCodefBuilder builder) {
String combinedKey = String.join(":", builder.getClientId().toString(), builder.getClientSecret().toString());
final int VALIDITY_PERIOD_DAYS = 7;
final String DELIMITER = ":";

String combinedKey = String.join(DELIMITER, builder.getClientId().toString(), builder.getClientSecret().toString());
this.oauthToken = Base64.getEncoder().encodeToString(combinedKey.getBytes());
this.accessToken = EasyCodefConnector.issueToken(oauthToken);
this.expiresAt = LocalDateTime.now();
this.expiresAt = LocalDateTime.now().plusDays(VALIDITY_PERIOD_DAYS);
}

public EasyCodefToken validateAndRefreshToken() {
if (expiresAt.isBefore(LocalDateTime.now().plusHours(24))) {
this.accessToken = EasyCodefConnector.issueToken(oauthToken);
this.expiresAt = LocalDateTime.now().plusDays(7);
}
return this;
}

public String getAccessToken() {
return accessToken;
}
}
16 changes: 16 additions & 0 deletions src/main/java/io/codef/api/constants/CodefClientType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package io.codef.api.constants;

public enum CodefClientType {
API(CodefHost.CODEF_API),
DEMO(CodefHost.CODEF_API_DEMO);

private final String host;

CodefClientType(String host) {
this.host = host;
}

public String getHost() {
return host;
}
}
7 changes: 7 additions & 0 deletions src/main/java/io/codef/api/constants/CodefHost.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package io.codef.api.constants;

public final class CodefHost {
public static final String CODEF_OAUTH_SERVER = "https://oauth.codef.io";
public static final String CODEF_API_DEMO = "https://development.codef.io";
public static final String CODEF_API = "https://api.codef.io";
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package io.codef.api;
package io.codef.api.constants;

final class CodefUri {
public final class CodefPath {
public static final String ISSUE_TOKEN = "/oauth/token?grant_type=client_credentials&scope=read";
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package io.codef.api;
package io.codef.api.constants;

public enum EasyCodefReferenceUrl {
public enum CodefReferenceUrl {
KEY("https://codef.io/account/keys"),
DEV_GUIDE_REST_API("https://developer.codef.io/common-guide/rest-api");
DEV_GUIDE_REST_API("https://developer.codef.io/common-guide/rest-api"),
GITHUB("https://github.com/codef-io/easycodef-java-v2"),
PRODUCT("https://developer.codef.io/product/api");

private final String url;

EasyCodefReferenceUrl(String url) {
CodefReferenceUrl(String url) {
this.url = url;
}

Expand Down
9 changes: 9 additions & 0 deletions src/main/java/io/codef/api/dto/EasyCodefRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package io.codef.api.dto;

import java.util.HashMap;

public record EasyCodefRequest(
String path,
HashMap<String, Object> requestParams
) {
}
Loading

0 comments on commit db6fffa

Please sign in to comment.