Skip to content
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
29 changes: 28 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,32 @@ String secondaryValue =
.getAsString();
```

> [!NOTE]
> `.getRawJsonObject()` is only available on the top-level object returned by an API call. For most requests (like `.retrieve()` or `.create()`) you'll get the object itself. But for `.list()` calls, the top level object is a `List<T>`, so you can only access the raw json of an individual object by going through the list itself.
>
> ```java
> var cards = stripeClient
> .v1()
> .issuing()
> .cards()
> .list(params);
>
> // doesn't work:
> cards
> .getData()
> .get(0)
> .getRawJsonObject(); // null
>
> // instead, go through the list:
> cards
> .getRawJsonObject()
> .getAsJsonArray("data")
> .get(0)
> .getAsJsonObject()
> .getAsJsonPrimitive("undocumented-val")
> .getAsString(); // "some-val"
> ```

### Writing a plugin

If you're writing a plugin that uses the library, we'd appreciate it if you
Expand Down Expand Up @@ -259,7 +285,7 @@ Stripe.enableTelemetry = false;
Stripe has features in the [public preview phase](https://docs.stripe.com/release-phases) that can be accessed via versions of this package that have the `-beta.X` suffix like `25.2.0-beta.2`.
We would love for you to try these as we incrementally release new features and improve them based on your feedback.

To install, pick the latest version with the `beta` suffix by reviewing the [releases page](https://github.com/stripe/stripe-java/releases/) and then use it [installation steps above](#installation).
To install, pick the latest version with the `beta` suffix by reviewing the [releases page](https://github.com/stripe/stripe-java/releases/) and then use it [installation steps above](#installation).

> **Note**
> There can be breaking changes between two versions of the public preview SDKs without a bump in the major version. Therefore we recommend pinning the package version to a specific version. This way you can install the same version each time without breaking changes unless you are intentionally looking for the latest public preview SDK.
Expand All @@ -269,6 +295,7 @@ Some preview features require a name and version to be set in the `Stripe-Versio
```java
Stripe.addBetaVersion("feature_beta", "v3");
```

### Private Preview SDKs

Stripe has features in the [private preview phase](https://docs.stripe.com/release-phases) that can be accessed via versions of this package that have the `-alpha.X` suffix like `25.2.0-alpha.2`. These are invite-only features. Once invited, you can install the private preview SDKs by following the same instructions as for the [public preview SDKs](https://github.com/stripe/stripe-java?tab=readme-ov-file#public-preview-sdks) above and replacing the term `beta` with `alpha`.
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/com/stripe/net/LiveStripeResponseGetter.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.logging.Logger;

public class LiveStripeResponseGetter implements StripeResponseGetter {
private static final Logger logger = Logger.getLogger("Stripe");

private final HttpClient httpClient;
private final StripeResponseGetterOptions options;

Expand Down Expand Up @@ -151,6 +154,8 @@ public <T extends StripeObject> T request(ApiRequest apiRequest, Type typeToken)
StripeResponse response =
sendWithTelemetry(request, apiRequest.getUsage(), r -> httpClient.requestWithRetries(r));

maybeEmitStripeNotice(response.headers());

int responseCode = response.code();
String responseBody = response.body();
String requestId = response.requestId();
Expand Down Expand Up @@ -194,6 +199,8 @@ public InputStream requestStream(ApiRequest apiRequest) throws StripeException {
sendWithTelemetry(
request, apiRequest.getUsage(), r -> httpClient.requestStreamWithRetries(r));

maybeEmitStripeNotice(responseStream.headers());

int responseCode = responseStream.code();

if (responseCode < 200 || responseCode >= 300) {
Expand Down Expand Up @@ -275,6 +282,10 @@ public InputStream requestStream(
return this.requestStream(new ApiRequest(baseAddress, method, path, params, options));
}

private static void maybeEmitStripeNotice(HttpHeaders headers) {
headers.firstValue("Stripe-Notice").ifPresent(logger::warning);
}

private static HttpClient buildDefaultHttpClient() {
return new HttpURLConnectionClient();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package com.stripe.functional;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gson.JsonSyntaxException;
import com.stripe.BaseStripeTest;
import com.stripe.exception.ApiException;
Expand All @@ -18,12 +22,92 @@
import com.stripe.net.StripeRequest;
import com.stripe.net.StripeResponse;
import com.stripe.net.StripeResponseGetter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

public class LiveStripeResponseGetterTest extends BaseStripeTest {
private Logger stripeLogger;
private CapturingHandler logHandler;

private static class CapturingHandler extends Handler {
final List<LogRecord> records = new ArrayList<>();

@Override
public void publish(LogRecord record) {
records.add(record);
}

@Override
public void flush() {}

@Override
public void close() {}
}

@BeforeEach
public void setUpLogger() {
stripeLogger = Logger.getLogger("Stripe");
logHandler = new CapturingHandler();
logHandler.setLevel(Level.ALL);
stripeLogger.addHandler(logHandler);
stripeLogger.setLevel(Level.ALL);
stripeLogger.setUseParentHandlers(false);
}

@AfterEach
public void tearDownLogger() {
stripeLogger.removeHandler(logHandler);
stripeLogger.setUseParentHandlers(true);
}

@Test
public void testStripeNoticeHeaderEmitsWarning() throws StripeException {
HttpClient spy = Mockito.spy(new HttpURLConnectionClient());
StripeResponseGetter srg = new LiveStripeResponseGetter(spy);
ApiResource.setGlobalResponseGetter(srg);
StripeResponse response =
new StripeResponse(
200,
HttpHeaders.of(
ImmutableMap.of(
"Stripe-Notice",
ImmutableList.of("This API version will be deprecated soon."))),
"{\"id\": \"sub_123\", \"object\": \"subscription\"}");
Mockito.doReturn(response).when(spy).requestWithRetries(Mockito.<StripeRequest>any());
Subscription.retrieve("sub_123");

assertEquals(1, logHandler.records.size());
assertEquals(Level.WARNING, logHandler.records.get(0).getLevel());
assertEquals(
"This API version will be deprecated soon.", logHandler.records.get(0).getMessage());
}

@Test
public void testNoStripeNoticeHeaderEmitsNoWarning() throws StripeException {
HttpClient spy = Mockito.spy(new HttpURLConnectionClient());
StripeResponseGetter srg = new LiveStripeResponseGetter(spy);
ApiResource.setGlobalResponseGetter(srg);
StripeResponse response =
new StripeResponse(
200,
HttpHeaders.of(Collections.emptyMap()),
"{\"id\": \"sub_123\", \"object\": \"subscription\"}");
Mockito.doReturn(response).when(spy).requestWithRetries(Mockito.<StripeRequest>any());
Subscription.retrieve("sub_123");

assertTrue(logHandler.records.isEmpty());
}

@Test
public void testInvalidJson() throws StripeException {
HttpClient spy = Mockito.spy(new HttpURLConnectionClient());
Expand Down
Loading