Skip to content

Commit 565cbc4

Browse files
Merge pull request #2065 from stripe/xavdid/merge-java-beta
Xavdid/merge java beta
2 parents 1d3c4c0 + fc559e4 commit 565cbc4

13 files changed

+557
-8
lines changed

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
update-version:
55
@echo "$(VERSION)" > VERSION
66
@perl -pi -e 's|badge/maven--central-v[.\d\-\w]+-blue|badge/maven--central-v$(VERSION)-blue|' README.md
7-
@perl -pi -e 's|https:\/\/search\.maven\.org\/remotecontent\?filepath=com\/stripe\/stripe-java\/[.\d\-\w]+\/stripe-java-[.\d\-\w]+.jar|https://search.maven.org/remotecontent?filepath=com/stripe/stripe-java/$(VERSION)/stripe-java-$(VERSION).jar|' README.md
7+
@perl -pi -e 's|https:\/\/repo1\.maven\.org\/maven2\/com\/stripe\/stripe-java\/[.\d\-\w]+\/stripe-java-[.\d\-\w]+.jar|https://repo1.maven.org/maven2/com/stripe/stripe-java/$(VERSION)/stripe-java-$(VERSION).jar|' README.md
8+
@perl -pi -e 's|Current release version: [.\d\-\w]+|Current release version: $(VERSION)|' README.md
89
@perl -pi -e 's|implementation "com\.stripe:stripe-java:[.\d\-\w]+"|implementation "com.stripe:stripe-java:$(VERSION)"|' README.md
910
@perl -pi -e 's|<version>[.\d\-\w]+<\/version>|<version>$(VERSION)</version>|' README.md
1011
@perl -pi -e 's|VERSION_NAME=[.\d\-\w]+|VERSION_NAME=$(VERSION)|' gradle.properties

justfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ format-check:
2828
update-version version:
2929
echo "{{ version }}" > VERSION
3030
perl -pi -e 's|badge/maven--central-v[.\d\-\w]+-blue|badge/maven--central-v{{ version }}-blue|' README.md
31-
perl -pi -e 's|https:\/\/search\.maven\.org\/remotecontent\?filepath=com\/stripe\/stripe-java\/[.\d\-\w]+\/stripe-java-[.\d\-\w]+.jar|https://search.maven.org/remotecontent?filepath=com/stripe/stripe-java/{{ version }}/stripe-java-{{ version }}.jar|' README.md
31+
perl -pi -e 's|https:\/\/repo1\.maven\.org\/maven2\/com\/stripe\/stripe-java\/[.\d\-\w]+\/stripe-java-[.\d\-\w]+.jar|https://repo1.maven.org/maven2/com/stripe/stripe-java/{{ version }}/stripe-java-{{ version }}.jar|' README.md
32+
perl -pi -e 's|Current release version: [.\d\-\w]+|Current release version: {{ version }}|' README.md
3233
perl -pi -e 's|implementation "com\.stripe:stripe-java:[.\d\-\w]+"|implementation "com.stripe:stripe-java:{{ version }}"|' README.md
3334
perl -pi -e 's|<version>[.\d\-\w]+<\/version>|<version>{{ version }}</version>|' README.md
3435
perl -pi -e 's|VERSION_NAME=[.\d\-\w]+|VERSION_NAME={{ version }}|' gradle.properties

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1326,6 +1326,11 @@ public StripeClientBuilder setStripeContext(String context) {
13261326
return this;
13271327
}
13281328

1329+
public StripeClientBuilder setStripeContext(StripeContext context) {
1330+
this.stripeContext = context == null ? null : context.toString();
1331+
return this;
1332+
}
1333+
13291334
public String getStripeContext() {
13301335
return this.stripeContext;
13311336
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package com.stripe;
2+
3+
import java.util.ArrayList;
4+
import java.util.Arrays;
5+
import java.util.Collections;
6+
import java.util.List;
7+
import lombok.EqualsAndHashCode;
8+
9+
/**
10+
* The StripeContext class provides an immutable container for interacting with the `Stripe-Context`
11+
* header.
12+
*
13+
* <p>You can use it whenever you're initializing a `StripeClient` or sending `stripe_context` with
14+
* a request. It's also found in the `EventNotification.context` property.
15+
*/
16+
@EqualsAndHashCode
17+
public final class StripeContext {
18+
private final List<String> segments;
19+
20+
/** Creates a new StripeContext with no segments. */
21+
public StripeContext() {
22+
this(null);
23+
}
24+
25+
/**
26+
* Creates a new StripeContext with the specified segments.
27+
*
28+
* @param segments the list of context segments
29+
*/
30+
public StripeContext(List<String> segments) {
31+
this.segments =
32+
segments == null
33+
? Collections.emptyList()
34+
: Collections.unmodifiableList(new ArrayList<>(segments));
35+
}
36+
37+
/**
38+
* Returns a new StripeContext with the given segment added to the end.
39+
*
40+
* @param segment the segment to add
41+
* @return a new StripeContext instance with the segment appended
42+
*/
43+
public StripeContext push(String segment) {
44+
List<String> newSegments = new ArrayList<>(this.segments);
45+
newSegments.add(segment);
46+
return new StripeContext(newSegments);
47+
}
48+
49+
/**
50+
* Returns a new StripeContext with the last segment removed.
51+
*
52+
* @return a new StripeContext instance with the last segment removed
53+
*/
54+
public StripeContext pop() {
55+
if (segments.isEmpty()) {
56+
throw new IllegalStateException("Cannot pop from an empty StripeContext");
57+
}
58+
59+
List<String> newSegments = new ArrayList<>(this.segments);
60+
newSegments.remove(newSegments.size() - 1);
61+
return new StripeContext(newSegments);
62+
}
63+
64+
/**
65+
* Converts the context to a string by joining segments with '/'.
66+
*
67+
* @return string representation of the context segments joined by '/', `null` if there are no
68+
* segments (useful for clearing context)
69+
*/
70+
@Override
71+
public String toString() {
72+
return String.join("/", segments);
73+
}
74+
75+
/**
76+
* Parse a context string into a StripeContext instance.
77+
*
78+
* @param contextStr string to parse (segments separated by '/')
79+
* @return StripeContext instance with segments from the string
80+
*/
81+
public static StripeContext parse(String contextStr) {
82+
if (contextStr == null || contextStr.isEmpty()) {
83+
return new StripeContext();
84+
}
85+
86+
List<String> segments = Arrays.asList(contextStr.split("/"));
87+
return new StripeContext(segments);
88+
}
89+
90+
/**
91+
* Returns an unmodifiable list of the current segments.
92+
*
93+
* @return the list of segments
94+
*/
95+
public List<String> getSegments() {
96+
return segments;
97+
}
98+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.stripe.model;
2+
3+
import com.google.gson.JsonDeserializationContext;
4+
import com.google.gson.JsonDeserializer;
5+
import com.google.gson.JsonElement;
6+
import com.google.gson.JsonParseException;
7+
import com.stripe.StripeContext;
8+
import java.lang.reflect.Type;
9+
10+
public class StripeContextDeserializer implements JsonDeserializer<StripeContext> {
11+
12+
@Override
13+
public StripeContext deserialize(
14+
JsonElement json, Type typeOfT, JsonDeserializationContext context)
15+
throws JsonParseException {
16+
if (json == null || json.isJsonNull()) {
17+
return null;
18+
}
19+
20+
String contextString = json.getAsString().trim();
21+
if (contextString.isEmpty()) {
22+
return null;
23+
}
24+
return StripeContext.parse(contextString);
25+
}
26+
}

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.google.gson.JsonObject;
44
import com.google.gson.annotations.SerializedName;
55
import com.stripe.StripeClient;
6+
import com.stripe.StripeContext;
67
import com.stripe.exception.StripeException;
78
import com.stripe.model.StripeObject;
89
import com.stripe.model.v2.Event.RelatedObject;
@@ -71,7 +72,7 @@ public static class Reason {
7172

7273
/** [Optional] Authentication context needed to fetch the event or related object. */
7374
@SerializedName("context")
74-
public String context;
75+
public StripeContext context;
7576

7677
/** [Optional] Reason for the event. */
7778
@SerializedName("reason")
@@ -98,14 +99,17 @@ public static EventNotification fromJson(String payload, StripeClient client) {
9899

99100
EventNotification e = ApiResource.GSON.fromJson(payload, cls);
100101
e.client = client;
102+
101103
return e;
102104
}
103105

104106
private RawRequestOptions getRequestOptions() {
105107
if (context == null) {
106108
return null;
107109
}
108-
return new RawRequestOptions.RawRequestOptionsBuilder().setStripeContext(context).build();
110+
return new RawRequestOptions.RawRequestOptionsBuilder()
111+
.setStripeContext(context.toString())
112+
.build();
109113
}
110114

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

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.stripe.net;
22

33
import com.google.gson.*;
4+
import com.stripe.StripeContext;
45
import com.stripe.exception.InvalidRequestException;
56
import com.stripe.model.*;
67
import com.stripe.model.v2.EventTypeAdapterFactory;
@@ -54,6 +55,7 @@ private static Gson createGson(boolean shouldSetResponseGetter) {
5455
.registerTypeAdapter(EphemeralKey.class, new EphemeralKeyDeserializer())
5556
.registerTypeAdapter(Event.Data.class, new EventDataDeserializer())
5657
.registerTypeAdapter(Event.Request.class, new EventRequestDeserializer())
58+
.registerTypeAdapter(StripeContext.class, new StripeContextDeserializer())
5759
.registerTypeAdapter(ExpandableField.class, new ExpandableFieldDeserializer())
5860
.registerTypeAdapter(Instant.class, new InstantDeserializer())
5961
.registerTypeAdapterFactory(new EventTypeAdapterFactory())

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.stripe.net;
22

3+
import com.stripe.StripeContext;
34
import java.net.PasswordAuthentication;
45
import java.net.Proxy;
56
import java.util.Map;
@@ -81,6 +82,12 @@ public RawRequestOptionsBuilder setStripeContext(String stripeContext) {
8182
return this;
8283
}
8384

85+
@Override
86+
public RawRequestOptionsBuilder setStripeContext(StripeContext stripeContext) {
87+
super.setStripeContext(stripeContext);
88+
return this;
89+
}
90+
8491
@Override
8592
public RawRequestOptionsBuilder setStripeAccount(String stripeAccount) {
8693
super.setStripeAccount(stripeAccount);

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

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,17 @@ public RequestOptionsBuilder setStripeContext(String context) {
237237
return this;
238238
}
239239

240+
public RequestOptionsBuilder setStripeContext(com.stripe.StripeContext context) {
241+
this.stripeContext = context != null ? context.toString() : null;
242+
return this;
243+
}
244+
245+
/**
246+
* Empties the current builder value for StripeContext, which will defer to the client options.
247+
*
248+
* <p>To send no context at all, call `setContext(new StripeContext())`or set the context to an
249+
* empty string.
250+
*/
240251
public RequestOptionsBuilder clearStripeContext() {
241252
this.stripeContext = null;
242253
return this;
@@ -474,15 +485,28 @@ static RequestOptions merge(StripeResponseGetterOptions clientOptions, RequestOp
474485
clientOptions.getProxyCredential() // proxyCredential
475486
);
476487
}
488+
489+
// callers need to be able to explicitly unset context per-request
490+
// an empty StripeContext serializes to a "", so check for that and empty context out if it's
491+
// there.
492+
String stripeContext;
493+
if (options.getStripeContext() != null) {
494+
String requestContext = options.getStripeContext().trim();
495+
if (requestContext.isEmpty()) {
496+
stripeContext = null;
497+
} else {
498+
stripeContext = requestContext;
499+
}
500+
} else {
501+
stripeContext = clientOptions.getStripeContext();
502+
}
477503
return new RequestOptions(
478504
options.getAuthenticator() != null
479505
? options.getAuthenticator()
480506
: clientOptions.getAuthenticator(),
481507
options.getClientId() != null ? options.getClientId() : clientOptions.getClientId(),
482508
options.getIdempotencyKey(),
483-
options.getStripeContext() != null
484-
? options.getStripeContext()
485-
: clientOptions.getStripeContext(),
509+
stripeContext,
486510
options.getStripeAccount() != null
487511
? options.getStripeAccount()
488512
: clientOptions.getStripeAccount(),

src/test/java/com/stripe/StripeClientTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ public void parsesEventNotificationWithRelatedObject()
248248
assertEquals("evt_234", eventNotification.getId());
249249
assertEquals("v1.billing.meter.error_report_triggered", eventNotification.getType());
250250
assertEquals(Instant.parse("2022-02-15T00:27:45.330Z"), eventNotification.created);
251-
assertEquals("org_123", eventNotification.context);
251+
assertEquals("org_123", eventNotification.getContext().toString());
252252
assertInstanceOf(V1BillingMeterErrorReportTriggeredEventNotification.class, eventNotification);
253253
assertEquals("request", eventNotification.getReason().getType());
254254
assertEquals("abc123", eventNotification.getReason().getRequest().getId());

0 commit comments

Comments
 (0)