Skip to content

Commit faa45a4

Browse files
Merge branch 'private-preview' into latest-codegen-private-preview
2 parents 0cf1766 + a2abd1b commit faa45a4

3 files changed

Lines changed: 87 additions & 2 deletions

File tree

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

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import com.stripe.net.Webhook.Signature;
99
import java.net.PasswordAuthentication;
1010
import java.net.Proxy;
11+
import lombok.Builder;
1112
import lombok.Getter;
1213

1314
/**
@@ -41,6 +42,62 @@ protected StripeResponseGetter getResponseGetter() {
4142
return responseGetter;
4243
}
4344

45+
/** Gets the current StripeContext from the client's configuration. Used in unit testing. */
46+
protected String getContext() {
47+
// TODO(major): add getOptions to the StripeResponseGetter interface? that would simplify this
48+
if (!(responseGetter instanceof LiveStripeResponseGetter)) {
49+
return null;
50+
}
51+
52+
LiveStripeResponseGetter liveGetter = (LiveStripeResponseGetter) responseGetter;
53+
StripeResponseGetterOptions options = liveGetter.getOptions();
54+
55+
return options.getStripeContext();
56+
}
57+
58+
/**
59+
* Creates a new StripeClient with the same configuration as this client but with a custom
60+
* StripeContext. This method is useful for creating thread-safe clients with different contexts,
61+
* such as when processing webhooks in parallel where each webhook has its own context.
62+
*
63+
* <p>The new client will share the same configuration (API key, timeouts, proxy settings, etc.)
64+
* and HTTP client as this client, but will have the specified context. This allows for efficient
65+
* parallel processing without reinitializing HTTP connections.
66+
*
67+
* @param context the custom stripe_context to use for the new client
68+
* @return a new StripeClient with the custom context
69+
* @throws IllegalStateException if this client doesn't use a LiveStripeResponseGetter
70+
*/
71+
public StripeClient withStripeContext(StripeContext context) {
72+
// Convert StripeContext to String
73+
String contextString = (context == null) ? null : context.toString();
74+
75+
StripeResponseGetter responseGetter = this.getResponseGetter();
76+
77+
// We can only create a new client for LiveStripeResponseGetter because it's the only class with
78+
// `getOptions()`. If we add that method to the interface in a later major, we could remove this
79+
// check.
80+
if (!(responseGetter instanceof LiveStripeResponseGetter)) {
81+
throw new IllegalStateException(
82+
"Cannot create a client with custom context for non-Live response getters");
83+
}
84+
85+
LiveStripeResponseGetter liveGetter = (LiveStripeResponseGetter) responseGetter;
86+
87+
// Create a new LiveStripeResponseGetter with updated context, reusing the HTTP client
88+
LiveStripeResponseGetter newResponseGetter =
89+
liveGetter.withNewOptions(
90+
options -> {
91+
ClientStripeResponseGetterOptions existingOptions =
92+
(ClientStripeResponseGetterOptions) options;
93+
94+
return existingOptions.toBuilder().stripeContext(contextString).build();
95+
});
96+
97+
// Create and return a new StripeClient with the new response getter
98+
return new StripeClient(newResponseGetter);
99+
}
100+
44101
/**
45102
* Returns an StripeEvent instance using the provided JSON payload. Throws a JsonSyntaxException
46103
* if the payload is not valid JSON, and a SignatureVerificationException if the signature
@@ -1128,6 +1185,8 @@ public com.stripe.service.WebhookEndpointService webhookEndpoints() {
11281185
}
11291186

11301187
// The end of the section generated from our OpenAPI spec
1188+
@SuppressWarnings("ObjectToString")
1189+
@Builder(toBuilder = true)
11311190
static class ClientStripeResponseGetterOptions extends StripeResponseGetterOptions {
11321191
// When adding setting here keep them in sync with settings in RequestOptions and
11331192
// in the RequestOptions.merge method
@@ -1533,4 +1592,9 @@ public StripeResponse rawRequest(
15331592
public StripeObject deserialize(String rawJson, ApiMode apiMode) throws StripeException {
15341593
return StripeObject.deserializeStripeObject(rawJson, this.getResponseGetter(), apiMode);
15351594
}
1595+
1596+
public StripeEventNotificationHandler notificationHandler(
1597+
String webhookSecret, StripeEventNotificationHandler.FallbackCallback fallbackCallback) {
1598+
return new StripeEventNotificationHandler(webhookSecret, this, fallbackCallback);
1599+
}
15361600
}

src/main/java/com/stripe/StripeContext.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ public StripeContext pop() {
6464
/**
6565
* Converts the context to a string by joining segments with '/'.
6666
*
67-
* @return string representation of the context segments joined by '/', `null` if there are no
68-
* segments (useful for clearing context)
67+
* @return string representation of the context segments joined by '/'. If there are no segments,
68+
* returns an empty string (useful for clearing context).
6969
*/
7070
@Override
7171
public String toString() {

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.List;
2222
import java.util.Map;
2323
import java.util.Optional;
24+
import java.util.function.Function;
2425

2526
public class LiveStripeResponseGetter implements StripeResponseGetter {
2627
private final HttpClient httpClient;
@@ -76,6 +77,26 @@ public LiveStripeResponseGetter(StripeResponseGetterOptions options, HttpClient
7677
this.httpClient = (httpClient != null) ? httpClient : buildDefaultHttpClient();
7778
}
7879

80+
/**
81+
* Creates a new LiveStripeResponseGetter with the same configuration and HTTP client as this
82+
* instance, but with a different stripe_context. This allows for efficient cloning when you need
83+
* to make requests with different contexts (e.g., webhook processing) without reinitializing HTTP
84+
* connections.
85+
*
86+
* @param contextCreator a function that takes the existing options and returns new options with
87+
* the desired context
88+
* @return a new LiveStripeResponseGetter with the updated options and the same HTTP client
89+
*/
90+
public LiveStripeResponseGetter withNewOptions(
91+
Function<StripeResponseGetterOptions, StripeResponseGetterOptions> contextCreator) {
92+
StripeResponseGetterOptions newOptions = contextCreator.apply(this.options);
93+
return new LiveStripeResponseGetter(newOptions, this.httpClient);
94+
}
95+
96+
public StripeResponseGetterOptions getOptions() {
97+
return this.options;
98+
}
99+
79100
private StripeRequest toStripeRequest(ApiRequest apiRequest, RequestOptions mergedOptions)
80101
throws StripeException {
81102
String fullUrl = fullUrl(apiRequest);

0 commit comments

Comments
 (0)