-
Notifications
You must be signed in to change notification settings - Fork 663
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add StripeError field to StripeException (#793)
**Summary** Add a `StripeError` field to `StripeException`. Access via `StripeException#getStripeError()` **Motivation** The error code is an important field for SDK users to be able to determine why a request failed, and allows them to better react to the failure. For example, a `"payment_method_not_available"` code may suggest to the developer to invite a customer to use another payment method. Additionally, a developer may choose to localize an user-facing error based on this code. Fixes #792 **Testing** Wrote automated tests.
- Loading branch information
1 parent
ba3f023
commit 44e1bf9
Showing
17 changed files
with
159 additions
and
108 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -147,11 +147,8 @@ static PaymentIntent confirmPaymentIntent( | |
return PaymentIntent.fromString(response.getResponseBody()); | ||
} catch (CardException unexpected) { | ||
// This particular kind of exception should not be possible from a PaymentI API endpoint | ||
throw new APIException( | ||
unexpected.getMessage(), | ||
unexpected.getRequestId(), | ||
unexpected.getStatusCode(), | ||
unexpected); | ||
throw new APIException(unexpected.getMessage(), unexpected.getRequestId(), | ||
unexpected.getStatusCode(), null, unexpected); | ||
} | ||
} | ||
|
||
|
@@ -200,11 +197,8 @@ static PaymentIntent retrievePaymentIntent( | |
return PaymentIntent.fromString(response.getResponseBody()); | ||
} catch (CardException unexpected) { | ||
// This particular kind of exception should not be possible from a PaymentI API endpoint | ||
throw new APIException( | ||
unexpected.getMessage(), | ||
unexpected.getRequestId(), | ||
unexpected.getStatusCode(), | ||
unexpected); | ||
throw new APIException(unexpected.getMessage(), unexpected.getRequestId(), | ||
unexpected.getStatusCode(), null, unexpected); | ||
} | ||
} | ||
|
||
|
@@ -288,11 +282,8 @@ static Source createSource( | |
return Source.fromString(response.getResponseBody()); | ||
} catch (CardException unexpected) { | ||
// This particular kind of exception should not be possible from a Source API endpoint. | ||
throw new APIException( | ||
unexpected.getMessage(), | ||
unexpected.getRequestId(), | ||
unexpected.getStatusCode(), | ||
unexpected); | ||
throw new APIException(unexpected.getMessage(), unexpected.getRequestId(), | ||
unexpected.getStatusCode(), null, unexpected); | ||
} | ||
} | ||
|
||
|
@@ -339,11 +330,8 @@ static Source retrieveSource( | |
return Source.fromString(response.getResponseBody()); | ||
} catch (CardException unexpected) { | ||
// This particular kind of exception should not be possible from a Source API endpoint. | ||
throw new APIException( | ||
unexpected.getMessage(), | ||
unexpected.getRequestId(), | ||
unexpected.getStatusCode(), | ||
unexpected); | ||
throw new APIException(unexpected.getMessage(), unexpected.getRequestId(), | ||
unexpected.getStatusCode(), null, unexpected); | ||
} | ||
} | ||
|
||
|
@@ -996,7 +984,7 @@ private static List<Parameter> flattenParamsValue(@NonNull Object value, | |
throw new InvalidRequestException("You cannot set '" + keyPrefix + "' to an empty " + | ||
"string. " + "We interpret empty strings as null in requests. " + "You may " + | ||
"set '" + keyPrefix + "' to null to delete the property.", keyPrefix, null, | ||
0, null, null, null); | ||
0, null, null, null, null); | ||
} else if (value == null) { | ||
flatParams = new LinkedList<>(); | ||
flatParams.add(new Parameter(keyPrefix, "")); | ||
|
@@ -1039,17 +1027,16 @@ private static byte[] getOutputBytes( | |
if (jsonData == null) { | ||
throw new InvalidRequestException("Unable to create JSON data from parameters. " | ||
+ "Please contact [email protected] for assistance.", | ||
null, null, 0, null, null, null); | ||
null, null, 0, null, null, null, null); | ||
} | ||
return jsonData.toString().getBytes(CHARSET); | ||
} else { | ||
return createQuery(params).getBytes(CHARSET); | ||
} | ||
} catch (UnsupportedEncodingException e) { | ||
throw new InvalidRequestException("Unable to encode parameters to " | ||
+ CHARSET | ||
+ ". Please contact [email protected] for assistance.", | ||
null, null, 0, null, null, e); | ||
throw new InvalidRequestException("Unable to encode parameters to " + CHARSET + "." + | ||
" Please contact [email protected] for assistance.", | ||
null, null, 0, null, null, null, e); | ||
} | ||
} | ||
|
||
|
@@ -1117,35 +1104,27 @@ private static StripeResponse getStripeResponse( | |
} | ||
} | ||
|
||
private static void handleAPIError(@Nullable String rBody, int rCode, | ||
private static void handleAPIError(@Nullable String responseBody, int responseCode, | ||
@Nullable String requestId) | ||
throws InvalidRequestException, AuthenticationException, | ||
CardException, APIException { | ||
throws InvalidRequestException, AuthenticationException, CardException, APIException { | ||
|
||
final ErrorParser.StripeError stripeError = ErrorParser.parseError(rBody); | ||
switch (rCode) { | ||
case 400: { | ||
throw new InvalidRequestException( | ||
stripeError.message, | ||
stripeError.param, | ||
requestId, | ||
rCode, | ||
stripeError.code, | ||
stripeError.declineCode, | ||
null); | ||
} | ||
final StripeError stripeError = ErrorParser.parseError(responseBody); | ||
switch (responseCode) { | ||
case 400: | ||
case 404: { | ||
throw new InvalidRequestException( | ||
stripeError.message, | ||
stripeError.param, | ||
requestId, | ||
rCode, | ||
responseCode, | ||
stripeError.code, | ||
stripeError.declineCode, | ||
stripeError, | ||
null); | ||
} | ||
case 401: { | ||
throw new AuthenticationException(stripeError.message, requestId, rCode); | ||
throw new AuthenticationException(stripeError.message, requestId, responseCode, | ||
stripeError); | ||
} | ||
case 402: { | ||
throw new CardException( | ||
|
@@ -1155,18 +1134,21 @@ private static void handleAPIError(@Nullable String rBody, int rCode, | |
stripeError.param, | ||
stripeError.declineCode, | ||
stripeError.charge, | ||
rCode, | ||
null); | ||
responseCode, | ||
stripeError | ||
); | ||
} | ||
case 403: { | ||
throw new PermissionException(stripeError.message, requestId, rCode); | ||
throw new PermissionException(stripeError.message, requestId, responseCode, | ||
stripeError); | ||
} | ||
case 429: { | ||
throw new RateLimitException(stripeError.message, stripeError.param, requestId, | ||
rCode, null); | ||
responseCode, stripeError); | ||
} | ||
default: { | ||
throw new APIException(stripeError.message, requestId, rCode, null); | ||
throw new APIException(stripeError.message, requestId, responseCode, stripeError, | ||
null); | ||
} | ||
} | ||
} | ||
|
@@ -1196,7 +1178,7 @@ private static StripeResponse requestData( | |
throw new AuthenticationException("No API key provided. (HINT: set your API key using" + | ||
" 'Stripe.apiKey = <API-KEY>'. You can generate API keys from the Stripe" + | ||
" web interface. See https://stripe.com/api for details or email " + | ||
"[email protected] if you have questions.", null, 0); | ||
"[email protected] if you have questions.", null, 0, null); | ||
} | ||
|
||
final StripeResponse response = getStripeResponse(method, url, params, options); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package com.stripe.android; | ||
|
||
import androidx.annotation.Nullable; | ||
|
||
/** | ||
* A model for error objects sent from the Stripe API. | ||
* | ||
* https://stripe.com/docs/api/errors | ||
*/ | ||
public class StripeError { | ||
|
||
// https://stripe.com/docs/api/errors (e.g. "invalid_request_error") | ||
@Nullable public final String type; | ||
@Nullable public final String message; | ||
|
||
// https://stripe.com/docs/error-codes (e.g. "payment_method_unactivated") | ||
@Nullable public final String code; | ||
@Nullable public final String param; | ||
|
||
// see https://stripe.com/docs/declines/codes | ||
@Nullable public final String declineCode; | ||
|
||
@Nullable public final String charge; | ||
|
||
StripeError(@Nullable String type, @Nullable String message, @Nullable String code, | ||
@Nullable String param, @Nullable String declineCode, @Nullable String charge) { | ||
this.type = type; | ||
this.message = message; | ||
this.code = code; | ||
this.param = param; | ||
this.declineCode = declineCode; | ||
this.charge = charge; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.