From 00e337c3639aa00b8ab4c29f721be52d6f4c604b Mon Sep 17 00:00:00 2001 From: Michael Shafrir Date: Tue, 5 Mar 2019 10:36:30 -0500 Subject: [PATCH] Pin all Stripe requests to API version 2017-06-05 **Summary** - Unconditionally set a `Stripe-Version` header on API requests - Remove API version setter from `RequestOptions` **Motivation** ANDROID-334 **Testing** Update unit tests --- .../java/com/stripe/android/ApiVersion.java | 8 +-- .../com/stripe/android/RequestOptions.java | 36 ---------- .../main/java/com/stripe/android/Stripe.java | 29 +------- .../com/stripe/android/StripeApiHandler.java | 72 +++++-------------- .../stripe/android/StripeApiHandlerTest.java | 6 +- .../java/com/stripe/android/StripeTest.java | 20 +++--- 6 files changed, 33 insertions(+), 138 deletions(-) diff --git a/stripe/src/main/java/com/stripe/android/ApiVersion.java b/stripe/src/main/java/com/stripe/android/ApiVersion.java index 20d58bf1630..9cae9f3603b 100644 --- a/stripe/src/main/java/com/stripe/android/ApiVersion.java +++ b/stripe/src/main/java/com/stripe/android/ApiVersion.java @@ -14,7 +14,7 @@ * See https://stripe.com/docs/upgrades for latest * API changes. */ -public class ApiVersion { +class ApiVersion { static final String DEFAULT_API_VERSION = "2017-06-05"; @NonNull private static final ApiVersion DEFAULT_INSTANCE = new ApiVersion(DEFAULT_API_VERSION); @@ -22,12 +22,12 @@ public class ApiVersion { @NonNull private final String mCode; @NonNull - public static ApiVersion create(@NonNull String code) { + static ApiVersion create(@NonNull String code) { return new ApiVersion(code); } @NonNull - public static ApiVersion getDefault() { + static ApiVersion getDefault() { return DEFAULT_INSTANCE; } @@ -36,7 +36,7 @@ private ApiVersion(@NonNull String code) { } @NonNull - public String getCode() { + String getCode() { return mCode; } diff --git a/stripe/src/main/java/com/stripe/android/RequestOptions.java b/stripe/src/main/java/com/stripe/android/RequestOptions.java index 8d0274e28b2..1bfa4e65bdf 100644 --- a/stripe/src/main/java/com/stripe/android/RequestOptions.java +++ b/stripe/src/main/java/com/stripe/android/RequestOptions.java @@ -18,7 +18,6 @@ public class RequestOptions { public static final String TYPE_QUERY = "source"; public static final String TYPE_JSON = "json_data"; - @Nullable private final String mApiVersion; @Nullable private final String mGuid; @Nullable private final String mIdempotencyKey; @Nullable private final String mPublishableApiKey; @@ -26,13 +25,11 @@ public class RequestOptions { @Nullable private final String mStripeAccount; private RequestOptions( - @Nullable String apiVersion, @Nullable String guid, @Nullable String idempotencyKey, @Nullable String publishableApiKey, @NonNull @RequestType String requestType, @Nullable String stripeAccount) { - mApiVersion = apiVersion; mGuid = guid; mIdempotencyKey = idempotencyKey; mPublishableApiKey = publishableApiKey; @@ -40,14 +37,6 @@ private RequestOptions( mStripeAccount = stripeAccount; } - /** - * @return the API version for this request - */ - @Nullable - String getApiVersion() { - return mApiVersion; - } - /** * @return the guid for this request */ @@ -123,7 +112,6 @@ public static RequestOptions.RequestOptionsBuilder builder( */ public static final class RequestOptionsBuilder { - private String apiVersion; private String guid; private String idempotencyKey; private String publishableApiKey; @@ -179,29 +167,6 @@ RequestOptionsBuilder setGuid(@Nullable String guid) { return this; } - /** - * Setter for the API version for this set of {@link RequestOptions}. If not set, - * your account default API version is used. - * - * @param apiVersion the API version to use - * @return {@code this}, for chaining purposes - */ - @NonNull - RequestOptionsBuilder setApiVersion(@Nullable String apiVersion) { - this.apiVersion = StripeTextUtils.isBlank(apiVersion) - ? null - : apiVersion; - return this; - } - - /** - * Convenience method for {@link #setApiVersion(String)} - */ - @NonNull - RequestOptionsBuilder setApiVersion(@Nullable ApiVersion apiVersion) { - return setApiVersion(apiVersion != null ? apiVersion.getCode() : null); - } - @NonNull RequestOptionsBuilder setStripeAccount(@Nullable String stripeAccount) { this.stripeAccount = stripeAccount; @@ -215,7 +180,6 @@ RequestOptionsBuilder setStripeAccount(@Nullable String stripeAccount) { */ public RequestOptions build() { return new RequestOptions( - this.apiVersion, this.guid, this.idempotencyKey, this.publishableApiKey, diff --git a/stripe/src/main/java/com/stripe/android/Stripe.java b/stripe/src/main/java/com/stripe/android/Stripe.java index 68c0a7b5485..c944251feae 100644 --- a/stripe/src/main/java/com/stripe/android/Stripe.java +++ b/stripe/src/main/java/com/stripe/android/Stripe.java @@ -690,21 +690,7 @@ public Token createAccountTokenSynchronous(@NonNull final AccountParams accountP InvalidRequestException, APIConnectionException, APIException { - return createAccountTokenSynchronous(accountParams, mDefaultPublishableKey, null); - } - - /** - * See {@link #createAccountTokenSynchronous(AccountParams)} - */ - @Nullable - @VisibleForTesting - Token createAccountTokenSynchronous(@NonNull final AccountParams accountParams, - @NonNull final ApiVersion apiVersion) - throws AuthenticationException, - InvalidRequestException, - APIConnectionException, - APIException { - return createAccountTokenSynchronous(accountParams, mDefaultPublishableKey, apiVersion); + return createAccountTokenSynchronous(accountParams, mDefaultPublishableKey); } /** @@ -730,18 +716,6 @@ public Token createAccountTokenSynchronous( InvalidRequestException, APIConnectionException, APIException { - return createAccountTokenSynchronous(accountParams, publishableKey, null); - } - - @Nullable - private Token createAccountTokenSynchronous( - @NonNull final AccountParams accountParams, - @Nullable String publishableKey, - @Nullable ApiVersion apiVersion) - throws AuthenticationException, - InvalidRequestException, - APIConnectionException, - APIException { String apiKey = publishableKey == null ? mDefaultPublishableKey : publishableKey; if (apiKey == null) { return null; @@ -749,7 +723,6 @@ private Token createAccountTokenSynchronous( validateKey(publishableKey); RequestOptions requestOptions = RequestOptions.builder( publishableKey, mStripeAccount, RequestOptions.TYPE_QUERY) - .setApiVersion(apiVersion) .build(); try { return StripeApiHandler.createToken( diff --git a/stripe/src/main/java/com/stripe/android/StripeApiHandler.java b/stripe/src/main/java/com/stripe/android/StripeApiHandler.java index 48a941ac659..aa6f4774a86 100644 --- a/stripe/src/main/java/com/stripe/android/StripeApiHandler.java +++ b/stripe/src/main/java/com/stripe/android/StripeApiHandler.java @@ -121,11 +121,8 @@ static PaymentIntent confirmPaymentIntent( APIException { final Map paramMap = paymentIntentParams.toParamMap(); StripeNetworkUtils.addUidParamsToPaymentIntent(uidProvider, context, paramMap); - final RequestOptions options = RequestOptions.builder( - publishableKey, - stripeAccount, + final RequestOptions options = RequestOptions.builder(publishableKey, stripeAccount, RequestOptions.TYPE_QUERY) - .setApiVersion(ApiVersion.DEFAULT_API_VERSION) .build(); try { @@ -173,12 +170,8 @@ static PaymentIntent retrievePaymentIntent( APIConnectionException, APIException { final Map paramMap = paymentIntentParams.toParamMap(); - final RequestOptions options = RequestOptions.builder( - publishableKey, - stripeAccount, - RequestOptions.TYPE_QUERY) - .setApiVersion(ApiVersion.DEFAULT_API_VERSION) - .build(); + final RequestOptions options = RequestOptions.builder(publishableKey, stripeAccount, + RequestOptions.TYPE_QUERY).build(); try { final String apiKey = options.getPublishableApiKey(); @@ -257,9 +250,7 @@ static Source createSource( APIException { final Map paramMap = sourceParams.toParamMap(); StripeNetworkUtils.addUidParams(uidProvider, context, paramMap); - final RequestOptions options = RequestOptions.builder( - publishableKey, - stripeAccount, + final RequestOptions options = RequestOptions.builder(publishableKey, stripeAccount, RequestOptions.TYPE_QUERY).build(); try { @@ -316,14 +307,10 @@ static Source retrieveSource( final Map paramMap = SourceParams.createRetrieveSourceParams(clientSecret); final RequestOptions options; if (stripeAccount == null) { - options = RequestOptions.builder(publishableKey) - .build(); + options = RequestOptions.builder(publishableKey).build(); } else { - options = RequestOptions.builder( - publishableKey, - stripeAccount, - RequestOptions.TYPE_QUERY) - .build(); + options = RequestOptions.builder(publishableKey, stripeAccount, + RequestOptions.TYPE_QUERY).build(); } try { final StripeResponse response = @@ -351,9 +338,7 @@ static PaymentMethod createPaymentMethod( final Map params = paymentMethodCreateParams.toParamMap(); StripeNetworkUtils.addUidParams(null, context, params); - final RequestOptions options = RequestOptions.builder( - publishableKey, - stripeAccount, + final RequestOptions options = RequestOptions.builder(publishableKey, stripeAccount, RequestOptions.TYPE_QUERY).build(); final String apiKey = options.getPublishableApiKey(); @@ -455,9 +440,7 @@ static Source addCustomerSource( context, productUsageTokens, publicKey, sourceType); // We use the public key to log, so we need different RequestOptions. - final RequestOptions loggingOptions = RequestOptions.builder(publicKey) - .setApiVersion(ApiVersion.DEFAULT_API_VERSION) - .build(); + final RequestOptions loggingOptions = RequestOptions.builder(publicKey).build(); logApiCall(loggingParamsMap, loggingOptions, listener); } @@ -465,9 +448,7 @@ static Source addCustomerSource( POST, getAddCustomerSourceUrl(customerId), paramsMap, - RequestOptions.builder(secret) - .setApiVersion(ApiVersion.DEFAULT_API_VERSION) - .build()); + RequestOptions.builder(secret).build()); // Method throws if errors are found, so no return value occurs. convertErrorsToExceptionsAndThrowIfNecessary(response); return Source.fromString(response.getResponseBody()); @@ -493,9 +474,7 @@ static Source deleteCustomerSource( LoggingUtils.getDeleteSourceParams(context, productUsageTokens, publicKey); // We use the public key to log, so we need different RequestOptions. - final RequestOptions loggingOptions = RequestOptions.builder(publicKey) - .setApiVersion(ApiVersion.DEFAULT_API_VERSION) - .build(); + final RequestOptions loggingOptions = RequestOptions.builder(publicKey).build(); logApiCall(loggingParamsMap, loggingOptions, listener); } @@ -503,9 +482,7 @@ static Source deleteCustomerSource( DELETE, getDeleteCustomerSourceUrl(customerId, sourceId), paramsMap, - RequestOptions.builder(secret) - .setApiVersion(ApiVersion.DEFAULT_API_VERSION) - .build()); + RequestOptions.builder(secret).build()); // Method throws if errors are found, so no return value occurs. convertErrorsToExceptionsAndThrowIfNecessary(response); return Source.fromString(response.getResponseBody()); @@ -531,9 +508,7 @@ static Customer setDefaultCustomerSource( // Context can be nullable because this action is performed with only a weak reference if (context != null) { - final RequestOptions loggingOptions = RequestOptions.builder(publicKey) - .setApiVersion(ApiVersion.DEFAULT_API_VERSION) - .build(); + final RequestOptions loggingOptions = RequestOptions.builder(publicKey).build(); final Map loggingParameters = LoggingUtils.getEventLoggingParams( context.getApplicationContext(), @@ -550,9 +525,7 @@ static Customer setDefaultCustomerSource( POST, getRetrieveCustomerUrl(customerId), paramsMap, - RequestOptions.builder(secret) - .setApiVersion(ApiVersion.DEFAULT_API_VERSION) - .build()); + RequestOptions.builder(secret).build()); // Method throws if errors are found, so no return value occurs. convertErrorsToExceptionsAndThrowIfNecessary(response); @@ -578,9 +551,7 @@ static Customer setCustomerShippingInfo( // Context can be nullable because this action is performed with only a weak reference if (context != null) { - final RequestOptions loggingOptions = RequestOptions.builder(publicKey) - .setApiVersion(ApiVersion.DEFAULT_API_VERSION) - .build(); + final RequestOptions loggingOptions = RequestOptions.builder(publicKey).build(); final Map loggingParameters = LoggingUtils.getEventLoggingParams( context.getApplicationContext(), @@ -597,9 +568,7 @@ static Customer setCustomerShippingInfo( POST, getRetrieveCustomerUrl(customerId), paramsMap, - RequestOptions.builder(secret) - .setApiVersion(ApiVersion.DEFAULT_API_VERSION) - .build()); + RequestOptions.builder(secret).build()); // Method throws if errors are found, so no return value occurs. convertErrorsToExceptionsAndThrowIfNecessary(response); return Customer.fromString(response.getResponseBody()); @@ -617,9 +586,7 @@ static Customer retrieveCustomer(@NonNull String customerId, @NonNull String sec GET, getRetrieveCustomerUrl(customerId), null, - RequestOptions.builder(secret) - .setApiVersion(ApiVersion.DEFAULT_API_VERSION) - .build()); + RequestOptions.builder(secret).build()); convertErrorsToExceptionsAndThrowIfNecessary(response); return Customer.fromString(response.getResponseBody()); } @@ -666,10 +633,7 @@ static Map getHeaders(@Nullable RequestOptions options) { propertyMap.put("publisher", "Stripe"); final JSONObject headerMappingObject = new JSONObject(propertyMap); headers.put("X-Stripe-Client-User-Agent", headerMappingObject.toString()); - - if (options != null && options.getApiVersion() != null) { - headers.put("Stripe-Version", options.getApiVersion()); - } + headers.put("Stripe-Version", ApiVersion.DEFAULT_API_VERSION); if (options != null && options.getStripeAccount() != null) { headers.put("Stripe-Account", options.getStripeAccount()); diff --git a/stripe/src/test/java/com/stripe/android/StripeApiHandlerTest.java b/stripe/src/test/java/com/stripe/android/StripeApiHandlerTest.java index ff8803e59ea..9ea16d62ef6 100644 --- a/stripe/src/test/java/com/stripe/android/StripeApiHandlerTest.java +++ b/stripe/src/test/java/com/stripe/android/StripeApiHandlerTest.java @@ -95,10 +95,8 @@ public void getHeaders_withAllRequestOptions_properlyMapsRequestOptions() { String fakePublicKey = "fake_public_key"; String idempotencyKey = "idempotency_rules"; String stripeAccount = "acct_123abc"; - String apiVersion = "2011-11-11"; RequestOptions requestOptions = RequestOptions.builder(fakePublicKey) .setIdempotencyKey(idempotencyKey) - .setApiVersion(apiVersion) .setStripeAccount(stripeAccount) .build(); Map headerMap = StripeApiHandler.getHeaders(requestOptions); @@ -106,7 +104,7 @@ public void getHeaders_withAllRequestOptions_properlyMapsRequestOptions() { assertNotNull(headerMap); assertEquals("Bearer " + fakePublicKey, headerMap.get("Authorization")); assertEquals(idempotencyKey, headerMap.get("Idempotency-Key")); - assertEquals(apiVersion, headerMap.get("Stripe-Version")); + assertEquals(ApiVersion.DEFAULT_API_VERSION, headerMap.get("Stripe-Version")); assertEquals(stripeAccount, headerMap.get("Stripe-Account")); } @@ -118,7 +116,7 @@ public void getHeaders_withOnlyRequiredOptions_doesNotAddEmptyOptions() { assertNotNull(headerMap); assertFalse(headerMap.containsKey("Idempotency-Key")); - assertFalse(headerMap.containsKey("Stripe-Version")); + assertTrue(headerMap.containsKey("Stripe-Version")); assertFalse(headerMap.containsKey("Stripe-Account")); assertTrue(headerMap.containsKey("Authorization")); } diff --git a/stripe/src/test/java/com/stripe/android/StripeTest.java b/stripe/src/test/java/com/stripe/android/StripeTest.java index 36dafa8bdba..f1232125a0c 100644 --- a/stripe/src/test/java/com/stripe/android/StripeTest.java +++ b/stripe/src/test/java/com/stripe/android/StripeTest.java @@ -977,7 +977,7 @@ public void createTokenSynchronous_withValidCvc_passesIntegrationTest() } @Test - public void createTokenSynchronous_withValidAccountOnApi20170605_passesIntegrationTest() + public void createTokenSynchronous_withValidLegalEntity_passesIntegrationTest() throws APIException, AuthenticationException, InvalidRequestException, APIConnectionException { final Address exampleAddress = new Address.Builder() @@ -996,8 +996,7 @@ public void createTokenSynchronous_withValidAccountOnApi20170605_passesIntegrati final TestLoggingListener listener = new TestLoggingListener(true); stripe.setLoggingResponseListener(listener); final Token token = stripe.createAccountTokenSynchronous( - AccountParams.createAccountParams(true, legalEntityData), - ApiVersion.getDefault()); + AccountParams.createAccountParams(true, legalEntityData)); assertNotNull(token); assertEquals(Token.TYPE_ACCOUNT, token.getType()); assertFalse(token.getLivemode()); @@ -1007,15 +1006,14 @@ public void createTokenSynchronous_withValidAccountOnApi20170605_passesIntegrati } @Test - public void createTokenSynchronous_withoutLegalEntityOnApi20170605_passesIntegrationTest() + public void createTokenSynchronous_withoutLegalEntity_passesIntegrationTest() throws APIException, AuthenticationException, InvalidRequestException, APIConnectionException { final Stripe stripe = new Stripe(mContext, FUNCTIONAL_PUBLISHABLE_KEY); final TestLoggingListener listener = new TestLoggingListener(true); stripe.setLoggingResponseListener(listener); final Token token = stripe.createAccountTokenSynchronous( - AccountParams.createAccountParams(true, null), - ApiVersion.getDefault()); + AccountParams.createAccountParams(true, null)); assertNotNull(token); assertEquals(Token.TYPE_ACCOUNT, token.getType()); assertFalse(token.getLivemode()); @@ -1025,7 +1023,7 @@ public void createTokenSynchronous_withoutLegalEntityOnApi20170605_passesIntegra } @Test - public void createTokenSynchronous_withIndividualEntityOnApi20190219_passesIntegrationTest() + public void createTokenSynchronous_withIndividualEntity_passesIntegrationTest() throws APIException, AuthenticationException, InvalidRequestException, APIConnectionException { final Address exampleAddress = new Address @@ -1045,8 +1043,7 @@ public void createTokenSynchronous_withIndividualEntityOnApi20190219_passesInteg stripe.setLoggingResponseListener(listener); final Token token = stripe.createAccountTokenSynchronous( AccountParams.createAccountParams(true, - AccountParams.BusinessType.Individual, businessData), - ApiVersion.create("2019-02-19")); + AccountParams.BusinessType.Individual, businessData)); assertNotNull(token); assertEquals(Token.TYPE_ACCOUNT, token.getType()); assertFalse(token.getLivemode()); @@ -1057,7 +1054,7 @@ public void createTokenSynchronous_withIndividualEntityOnApi20190219_passesInteg @Test - public void createTokenSynchronous_withCompanyEntityOnApi20190219_passesIntegrationTest() + public void createTokenSynchronous_withCompanyEntity_passesIntegrationTest() throws APIException, AuthenticationException, InvalidRequestException, APIConnectionException { final Address exampleAddress = new Address @@ -1076,8 +1073,7 @@ public void createTokenSynchronous_withCompanyEntityOnApi20190219_passesIntegrat stripe.setLoggingResponseListener(listener); final Token token = stripe.createAccountTokenSynchronous( AccountParams.createAccountParams(true, - AccountParams.BusinessType.Company, businessData), - ApiVersion.create("2019-02-19")); + AccountParams.BusinessType.Company, businessData)); assertNotNull(token); assertEquals(Token.TYPE_ACCOUNT, token.getType()); assertFalse(token.getLivemode());