-
Notifications
You must be signed in to change notification settings - Fork 662
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bindings to support Custom Connect onboarding in Europe #492
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -13,6 +13,7 @@ | |||||||
import com.stripe.android.exception.CardException; | ||||||||
import com.stripe.android.exception.InvalidRequestException; | ||||||||
import com.stripe.android.exception.StripeException; | ||||||||
import com.stripe.android.model.AccountParams; | ||||||||
import com.stripe.android.model.BankAccount; | ||||||||
import com.stripe.android.model.Card; | ||||||||
import com.stripe.android.model.Source; | ||||||||
|
@@ -29,7 +30,7 @@ | |||||||
import static com.stripe.android.StripeNetworkUtils.hashMapFromPersonalId; | ||||||||
|
||||||||
/** | ||||||||
* Class that handles {@link Token} creation from charges and {@link Card} models. | ||||||||
* Class that handles {@link Token} creation from charges, {@link Card}, and accounts. | ||||||||
*/ | ||||||||
public class Stripe { | ||||||||
|
||||||||
|
@@ -543,6 +544,68 @@ public Token createPiiTokenSynchronous(@NonNull String personalId, String publis | |||||||
mLoggingResponseListener); | ||||||||
} | ||||||||
|
||||||||
/** | ||||||||
* Blocking method to create a {@link Token} for a Connect Account. Do not call this on the UI | ||||||||
* thread or your app will crash. The method uses the currently set | ||||||||
* {@link #mDefaultPublishableKey}. | ||||||||
* | ||||||||
* @param accountParams params to use for this token. | ||||||||
* @return a {@link Token} that can be used for this account. | ||||||||
* | ||||||||
* @throws AuthenticationException failure to properly authenticate yourself (check your key) | ||||||||
* @throws InvalidRequestException your request has invalid parameters | ||||||||
* @throws APIConnectionException failure to connect to Stripe's API | ||||||||
* @throws APIException any other type of problem (for instance, a temporary issue with | ||||||||
* Stripe's servers) | ||||||||
*/ | ||||||||
public Token createAccountTokenSynchronous(@NonNull final AccountParams accountParams) | ||||||||
throws AuthenticationException, | ||||||||
InvalidRequestException, | ||||||||
APIConnectionException, | ||||||||
CardException, | ||||||||
APIException { | ||||||||
return createAccountTokenSynchronous(accountParams, mDefaultPublishableKey); | ||||||||
} | ||||||||
|
||||||||
/** | ||||||||
* Blocking method to create a {@link Token} for a Connect Account. Do not call this on the UI | ||||||||
* thread. | ||||||||
* | ||||||||
* @param accountParams params to use for this token. | ||||||||
* @param publishableKey the publishable key to use with this request | ||||||||
* @return a {@link Token} that can be used for this account. | ||||||||
* | ||||||||
* @throws AuthenticationException failure to properly authenticate yourself (check your key) | ||||||||
* @throws InvalidRequestException your request has invalid parameters | ||||||||
* @throws APIConnectionException failure to connect to Stripe's API | ||||||||
* @throws APIException any other type of problem (for instance, a temporary issue with | ||||||||
* Stripe's servers) | ||||||||
*/ | ||||||||
public Token createAccountTokenSynchronous( | ||||||||
@NonNull final AccountParams accountParams, | ||||||||
@Nullable String publishableKey) | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You might document what this does if |
||||||||
throws AuthenticationException, | ||||||||
InvalidRequestException, | ||||||||
APIConnectionException, | ||||||||
CardException, | ||||||||
APIException { | ||||||||
String apiKey = publishableKey == null ? mDefaultPublishableKey : publishableKey; | ||||||||
if (apiKey == null) { | ||||||||
return null; | ||||||||
} | ||||||||
validateKey(publishableKey); | ||||||||
RequestOptions requestOptions = RequestOptions.builder( | ||||||||
publishableKey, | ||||||||
null, | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The other create token methods pass in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My thinking is that this is the function for creating a Stripe account so there should never be a pre-existing Stripe Account passed to it...since we're creating it with this function. In particular, I was concerned this would be cause unexpected server behavior since the token can be used for updates as well. Ex: somehow the user has an only StripeAccount string saved in the Stripe object and goes to create a new account with a new legal entity and accidentally changes their old legal entity. EDIT: I checked and it doesn't cause issues. On account updates: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Then I like this method better: stripe-android/stripe/src/main/java/com/stripe/android/RequestOptions.java Lines 112 to 114 in 4163e57
|
||||||||
RequestOptions.TYPE_QUERY).build(); | ||||||||
return StripeApiHandler.createToken( | ||||||||
mContext, | ||||||||
accountParams.toParamMap(), | ||||||||
requestOptions, | ||||||||
Token.TYPE_ACCOUNT, | ||||||||
mLoggingResponseListener); | ||||||||
} | ||||||||
|
||||||||
public void logEventSynchronous( | ||||||||
@NonNull List<String> productUsageTokens, | ||||||||
@NonNull StripePaymentSource paymentSource) { | ||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
package com.stripe.android.model; | ||
|
||
import android.support.annotation.NonNull; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
import static com.stripe.android.StripeNetworkUtils.removeNullAndEmptyParams; | ||
|
||
/** | ||
* Represents a grouping of parameters needed to create a Token for a Connect account on the server. | ||
*/ | ||
public class AccountParams { | ||
|
||
static final String API_PARAM_LEGAL_ENTITY = "legal_entity"; | ||
static final String API_TOS_SHOWN_AND_ACCEPTED = "tos_shown_and_accepted"; | ||
private Boolean mTosShownAndAccepted; | ||
private Map<String, Object> mLegalEntity; | ||
|
||
/** | ||
* @param tosShownAndAccepted indicates that the platform showed the user the appropriate text | ||
* and links to Stripe's terms of service. Tokens will only generated | ||
* when this is true. | ||
* @param legalEntity map that specifies the legal entity for which the connect account is being | ||
* created. Can contain any of the field specified by legal_entity is the API | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. typos: "any of the fields specified by legal_entity in the API" Same typos below |
||
* docs. | ||
* See {@linktourl https://stripe.com/docs/api#account_object-legal_entity} | ||
* @return | ||
*/ | ||
public static AccountParams createAccountParams( | ||
boolean tosShownAndAccepted, | ||
Map<String, Object> legalEntity) { | ||
AccountParams accountParams = new AccountParams() | ||
.setTosShownAndAccepted(tosShownAndAccepted) | ||
.setLegalEntity(legalEntity); | ||
return accountParams; | ||
} | ||
|
||
/** | ||
* @param tosShownAndAccepted whether the platform showed the user the appropriate text | ||
* and links to Stripe's terms of service. Tokens will only generated | ||
* when this is true. | ||
* @return {@code this}, for chaining purposes | ||
*/ | ||
public AccountParams setTosShownAndAccepted(boolean tosShownAndAccepted) { | ||
mTosShownAndAccepted = tosShownAndAccepted; | ||
return this; | ||
} | ||
|
||
/** | ||
* @param legalEntity map that specifies the legal entity for which the connect account is being | ||
* created. Can contain any of the field specified by legal_entity is the API | ||
* docs. | ||
* See {@linktourl https://stripe.com/docs/api#account_object-legal_entity} | ||
* @return {@code this}, for chaining purposes | ||
*/ | ||
public AccountParams setLegalEntity(Map<String, Object> legalEntity) { | ||
mLegalEntity = legalEntity; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any concerns about validating that the user hasn't stuck something non-serializable into the legalEntity? For example, I'm not sure what happens if they try to use I followed some of the code down, and it looked like the networking code was going to eventually call to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hrm...yes...that is a good concern. we should check that. |
||
return this; | ||
} | ||
|
||
/** | ||
* Create a string-keyed map representing this object that is | ||
* ready to be sent over the network. | ||
* | ||
* @return a String-keyed map | ||
*/ | ||
@NonNull | ||
public Map<String, Object> toParamMap() { | ||
Map<String, Object> networkReadyMap = new HashMap<>(); | ||
Map<String, Object> tokenMap = new HashMap<>(); | ||
tokenMap.put(API_TOS_SHOWN_AND_ACCEPTED, mTosShownAndAccepted); | ||
tokenMap.put(API_PARAM_LEGAL_ENTITY, mLegalEntity); | ||
networkReadyMap.put("account", tokenMap); | ||
removeNullAndEmptyParams(networkReadyMap); | ||
return networkReadyMap; | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,11 +17,12 @@ | |
public class Token implements StripePaymentSource { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The documentation of the |
||
|
||
@Retention(RetentionPolicy.SOURCE) | ||
@StringDef({TYPE_CARD, TYPE_BANK_ACCOUNT, TYPE_PII}) | ||
@StringDef({TYPE_CARD, TYPE_BANK_ACCOUNT, TYPE_PII, TYPE_ACCOUNT}) | ||
public @interface TokenType {} | ||
public static final String TYPE_CARD = "card"; | ||
public static final String TYPE_BANK_ACCOUNT = "bank_account"; | ||
public static final String TYPE_PII = "pii"; | ||
public static final String TYPE_ACCOUNT = "account"; | ||
|
||
// The key for these object fields is identical to their retrieved values | ||
// from the Type field. | ||
|
@@ -85,12 +86,13 @@ public Token( | |
*/ | ||
public Token( | ||
String id, | ||
String type, | ||
boolean livemode, | ||
Date created, | ||
Boolean used | ||
) { | ||
mId = id; | ||
mType = TYPE_PII; | ||
mType = type; | ||
mCreated = created; | ||
mCard = null; | ||
mBankAccount = null; | ||
|
@@ -192,10 +194,9 @@ public static Token fromJson(@Nullable JSONObject jsonObject) { | |
} | ||
Card card = Card.fromJson(cardObject); | ||
token = new Token(tokenId, liveMode, date, used, card); | ||
} else if (Token.TYPE_PII.equals(tokenType)) { | ||
token = new Token(tokenId, liveMode, date, used); | ||
} else if (Token.TYPE_PII.equals(tokenType) || Token.TYPE_ACCOUNT.equals(tokenType)) { | ||
token = new Token(tokenId, tokenType, liveMode, date, used); | ||
} | ||
|
||
return token; | ||
} | ||
|
||
|
@@ -219,6 +220,8 @@ static String asTokenType(@Nullable String possibleTokenType) { | |
return Token.TYPE_BANK_ACCOUNT; | ||
} else if (Token.TYPE_PII.equals(possibleTokenType)) { | ||
return Token.TYPE_PII; | ||
} else if (Token.TYPE_ACCOUNT.equals(possibleTokenType)) { | ||
return Token.TYPE_ACCOUNT; | ||
} | ||
|
||
return null; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method signature also says this throws
CardException
, but it's not covered by the documentation block. ThecreatePii
methods have the same problem. Maybe just a copy/paste error fromcreateToken
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made it deeper into the code, looks like this is because
StripeAPIHandler.createToken()
can throwCardException
. For PII & Connect Account creation, I think you should probably "catch & swallow"CardException
(only if it cannot happen, obviously). This prevents the underlying implementation (that you're sharing a method) from leaking to clients of the SDK. Otherwise I think it'd be good to document under what conditions it'd be thrown.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, you might want to update variable names, etc, in
StripeAPIHandler.createToken()
- things likecardParams
are now more general than just cards.