From 1f7295b2f2ae24e3ba6ac7c0f4278c0812b41c83 Mon Sep 17 00:00:00 2001 From: jar-stripe Date: Fri, 25 Oct 2024 15:57:06 -0700 Subject: [PATCH] Fix StripeException#getUserMessage on v1 API errors (#1911) added stripeErrorApiMode field to StripeException to let us capture the API version that produced the error when setStripeError or setStripeV2Error is called updated getUserMessage to return stripeError.getMessage for v1 errors added StripeExceptionTest tests --- .../com/stripe/exception/StripeException.java | 20 +++++- .../stripe/net/LiveStripeResponseGetter.java | 2 +- .../stripe/exception/StripeExceptionTest.java | 61 +++++++++++++++++++ 3 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 src/test/java/com/stripe/exception/StripeExceptionTest.java diff --git a/src/main/java/com/stripe/exception/StripeException.java b/src/main/java/com/stripe/exception/StripeException.java index 09479171da9..ba7bf85ff83 100644 --- a/src/main/java/com/stripe/exception/StripeException.java +++ b/src/main/java/com/stripe/exception/StripeException.java @@ -2,6 +2,7 @@ import com.google.gson.JsonObject; import com.stripe.model.StripeError; +import com.stripe.net.ApiMode; import com.stripe.net.StripeResponseGetter; import lombok.Getter; @@ -14,10 +15,19 @@ public abstract class StripeException extends Exception { // implement Serializable transient StripeError stripeError; + // This field and its getter are used internally and may change in a non-major version + // of the SDK + ApiMode stripeErrorApiMode; + public void setStripeError(StripeError err) { stripeError = err; + stripeErrorApiMode = ApiMode.V1; } + public void setStripeV2Error(StripeError err) { + stripeError = err; + stripeErrorApiMode = ApiMode.V2; + } /** * Returns the error code of the response that triggered this exception. For {@link ApiException} * the error code will be equal to {@link StripeError#getCode()}. @@ -68,7 +78,8 @@ public String getMessage() { if (requestId != null) { additionalInfo += "; request-id: " + requestId; } - if (this.getUserMessage() != null) { + // a separate user message is only available on v2 errors + if (stripeErrorApiMode == ApiMode.V2 && this.getUserMessage() != null) { additionalInfo += "; user-message: " + this.getUserMessage(); } return super.getMessage() + additionalInfo; @@ -81,7 +92,12 @@ public String getMessage() { */ public String getUserMessage() { if (this.getStripeError() != null) { - return this.getStripeError().getUserMessage(); + switch (stripeErrorApiMode) { + case V1: + return this.getStripeError().getMessage(); + case V2: + return this.getStripeError().getUserMessage(); + } } return null; } diff --git a/src/main/java/com/stripe/net/LiveStripeResponseGetter.java b/src/main/java/com/stripe/net/LiveStripeResponseGetter.java index d40b1af01b3..0caba0cfd38 100644 --- a/src/main/java/com/stripe/net/LiveStripeResponseGetter.java +++ b/src/main/java/com/stripe/net/LiveStripeResponseGetter.java @@ -409,7 +409,7 @@ private void handleV2ApiError(StripeResponse response) throws StripeException { error.setLastResponse(response); exception = new ApiException(error.getMessage(), response.requestId(), code, response.code(), null); - exception.setStripeError(error); + exception.setStripeV2Error(error); throw exception; } diff --git a/src/test/java/com/stripe/exception/StripeExceptionTest.java b/src/test/java/com/stripe/exception/StripeExceptionTest.java new file mode 100644 index 00000000000..75730cb74d5 --- /dev/null +++ b/src/test/java/com/stripe/exception/StripeExceptionTest.java @@ -0,0 +1,61 @@ +package com.stripe.exception; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import com.google.gson.JsonObject; +import com.stripe.BaseStripeTest; +import com.stripe.model.StripeError; +import com.stripe.net.ApiMode; +import com.stripe.net.ApiResource; +import java.io.IOException; +import org.junit.jupiter.api.Test; + +public class StripeExceptionTest extends BaseStripeTest { + + @Test + public void testSetStripeError() throws IOException { + final String data = getResourceAsString("/api_fixtures/error_invalid_request.json"); + final JsonObject jsonObject = + ApiResource.GSON.fromJson(data, JsonObject.class).getAsJsonObject("error"); + final StripeError error = ApiResource.GSON.fromJson(jsonObject, StripeError.class); + error.setUserMessage("it broke"); + + StripeException exception = + new StripeException(error.getMessage(), "1234", error.getCode(), 400) {}; + + exception.setStripeError(error); + + assertNotNull(exception.getStripeError()); + assertEquals(ApiMode.V1, exception.getStripeErrorApiMode()); + + assertEquals("parameter_unknown", exception.getCode()); + assertEquals( + "Received unknown parameter: foo; code: parameter_unknown; request-id: 1234", + exception.getMessage()); + assertEquals(error.getMessage(), exception.getUserMessage()); + } + + @Test + public void testSetStripeV2Error() throws IOException { + final String data = getResourceAsString("/api_fixtures/error_invalid_request.json"); + final JsonObject jsonObject = + ApiResource.GSON.fromJson(data, JsonObject.class).getAsJsonObject("error"); + final StripeError error = ApiResource.GSON.fromJson(jsonObject, StripeError.class); + StripeException exception = + new StripeException(error.getMessage(), "1234", error.getCode(), 400) {}; + error.setUserMessage("it broke"); + + exception.setStripeV2Error(error); + + assertNotNull(exception.getStripeError()); + assertEquals(ApiMode.V2, exception.getStripeErrorApiMode()); + + assertNotNull(error); + assertEquals("parameter_unknown", exception.getCode()); + assertEquals( + "Received unknown parameter: foo; code: parameter_unknown; request-id: 1234; user-message: it broke", + exception.getMessage()); + assertEquals("it broke", exception.getUserMessage()); + } +}