Skip to content

Commit 150d985

Browse files
⚠️ Throw an error when using the wrong webhook parsing method (#2190)
* Add errors when parsing the wrong kind of webhooks payload * fix tests
1 parent 0085a0d commit 150d985

File tree

4 files changed

+82
-7
lines changed

4 files changed

+82
-7
lines changed

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,12 @@ public static EventNotification fromJson(String payload, StripeClient client) {
9393
// don't love the double json parse here, but I don't think we can avoid it?
9494
JsonObject jsonObject = ApiResource.GSON.fromJson(payload, JsonObject.class).getAsJsonObject();
9595

96+
if (jsonObject.has("object") && "event".equals(jsonObject.get("object").getAsString())) {
97+
throw new IllegalArgumentException(
98+
"You passed a webhook payload to StripeClient.parseEventNotification, which expects an event notification."
99+
+ " Use StripeClient.constructEvent instead.");
100+
}
101+
96102
Class<? extends EventNotification> cls =
97103
EventNotificationClassLookup.eventClassLookup.get(jsonObject.get("type").getAsString());
98104
if (cls == null) {

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ public static Event constructEvent(
5454

5555
/**
5656
* Returns an Event instance using the provided JSON payload. Throws a JsonSyntaxException if the
57-
* payload is not valid JSON, and a SignatureVerificationException if the signature verification
58-
* fails for any reason.
57+
* payload is not valid JSON, a SignatureVerificationException if the signature verification fails
58+
* for any reason, and an IllegalArgumentException if you pass the wrong type of input.
5959
*
6060
* @param payload the payload sent by Stripe.
6161
* @param sigHeader the contents of the signature header sent by Stripe.
@@ -72,6 +72,13 @@ public static Event constructEvent(
7272
Event event =
7373
StripeObject.deserializeStripeObject(
7474
payload, Event.class, ApiResource.getGlobalResponseGetter());
75+
76+
if ("v2.core.event".equals(event.getObject())) {
77+
throw new IllegalArgumentException(
78+
"You passed an event notification to Webhook.constructEvent, which expects a webhook payload."
79+
+ " Use StripeClient.parseEventNotification instead.");
80+
}
81+
7582
Signature.verifyHeader(payload, sigHeader, secret, tolerance, clock);
7683
// StripeObjects source their raw JSON object from their last response, but constructed webhooks
7784
// don't have that

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

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ public void checksWebhookSignature()
140140
StripeClient client = new StripeClient("sk_123");
141141

142142
String payload =
143-
"{\n \"id\": \"evt_test_webhook\",\n \"type\": \"v1.whatever\",\n \"object\": \"event\"\n}";
143+
"{\n \"id\": \"evt_test_webhook\",\n \"type\": \"v1.whatever\",\n \"object\": \"v2.core.event\"\n}";
144144
String secret = "whsec_test_secret";
145145

146146
Map<String, Object> options = new HashMap<>();
@@ -159,7 +159,7 @@ public void failsWebhookVerification()
159159
StripeClient client = new StripeClient("sk_123");
160160

161161
String payload =
162-
"{\n \"id\": \"evt_test_webhook\",\n \"type\": \"v1.whatever\",\n \"object\": \"event\"\n}";
162+
"{\n \"id\": \"evt_test_webhook\",\n \"type\": \"v1.whatever\",\n \"object\": \"v2.core.event\"\n}";
163163
String secret = "whsec_test_secret";
164164
String signature = "bad signature";
165165

@@ -173,7 +173,7 @@ public void failsWebhookVerification()
173173
static final String v2EventNotificationWithRelatedObject =
174174
"{\n"
175175
+ " \"id\": \"evt_234\",\n"
176-
+ " \"object\": \"event\",\n"
176+
+ " \"object\": \"v2.core.event\",\n"
177177
+ " \"type\": \"v1.billing.meter.error_report_triggered\",\n"
178178
+ " \"livemode\": false,\n"
179179
+ " \"context\": \"org_123\",\n"
@@ -191,7 +191,7 @@ public void failsWebhookVerification()
191191
static final String v2EventNotificationWithoutRelatedObject =
192192
"{\n"
193193
+ " \"id\": \"evt_234\",\n"
194-
+ " \"object\": \"event\",\n"
194+
+ " \"object\": \"v2.core.event\",\n"
195195
+ " \"type\": \"v1.billing.meter.no_meter_found\",\n"
196196
+ " \"livemode\": false,\n"
197197
+ " \"created\": \"2022-02-15T00:27:45.330Z\"\n"
@@ -200,7 +200,7 @@ public void failsWebhookVerification()
200200
static final String v2UnknownEventNotification =
201201
"{\n"
202202
+ " \"id\": \"evt_234\",\n"
203-
+ " \"object\": \"event\",\n"
203+
+ " \"object\": \"v2.core.event\",\n"
204204
+ " \"type\": \"v1.imaginary_event\",\n"
205205
+ " \"livemode\": false,\n"
206206
+ " \"created\": \"2022-02-15T00:27:45.330Z\"\n"
@@ -417,4 +417,28 @@ public void parseEventNotificationAndPull()
417417
assertEquals("org_123", v.getOptions().getStripeContext());
418418
}
419419
}
420+
421+
@Test
422+
public void parseEventNotificationRejectsV1Payload()
423+
throws InvalidKeyException, NoSuchAlgorithmException {
424+
StripeClient client = new StripeClient("sk_123");
425+
426+
String payload =
427+
"{\n \"id\": \"evt_test_webhook\",\n \"object\": \"event\",\n \"type\": \"charge.succeeded\"\n}";
428+
String secret = "whsec_test_secret";
429+
430+
Map<String, Object> options = new HashMap<>();
431+
options.put("payload", payload);
432+
options.put("secret", secret);
433+
434+
String signature = WebhookTest.generateSigHeader(options);
435+
436+
IllegalArgumentException exception =
437+
assertThrows(
438+
IllegalArgumentException.class,
439+
() -> {
440+
client.parseEventNotification(payload, signature, secret);
441+
});
442+
assertTrue(exception.getMessage().contains("constructEvent"));
443+
}
420444
}

src/test/java/com/stripe/net/WebhookTest.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,4 +335,42 @@ public void testConstructEventWithRawJson()
335335

336336
assertNotNull(event.getRawJsonObject());
337337
}
338+
339+
@Test
340+
public void testConstructEventRejectsV2Payload()
341+
throws NoSuchAlgorithmException, InvalidKeyException {
342+
final String v2Payload =
343+
"{\n \"id\": \"evt_test_webhook\",\n \"object\": \"v2.core.event\"\n}";
344+
final Map<String, Object> options = new HashMap<>();
345+
options.put("payload", v2Payload);
346+
final String sigHeader = generateSigHeader(options);
347+
348+
Throwable exception =
349+
assertThrows(
350+
IllegalArgumentException.class,
351+
() -> {
352+
Webhook.constructEvent(v2Payload, sigHeader, secret);
353+
});
354+
assertTrue(exception.getMessage().contains("StripeClient.parseEventNotification"));
355+
}
356+
357+
@Test
358+
public void testClientConstructEventRejectsV2Payload()
359+
throws NoSuchAlgorithmException, InvalidKeyException {
360+
StripeClient client = new StripeClient(new LiveStripeResponseGetter());
361+
362+
final String v2Payload =
363+
"{\n \"id\": \"evt_test_webhook\",\n \"object\": \"v2.core.event\"\n}";
364+
final Map<String, Object> options = new HashMap<>();
365+
options.put("payload", v2Payload);
366+
final String sigHeader = generateSigHeader(options);
367+
368+
Throwable exception =
369+
assertThrows(
370+
IllegalArgumentException.class,
371+
() -> {
372+
client.constructEvent(v2Payload, sigHeader, secret);
373+
});
374+
assertTrue(exception.getMessage().contains("StripeClient.parseEventNotification"));
375+
}
338376
}

0 commit comments

Comments
 (0)