diff --git a/justfile b/justfile index d48f299877e..072f3a4600f 100644 --- a/justfile +++ b/justfile @@ -5,6 +5,10 @@ import? '../sdk-codegen/utils.just' _default: just --list --unsorted +# ⭐ run format and tests to prepare for CI +[no-exit-message] +prepare: format test + # ⭐ run the whole test suite [no-exit-message] test *args: diff --git a/src/main/java/com/stripe/model/v2/core/Event.java b/src/main/java/com/stripe/model/v2/core/Event.java index 1c9b0fed797..17d4f3dfd5a 100644 --- a/src/main/java/com/stripe/model/v2/core/Event.java +++ b/src/main/java/com/stripe/model/v2/core/Event.java @@ -98,12 +98,15 @@ protected StripeObject fetchRelatedObject(RelatedObject relatedObject) throws St objectClass = StripeRawJsonObject.class; } - RequestOptions opts = null; + RequestOptions.RequestOptionsBuilder optsBuilder = new RequestOptions.RequestOptionsBuilder(); + // optsBuilder.setStripeRequestTrigger("event=" + id); // TODO https://go/j/DEVSDK-3018 if (context != null) { - opts = new RequestOptions.RequestOptionsBuilder().setStripeAccount(context).build(); + optsBuilder.setStripeAccount(context); } + RequestOptions opts = optsBuilder.build(); + return this.responseGetter.request( new ApiRequest( BaseAddress.API, ApiResource.RequestMethod.GET, relatedObject.getUrl(), null, opts), diff --git a/src/main/java/com/stripe/model/v2/core/EventNotification.java b/src/main/java/com/stripe/model/v2/core/EventNotification.java index 99c99b13fb7..2f77dd9d6b4 100644 --- a/src/main/java/com/stripe/model/v2/core/EventNotification.java +++ b/src/main/java/com/stripe/model/v2/core/EventNotification.java @@ -15,6 +15,7 @@ import com.stripe.net.RawRequestOptions; import com.stripe.net.StripeResponse; import java.time.Instant; +import java.util.Collections; import lombok.AccessLevel; import lombok.Getter; @@ -106,12 +107,14 @@ public static EventNotification fromJson(String payload, StripeClient client) { } private RawRequestOptions getRequestOptions() { - if (context == null) { - return null; + RawRequestOptions.RawRequestOptionsBuilder builder = + new RawRequestOptions.RawRequestOptionsBuilder() + .setAdditionalHeaders( + Collections.singletonMap("Stripe-Request-Trigger", "event=" + id)); + if (context != null) { + builder.setStripeContext(context.toString()); } - return new RawRequestOptions.RawRequestOptionsBuilder() - .setStripeContext(context.toString()) - .build(); + return builder.build(); } /* retrieves the full payload for an event. Protected because individual push classes use it, but type it correctly */ diff --git a/src/main/java/com/stripe/net/RawRequestOptions.java b/src/main/java/com/stripe/net/RawRequestOptions.java index ba0384c338e..4d91dc9847a 100644 --- a/src/main/java/com/stripe/net/RawRequestOptions.java +++ b/src/main/java/com/stripe/net/RawRequestOptions.java @@ -8,6 +8,8 @@ public class RawRequestOptions extends RequestOptions { private Map additionalHeaders; + // TODO: make this private + // see: https://go/j/DEVSDK-3018 public RawRequestOptions( Authenticator authenticator, String clientId, @@ -27,6 +29,7 @@ public RawRequestOptions( clientId, idempotencyKey, stripeContext, + null, stripeAccount, stripeVersionOverride, baseUrl, diff --git a/src/main/java/com/stripe/net/RequestOptions.java b/src/main/java/com/stripe/net/RequestOptions.java index 42c910777a2..39a0c97a48f 100644 --- a/src/main/java/com/stripe/net/RequestOptions.java +++ b/src/main/java/com/stripe/net/RequestOptions.java @@ -13,6 +13,7 @@ public class RequestOptions { private final Authenticator authenticator; private final String clientId; private final String stripeContext; + private final String stripeRequestTrigger; private final String idempotencyKey; private final String stripeAccount; private final String baseUrl; @@ -31,8 +32,7 @@ public class RequestOptions { private final PasswordAuthentication proxyCredential; public static RequestOptions getDefault() { - return new RequestOptions( - null, null, null, null, null, null, null, null, null, null, null, null); + return new RequestOptionsBuilder().build(); } protected RequestOptions( @@ -40,6 +40,7 @@ protected RequestOptions( String clientId, String idempotencyKey, String stripeContext, + String stripeRequestTrigger, String stripeAccount, String stripeVersionOverride, String baseUrl, @@ -52,6 +53,7 @@ protected RequestOptions( this.clientId = clientId; this.idempotencyKey = idempotencyKey; this.stripeContext = stripeContext; + this.stripeRequestTrigger = stripeRequestTrigger; this.stripeAccount = stripeAccount; this.stripeVersionOverride = stripeVersionOverride; this.baseUrl = baseUrl; @@ -82,6 +84,10 @@ public String getStripeContext() { return stripeContext; } + public String getStripeRequestTrigger() { + return stripeRequestTrigger; + } + public String getIdempotencyKey() { return idempotencyKey; } @@ -153,6 +159,7 @@ public RequestOptionsBuilder toBuilderFullCopy() { .setClientId(this.clientId) .setIdempotencyKey(this.idempotencyKey) .setStripeAccount(this.stripeAccount) + .setStripeRequestTrigger(this.stripeRequestTrigger) .setConnectTimeout(this.connectTimeout) .setReadTimeout(this.readTimeout) .setMaxNetworkRetries(this.maxNetworkRetries) @@ -166,6 +173,7 @@ public static class RequestOptionsBuilder { protected String clientId; protected String idempotencyKey; protected String stripeContext; + protected String stripeRequestTrigger; protected String stripeAccount; protected String stripeVersionOverride; protected Integer connectTimeout; @@ -251,6 +259,15 @@ public RequestOptionsBuilder clearStripeContext() { return this; } + public String getStripeRequestTrigger() { + return stripeRequestTrigger; + } + + public RequestOptionsBuilder setStripeRequestTrigger(String stripeRequestTrigger) { + this.stripeRequestTrigger = stripeRequestTrigger; + return this; + } + public RequestOptionsBuilder setIdempotencyKey(String idempotencyKey) { this.idempotencyKey = idempotencyKey; return this; @@ -371,6 +388,7 @@ public RequestOptions build() { normalizeClientId(this.clientId), normalizeIdempotencyKey(this.idempotencyKey), stripeContext, + stripeRequestTrigger, normalizeStripeAccount(this.stripeAccount), normalizeStripeVersion(this.stripeVersionOverride), normalizeBaseUrl(this.baseUrl), @@ -468,20 +486,17 @@ protected static String normalizeStripeAccount(String stripeAccount) { static RequestOptions merge(StripeResponseGetterOptions clientOptions, RequestOptions options) { if (options == null) { - return new RequestOptions( - clientOptions.getAuthenticator(), // authenticator - clientOptions.getClientId(), // clientId - null, // idempotencyKey - clientOptions.getStripeContext(), // stripeContext - clientOptions.getStripeAccount(), // stripeAccount - null, // stripeVersionOverride - null, // baseUrl - clientOptions.getConnectTimeout(), // connectTimeout - clientOptions.getReadTimeout(), // readTimeout - clientOptions.getMaxNetworkRetries(), // maxNetworkRetries - clientOptions.getConnectionProxy(), // connectionProxy - clientOptions.getProxyCredential() // proxyCredential - ); + return new RequestOptionsBuilder() + .setAuthenticator(clientOptions.getAuthenticator()) + .setClientId(clientOptions.getClientId()) + .setStripeContext(clientOptions.getStripeContext()) + .setStripeAccount(clientOptions.getStripeAccount()) + .setConnectTimeout(clientOptions.getConnectTimeout()) + .setReadTimeout(clientOptions.getReadTimeout()) + .setMaxNetworkRetries(clientOptions.getMaxNetworkRetries()) + .setConnectionProxy(clientOptions.getConnectionProxy()) + .setProxyCredential(clientOptions.getProxyCredential()) + .build(); } // callers need to be able to explicitly unset context per-request @@ -505,6 +520,7 @@ static RequestOptions merge(StripeResponseGetterOptions clientOptions, RequestOp options.getClientId() != null ? options.getClientId() : clientOptions.getClientId(), options.getIdempotencyKey(), stripeContext, + options.getStripeRequestTrigger(), options.getStripeAccount() != null ? options.getStripeAccount() : clientOptions.getStripeAccount(), diff --git a/src/main/java/com/stripe/net/StripeRequest.java b/src/main/java/com/stripe/net/StripeRequest.java index 89433bfde9f..63dde82a3f6 100644 --- a/src/main/java/com/stripe/net/StripeRequest.java +++ b/src/main/java/com/stripe/net/StripeRequest.java @@ -321,6 +321,11 @@ private static HttpHeaders buildHeaders( headerMap.put("Stripe-Context", Arrays.asList(options.getStripeContext())); } + // Stripe-Request-Trigger + if (options.getStripeRequestTrigger() != null) { + headerMap.put("Stripe-Request-Trigger", Arrays.asList(options.getStripeRequestTrigger())); + } + // Stripe-Account if (options.getStripeAccount() != null) { headerMap.put("Stripe-Account", Arrays.asList(options.getStripeAccount())); diff --git a/src/test/java/com/stripe/model/v2/EventTests.java b/src/test/java/com/stripe/model/v2/EventTests.java index dabebb682b8..46ee05be680 100644 --- a/src/test/java/com/stripe/model/v2/EventTests.java +++ b/src/test/java/com/stripe/model/v2/EventTests.java @@ -8,10 +8,15 @@ import com.stripe.model.billing.Meter; import com.stripe.model.v2.core.Event; import com.stripe.net.ApiResource; +import com.stripe.net.HttpHeaders; +import com.stripe.net.StripeResponse; import java.io.IOException; import java.time.Instant; +import java.util.Collections; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.mockito.stubbing.Answer; public class EventTests extends BaseStripeTest { public static String v2PayloadNoData = null; @@ -110,17 +115,19 @@ public void parsesV2EventAndDeserializesEventData() throws StripeException { assertEquals("foo", data.getDeveloperMessageSummary()); } + // currently intentionally broken while we wait for the major & https://go/j/DEVSDK-3018 @Test public void retrieveObjectFetchesAndDeserializesObject() throws StripeException, IOException { V1BillingMeterErrorReportTriggeredEvent event = (V1BillingMeterErrorReportTriggeredEvent) Event.parse(v2PayloadNoData); event.setResponseGetter(networkSpy); - stubRequest( - ApiResource.RequestMethod.GET, - "/v1/billing/meters/meter_123", - null, - Meter.class, - getResourceAsString("/api_fixtures/billing_meter.json")); + String fixtureJson = getResourceAsString("/api_fixtures/billing_meter.json"); + Mockito.doAnswer( + (Answer) + invocation -> + new StripeResponse(200, HttpHeaders.of(Collections.emptyMap()), fixtureJson)) + .when(httpClientSpy) + .request(Mockito.any()); assertEquals("/v1/billing/meters/meter_123", event.getRelatedObject().getUrl()); assertEquals("meter_123", event.getRelatedObject().getId()); @@ -141,6 +148,11 @@ public void retrieveObjectFetchesAndDeserializesObject() throws StripeException, assertEquals("active", meter.getStatus()); assertNull(meter.getStatusTransitions().getDeactivatedAt()); assertEquals(1727303036, meter.getUpdated()); + + verifyStripeRequest( + req -> + assertEquals( + "event=evt_234", req.headers().firstValue("Stripe-Request-Trigger").orElse(null))); } // FIXME (jar) this should no longer be possible; confirm this and remove before merge