Skip to content

Commit 9d6f688

Browse files
Merge pull request #2188 from stripe/xavdid/merge-java-private-preview
Merge to private-preview
2 parents 6d91dc6 + 63abb1f commit 9d6f688

17 files changed

Lines changed: 290 additions & 151 deletions

.github/workflows/ci.yml

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ jobs:
7373
- "25"
7474
# non-LTS versions
7575
# we should periodically add the latest non-LTS version here to test against
76-
# as of 2025-09-29, the latest version of java (25) is LTS, so this section is empty. In March 2026, we'll add "26".
76+
- "26"
7777

7878
steps:
7979
- uses: extractions/setup-just@v2
@@ -114,8 +114,7 @@ jobs:
114114
publish:
115115
if: >-
116116
((github.event_name == 'workflow_dispatch') || (github.event_name == 'push')) &&
117-
startsWith(github.ref, 'refs/tags/v') &&
118-
endsWith(github.actor, '-stripe')
117+
startsWith(github.ref, 'refs/tags/v')
119118
needs: [build, test]
120119
runs-on: "ubuntu-24.04"
121120
permissions:
@@ -157,12 +156,11 @@ jobs:
157156
((github.event_name == 'workflow_dispatch') || (github.event_name == 'push')) &&
158157
startsWith(github.ref, 'refs/tags/v') &&
159158
!contains(github.ref, 'beta') &&
160-
!contains(github.ref, 'alpha') &&
161-
endsWith(github.actor, '-stripe')
159+
!contains(github.ref, 'alpha')
162160
needs: [build, test]
163161
runs-on: "ubuntu-24.04"
164162
permissions:
165-
contents: write
163+
contents: write
166164
steps:
167165
- uses: actions/checkout@master
168166
- name: Setup Java

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ jar {
100100
"Implementation-Vendor": VENDOR_NAME,
101101
"Bundle-SymbolicName": POM_ARTIFACT_ID,
102102
"Export-Package": "com.stripe.*",
103-
"Automatic-Module-Name": "stripe.java")
103+
"Automatic-Module-Name": "com.stripe")
104104

105105
archiveVersion = VERSION_NAME
106106
}

justfile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ import? '../sdk-codegen/utils.just'
55
_default:
66
just --list --unsorted
77

8+
# ⭐ run format and tests to prepare for CI
9+
[no-exit-message]
10+
prepare: format test
11+
812
# ⭐ run the whole test suite
913
[no-exit-message]
1014
test *args:

src/main/java/com/stripe/StripeClient.java

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,6 +1210,7 @@ public static final class StripeClientBuilder {
12101210
private String meterEventsBase = Stripe.METER_EVENTS_API_BASE;
12111211
private String stripeAccount;
12121212
private String stripeContext;
1213+
private HttpClient httpClient;
12131214

12141215
/**
12151216
* Constructs a request options builder with the global parameters (API key and client ID) as
@@ -1221,19 +1222,29 @@ public Authenticator getAuthenticator() {
12211222
return this.authenticator;
12221223
}
12231224

1225+
/**
1226+
* Sets the authenticator used to authorize requests. Use this for custom authentication
1227+
* strategies. For standard API key authentication, prefer {@link #setApiKey(String)}.
1228+
*
1229+
* <p>This shares a backing field with {@link #setApiKey(String)} — calling one overwrites the
1230+
* other.
1231+
*
1232+
* @param authenticator the authenticator to use
1233+
*/
12241234
public StripeClientBuilder setAuthenticator(Authenticator authenticator) {
12251235
this.authenticator = authenticator;
12261236
return this;
12271237
}
12281238

1229-
public String getApiKey() {
1230-
if (authenticator instanceof BearerTokenAuthenticator) {
1231-
return ((BearerTokenAuthenticator) authenticator).getApiKey();
1232-
}
1233-
1234-
return null;
1235-
}
1236-
1239+
/**
1240+
* Sets the API key for bearer token authentication. This is a convenience method equivalent to
1241+
* calling {@code setAuthenticator(new BearerTokenAuthenticator(apiKey))}.
1242+
*
1243+
* <p>This shares a backing field with {@link #setAuthenticator(Authenticator)} — calling one
1244+
* overwrites the other.
1245+
*
1246+
* @param apiKey the API key; if null, clears the authenticator
1247+
*/
12371248
public StripeClientBuilder setApiKey(String apiKey) {
12381249
if (apiKey == null) {
12391250
this.authenticator = null;
@@ -1341,7 +1352,8 @@ public StripeClientBuilder setProxyCredential(PasswordAuthentication proxyCreden
13411352
* Set the base URL for the Stripe API. By default this is "https://api.stripe.com".
13421353
*
13431354
* <p>This only affects requests made with a {@link com.stripe.net.BaseAddress} of API. Use
1344-
* {@link setFilesBase} or {@link setConnectBase} to interpect requests with other bases.
1355+
* {@link #setFilesBase}, {@link #setConnectBase} or {@link #setMeterEventsBase} to interpect
1356+
* requests with other bases.
13451357
*/
13461358
public StripeClientBuilder setApiBase(String address) {
13471359
this.apiBase = address;
@@ -1418,9 +1430,23 @@ public String getStripeContext() {
14181430
return this.stripeContext;
14191431
}
14201432

1433+
/**
1434+
* Sets the HTTP client to use for making requests to the Stripe API. If not set, a default
1435+
* {@link HttpURLConnectionClient} will be created.
1436+
*
1437+
* <p>This is useful for providing a custom HTTP client implementation, e.g. for testing or for
1438+
* using a different HTTP library.
1439+
*
1440+
* @param httpClient the HTTP client to use
1441+
*/
1442+
public StripeClientBuilder setHttpClient(HttpClient httpClient) {
1443+
this.httpClient = httpClient;
1444+
return this;
1445+
}
1446+
14211447
/** Constructs a {@link StripeResponseGetterOptions} with the specified values. */
14221448
public StripeClient build() {
1423-
return new StripeClient(new LiveStripeResponseGetter(buildOptions(), null));
1449+
return new StripeClient(new LiveStripeResponseGetter(buildOptions(), this.httpClient));
14241450
}
14251451

14261452
StripeResponseGetterOptions buildOptions() {
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.stripe.model;
2+
3+
import com.google.gson.TypeAdapter;
4+
import com.google.gson.stream.JsonReader;
5+
import com.google.gson.stream.JsonToken;
6+
import com.google.gson.stream.JsonWriter;
7+
import java.io.IOException;
8+
9+
public class StringInt64TypeAdapter extends TypeAdapter<Long> {
10+
/** Serializes Long values as JSON strings and deserializes string-encoded integers. */
11+
@Override
12+
public void write(JsonWriter out, Long value) throws IOException {
13+
if (value == null) {
14+
out.nullValue();
15+
return;
16+
}
17+
18+
out.value(value.toString());
19+
}
20+
21+
@Override
22+
public Long read(JsonReader in) throws IOException {
23+
JsonToken token = in.peek();
24+
if (token == JsonToken.NULL) {
25+
in.nextNull();
26+
return null;
27+
}
28+
29+
return Long.valueOf(in.nextString());
30+
}
31+
}

src/main/java/com/stripe/model/v2/core/Event.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ protected StripeObject fetchRelatedObject(RelatedObject relatedObject) throws St
9999
}
100100

101101
RequestOptions.RequestOptionsBuilder optsBuilder = new RequestOptions.RequestOptionsBuilder();
102-
// optsBuilder.setStripeRequestTrigger("event=" + id); // TODO https://go/j/DEVSDK-3018
102+
optsBuilder.setStripeRequestTrigger("event=" + id);
103103

104104
if (context != null) {
105105
optsBuilder.setStripeAccount(context);

src/main/java/com/stripe/model/v2/core/EventNotification.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,12 @@ public static EventNotification fromJson(String payload, StripeClient client) {
106106
}
107107

108108
private RawRequestOptions getRequestOptions() {
109-
if (context == null) {
110-
return null;
109+
RawRequestOptions.RawRequestOptionsBuilder builder =
110+
RawRequestOptions.builder().setStripeRequestTrigger("event=" + id);
111+
if (context != null) {
112+
builder.setStripeContext(context.toString());
111113
}
112-
return new RawRequestOptions.RawRequestOptionsBuilder()
113-
.setStripeContext(context.toString())
114-
.build();
114+
return builder.build();
115115
}
116116

117117
/* retrieves the full payload for an event. Protected because individual push classes use it, but type it correctly */

src/main/java/com/stripe/net/Authenticator.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,16 @@
22

33
import com.stripe.exception.StripeException;
44

5-
/** * Represents a request authentication mechanism. */
5+
/**
6+
* Interface for applying authentication to a request. This is used by {@link StripeResponseGetter}
7+
* to apply authentication to requests before they are sent. Implementations of this interface
8+
* should not modify the request in-place, but should instead return a new request with the
9+
* appropriate authentication headers applied. The default implementation of this interface is
10+
* {@link BearerTokenAuthenticator}, which applies the API key as a Bearer token in the
11+
* Authorization header. Users can also implement this interface to provide custom authentication
12+
* logic, often by wrapping the BearerTokenAuthenticator and applying additional headers or logic as
13+
* needed.
14+
*/
615
public interface Authenticator {
716
/**
817
* * Authenticate the request

src/main/java/com/stripe/net/RawRequestOptions.java

Lines changed: 10 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -8,34 +8,9 @@
88
public class RawRequestOptions extends RequestOptions {
99
private Map<String, String> additionalHeaders;
1010

11-
public RawRequestOptions(
12-
Authenticator authenticator,
13-
String clientId,
14-
String idempotencyKey,
15-
String stripeContext,
16-
String stripeAccount,
17-
String stripeVersionOverride,
18-
String baseUrl,
19-
Integer connectTimeout,
20-
Integer readTimeout,
21-
Integer maxNetworkRetries,
22-
Proxy connectionProxy,
23-
PasswordAuthentication proxyCredential,
24-
Map<String, String> additionalHeaders) {
25-
super(
26-
authenticator,
27-
clientId,
28-
idempotencyKey,
29-
stripeContext,
30-
stripeAccount,
31-
stripeVersionOverride,
32-
baseUrl,
33-
connectTimeout,
34-
readTimeout,
35-
maxNetworkRetries,
36-
connectionProxy,
37-
proxyCredential);
38-
this.additionalHeaders = additionalHeaders;
11+
private RawRequestOptions(RawRequestOptionsBuilder builder) {
12+
super(builder);
13+
this.additionalHeaders = builder.additionalHeaders;
3914
}
4015

4116
public Map<String, String> getAdditionalHeaders() {
@@ -88,6 +63,12 @@ public RawRequestOptionsBuilder setStripeContext(StripeContext stripeContext) {
8863
return this;
8964
}
9065

66+
@Override
67+
public RawRequestOptionsBuilder setStripeRequestTrigger(String stripeRequestTrigger) {
68+
super.setStripeRequestTrigger(stripeRequestTrigger);
69+
return this;
70+
}
71+
9172
@Override
9273
public RawRequestOptionsBuilder setStripeAccount(String stripeAccount) {
9374
super.setStripeAccount(stripeAccount);
@@ -132,20 +113,7 @@ public RawRequestOptionsBuilder setProxyCredential(PasswordAuthentication proxyC
132113

133114
@Override
134115
public RawRequestOptions build() {
135-
return new RawRequestOptions(
136-
authenticator,
137-
normalizeClientId(this.clientId),
138-
normalizeIdempotencyKey(this.idempotencyKey),
139-
normalizeStripeContext(this.stripeContext),
140-
normalizeStripeAccount(this.stripeAccount),
141-
normalizeStripeVersion(this.stripeVersionOverride),
142-
normalizeBaseUrl(this.baseUrl),
143-
connectTimeout,
144-
readTimeout,
145-
maxNetworkRetries,
146-
connectionProxy,
147-
proxyCredential,
148-
additionalHeaders);
116+
return new RawRequestOptions(this);
149117
}
150118
}
151119
}

0 commit comments

Comments
 (0)