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: Add token caching #38

Merged
merged 1 commit into from
Dec 11, 2023
Merged
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Add the `gr4vy-java` dependency to your pom.xml:
<dependency>
<groupId>com.github.gr4vy</groupId>
<artifactId>gr4vy-java</artifactId>
<version>0.21.0</version>
<version>0.22.0</version>
</dependency>
```

Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<artifactId>gr4vy</artifactId>
<packaging>jar</packaging>
<name>gr4vy</name>
<version>0.21.0</version>
<version>0.22.0</version>
<url>https://gr4vy.com</url>
<description>Gr4vy Java SDK</description>

Expand Down
28 changes: 28 additions & 0 deletions src/main/java/com/gr4vy/sdk/CachedToken.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.gr4vy.sdk;

import java.time.Instant;

public class CachedToken {
private final long LEEWAY = 200;
private String token;
private long expiresAt;

public CachedToken(String token, long expiresAt) {
this.token = token;
this.expiresAt = expiresAt;
}

public Boolean isValid() {
long now = Instant.now().toEpochMilli();
// Add leeway in millis to give time for the HTTP request
return now < (expiresAt - LEEWAY);
}

public Boolean hasExpired() {
return !this.isValid();
}

public String getToken() {
return this.token;
}
}
68 changes: 54 additions & 14 deletions src/main/java/com/gr4vy/sdk/Gr4vyClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ public class Gr4vyClient {
public static final MediaType JSON
= MediaType.parse("application/json; charset=utf-8");

private CachedToken cachedToken = null;

/**
* Constructor
*/
Expand Down Expand Up @@ -131,15 +133,15 @@ public Builder connectTimeout(Duration connect) {
}
public Gr4vyClient build() {
if (this.host == null) {
String apiPrefix = this.environment == "sandbox" ? "sandbox." : "";
String apiPrefix = this.environment.equals("sandbox") ? "sandbox." : "";
this.host = "https://api." + apiPrefix + this.gr4vyId + ".gr4vy.app";
}
return new Gr4vyClient(this);
}
}

public void setHost(String host) {
this.host = host;
public void resetCachedToken() {
this.cachedToken = null;
}

private OkHttpClient getClient() {
Expand Down Expand Up @@ -193,6 +195,9 @@ public String getToken(String key, String[] scopes, Map<String, Object> embed, U
}

public String getToken(String key, String[] scopes, Map<String, Object> embed, UUID checkoutSessionId, int tokenExpiryMillis) throws IOException, NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException, JOSEException, ParseException {
if (cachedToken != null && cachedToken.isValid()) {
return cachedToken.getToken();
}
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

Reader reader = new StringReader(key);
Expand All @@ -215,7 +220,7 @@ public String getToken(String key, String[] scopes, Map<String, Object> embed, U
.jwtID(UUID.randomUUID().toString())
.notBeforeTime(now)
.issueTime(now)
.issuer("Gr4vy SDK 0.19.0 - Java")
.issuer("Gr4vy SDK 0.22.0 - Java")
.expirationTime(expire)
.claim("scopes", scopes);

Expand All @@ -234,7 +239,9 @@ public String getToken(String key, String[] scopes, Map<String, Object> embed, U

signedJWT.sign(signer);

return signedJWT.serialize();
String token = signedJWT.serialize();
cachedToken = new CachedToken(token, expire.getTime());
return token;
}

private static ECPublicKey publicFromPrivate(ECPrivateKey key) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException {
Expand Down Expand Up @@ -269,11 +276,11 @@ public String getKey() {
}
}

private String get(String endpoint) throws Gr4vyException {
public String get(String endpoint) throws Gr4vyException {
String[] scopes = {"*.read", "*.write"};
String accessToken = null;
try {
accessToken = this.getToken(this.getKey(), scopes, null);
accessToken = this.getToken(scopes);
} catch (Exception e2) {
throw new Gr4vyException("Unable to generate token", e2);
}
Expand Down Expand Up @@ -305,15 +312,15 @@ private String get(String endpoint) throws Gr4vyException {
return responseData;
}

private String post(String endpoint, String jsonBody) throws Gr4vyException {
public String post(String endpoint, String jsonBody) throws Gr4vyException {
return this.post(endpoint, jsonBody, null);
}

private String post(String endpoint, String jsonBody, String idempotencyKey) throws Gr4vyException {
public String post(String endpoint, String jsonBody, String idempotencyKey) throws Gr4vyException {
String[] scopes = {"*.read", "*.write"};
String accessToken = null;
try {
accessToken = this.getToken(this.getKey(), scopes, null);
accessToken = this.getToken(scopes);
} catch (Exception e2) {
throw new Gr4vyException("Unable to generate token", e2);
}
Expand Down Expand Up @@ -358,11 +365,11 @@ private String post(String endpoint, String jsonBody, String idempotencyKey) thr
return responseData;
}

private String put(String endpoint, String jsonBody) throws Gr4vyException {
public String put(String endpoint, String jsonBody) throws Gr4vyException {
String[] scopes = {"*.read", "*.write"};
String accessToken = null;
try {
accessToken = this.getToken(this.getKey(), scopes, null);
accessToken = this.getToken(scopes);
} catch (Exception e2) {
throw new Gr4vyException("Unable to generate token", e2);
}
Expand Down Expand Up @@ -405,11 +412,11 @@ private String put(String endpoint, String jsonBody) throws Gr4vyException {
return responseData;
}

private boolean delete(String endpoint) throws Gr4vyException {
public boolean delete(String endpoint) throws Gr4vyException {
String[] scopes = {"*.read", "*.write"};
String accessToken = null;
try {
accessToken = this.getToken(this.getKey(), scopes, null);
accessToken = this.getToken(scopes);
} catch (Exception e2) {
throw new Gr4vyException("Unable to generate token", e2);
}
Expand Down Expand Up @@ -546,6 +553,25 @@ public Refund refundTransaction(String transactionId, TransactionRefundRequest r
String response = this.post("/transactions/" + transactionId + "/refunds", this.gson.toJson(request));
return this.gson.fromJson(response,Refund.class);
}
public Refunds listRefundsForTransaction(String transactionId) {
String response = this.get("/transactions/" + transactionId + "/refunds");
return this.gson.fromJson(response,Refunds.class);
}
public Refunds listRefundsForTransaction(String transactionId, Map<String, Object> params) {
String endpoint = "/transactions/" + transactionId + "/refunds";
if (params.size() > 0) {
String encoded = Helper.urlEncodeUTF8(params);
endpoint = endpoint + "?" + encoded;
}
String response = this.get(endpoint);
return this.gson.fromJson(response,Refunds.class);
}
public Refund getRefund(String transactionId, String refundId) {
String endpoint = "/transactions/" + transactionId + "/refunds/" + refundId;
String response = this.get(endpoint);
return this.gson.fromJson(response,Refund.class);
}

public CheckoutSession newCheckoutSession(CheckoutSessionCreateRequest request) {
String response = this.post("/checkout/sessions", this.gson.toJson(request));
return this.gson.fromJson(response,CheckoutSession.class);
Expand All @@ -561,4 +587,18 @@ public CheckoutSession updateCheckoutSession(String checkoutSessionId, CheckoutS
public boolean deleteCheckoutSession(String checkoutSessionId) {
return this.delete("/checkout/sessions/" + checkoutSessionId);
}

public PaymentOptions listPaymentOptions(Map<String, Object> params) {
String endpoint = "/payment-options";
if (params.size() > 0) {
String encoded = Helper.urlEncodeUTF8(params);
endpoint = endpoint + "?" + encoded;
}
String response = this.get(endpoint);
return this.gson.fromJson(response, PaymentOptions.class);
}
public PaymentOptions listPaymentOptions(PaymentOptionsRequest request) {
String response = this.post("/payment-options", this.gson.toJson(request));
return this.gson.fromJson(response, PaymentOptions.class);
}
}
Loading
Loading