From 3f2bc395c77e9b55953d2d5106525cec94e9d0ef Mon Sep 17 00:00:00 2001 From: Dan Jackson Date: Mon, 8 Jan 2018 17:50:59 -0800 Subject: [PATCH] Add STPAPIClient method for creating Connect Account tokens. 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! --- Stripe.xcodeproj/project.pbxproj | 24 +++ Stripe/PublicHeaders/STPAPIClient.h | 24 ++- .../PublicHeaders/STPConnectAccountParams.h | 72 +++++++++ Stripe/PublicHeaders/STPLegalEntityParams.h | 138 ++++++++++++++++ Stripe/PublicHeaders/Stripe.h | 2 + Stripe/STPAPIClient.m | 13 ++ Stripe/STPAnalyticsClient.m | 2 +- Stripe/STPConnectAccountParams.m | 65 ++++++++ Stripe/STPLegalEntityParams.m | 150 ++++++++++++++++++ Tests/Tests/STPAnalyticsClientTest.m | 4 + Tests/Tests/STPFixtures.h | 11 ++ Tests/Tests/STPFixtures.m | 60 +++++++ 12 files changed, 563 insertions(+), 2 deletions(-) create mode 100644 Stripe/PublicHeaders/STPConnectAccountParams.h create mode 100644 Stripe/PublicHeaders/STPLegalEntityParams.h create mode 100644 Stripe/STPConnectAccountParams.m create mode 100644 Stripe/STPLegalEntityParams.m diff --git a/Stripe.xcodeproj/project.pbxproj b/Stripe.xcodeproj/project.pbxproj index 5514f3e2a32..7c33695869a 100644 --- a/Stripe.xcodeproj/project.pbxproj +++ b/Stripe.xcodeproj/project.pbxproj @@ -352,6 +352,14 @@ B347DD481FE35423006B3BAC /* STPValidatedTextField.h in Headers */ = {isa = PBXBuildFile; fileRef = B347DD461FE35423006B3BAC /* STPValidatedTextField.h */; }; B347DD491FE35423006B3BAC /* STPValidatedTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = B347DD471FE35423006B3BAC /* STPValidatedTextField.m */; }; B382D6611FE8BEA0009B56AB /* STPValidatedTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = B347DD471FE35423006B3BAC /* STPValidatedTextField.m */; }; + B3A241391FFEB57400A2F00D /* STPConnectAccountParams.h in Headers */ = {isa = PBXBuildFile; fileRef = B3A241371FFEB57400A2F00D /* STPConnectAccountParams.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B3A2413A1FFEB57400A2F00D /* STPConnectAccountParams.h in Headers */ = {isa = PBXBuildFile; fileRef = B3A241371FFEB57400A2F00D /* STPConnectAccountParams.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B3A2413B1FFEB57400A2F00D /* STPConnectAccountParams.m in Sources */ = {isa = PBXBuildFile; fileRef = B3A241381FFEB57400A2F00D /* STPConnectAccountParams.m */; }; + B3A2413C1FFEB57400A2F00D /* STPConnectAccountParams.m in Sources */ = {isa = PBXBuildFile; fileRef = B3A241381FFEB57400A2F00D /* STPConnectAccountParams.m */; }; + B3A99BC31FEAF2CA003F6ED3 /* STPLegalEntityParams.h in Headers */ = {isa = PBXBuildFile; fileRef = B3A99BC11FEAF2CA003F6ED3 /* STPLegalEntityParams.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B3A99BC41FEAF2CA003F6ED3 /* STPLegalEntityParams.h in Headers */ = {isa = PBXBuildFile; fileRef = B3A99BC11FEAF2CA003F6ED3 /* STPLegalEntityParams.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B3A99BC51FEAF2CA003F6ED3 /* STPLegalEntityParams.m in Sources */ = {isa = PBXBuildFile; fileRef = B3A99BC21FEAF2CA003F6ED3 /* STPLegalEntityParams.m */; }; + B3A99BC61FEAF2CA003F6ED3 /* STPLegalEntityParams.m in Sources */ = {isa = PBXBuildFile; fileRef = B3A99BC21FEAF2CA003F6ED3 /* STPLegalEntityParams.m */; }; C1054F911FE197AE0033C87E /* STPPaymentContextSnapshotTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C1054F901FE197AE0033C87E /* STPPaymentContextSnapshotTests.m */; }; C1080F491CBECF7B007B2D89 /* STPAddress.h in Headers */ = {isa = PBXBuildFile; fileRef = C1080F471CBECF7B007B2D89 /* STPAddress.h */; settings = {ATTRIBUTES = (Public, ); }; }; C1080F4A1CBECF7B007B2D89 /* STPAddress.m in Sources */ = {isa = PBXBuildFile; fileRef = C1080F481CBECF7B007B2D89 /* STPAddress.m */; }; @@ -1001,6 +1009,10 @@ 8BE5AE8A1EF8905B0081A33C /* STPCardParamsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STPCardParamsTest.m; sourceTree = ""; }; B347DD461FE35423006B3BAC /* STPValidatedTextField.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = STPValidatedTextField.h; sourceTree = ""; }; B347DD471FE35423006B3BAC /* STPValidatedTextField.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = STPValidatedTextField.m; sourceTree = ""; }; + B3A241371FFEB57400A2F00D /* STPConnectAccountParams.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = STPConnectAccountParams.h; sourceTree = ""; }; + B3A241381FFEB57400A2F00D /* STPConnectAccountParams.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = STPConnectAccountParams.m; sourceTree = ""; }; + B3A99BC11FEAF2CA003F6ED3 /* STPLegalEntityParams.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = STPLegalEntityParams.h; sourceTree = ""; }; + B3A99BC21FEAF2CA003F6ED3 /* STPLegalEntityParams.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = STPLegalEntityParams.m; sourceTree = ""; }; C1054F901FE197AE0033C87E /* STPPaymentContextSnapshotTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = STPPaymentContextSnapshotTests.m; sourceTree = ""; }; C1080F471CBECF7B007B2D89 /* STPAddress.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = STPAddress.h; path = PublicHeaders/STPAddress.h; sourceTree = ""; }; C1080F481CBECF7B007B2D89 /* STPAddress.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STPAddress.m; sourceTree = ""; }; @@ -1876,11 +1888,15 @@ 04CDE5BB1BC1F21500548833 /* STPCardParams.h */, 04CDE5B41BC1F1F100548833 /* STPCardParams.m */, 04EBC7511B7533C300A0E6AE /* STPCardValidationState.h */, + B3A241371FFEB57400A2F00D /* STPConnectAccountParams.h */, + B3A241381FFEB57400A2F00D /* STPConnectAccountParams.m */, 04B31DD21D08E6E200EF1631 /* STPCustomer.h */, 04B31DD31D08E6E200EF1631 /* STPCustomer.m */, F1D3A2501EB0120F0095BFA9 /* STPFile.h */, F1D3A2461EB012010095BFA9 /* STPFile.m */, 04F213301BCEAB61001D6F22 /* STPFormEncodable.h */, + B3A99BC11FEAF2CA003F6ED3 /* STPLegalEntityParams.h */, + B3A99BC21FEAF2CA003F6ED3 /* STPLegalEntityParams.m */, C1D7B51E1E36C32F002181F5 /* STPSource.h */, C1D7B51F1E36C32F002181F5 /* STPSource.m */, F19491DD1E5F6B8C001E1FC2 /* STPSourceCardDetails.h */, @@ -2016,6 +2032,7 @@ 04EBC75A1B7533C300A0E6AE /* STPCardValidator.h in Headers */, C159933D1D8808970047950D /* STPShippingMethodsViewController.h in Headers */, F15232251EA9303800D65C67 /* STPURLCallbackHandler.h in Headers */, + B3A2413A1FFEB57400A2F00D /* STPConnectAccountParams.h in Headers */, F1D3A2561EB012350095BFA9 /* STPMultipartFormDataPart.h in Headers */, 04F94DCD1D22A22F004FC826 /* UIViewController+Stripe_KeyboardAvoiding.h in Headers */, C1BD9B3A1E39416700CEE925 /* STPSourceOwner.h in Headers */, @@ -2098,6 +2115,7 @@ C15608DE1FE08F2E0032AE66 /* UIView+Stripe_SafeAreaBounds.h in Headers */, 049E84EC1A605EF0000B66CD /* StripeError.h in Headers */, 046FE9A31CE5608000DA6A7B /* STPPaymentActivityIndicatorView.h in Headers */, + B3A99BC41FEAF2CA003F6ED3 /* STPLegalEntityParams.h in Headers */, F1DEB88B1E2047CA0066B8E8 /* STPCoreTableViewController.h in Headers */, F1FA6F931E258F6800EB444D /* STPCoreViewController+Private.h in Headers */, 04793F571D1D9C0200B3C551 /* STPSourceProtocol.h in Headers */, @@ -2153,6 +2171,7 @@ F1D3A24E1EB012010095BFA9 /* STPMultipartFormDataPart.h in Headers */, C11810A71CC6EE840022FB55 /* STPBackendAPIAdapter.h in Headers */, F12C8DC01D63DE9F00ADA0D7 /* STPPaymentContextAmountModel.h in Headers */, + B3A241391FFEB57400A2F00D /* STPConnectAccountParams.h in Headers */, F19491DE1E5F6B8C001E1FC2 /* STPSourceCardDetails.h in Headers */, 0439B9871C454F97005A1ED5 /* STPPaymentMethodsViewController.h in Headers */, 04B31DF91D11AC6400EF1631 /* STPUserInformation.h in Headers */, @@ -2235,6 +2254,7 @@ C15608DD1FE08F2E0032AE66 /* UIView+Stripe_SafeAreaBounds.h in Headers */, F1852F931D80B6EC00367C86 /* STPStringUtils.h in Headers */, 049A3FAE1CC9AA9900F57DE7 /* STPAddressViewModel.h in Headers */, + B3A99BC31FEAF2CA003F6ED3 /* STPLegalEntityParams.h in Headers */, C175B7941FE834A3009F5A0E /* STPCustomer+Private.h in Headers */, F1D3A2651EBA5BAE0095BFA9 /* STPPaymentCardTextField+Private.h in Headers */, 0426B96E1CEADC98006AC8DD /* STPColorUtils.h in Headers */, @@ -2773,8 +2793,10 @@ C159933A1D8808880047950D /* STPShippingAddressViewController.m in Sources */, 04F94DA41D229F1C004FC826 /* STPAddressViewModel.m in Sources */, 049880FF1CED5A2300EA4FFD /* STPPaymentConfiguration.m in Sources */, + B3A99BC61FEAF2CA003F6ED3 /* STPLegalEntityParams.m in Sources */, C180211D1E3A58710089D712 /* STPSourcePoller.m in Sources */, 04F94DB91D229F86004FC826 /* STPApplePayPaymentMethod.m in Sources */, + B3A2413C1FFEB57400A2F00D /* STPConnectAccountParams.m in Sources */, C1BD9B2B1E39406C00CEE925 /* STPSourceOwner.m in Sources */, C1BD9B311E3940A200CEE925 /* STPSourceRedirect.m in Sources */, 04B31DE91D09D25F00EF1631 /* STPPaymentMethodsInternalViewController.m in Sources */, @@ -2877,12 +2899,14 @@ C1BD9B241E393FFE00CEE925 /* STPSourceReceiver.m in Sources */, 04B31DD61D08E6E200EF1631 /* STPCustomer.m in Sources */, 0438EF351B7416BB00D506CC /* STPPaymentCardTextField.m in Sources */, + B3A2413B1FFEB57400A2F00D /* STPConnectAccountParams.m in Sources */, F1D3A24F1EB012010095BFA9 /* STPMultipartFormDataPart.m in Sources */, 04827D121D2575C6002DB3E8 /* STPImageLibrary.m in Sources */, 04CDB5041A5F30A700B854EE /* STPFormEncoder.m in Sources */, 0426B96F1CEADC98006AC8DD /* STPColorUtils.m in Sources */, C1D7B51C1E36B8B9002181F5 /* STPSourceParams.m in Sources */, 049880FE1CED5A2300EA4FFD /* STPPaymentConfiguration.m in Sources */, + B3A99BC51FEAF2CA003F6ED3 /* STPLegalEntityParams.m in Sources */, 046FE9A21CE55D1D00DA6A7B /* STPPaymentActivityIndicatorView.m in Sources */, 045D71221CEFA57000F6CD65 /* UIViewController+Stripe_Promises.m in Sources */, C124A1721CCA968B007D42EE /* STPAnalyticsClient.m in Sources */, diff --git a/Stripe/PublicHeaders/STPAPIClient.h b/Stripe/PublicHeaders/STPAPIClient.h index 18f1ce92155..af9ba9aadf6 100644 --- a/Stripe/PublicHeaders/STPAPIClient.h +++ b/Stripe/PublicHeaders/STPAPIClient.h @@ -20,7 +20,7 @@ NS_ASSUME_NONNULL_BEGIN */ static NSString *const STPSDKVersion = @"11.5.0"; -@class STPBankAccount, STPBankAccountParams, STPCard, STPCardParams, STPSourceParams, STPToken, STPPaymentConfiguration; +@class STPBankAccount, STPBankAccountParams, STPCard, STPCardParams, STPConnectAccountParams, STPSourceParams, STPToken, STPPaymentConfiguration; /** A top-level class that imports the rest of the Stripe SDK. @@ -127,6 +127,28 @@ static NSString *const STPSDKVersion = @"11.5.0"; @end +#pragma mark Connect Accounts + +/** + Stripe extensions for working with Connect Accounts + */ +@interface STPAPIClient (ConnectAccounts) + + +/** + Converts an `STPConnectAccountParams` object into a Stripe token using the Stripe API. + + This allows the connected account to accept the Terms of Service, and/or send Legal Entity information. + + @param account The Connect Account parameters. Cannot be nil. + @param completion The callback to run with the returned Stripe token (and any errors that may have occurred). + */ +- (void)createTokenWithConnectAccount:(STPConnectAccountParams *)account completion:(__nullable STPTokenCompletionBlock)completion; + +@end + +#pragma mark Upload + /** STPAPIClient extensions to upload files. */ diff --git a/Stripe/PublicHeaders/STPConnectAccountParams.h b/Stripe/PublicHeaders/STPConnectAccountParams.h new file mode 100644 index 00000000000..620e75fee34 --- /dev/null +++ b/Stripe/PublicHeaders/STPConnectAccountParams.h @@ -0,0 +1,72 @@ +// +// STPConnectAccountParams.h +// Stripe +// +// Created by Daniel Jackson on 1/4/18. +// Copyright © 2018 Stripe, Inc. All rights reserved. +// + +#import + +#import "STPFormEncodable.h" + +@class STPLegalEntityParams; + +NS_ASSUME_NONNULL_BEGIN + +/** + Parameters for creating a Connect Account token. + */ +@interface STPConnectAccountParams : NSObject + +/** + Optional boolean indicating that the Terms Of Service were shown to the user & + the user accepted them. + */ +@property (nonatomic, nullable, readonly) NSNumber *tosShownAndAccepted; + +/** + Required property with information about the legal entity for this account. + + At least one field in the legalEntity must have a value, otherwise the create token + call will fail. + */ +@property (nonatomic, readonly) STPLegalEntityParams *legalEntity; + +/** + `STPConnectAccountParams` cannot be directly instantiated, use `initTosShownAndAccepted:legalEntity:` + or `initWithLegalEntity:` + */ +- (instancetype)init __attribute__((unavailable("Cannot be directly instantiated"))); + +/** + Initialize `STPConnectAccountParams` with tosShownAndAccepted = YES + + This method cannot be called with `wasAccepted == NO`, guarded by a `NSParameterAssert()`. + + Use this init method if you want to set the `tosShownAndAccepted` parameter. If you + don't, use the `initWithLegalEntity:` version instead. + + @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 + legalEntity:(STPLegalEntityParams *)legalEntity; + +/** + Initialize `STPConnectAccountParams` with the `STPLegalEntityParams` provided. + + This init method cannot change the `tosShownAndAccepted` parameter. Use + `initTosShownAndAccepted:legalEntity:` instead if you need to do that. + + These two init methods exist to avoid the (slightly awkward) NSNumber box that would + be needed around `tosShownAndAccepted` if it was optional/nullable, and to enforce + that it is either nil or YES. + + @param legalEntity data to send to Stripe about the legal entity + */ +- (instancetype)initWithLegalEntity:(STPLegalEntityParams *)legalEntity; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Stripe/PublicHeaders/STPLegalEntityParams.h b/Stripe/PublicHeaders/STPLegalEntityParams.h new file mode 100644 index 00000000000..47d06936392 --- /dev/null +++ b/Stripe/PublicHeaders/STPLegalEntityParams.h @@ -0,0 +1,138 @@ +// +// STPLegalEntityParams.h +// Stripe +// +// Created by Daniel Jackson on 12/20/17. +// Copyright © 2017 Stripe, Inc. All rights reserved. +// + +#import +#import "STPFormEncodable.h" + +@class STPAddress, STPVerificationParams; + + +/** + Stripe API parameters to define a Person. Things like their name, address, etc. + + All of the fields are optional. + */ +@interface STPPersonParams: NSObject + +/** + The first name of this person. + */ +@property (nonatomic, copy, nullable) NSString *firstName; + +/** + The last name of this person. + */ +@property (nonatomic, copy, nullable) NSString *lastName; + +/** + The maiden name of this person. + */ +@property (nonatomic, copy, nullable) NSString *maidenName; + +/** + The address parameter. For `STPPersonParams`, this is the address of the person. + For the `STPLegalEntityParams` subclass, see also `personalAddress`. + */ +@property (nonatomic, strong, nullable) STPAddress *address; + +/** + The date of birth (dob) of this person. + + Must include `day`, `month`, and `year`, and only those fields are used. + */ +@property (nonatomic, copy, nullable) NSDateComponents *dateOfBirth; + +/** + Verification document for this person. + */ +@property (nonatomic, strong, nullable) STPVerificationParams *verification; + +@end + + +/** + Stripe API parameters to define a Legal Entity. This extends `STPPersonParams` + and adds some more fields. + + Legal entities can be either an individual or a company. + */ +@interface STPLegalEntityParams : STPPersonParams + +/** + Additional owners of the legal entity. + */ +@property (nonatomic, strong, nullable) NSArray *additionalOwners; + +/** + The business name + */ +@property (nonatomic, copy, nullable) NSString *businessName; + +/** + The business Tax Id + */ +@property (nonatomic, copy, nullable) NSString *businessTaxId; + +/** + The business VAT Id + */ +@property (nonatomic, copy, nullable) NSString *businessVATId; + +/** + The gender of the individual, as a string. + + Currently either `male` or `female` are supported values. + */ +@property (nonatomic, copy, nullable) NSString *genderString; + +/** + The personal address field. + */ +@property (nonatomic, strong, nullable) STPAddress *personalAddress; + +/** + The Personal Id number + */ +@property (nonatomic, copy, nullable) NSString *personalIdNumber; + +/** + The phone number of the entity. + */ +@property (nonatomic, copy, nullable) NSString *phoneNumber; + +/** + The last four digits of the SSN of the individual. + */ +@property (nonatomic, copy, nullable) NSString *ssnLast4; + +/** + The Tax Id Registrar + */ +@property (nonatomic, copy, nullable) NSString *taxIdRegistrar; + +/** + The type of this legal entity, as a string. + + Currently `individual` or `company` are supported values. + */ +@property (nonatomic, copy, nullable) NSString *entityTypeString; + +@end + + +/** + Parameters for supported types of verification. + */ +@interface STPVerificationParams: NSObject + +/** + The file id for the uploaded verification document. + */ +@property (nonatomic, copy, nullable) NSString *document; + +@end diff --git a/Stripe/PublicHeaders/Stripe.h b/Stripe/PublicHeaders/Stripe.h index df39ac3ff72..7e2a1a5ffb9 100644 --- a/Stripe/PublicHeaders/Stripe.h +++ b/Stripe/PublicHeaders/Stripe.h @@ -22,6 +22,7 @@ #import "STPCardParams.h" #import "STPCardValidationState.h" #import "STPCardValidator.h" +#import "STPConnectAccountParams.h" #import "STPCoreScrollViewController.h" #import "STPCoreTableViewController.h" #import "STPCoreViewController.h" @@ -31,6 +32,7 @@ #import "STPFile.h" #import "STPFormEncodable.h" #import "STPImageLibrary.h" +#import "STPLegalEntityParams.h" #import "STPPaymentActivityIndicatorView.h" #import "STPPaymentCardTextField.h" #import "STPPaymentConfiguration.h" diff --git a/Stripe/STPAPIClient.m b/Stripe/STPAPIClient.m index 7d13dd1810e..6f73fc8d80f 100644 --- a/Stripe/STPAPIClient.m +++ b/Stripe/STPAPIClient.m @@ -288,6 +288,19 @@ - (void)createTokenWithPersonalIDNumber:(NSString *)pii completion:(__nullable S @end +#pragma mark - Connect Accounts + +@implementation STPAPIClient (ConnectAccounts) + +- (void)createTokenWithConnectAccount:(__unused id)account completion:(__nullable STPTokenCompletionBlock)completion { + NSMutableDictionary *params = [[STPFormEncoder dictionaryForObject:account] mutableCopy]; + [[STPTelemetryClient sharedInstance] addTelemetryFieldsToParams:params]; + [self createTokenWithParameters:params completion:completion]; + [[STPTelemetryClient sharedInstance] sendTelemetryData]; +} + +@end + #pragma mark - Upload @implementation STPAPIClient (Upload) diff --git a/Stripe/STPAnalyticsClient.m b/Stripe/STPAnalyticsClient.m index 633fddc7b12..79c0ff35b6f 100644 --- a/Stripe/STPAnalyticsClient.m +++ b/Stripe/STPAnalyticsClient.m @@ -117,7 +117,7 @@ + (BOOL)shouldCollectAnalytics { + (NSString *)tokenTypeFromParameters:(NSDictionary *)parameters { if ([parameters.allKeys count] == 1) { - NSArray *validTypes = @[@"bank_account", @"card", @"pii"]; + NSArray *validTypes = @[@"account", @"bank_account", @"card", @"pii"]; NSString *type = [parameters.allKeys firstObject]; if ([validTypes containsObject:type]) { return type; diff --git a/Stripe/STPConnectAccountParams.m b/Stripe/STPConnectAccountParams.m new file mode 100644 index 00000000000..908a58c826c --- /dev/null +++ b/Stripe/STPConnectAccountParams.m @@ -0,0 +1,65 @@ +// +// STPConnectAccountParams.m +// Stripe +// +// Created by Daniel Jackson on 1/4/18. +// Copyright © 2018 Stripe, Inc. All rights reserved. +// + +#import "STPConnectAccountParams.h" + +#import "STPLegalEntityParams.h" + +@implementation STPConnectAccountParams + +@synthesize additionalAPIParameters; + +- (instancetype)initTosShownAndAccepted:(BOOL)wasAccepted + legalEntity:(STPLegalEntityParams *)legalEntity { + // It is an error to call this method with wasAccepted == NO + NSParameterAssert(wasAccepted == YES); + self = [super init]; + if (self) { + _tosShownAndAccepted = [NSNumber numberWithBool:wasAccepted]; + _legalEntity = legalEntity; + } + return self; +} + +- (instancetype)initWithLegalEntity:(STPLegalEntityParams *)legalEntity { + self = [super init]; + if (self) { + _tosShownAndAccepted = nil; + _legalEntity = legalEntity; + } + return self; +} + +#pragma mark - description + +- (NSString *)description { + NSArray *props = @[ + [NSString stringWithFormat:@"%@: %p", NSStringFromClass([self class]), self], + // We use NSParameterAssert to block this being NO: + [NSString stringWithFormat:@"tosShownAndAccepted = %@", + self.tosShownAndAccepted != nil ? @"YES" : @""], + [NSString stringWithFormat:@"legalEntity = %@", self.legalEntity.description], + ]; + + return [NSString stringWithFormat:@"<%@>", [props componentsJoinedByString:@"; "]]; +} + +#pragma mark - STPFormEncodable + ++ (nullable NSString *)rootObjectName { + return @"account"; +} + ++ (nonnull NSDictionary *)propertyNamesToFormFieldNamesMapping { + return @{ + NSStringFromSelector(@selector(tosShownAndAccepted)): @"tos_shown_and_accepted", + NSStringFromSelector(@selector(legalEntity)): @"legal_entity", + }; +} + +@end diff --git a/Stripe/STPLegalEntityParams.m b/Stripe/STPLegalEntityParams.m new file mode 100644 index 00000000000..d028ddd9ffe --- /dev/null +++ b/Stripe/STPLegalEntityParams.m @@ -0,0 +1,150 @@ +// +// STPLegalEntityParams.m +// Stripe +// +// Created by Daniel Jackson on 12/20/17. +// Copyright © 2017 Stripe, Inc. All rights reserved. +// + +#import "STPLegalEntityParams.h" + +@implementation STPVerificationParams +@synthesize additionalAPIParameters; + +- (NSString *)description { + NSArray *props = @[ + [NSString stringWithFormat:@"%@: %p", NSStringFromClass([self class]), self], + [NSString stringWithFormat:@"document = %@", self.document], + ]; + + return [NSString stringWithFormat:@"<%@>", [props componentsJoinedByString:@"; "]]; +} + ++ (nullable NSString *)rootObjectName { + return @"verification"; +} + ++ (nonnull NSDictionary *)propertyNamesToFormFieldNamesMapping { + return @{ + NSStringFromSelector(@selector(document)): @"document", + }; +} + +@end + +@implementation STPPersonParams +@synthesize additionalAPIParameters; + +- (NSString *)description { + NSArray *props = @[ + [NSString stringWithFormat:@"%@: %p", NSStringFromClass([self class]), self], + + [NSString stringWithFormat:@"firstName = %@", self.firstName], + [NSString stringWithFormat:@"lastName = %@", self.lastName], + [NSString stringWithFormat:@"maidenName = %@", self.maidenName], + [NSString stringWithFormat:@"address = <%@>", self.address], + [NSString stringWithFormat:@"dateOfBirth = <%@>", self.dateOfBirth], + [NSString stringWithFormat:@"verification = %@", self.verification], + ]; + + return [NSString stringWithFormat:@"<%@>", [props componentsJoinedByString:@"; "]]; +} + ++ (nullable NSString *)rootObjectName { + // STPPersonParams is never a named root object. It's either inherited by STPLegalEntityParams + // or an element in the STPLegalEntityParams.additionalOwners array + return nil; +} + ++ (nonnull NSDictionary *)propertyNamesToFormFieldNamesMapping { + return @{ + NSStringFromSelector(@selector(firstName)): @"first_name", + NSStringFromSelector(@selector(lastName)): @"last_name", + NSStringFromSelector(@selector(maidenName)): @"maiden_name", + NSStringFromSelector(@selector(address)): @"address", + NSStringFromSelector(@selector(dateOfBirth)): @"dob", + NSStringFromSelector(@selector(verification)): @"verification", + }; +} + +@end + +@implementation STPLegalEntityParams + +- (NSString *)description { + + NSArray *props = @[ + // Object + [NSString stringWithFormat:@"%@: %p", NSStringFromClass([self class]), self], + [NSString stringWithFormat:@"super = %@", [super description]], + + [NSString stringWithFormat:@"additionalOwners = %@", self.additionalOwners], + [NSString stringWithFormat:@"businessName = %@", self.businessName], + [NSString stringWithFormat:@"businessTaxId = %@", self.businessTaxId], + [NSString stringWithFormat:@"businessVATId = %@", self.businessVATId], + [NSString stringWithFormat:@"genderString = %@", self.genderString], + [NSString stringWithFormat:@"personalAddress = %@", self.personalAddress], + [NSString stringWithFormat:@"personalIdNumber = %@", self.personalIdNumber], + [NSString stringWithFormat:@"phoneNumber = %@", self.phoneNumber], + [NSString stringWithFormat:@"ssnLast4 = %@", self.ssnLast4], + [NSString stringWithFormat:@"taxIdRegistrar = %@", self.taxIdRegistrar], + [NSString stringWithFormat:@"entityTypeString = %@", self.entityTypeString], + ]; + + return [NSString stringWithFormat:@"<%@>", [props componentsJoinedByString:@"; "]]; +} + ++ (nullable NSString *)rootObjectName { + return @"legal_entity"; +} + ++ (nonnull NSDictionary *)propertyNamesToFormFieldNamesMapping { + NSMutableDictionary *props = [@{ + NSStringFromSelector(@selector(additionalOwners)): @"additional_owners", + NSStringFromSelector(@selector(businessName)): @"business_name", + NSStringFromSelector(@selector(businessTaxId)): @"business_tax_id", + NSStringFromSelector(@selector(businessVATId)): @"business_vat_id", + NSStringFromSelector(@selector(genderString)): @"gender", + NSStringFromSelector(@selector(personalAddress)): @"personal_address", + NSStringFromSelector(@selector(personalIdNumber)): @"personal_id_number", + NSStringFromSelector(@selector(phoneNumber)): @"phone_number", + NSStringFromSelector(@selector(ssnLast4)): @"ssn_last_4", + NSStringFromSelector(@selector(taxIdRegistrar)): @"tax_id_registrar", + NSStringFromSelector(@selector(entityTypeString)): @"type", + } mutableCopy]; + + [props addEntriesFromDictionary:[super propertyNamesToFormFieldNamesMapping]]; + + return [props copy]; +} + +@end + + +/* + Add STPFormEncodable conformance for `STPPersonParams.dateOfBirth` + */ +@interface NSDateComponents (STPFormEncodable) @end +@implementation NSDateComponents (STPFormEncodable) + +- (NSDictionary *)additionalAPIParameters { + return @{}; +} + +- (void)setAdditionalAPIParameters:(__unused NSDictionary *)additionalAPIParameters { + [self doesNotRecognizeSelector:_cmd]; +} + ++ (nullable NSString *)rootObjectName { + return nil; +} + ++ (nonnull NSDictionary *)propertyNamesToFormFieldNamesMapping { + return @{ + NSStringFromSelector(@selector(day)): @"day", + NSStringFromSelector(@selector(month)): @"month", + NSStringFromSelector(@selector(year)): @"year", + }; +} + +@end diff --git a/Tests/Tests/STPAnalyticsClientTest.m b/Tests/Tests/STPAnalyticsClientTest.m index 0b6a16ddff5..b2c6545231a 100644 --- a/Tests/Tests/STPAnalyticsClientTest.m +++ b/Tests/Tests/STPAnalyticsClientTest.m @@ -34,6 +34,10 @@ - (void)testTokenTypeFromParameters { NSDictionary *cardDict = [STPFormEncoder dictionaryForObject:card]; XCTAssertEqualObjects([STPAnalyticsClient tokenTypeFromParameters:cardDict], @"card"); + STPConnectAccountParams *account = [STPFixtures accountParams]; + NSDictionary *accountDict = [STPFormEncoder dictionaryForObject:account]; + XCTAssertEqualObjects([STPAnalyticsClient tokenTypeFromParameters:accountDict], @"account"); + STPBankAccountParams *bank = [STPFixtures bankAccountParams]; NSDictionary *bankDict = [STPFormEncoder dictionaryForObject:bank]; XCTAssertEqualObjects([STPAnalyticsClient tokenTypeFromParameters:bankDict], @"bank_account"); diff --git a/Tests/Tests/STPFixtures.h b/Tests/Tests/STPFixtures.h index e9bb27beb9f..4445d063f72 100644 --- a/Tests/Tests/STPFixtures.h +++ b/Tests/Tests/STPFixtures.h @@ -24,6 +24,12 @@ extern NSString *const STPTestJSONSourceSEPADebit; @interface STPFixtures : NSObject +/** + An STPConnectAccountParams object with all of the fields filled in, and + ToS accepted. + */ ++ (STPConnectAccountParams *)accountParams; + /** An Address object with all fields filled. */ @@ -133,6 +139,11 @@ extern NSString *const STPTestJSONSourceSEPADebit; */ + (STPEphemeralKey *)expiringEphemeralKey; +/** + A fully specified STPLegalEntityParams + */ ++ (STPLegalEntityParams *)legalEntityParams; + @end @interface STPJsonSources : NSObject diff --git a/Tests/Tests/STPFixtures.m b/Tests/Tests/STPFixtures.m index ce0b28d14f9..cf50745ac67 100644 --- a/Tests/Tests/STPFixtures.m +++ b/Tests/Tests/STPFixtures.m @@ -23,6 +23,11 @@ @implementation STPFixtures ++ (STPConnectAccountParams *)accountParams { + return [[STPConnectAccountParams alloc] initTosShownAndAccepted:YES + legalEntity:[self legalEntityParams]]; +} + + (STPAddress *)address { STPAddress *address = [STPAddress new]; address.name = @"Jenny Rosen"; @@ -248,4 +253,59 @@ + (PKPayment *)applePayPayment { return payment; } ++ (STPLegalEntityParams *)legalEntityParams { + STPLegalEntityParams *legalEntity = [STPLegalEntityParams new]; + + legalEntity.firstName = @"Jessica"; + legalEntity.lastName = @"Jones"; + legalEntity.maidenName = @"Smith"; + legalEntity.address = [self address]; + + legalEntity.dateOfBirth = [NSDateComponents new]; + legalEntity.dateOfBirth.year = 1980; + legalEntity.dateOfBirth.month = 7; + legalEntity.dateOfBirth.day = 4; + + legalEntity.verification = [STPVerificationParams new]; + legalEntity.verification.document = @"file_abc"; + + STPPersonParams *jenny = [self personParams], *jacob = [self personParams]; + jenny.firstName = @"Jenny"; + jacob.firstName = @"Jacob"; + legalEntity.additionalOwners = @[jenny, jacob]; + + legalEntity.businessName = @"Internet Business"; + legalEntity.businessTaxId = @"123"; + legalEntity.businessVATId = @"456"; + legalEntity.genderString = @"female"; + legalEntity.personalAddress = [self address]; + legalEntity.personalAddress.state = @"CA"; + legalEntity.personalIdNumber = @"000000000"; + legalEntity.phoneNumber = @"555-1234"; + legalEntity.ssnLast4 = @"0000"; + legalEntity.taxIdRegistrar = @"321"; + legalEntity.entityTypeString = @"individual"; + + return legalEntity; +} + ++ (STPPersonParams *)personParams { + STPPersonParams *person = [STPPersonParams new]; + + person.firstName = @"James"; + person.lastName = @"Smith"; + person.maidenName = @"Jones"; + person.address = [self address]; + + person.dateOfBirth = [NSDateComponents new]; + person.dateOfBirth.year = 1980; + person.dateOfBirth.month = 7; + person.dateOfBirth.day = 4; + + person.verification = [STPVerificationParams new]; + person.verification.document = @"file_abc"; + + return person; +} + @end