Skip to content

Commit

Permalink
Pin all Stripe requests to API version 2017-06-05 (#832)
Browse files Browse the repository at this point in the history
**Summary**
- Unconditionally set a `Stripe-Version` header on API requests
- Remove API version setter from `RequestOptions`

**Motivation**
ANDROID-334

**Testing**
Update unit tests
  • Loading branch information
mshafrir-stripe authored Mar 6, 2019
1 parent b7aa8fc commit 7f376da
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 138 deletions.
8 changes: 4 additions & 4 deletions stripe/src/main/java/com/stripe/android/ApiVersion.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,20 @@
* See <a href="https://stripe.com/docs/upgrades">https://stripe.com/docs/upgrades</a> 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);

@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;
}

Expand All @@ -36,7 +36,7 @@ private ApiVersion(@NonNull String code) {
}

@NonNull
public String getCode() {
String getCode() {
return mCode;
}

Expand Down
36 changes: 0 additions & 36 deletions stripe/src/main/java/com/stripe/android/RequestOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,36 +18,25 @@ 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;
@NonNull @RequestType private final String mRequestType;
@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;
mRequestType = requestType;
mStripeAccount = stripeAccount;
}

/**
* @return the API version for this request
*/
@Nullable
String getApiVersion() {
return mApiVersion;
}

/**
* @return the guid for this request
*/
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -215,7 +180,6 @@ RequestOptionsBuilder setStripeAccount(@Nullable String stripeAccount) {
*/
public RequestOptions build() {
return new RequestOptions(
this.apiVersion,
this.guid,
this.idempotencyKey,
this.publishableApiKey,
Expand Down
29 changes: 1 addition & 28 deletions stripe/src/main/java/com/stripe/android/Stripe.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/**
Expand All @@ -730,26 +716,13 @@ 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;
}
validateKey(publishableKey);
RequestOptions requestOptions = RequestOptions.builder(
publishableKey, mStripeAccount, RequestOptions.TYPE_QUERY)
.setApiVersion(apiVersion)
.build();
try {
return StripeApiHandler.createToken(
Expand Down
72 changes: 18 additions & 54 deletions stripe/src/main/java/com/stripe/android/StripeApiHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,8 @@ static PaymentIntent confirmPaymentIntent(
APIException {
final Map<String, Object> 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 {
Expand Down Expand Up @@ -173,12 +170,8 @@ static PaymentIntent retrievePaymentIntent(
APIConnectionException,
APIException {
final Map<String, Object> 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();
Expand Down Expand Up @@ -257,9 +250,7 @@ static Source createSource(
APIException {
final Map<String, Object> 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 {
Expand Down Expand Up @@ -316,14 +307,10 @@ static Source retrieveSource(
final Map<String, Object> 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 =
Expand Down Expand Up @@ -351,9 +338,7 @@ static PaymentMethod createPaymentMethod(
final Map<String, Object> 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();
Expand Down Expand Up @@ -455,19 +440,15 @@ 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);
}

final StripeResponse response = getStripeResponse(
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());
Expand All @@ -493,19 +474,15 @@ 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);
}

final StripeResponse response = getStripeResponse(
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());
Expand All @@ -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<String, Object> loggingParameters = LoggingUtils.getEventLoggingParams(
context.getApplicationContext(),
Expand All @@ -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);
Expand All @@ -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<String, Object> loggingParameters = LoggingUtils.getEventLoggingParams(
context.getApplicationContext(),
Expand All @@ -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());
Expand All @@ -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());
}
Expand Down Expand Up @@ -666,10 +633,7 @@ static Map<String, String> 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());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,18 +95,16 @@ 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<String, String> headerMap = StripeApiHandler.getHeaders(requestOptions);

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"));
}

Expand All @@ -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"));
}
Expand Down
Loading

0 comments on commit 7f376da

Please sign in to comment.