Skip to content
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

Connect Account tokenization #876

Merged
merged 13 commits into from Jan 12, 2018
Merged

Conversation

danj-stripe
Copy link
Contributor

@danj-stripe danj-stripe commented Dec 21, 2017

Summary

Add API method for creating Connect Account tokens.

Motivation

Supporting Stripe API changes.

Testing

Unit and functional tests have been added. Manually tested with tokens created by this code to ensure I could consume them from a connect platform (although the tokens generated by the fully specific fixture in the functional test aren't consumable, they don't pass the required data validation)

*/
@interface STPAPIClient (ConnectAccounts)

- (void)createTokenWithConnectAccount:(id)obj completion:(__nullable STPTokenCompletionBlock)completion;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

obj needs to turn into:

account: {
  legal_entity: {...},
  tos_shown_and_accepted: true,
}

with either legal_entity or tos_shown_and_accepted, or both.

I don't know whether I want to create another ...Params class, or change this method to take two nullable parameters.

I also think it's unfortunate that Bool? is nullable NSNumber in Obj-C

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I think it'd be better to make this method take parameters rather than make a parent AccountParams class, but don't feel strongly.

Is it necessary to model tos_shown_and_accepted as a Bool?, or can we treat tos_shown_and_accepted: nil as tos_shown_and_accepted: false?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that would work. Valid values for tos_shown_and_accepted are {true, nil}. Some basic use cases:

  • account: { tos_shown_and_accepted: true }: minimum required to set up a new account
  • account: { legal_entity: { ... }, tos_shown_and_accepted: true }: setting up new account with some data about the legal entity
  • account: { legal_entity: { ... } }: valid for updating a pre-existing account
  • account: { tos_shown_and_accepted: false, ... }: rejected by the server as invalid

As I understand it, the initial purpose for this API is collecting positive affirmation that the user has seen & accepted the ToS, instead of the old world where the platform is allowed to vouch that fact as true. However, it's also just as usable for updating the legal entity info directly.

I'll think about AccountParams a little more. I like that it's easier to add new fields in the future, and the possibility of providing >1 constructors to help understand the legal_entity/tos_shown_and_accepted distinction. But it's a lot just for two optional fields

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah interesting, if that's the case then perhaps an AccountParams object with multiple constructors makes sense. thanks for the explanation!

};


@interface STPLegalEntityParams : STPPersonParams
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any problems foreseen by inheriting from STPPersonParams, which conforms to STPFormEncodable?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, I can't think of any

};


@interface STPLegalEntityParams : STPPersonParams
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do STPVerificationParams and STPPersonParams belong in their own files? Or are they fine here?

They're only used here (for now?), and the inheritance also links STPLegalEntityParams with STPPersonParams pretty closely.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think they're fine together!

@danj-stripe
Copy link
Contributor Author

@bg-stripe WDYT? Does this look ~reasonable?

@bg-stripe
Copy link
Contributor

this looks reasonable to me!

Adding a test to verify this works, and that this doesn't break other NSNumber instances
that store 0 or 1.
@danj-stripe danj-stripe force-pushed the danj/feature/connect-account-tokens branch 2 times, most recently from 80aa4e0 to d59c935 Compare January 11, 2018 02:31
@danj-stripe
Copy link
Contributor Author

This includes the commit for #881, and I think it's now complete.

r? @bg-stripe

@danj-stripe danj-stripe changed the title [WIP] Connect Account tokenization Connect Account tokenization Jan 11, 2018
@danj-stripe danj-stripe force-pushed the danj/feature/connect-account-tokens branch from d59c935 to 139c516 Compare January 11, 2018 04:20
It takes a single parameter, an `STPConnectAccountParams` object. This has an optional
BOOL and an optional STPLegalEntityParams object (one of fields must be provided).

Still TODO: adding `description` implementations in STPLegalEntityParams.m, and
testing!
This currently fails, because `legal_entity` is actually required all the time, contrary
to what I thought.
These are pretty basic, but then so are the implementations of the classes.

I wanted to add custom Asserts (like https://www.objc.io/issues/15-testing/xctest/#custom-assert-macros)
for these *very* repetitive tests (which already exist 4x times), but I think this is
okay-ish.
@danj-stripe danj-stripe force-pushed the danj/feature/connect-account-tokens branch from 139c516 to b93b5ac Compare January 11, 2018 05:26
Last night I had moved the public headers into the right directory to fix a different
failure, and rebased that into 3f2bc39.

Now that bg-stripe's reviewed this PR, not going to force-push anymore.
Copy link
Contributor

@bg-stripe bg-stripe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good, just a few nits

/**
Initialize `STPConnectAccountParams` with tosShownAndAccepted = YES

This method cannot be called with `wasAccepted == NO`, guarded by a `NSParameterAssert()`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, interesting design choice forcing the user to explicitly pass YES. I like it.

It finally clicked for me why we model this as true/nil instead of true/false :) with shownAndAccepted=false it's unclear whether the TOS was not shown or not accepted. 🤓

@param wasAccepted Must be YES, but only if the user was shown & accepted the ToS
@param legalEntity data about the legal entity
*/
- (instancetype)initTosShownAndAccepted:(BOOL)wasAccepted
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably be initWithTos....

#import "STPFormEncodable.h"

@class STPAddress, STPVerificationParams;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NS_ASSUME_NONNULL


@implementation STPAPIClient (ConnectAccounts)

- (void)createTokenWithConnectAccount:(__unused id)account completion:(__nullable STPTokenCompletionBlock)completion {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replace __unused id with `STPConnectAccountParams *``


- (void)createTokenWithConnectAccount:(__unused id)account completion:(__nullable STPTokenCompletionBlock)completion {
NSMutableDictionary *params = [[STPFormEncoder dictionaryForObject:account] mutableCopy];
[[STPTelemetryClient sharedInstance] addTelemetryFieldsToParams:params];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we probably don't need to add telemetry data.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Papertrail: bg and I discussed in Slack. Android sends telemetry for all tokens. We think this is fine, but I have an open ask out to the team that owns telemetry.

addressDict[@"country"] = address.country;
params[@"address"] = [addressDict copy];
// Re-use STPFormEncoder
params[@"address"] = [STPFormEncoder dictionaryForObject:address];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

return @{};
}

- (void)setAdditionalAPIParameters:(__unused NSDictionary *)additionalAPIParameters {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

//

#import "STPConnectAccountParams.h"

Copy link
Contributor

@bg-stripe bg-stripe Jan 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NS_ASSUME_NONNULL

// Copyright © 2017 Stripe, Inc. All rights reserved.
//

#import "STPLegalEntityParams.h"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NS_ASSUME_NONNULL

@danj-stripe
Copy link
Contributor Author

Also, cc @ksun-stripe, who implemented this in stripe/stripe-android#492

…ormance.

Faux Pas (correctly) points out adding un-prefixed methods to a Foundation class via
a category is dangerous. Probably a better thing to do is either prefix all of these
methods in the protocol, or add custom support for `NSDateComponents` in
`+[STPFormEncoder formEncodableValueForObject:]`.

For now, I think this is safe enough.
@danj-stripe
Copy link
Contributor Author

@bg-stripe I've addressed your comments (thanks for all the help!), and fixed some other problems. Travis has a 1000+ build backlog and is running at half capacity. If you want to re-review now you can, or I'll assign to you again if/when the build has succeeded.

@danj-stripe danj-stripe assigned bg-stripe and unassigned danj-stripe Jan 12, 2018
@stripe-ci stripe-ci assigned danj-stripe and unassigned bg-stripe Jan 12, 2018
@danj-stripe danj-stripe merged commit 3da97ec into master Jan 12, 2018
@danj-stripe danj-stripe deleted the danj/feature/connect-account-tokens branch January 12, 2018 17:32
mludowise-stripe pushed a commit that referenced this pull request Mar 24, 2022
…876)

* Defines iDEAL form in JSON instead of code
- Adds spec for custom_dropdown
- Defines iDEAL form in JSON instead of code

* Fix complaint

* PR feedback

* Oops, fix form specs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants