From 5ce1b7e0a0f4a9c8ef442af8c8772c2f1979b15d Mon Sep 17 00:00:00 2001 From: Brian Dorfman Date: Tue, 1 Aug 2017 17:20:08 -0700 Subject: [PATCH 1/4] Split up cards and card params. Make STPCard not subclass STPCardParams. Make many STPCard properties readonly. Deprecate some public methods that didn't actually need to be public. Deprecate broken out address methods in favor of STPAddress object. This brings STPCard and STPCardParams more line with the sources API. --- CHANGELOG | 1 + MIGRATING.md | 6 + Stripe/PublicHeaders/STPCard.h | 148 ++++++++++++--------- Stripe/PublicHeaders/STPCardParams.h | 59 +++++++-- Stripe/STPAPIClient.m | 4 +- Stripe/STPCard+Private.h | 4 + Stripe/STPCard.m | 150 ++++++++++++---------- Stripe/STPCardParams.m | 76 ++++++++--- Stripe/STPPaymentCardTextField.m | 4 +- Stripe/STPSourceCardDetails.m | 11 +- Tests/Tests/STPAPIRequestTest.m | 6 +- Tests/Tests/STPCardFunctionalTest.m | 12 +- Tests/Tests/STPCardParamsTest.m | 5 + Tests/Tests/STPCardTest.m | 91 ++++++------- Tests/Tests/STPFixtures.h | 5 + Tests/Tests/STPFixtures.m | 4 + Tests/Tests/STPPaymentCardTextFieldTest.m | 5 + Tests/Tests/STPSourceFunctionalTest.m | 36 +++--- Tests/Tests/STPSourceParamsTest.m | 25 ++-- 19 files changed, 401 insertions(+), 251 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 4734b76686a..a914b08883d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,5 @@ == X.Y.Z 2017-XX-YY +* Many methods on `STPCard` and `STPCardParams` have been deprecated or made readonly to bring card objects more in line with the rest of the API. See MIGRATING for further details. * Adds nullability annotations to `STPPaymentMethod` protocol * Improves the `[STPAPIResponseDecodable allResponseFields]` by removing all instances of `[NSNull null]` including ones that are nested. See MIGRATING.md. diff --git a/MIGRATING.md b/MIGRATING.md index 30e8a668b93..360f4245abf 100644 --- a/MIGRATING.md +++ b/MIGRATING.md @@ -1,6 +1,12 @@ ## Migration Guides ### Migration from versions < X.Y.Z +* Changes to `STPCard` and `STPCardParams` + * `STPCard` no longer subclasses from `STPCardParams`. You must now specifically create `STPCardParams` objects to create new tokens. + * You can no longer directly create `STPCard` objects, you should only use ones that have been decoded from Stripe API responses via `STPAPIClient`. + * All `STPCard` properties have been made readonly. + * Broken out individual address properties on `STPCard` and `STPCardParams` have been deprecated in favor of the grouped `address` property. + * The value of `[STPAPIResponseDecodable allResponseFields]` is now completely (deeply) filtered to not contain any instances of `[NSNull null]`. Previously, only `[NSNull null]` one level deep (shallow) were removed. ### Migrating from versions < 11.2.0 diff --git a/Stripe/PublicHeaders/STPCard.h b/Stripe/PublicHeaders/STPCard.h index e26bdd08e64..a2bbbf1a4be 100644 --- a/Stripe/PublicHeaders/STPCard.h +++ b/Stripe/PublicHeaders/STPCard.h @@ -31,123 +31,151 @@ typedef NS_ENUM(NSInteger, STPCardFundingType) { @see https://stripe.com/docs/api#cards */ -@interface STPCard : STPCardParams +@interface STPCard : NSObject /** - Create an STPCard from a Stripe API response. - - @param cardID The Stripe ID of the card, e.g. `card_185iQx4JYtv6MPZKfcuXwkOx` - @param brand The brand of the card (e.g. "Visa". To obtain this enum value from a string, use `[STPCardBrand brandFromString:string]`; - @param last4 The last 4 digits of the card, e.g. 4242 - @param expMonth The card's expiration month, 1-indexed (i.e. 1 = January) - @param expYear The card's expiration year - @param funding The card's funding type (credit, debit, or prepaid). To obtain this enum value from a string, use `[STPCardBrand fundingFromString:string]`. - - @return an STPCard instance populated with the provided values. + You cannot directly instantiate an `STPCard`. You should only use one that has been returned from an `STPAPIClient` callback. */ -- (instancetype)initWithID:(NSString *)cardID - brand:(STPCardBrand)brand - last4:(NSString *)last4 - expMonth:(NSUInteger)expMonth - expYear:(NSUInteger)expYear - funding:(STPCardFundingType)funding; +- (nonnull instancetype) init __attribute__((unavailable("You cannot directly instantiate an STPCard. You should only use one that has been returned from an STPAPIClient callback."))); /** - This parses a string representing a card's brand into the appropriate STPCardBrand enum value, i.e. `[STPCard brandFromString:@"American Express"] == STPCardBrandAmex` + The last 4 digits of the card. + */ +@property (nonatomic, readonly) NSString *last4; - @param string a string representing the card's brand as returned from the Stripe API +/** + For cards made with Apple Pay, this refers to the last 4 digits of the "Device Account Number" for the tokenized card. For regular cards, it will be nil. + */ +@property (nonatomic, readonly, nullable) NSString *dynamicLast4; - @return an enum value mapped to that string. If the string is unrecognized, returns STPCardBrandUnknown. +/** + Whether or not the card originated from Apple Pay. */ -+ (STPCardBrand)brandFromString:(NSString *)string; +@property (nonatomic, readonly) BOOL isApplePayCard; /** - Returns a string representation for the provided card brand; i.e. `[NSString stringFromBrand:STPCardBrandVisa] == @"Visa"`. + The card's expiration month. 1-indexed (i.e. 1 == January) + */ +@property (nonatomic, readonly) NSUInteger expMonth; - @param brand the brand you want to convert to a string +/** + The card's expiration year. + */ +@property (nonatomic, readonly) NSUInteger expYear; - @return A string representing the brand, suitable for displaying to a user. +/** + The cardholder's name. */ -+ (NSString *)stringFromBrand:(STPCardBrand)brand; +@property (nonatomic, copy, nullable, readonly) NSString *name; /** - This parses a string representing a card's funding type into the appropriate `STPCardFundingType` enum value, i.e. `[STPCard fundingFromString:@"prepaid"] == STPCardFundingTypePrepaid`. + The cardholder's address. + */ +@property (nonatomic, nonnull, readonly) STPAddress *address; - @param string a string representing the card's funding type as returned from the Stripe API +/** + The issuer of the card. + */ +@property (nonatomic, readonly) STPCardBrand brand; - @return an enum value mapped to that string. If the string is unrecognized, returns `STPCardFundingTypeOther`. +/** + The funding source for the card (credit, debit, prepaid, or other) */ -+ (STPCardFundingType)fundingFromString:(NSString *)string; +@property (nonatomic, readonly) STPCardFundingType funding; /** - The last 4 digits of the card. + Two-letter ISO code representing the issuing country of the card. */ -@property (nonatomic, readonly) NSString *last4; +@property (nonatomic, nullable, readonly) NSString *country; /** - For cards made with Apple Pay, this refers to the last 4 digits of the "Device Account Number" for the tokenized card. For regular cards, it will be nil. + This is only applicable when tokenizing debit cards to issue payouts to managed accounts. You should not set it otherwise. The card can then be used as a transfer destination for funds in this currency. */ -@property (nonatomic, readonly, nullable) NSString *dynamicLast4; +@property (nonatomic, nullable, readonly) NSString *currency; /** - Whether or not the card originated from Apple Pay. + Returns a string representation for the provided card brand; i.e. `[NSString stringFromBrand:STPCardBrandVisa] == @"Visa"`. + + @param brand the brand you want to convert to a string + + @return A string representing the brand, suitable for displaying to a user. */ -@property (nonatomic, readonly) BOOL isApplePayCard; ++ (NSString *)stringFromBrand:(STPCardBrand)brand; + + +#pragma mark - Deprecated methods /** - The card's expiration month. 1-indexed (i.e. 1 == January) + The Stripe ID for the card. */ -@property (nonatomic) NSUInteger expMonth; +@property (nonatomic, nullable, readonly) NSString *cardId DEPRECATED_MSG_ATTRIBUTE("Use stripeID (defined in STPSourceProtocol)"); /** - The card's expiration year. + The first line of the cardholder's address */ -@property (nonatomic) NSUInteger expYear; +@property (nonatomic, copy, nullable, readonly) NSString *addressLine1 DEPRECATED_MSG_ATTRIBUTE("Use address.line1"); /** - The cardholder's name. + The second line of the cardholder's address */ -@property (nonatomic, copy, nullable) NSString *name; +@property (nonatomic, copy, nullable, readonly) NSString *addressLine2 DEPRECATED_MSG_ATTRIBUTE("Use address.line2"); /** - The cardholder's address. + The city of the cardholder's address */ -@property (nonatomic, copy, nullable) STPAddress *address; +@property (nonatomic, copy, nullable, readonly) NSString *addressCity DEPRECATED_MSG_ATTRIBUTE("Use address.city"); /** - The cardholder's address. + The state of the cardholder's address */ -@property (nonatomic, copy, nullable) NSString *addressLine1; -@property (nonatomic, copy, nullable) NSString *addressLine2; -@property (nonatomic, copy, nullable) NSString *addressCity; -@property (nonatomic, copy, nullable) NSString *addressState; -@property (nonatomic, copy, nullable) NSString *addressZip; -@property (nonatomic, copy, nullable) NSString *addressCountry; +@property (nonatomic, copy, nullable, readonly) NSString *addressState DEPRECATED_MSG_ATTRIBUTE("Use address.state"); /** - The Stripe ID for the card. + The zip code of the cardholder's address */ -@property (nonatomic, readonly, nullable) NSString *cardId; +@property (nonatomic, copy, nullable, readonly) NSString *addressZip DEPRECATED_MSG_ATTRIBUTE("Use address.postalCode"); /** - The issuer of the card. + The country of the cardholder's address */ -@property (nonatomic, readonly) STPCardBrand brand; +@property (nonatomic, copy, nullable, readonly) NSString *addressCountry DEPRECATED_MSG_ATTRIBUTE("Use address.country"); /** - The funding source for the card (credit, debit, prepaid, or other) + Create an STPCard from a Stripe API response. + + @param cardID The Stripe ID of the card, e.g. `card_185iQx4JYtv6MPZKfcuXwkOx` + @param brand The brand of the card (e.g. "Visa". To obtain this enum value from a string, use `[STPCardBrand brandFromString:string]`; + @param last4 The last 4 digits of the card, e.g. 4242 + @param expMonth The card's expiration month, 1-indexed (i.e. 1 = January) + @param expYear The card's expiration year + @param funding The card's funding type (credit, debit, or prepaid). To obtain this enum value from a string, use `[STPCardBrand fundingFromString:string]`. + + @return an STPCard instance populated with the provided values. */ -@property (nonatomic, readonly) STPCardFundingType funding; +- (instancetype)initWithID:(NSString *)cardID + brand:(STPCardBrand)brand + last4:(NSString *)last4 + expMonth:(NSUInteger)expMonth + expYear:(NSUInteger)expYear + funding:(STPCardFundingType)funding DEPRECATED_MSG_ATTRIBUTE("You cannot directly instantiate an STPCard. You should only use one that has been returned from an STPAPIClient callback."); /** - Two-letter ISO code representing the issuing country of the card. + This parses a string representing a card's funding type into the appropriate `STPCardFundingType` enum value, i.e. `[STPCard fundingFromString:@"prepaid"] == STPCardFundingTypePrepaid`. + + @param string a string representing the card's funding type as returned from the Stripe API + + @return an enum value mapped to that string. If the string is unrecognized, returns `STPCardFundingTypeOther`. */ -@property (nonatomic, readonly, nullable) NSString *country; ++ (STPCardFundingType)fundingFromString:(NSString *)string DEPRECATED_ATTRIBUTE; /** - This is only applicable when tokenizing debit cards to issue payouts to managed accounts. You should not set it otherwise. The card can then be used as a transfer destination for funds in this currency. + This parses a string representing a card's brand into the appropriate STPCardBrand enum value, i.e. `[STPCard brandFromString:@"American Express"] == STPCardBrandAmex` + + @param string a string representing the card's brand as returned from the Stripe API + + @return an enum value mapped to that string. If the string is unrecognized, returns STPCardBrandUnknown. */ -@property (nonatomic, copy, nullable) NSString *currency; ++ (STPCardBrand)brandFromString:(NSString *)string DEPRECATED_ATTRIBUTE; @end diff --git a/Stripe/PublicHeaders/STPCardParams.h b/Stripe/PublicHeaders/STPCardParams.h index 3e4daaf867e..d54495fe71f 100644 --- a/Stripe/PublicHeaders/STPCardParams.h +++ b/Stripe/PublicHeaders/STPCardParams.h @@ -14,8 +14,9 @@ #endif /** - Representation of a user's credit card details. You can assemble these with information that your user enters and - then create Stripe tokens with them using an STPAPIClient. + Representation of a user's credit card details. You can assemble these with + information that your user enters and then create Stripe tokens with them using + an STPAPIClient. @see https://stripe.com/docs/api#cards */ @@ -48,24 +49,60 @@ /** The cardholder's name. + + @note Changing this property will also changing the name of the + param's `address` property. */ @property (nonatomic, copy, nullable) NSString *name; /** The cardholder's address. + + @note Changing this property will also changing the name of the + param's `name` property */ -@property (nonatomic, copy, nonnull) STPAddress *address; - -@property (nonatomic, copy, nullable) NSString *addressLine1; -@property (nonatomic, copy, nullable) NSString *addressLine2; -@property (nonatomic, copy, nullable) NSString *addressCity; -@property (nonatomic, copy, nullable) NSString *addressState; -@property (nonatomic, copy, nullable) NSString *addressZip; -@property (nonatomic, copy, nullable) NSString *addressCountry; +@property (nonatomic, strong, nonnull) STPAddress *address; /** - Three-letter ISO currency code representing the currency paid out to the bank account. This is only applicable when tokenizing debit cards to issue payouts to managed accounts. You should not set it otherwise. The card can then be used as a transfer destination for funds in this currency. + Three-letter ISO currency code representing the currency paid out to the bank + account. This is only applicable when tokenizing debit cards to issue payouts + to managed accounts. You should not set it otherwise. The card can then be + used as a transfer destination for funds in this currency. */ @property (nonatomic, copy, nullable) NSString *currency; + +#pragma mark - Deprecated methods + +/** + The first line of the cardholder's address + */ +@property (nonatomic, copy, nullable) NSString *addressLine1 DEPRECATED_MSG_ATTRIBUTE("Use address.line1"); + +/** + The second line of the cardholder's address + */ +@property (nonatomic, copy, nullable) NSString *addressLine2 DEPRECATED_MSG_ATTRIBUTE("Use address.line2"); + +/** + The city of the cardholder's address + */ +@property (nonatomic, copy, nullable) NSString *addressCity DEPRECATED_MSG_ATTRIBUTE("Use address.city"); + +/** + The state of the cardholder's address + */ +@property (nonatomic, copy, nullable) NSString *addressState DEPRECATED_MSG_ATTRIBUTE("Use address.state"); + +/** + The zip code of the cardholder's address + */ +@property (nonatomic, copy, nullable) NSString *addressZip DEPRECATED_MSG_ATTRIBUTE("Use address.postalCode"); + +/** + The country of the cardholder's address + */ +@property (nonatomic, copy, nullable) NSString *addressCountry DEPRECATED_MSG_ATTRIBUTE("Use address.country"); + + @end diff --git a/Stripe/STPAPIClient.m b/Stripe/STPAPIClient.m index 301180dd541..aae176efe73 100644 --- a/Stripe/STPAPIClient.m +++ b/Stripe/STPAPIClient.m @@ -365,8 +365,8 @@ - (void)uploadImage:(UIImage *)image @implementation STPAPIClient (CreditCards) -- (void)createTokenWithCard:(STPCard *)card completion:(STPTokenCompletionBlock)completion { - NSMutableDictionary *params = [[STPFormEncoder dictionaryForObject:card] mutableCopy]; +- (void)createTokenWithCard:(STPCardParams *)cardParams completion:(STPTokenCompletionBlock)completion { + NSMutableDictionary *params = [[STPFormEncoder dictionaryForObject:cardParams] mutableCopy]; [[STPTelemetryClient sharedInstance] addTelemetryFieldsToParams:params]; [self createTokenWithParameters:params completion:completion]; [[STPTelemetryClient sharedInstance] sendTelemetryData]; diff --git a/Stripe/STPCard+Private.h b/Stripe/STPCard+Private.h index 74d9756aee9..ddeed4a1366 100644 --- a/Stripe/STPCard+Private.h +++ b/Stripe/STPCard+Private.h @@ -13,8 +13,12 @@ NS_ASSUME_NONNULL_BEGIN @interface STPCard () ++ (STPCardFundingType)fundingFromString:(NSString *)string; + (nullable NSString *)stringFromFunding:(STPCardFundingType)funding; ++ (STPCardBrand)brandFromString:(NSString *)string; ++ (NSString *)stringFromBrand:(STPCardBrand)brand; + @end NS_ASSUME_NONNULL_END diff --git a/Stripe/STPCard.m b/Stripe/STPCard.m index fbef1d53778..696b63f2588 100644 --- a/Stripe/STPCard.m +++ b/Stripe/STPCard.m @@ -15,12 +15,17 @@ @interface STPCard () -@property (nonatomic, readwrite) NSString *cardId; +@property (nonatomic, nonnull) NSString *stripeID; +@property (nonatomic, readwrite) NSString *name; @property (nonatomic, readwrite) NSString *last4; @property (nonatomic, readwrite) NSString *dynamicLast4; @property (nonatomic, readwrite) STPCardBrand brand; @property (nonatomic, readwrite) STPCardFundingType funding; @property (nonatomic, readwrite) NSString *country; +@property (nonatomic, readwrite) NSString *currency; +@property (nonatomic, readwrite) NSUInteger expMonth; +@property (nonatomic, readwrite) NSUInteger expYear; +@property (nonatomic, readwrite, nonnull, strong) STPAddress *address; @property (nonatomic, readwrite, nonnull, copy) NSDictionary *allResponseFields; // See STPCard+Private.h @@ -29,8 +34,6 @@ @interface STPCard () @implementation STPCard -@dynamic number, cvc, expMonth, expYear, currency, name, address, addressLine1, addressLine2, addressCity, addressState, addressZip, addressCountry; - #pragma mark - STPCardBrand + (STPCardBrand)brandFromString:(NSString *)string { @@ -98,57 +101,10 @@ + (nullable NSString *)stringFromFunding:(STPCardFundingType)funding { #pragma mark - -- (instancetype)initWithID:(NSString *)stripeID - brand:(STPCardBrand)brand - last4:(NSString *)last4 - expMonth:(NSUInteger)expMonth - expYear:(NSUInteger)expYear - funding:(STPCardFundingType)funding { - self = [super init]; - if (self) { - _cardId = stripeID; - _brand = brand; - _last4 = last4; - self.expMonth = expMonth; - self.expYear = expYear; - _funding = funding; - } - return self; -} - -- (instancetype)init { - self = [super init]; - if (self) { - _brand = STPCardBrandUnknown; - _funding = STPCardFundingTypeOther; - } - - return self; -} - -- (NSString *)last4 { - return _last4 ?: [super last4]; -} - - (BOOL)isApplePayCard { return [self.allResponseFields[@"tokenization_method"] isEqualToString:@"apple_pay"]; } -- (STPAddress *)address { - if (self.name || self.addressLine1 || self.addressLine2 || self.addressZip || self.addressCity || self.addressState || self.addressCountry) { - STPAddress *address = [STPAddress new]; - address.name = self.name; - address.line1 = self.addressLine1; - address.line2 = self.addressLine2; - address.postalCode = self.addressZip; - address.city = self.addressCity; - address.state = self.addressState; - address.country = self.addressCountry; - return address; - } - return nil; -} - #pragma mark - Equality - (BOOL)isEqual:(id)other { @@ -156,7 +112,7 @@ - (BOOL)isEqual:(id)other { } - (NSUInteger)hash { - return [self.cardId hash]; + return [self.stripeID hash]; } - (BOOL)isEqualToCard:(STPCard *)other { @@ -168,7 +124,7 @@ - (BOOL)isEqualToCard:(STPCard *)other { return NO; } - return [self.cardId isEqualToString:other.cardId]; + return [self.stripeID isEqualToString:other.stripeID]; } #pragma mark - Description @@ -179,7 +135,7 @@ - (NSString *)description { [NSString stringWithFormat:@"%@: %p", NSStringFromClass([self class]), self], // Identifier - [NSString stringWithFormat:@"cardId = %@", self.cardId], + [NSString stringWithFormat:@"stripeID = %@", self.stripeID], // Basic card details [NSString stringWithFormat:@"brand = %@", [self.class stringFromBrand:self.brand]], @@ -217,37 +173,40 @@ + (instancetype)decodedObjectFromAPIResponse:(NSDictionary *)response { if (!dict) { return nil; } - + STPCard *card = [self new]; - card.cardId = dict[@"id"]; + card.address = [STPAddress new]; + + card.stripeID = dict[@"id"]; card.name = dict[@"name"]; card.last4 = dict[@"last4"]; card.dynamicLast4 = dict[@"dynamic_last4"]; - NSString *brand = [dict[@"brand"] lowercaseString]; - card.brand = [self.class brandFromString:brand]; - NSString *funding = dict[@"funding"]; - card.funding = [self.class fundingFromString:funding]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated" + // These are only intended to be deprecated publicly. + // When removed from public header, can remove these pragmas + + card.brand = [self.class brandFromString:dict[@"brand"]]; + card.funding = [self.class fundingFromString:dict[@"funding"]]; +#pragma clang diagnostic pop + card.country = dict[@"country"]; card.currency = dict[@"currency"]; card.expMonth = [dict[@"exp_month"] intValue]; card.expYear = [dict[@"exp_year"] intValue]; - card.addressLine1 = dict[@"address_line1"]; - card.addressLine2 = dict[@"address_line2"]; - card.addressCity = dict[@"address_city"]; - card.addressState = dict[@"address_state"]; - card.addressZip = dict[@"address_zip"]; - card.addressCountry = dict[@"address_country"]; + + card.address.name = card.name; + card.address.line1 = dict[@"address_line1"]; + card.address.line2 = dict[@"address_line2"]; + card.address.city = dict[@"address_city"]; + card.address.state = dict[@"address_state"]; + card.address.postalCode = dict[@"address_zip"]; + card.address.country = dict[@"address_country"]; card.allResponseFields = dict; return card; } -#pragma mark - STPSourceProtocol - -- (NSString *)stripeID { - return self.cardId; -} - #pragma mark - STPPaymentMethod - (UIImage *)image { @@ -263,4 +222,53 @@ - (NSString *)label { return [NSString stringWithFormat:@"%@ %@", brand, self.last4]; } +#pragma mark - Deprecated methods + +- (instancetype)initWithID:(NSString *)stripeID + brand:(STPCardBrand)brand + last4:(NSString *)last4 + expMonth:(NSUInteger)expMonth + expYear:(NSUInteger)expYear + funding:(STPCardFundingType)funding { + self = [super init]; + if (self) { + _stripeID = stripeID.copy; + _brand = brand; + _last4 = last4.copy; + _expMonth = expMonth; + _expYear = expYear; + _funding = funding; + _address = [STPAddress new]; + } + return self; +} + +- (NSString *)cardId { + return self.stripeID; +} + +- (NSString *)addressLine1 { + return self.address.line1; +} + +- (NSString *)addressLine2 { + return self.address.line2; +} + +- (NSString *)addressZip { + return self.address.postalCode; +} + +- (NSString *)addressCity { + return self.address.city; +} + +- (NSString *)addressState { + return self.address.state; +} + +- (NSString *)addressCountry { + return self.address.country; +} + @end diff --git a/Stripe/STPCardParams.m b/Stripe/STPCardParams.m index 2cadda214f6..7ef58f88687 100644 --- a/Stripe/STPCardParams.m +++ b/Stripe/STPCardParams.m @@ -7,6 +7,7 @@ // #import "STPCardParams.h" +#import "STPCard+Private.h" #import "STPCardValidator.h" #import "StripeError.h" @@ -19,6 +20,7 @@ - (instancetype)init { self = [super init]; if (self) { _additionalAPIParameters = @{}; + _address = [STPAddress new]; } return self; } @@ -31,26 +33,9 @@ - (NSString *)last4 { } } -- (STPAddress *)address { - STPAddress *address = [STPAddress new]; - address.name = self.name; - address.line1 = self.addressLine1; - address.line2 = self.addressLine2; - address.city = self.addressCity; - address.state = self.addressState; - address.postalCode = self.addressZip; - address.country = self.addressCountry; - return address; -} - - (void)setAddress:(STPAddress *)address { + _address = address; self.name = address.name; - self.addressLine1 = address.line1; - self.addressLine2 = address.line2; - self.addressCity = address.city; - self.addressState = address.state; - self.addressZip = address.postalCode; - self.addressCountry = address.country; } #pragma mark - Description @@ -100,4 +85,59 @@ + (NSDictionary *)propertyNamesToFormFieldNamesMapping { }; } +- (void)setName:(NSString *)name { + _name = name.copy; + self.address.name = name; +} + +#pragma mark - Deprecated methods + +- (void)setAddressLine1:(NSString *)addressLine1 { + self.address.line1 = addressLine1; +} + +- (NSString *)addressLine1 { + return self.address.line1; +} + +- (void)setAddressLine2:(NSString *)addressLine2 { + self.address.line2 = addressLine2; +} + +- (NSString *)addressLine2 { + return self.address.line2; +} + +- (void)setAddressZip:(NSString *)addressZip { + self.address.postalCode = addressZip; +} + +- (NSString *)addressZip { + return self.address.postalCode; +} + +- (void)setAddressCity:(NSString *)addressCity { + self.address.city = addressCity; +} + +- (NSString *)addressCity { + return self.address.city; +} + +- (void)setAddressState:(NSString *)addressState { + self.address.state = addressState; +} + +- (NSString *)addressState { + return self.address.state; +} + +- (void)setAddressCountry:(NSString *)addressCountry { + self.address.country = addressCountry; +} + +- (NSString *)addressCountry { + return self.address.country; +} + @end diff --git a/Stripe/STPPaymentCardTextField.m b/Stripe/STPPaymentCardTextField.m index 0fcfc6db3f9..798ae32c9d0 100644 --- a/Stripe/STPPaymentCardTextField.m +++ b/Stripe/STPPaymentCardTextField.m @@ -608,7 +608,7 @@ - (STPCardParams *)cardParams { if (self.postalCodeEntryEnabled) { // We don't clobber any manually set address zip code that was on our params // if we are not showing the postal code entry field. - self.internalCardParams.addressZip = self.postalCode; + self.internalCardParams.address.postalCode = self.postalCode; } return self.internalCardParams; } @@ -644,7 +644,7 @@ behaves identically to user entering text (and will have the same forwarding } [self setText:cardParams.cvc inField:STPCardFieldTypeCVC]; - [self setText:cardParams.addressZip inField:STPCardFieldTypePostalCode]; + [self setText:cardParams.address.postalCode inField:STPCardFieldTypePostalCode]; if ([self isFirstResponder]) { STPCardFieldType fieldType = originalSubResponder.tag; diff --git a/Stripe/STPSourceCardDetails.m b/Stripe/STPSourceCardDetails.m index e92e086dd9b..c18022b7e38 100644 --- a/Stripe/STPSourceCardDetails.m +++ b/Stripe/STPSourceCardDetails.m @@ -40,10 +40,13 @@ - (instancetype)initWithDictionary:(NSDictionary *)dict { self = [super init]; if (self) { _last4 = dict[@"last4"]; - NSString *brand = [dict[@"brand"] lowercaseString]; - _brand = [STPCard brandFromString:brand]; - NSString *funding = dict[@"funding"]; - _funding = [STPCard fundingFromString:funding]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated" + // These are only intended to be deprecated publicly. + // When removed from public header, can remove these pragmas + _brand = [STPCard brandFromString:dict[@"brand"]]; + _funding = [STPCard fundingFromString:dict[@"funding"]]; +#pragma clang diagnostic pop _country = dict[@"country"]; _expMonth = [dict[@"exp_month"] intValue]; _expYear = [dict[@"exp_year"] intValue]; diff --git a/Tests/Tests/STPAPIRequestTest.m b/Tests/Tests/STPAPIRequestTest.m index bbb874d73ca..0dbda44cdab 100644 --- a/Tests/Tests/STPAPIRequestTest.m +++ b/Tests/Tests/STPAPIRequestTest.m @@ -62,7 +62,7 @@ - (void)testPostWithAPIClient { // Perform request NSString *endpoint = @"endpoint"; NSDictionary *parameters = @{@"key": @"value"}; - STPCard *deserializer = [[STPCard alloc] init]; + STPCard *deserializer = [STPCard new]; NSURLSessionDataTask *task = [STPAPIRequest postWithAPIClient:apiClientMock endpoint:endpoint @@ -130,7 +130,7 @@ - (void)testGetWithAPIClient { // Perform request NSString *endpoint = @"endpoint"; NSDictionary *parameters = @{@"key": @"value"}; - STPCard *deserializer = [[STPCard alloc] init]; + STPCard *deserializer = [STPCard new]; NSURLSessionDataTask *task = [STPAPIRequest getWithAPIClient:apiClientMock endpoint:endpoint @@ -198,7 +198,7 @@ - (void)testDeleteWithAPIClient { // Perform request NSString *endpoint = @"endpoint"; NSDictionary *parameters = @{@"key": @"value"}; - STPCard *deserializer = [[STPCard alloc] init]; + STPCard *deserializer = [STPCard new]; NSURLSessionDataTask *task = [STPAPIRequest deleteWithAPIClient:apiClientMock endpoint:endpoint diff --git a/Tests/Tests/STPCardFunctionalTest.m b/Tests/Tests/STPCardFunctionalTest.m index cea0b0ea290..2ee5b8a3d7c 100644 --- a/Tests/Tests/STPCardFunctionalTest.m +++ b/Tests/Tests/STPCardFunctionalTest.m @@ -22,12 +22,12 @@ - (void)testCreateCardToken { card.expMonth = 6; card.expYear = 2018; card.currency = @"usd"; - card.addressLine1 = @"123 Fake Street"; - card.addressLine2 = @"Apartment 4"; - card.addressCity = @"New York"; - card.addressState = @"NY"; - card.addressCountry = @"USA"; - card.addressZip = @"10002"; + card.address.line1 = @"123 Fake Street"; + card.address.line2 = @"Apartment 4"; + card.address.city = @"New York"; + card.address.state = @"NY"; + card.address.country = @"USA"; + card.address.postalCode = @"10002"; STPAPIClient *client = [[STPAPIClient alloc] initWithPublishableKey:@"pk_test_vOo1umqsYxSrP5UXfOeL3ecm"]; diff --git a/Tests/Tests/STPCardParamsTest.m b/Tests/Tests/STPCardParamsTest.m index 1911ba732c1..487d46ae702 100644 --- a/Tests/Tests/STPCardParamsTest.m +++ b/Tests/Tests/STPCardParamsTest.m @@ -35,6 +35,9 @@ - (void)testLast4ReturnsNilWhenCardNumberIsLessThanLength4 { XCTAssertNil(cardParams.last4); } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated" + - (void)testAddress { STPCardParams *cardParams = [[STPCardParams alloc] init]; cardParams.name = @"John Smith"; @@ -78,6 +81,8 @@ - (void)testSetAddress { XCTAssertEqualObjects(cardParams.addressCountry, @"US"); } +#pragma clang diagnostic pop + #pragma mark - Description Tests - (void)testDescription { diff --git a/Tests/Tests/STPCardTest.m b/Tests/Tests/STPCardTest.m index 5954d5869dd..287b59cb5cd 100644 --- a/Tests/Tests/STPCardTest.m +++ b/Tests/Tests/STPCardTest.m @@ -12,6 +12,7 @@ #import "STPCard+Private.h" #import "NSDictionary+Stripe.h" +#import "STPFixtures.h" #import "STPTestUtils.h" @interface STPCard () @@ -31,6 +32,10 @@ @implementation STPCardTest #pragma mark - STPCardBrand Tests +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated" +// These are only intended to be deprecated publicly. +// When removed from public header, can remove these pragmas - (void)testBrandFromString { XCTAssertEqual([STPCard brandFromString:@"visa"], STPCardBrandVisa); XCTAssertEqual([STPCard brandFromString:@"VISA"], STPCardBrandVisa); @@ -56,6 +61,7 @@ - (void)testBrandFromString { XCTAssertEqual([STPCard brandFromString:@"garbage"], STPCardBrandUnknown); XCTAssertEqual([STPCard brandFromString:@"GARBAGE"], STPCardBrandUnknown); } +#pragma clang diagnostic pop - (void)testStringFromBrand { [self forEachBrand:^(STPCardBrand brand) { @@ -89,6 +95,11 @@ - (void)testStringFromBrand { #pragma mark - STPCardFundingType Tests +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated" +// These are only intended to be deprecated publicly. +// When removed from public header, can remove these pragmas + - (void)testFundingFromString { XCTAssertEqual([STPCard fundingFromString:@"credit"], STPCardFundingTypeCredit); XCTAssertEqual([STPCard fundingFromString:@"CREDIT"], STPCardFundingTypeCredit); @@ -109,6 +120,8 @@ - (void)testFundingFromString { XCTAssertEqual([STPCard fundingFromString:@"GARBAGE"], STPCardFundingTypeOther); } +#pragma clang diagnostic pop + - (void)testStringFromFunding { NSArray *values = @[ @(STPCardFundingTypeCredit), @@ -139,6 +152,10 @@ - (void)testStringFromFunding { } #pragma mark - +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated" +// These tests can ber removed in the future, they should be covered by +// the equivalent response decodeable tests - (void)testInitWithIDBrandLast4ExpMonthExpYearFunding { STPCard *card = [[STPCard alloc] initWithID:@"card_1AVRojEOD54MuFwSxr93QJSx" @@ -147,7 +164,7 @@ - (void)testInitWithIDBrandLast4ExpMonthExpYearFunding { expMonth:12 expYear:2034 funding:STPCardFundingTypeDebit]; - XCTAssertEqualObjects(card.cardId, @"card_1AVRojEOD54MuFwSxr93QJSx"); + XCTAssertEqualObjects(card.stripeID, @"card_1AVRojEOD54MuFwSxr93QJSx"); XCTAssertEqual(card.brand, STPCardBrandVisa); XCTAssertEqualObjects(card.last4, @"5556"); XCTAssertEqual(card.expMonth, (NSUInteger)12); @@ -155,38 +172,10 @@ - (void)testInitWithIDBrandLast4ExpMonthExpYearFunding { XCTAssertEqual(card.funding, STPCardFundingTypeDebit); } -- (void)testInit { - STPCard *card = [[STPCard alloc] init]; - XCTAssertEqual(card.brand, STPCardBrandUnknown); - XCTAssertEqual(card.funding, STPCardFundingTypeOther); -} - -- (void)testLast4ReturnsCardNumberLast4WhenNotSet { - STPCard *card = [[STPCard alloc] init]; - card.number = @"4242424242424242"; - XCTAssertEqualObjects(card.last4, @"4242"); -} - -- (void)testLast4ReturnsNilWhenNoCardNumberSet { - STPCard *card = [[STPCard alloc] init]; - XCTAssertNil(card.last4); -} - -- (void)testLast4ReturnsNilWhenCardNumberIsLessThanLength4 { - STPCard *card = [[STPCard alloc] init]; - card.number = @"123"; - XCTAssertNil(card.last4); -} - -- (void)testLast4ReturnsValueOverCardNumberDerivation { - STPCard *card = [[STPCard alloc] init]; - card.number = nil; - card.last4 = @"1234"; - XCTAssertEqualObjects(card.last4, @"1234"); -} +#pragma clang diagnostic pop - (void)testIsApplePayCard { - STPCard *card = [[STPCard alloc] init]; + STPCard *card = [STPFixtures card]; card.allResponseFields = @{}; XCTAssertFalse(card.isApplePayCard); @@ -207,7 +196,7 @@ - (void)testIsApplePayCard { } - (void)testAddressPopulated { - STPCard *card = [STPCard decodedObjectFromAPIResponse:[STPTestUtils jsonNamed:@"Card"]]; + STPCard *card = [STPFixtures card]; XCTAssertEqualObjects(card.address.name, @"Jane Austen"); XCTAssertEqualObjects(card.address.line1, @"123 Fake St"); XCTAssertEqualObjects(card.address.line2, @"Apt 1"); @@ -217,16 +206,11 @@ - (void)testAddressPopulated { XCTAssertEqualObjects(card.address.country, @"US"); } -- (void)testAddressEmpty { - STPCard *card = [[STPCard alloc] init]; - XCTAssertNil(card.address); -} - #pragma mark - Equality Tests - (void)testCardEquals { - STPCard *card1 = [STPCard decodedObjectFromAPIResponse:[STPTestUtils jsonNamed:@"Card"]]; - STPCard *card2 = [STPCard decodedObjectFromAPIResponse:[STPTestUtils jsonNamed:@"Card"]]; + STPCard *card1 = [STPFixtures card]; + STPCard *card2 = [STPFixtures card]; XCTAssertNotEqual(card1, card2); @@ -240,7 +224,7 @@ - (void)testCardEquals { #pragma mark - Description Tests - (void)testDescription { - STPCard *card = [STPCard decodedObjectFromAPIResponse:[STPTestUtils jsonNamed:@"Card"]]; + STPCard *card = [STPFixtures card]; XCTAssert(card.description); } @@ -265,17 +249,35 @@ - (void)testDecodedObjectFromAPIResponseRequiredFields { XCTAssert([STPCard decodedObjectFromAPIResponse:[STPTestUtils jsonNamed:@"Card"]]); } + + - (void)testDecodedObjectFromAPIResponseMapping { NSDictionary *response = [STPTestUtils jsonNamed:@"Card"]; STPCard *card = [STPCard decodedObjectFromAPIResponse:response]; + XCTAssertEqualObjects(card.stripeID, @"card_103kbR2eZvKYlo2CDczLmw4K"); + + XCTAssertEqualObjects(card.address.city, @"Pittsburgh"); + XCTAssertEqualObjects(card.address.country, @"US"); + XCTAssertEqualObjects(card.address.line1, @"123 Fake St"); + XCTAssertEqualObjects(card.address.line2, @"Apt 1"); + XCTAssertEqualObjects(card.address.state, @"PA"); + XCTAssertEqualObjects(card.address.postalCode, @"19219"); + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated" + XCTAssertEqualObjects(card.cardId, @"card_103kbR2eZvKYlo2CDczLmw4K"); + XCTAssertEqualObjects(card.addressCity, @"Pittsburgh"); XCTAssertEqualObjects(card.addressCountry, @"US"); XCTAssertEqualObjects(card.addressLine1, @"123 Fake St"); XCTAssertEqualObjects(card.addressLine2, @"Apt 1"); XCTAssertEqualObjects(card.addressState, @"PA"); XCTAssertEqualObjects(card.addressZip, @"19219"); + +#pragma clang diagnostic pop + XCTAssertEqual(card.brand, STPCardBrandVisa); XCTAssertEqualObjects(card.country, @"US"); XCTAssertEqualObjects(card.currency, @"usd"); @@ -290,27 +292,28 @@ - (void)testDecodedObjectFromAPIResponseMapping { XCTAssertEqualObjects(card.allResponseFields, [response stp_dictionaryByRemovingNullsValidatingRequiredFields:@[]]); } + + #pragma mark - STPSourceProtocol Tests - (void)testStripeID { - STPCard *card = [STPCard decodedObjectFromAPIResponse:[STPTestUtils jsonNamed:@"Card"]]; + STPCard *card = [STPFixtures card]; XCTAssertEqualObjects(card.stripeID, @"card_103kbR2eZvKYlo2CDczLmw4K"); } #pragma mark - STPPaymentMethod Tests - (void)testImage { + STPCard *card = [STPFixtures card]; [self forEachBrand:^(STPCardBrand brand) { - STPCard *card = [[STPCard alloc] init]; card.brand = brand; - XCTAssert([card image]); }]; } - (void)testTemplateImage { + STPCard *card = [STPFixtures card]; [self forEachBrand:^(STPCardBrand brand) { - STPCard *card = [[STPCard alloc] init]; card.brand = brand; XCTAssert([card templateImage]); diff --git a/Tests/Tests/STPFixtures.h b/Tests/Tests/STPFixtures.h index 9c591f58204..aa93d130353 100644 --- a/Tests/Tests/STPFixtures.h +++ b/Tests/Tests/STPFixtures.h @@ -33,6 +33,11 @@ */ + (STPCardParams *)cardParams; +/** + A valid card object + */ ++ (STPCard *)card; + /** A Source object with type card */ diff --git a/Tests/Tests/STPFixtures.m b/Tests/Tests/STPFixtures.m index 8fb92451578..d1098139705 100644 --- a/Tests/Tests/STPFixtures.m +++ b/Tests/Tests/STPFixtures.m @@ -46,6 +46,10 @@ + (STPCardParams *)cardParams { return cardParams; } ++ (STPCard *)card { + return [STPCard decodedObjectFromAPIResponse:[STPTestUtils jsonNamed:@"Card"]]; +} + + (STPSource *)cardSource { return [STPSource decodedObjectFromAPIResponse:[STPTestUtils jsonNamed:@"CardSource"]]; } diff --git a/Tests/Tests/STPPaymentCardTextFieldTest.m b/Tests/Tests/STPPaymentCardTextFieldTest.m index af7e47a401e..5d0e0a4d303 100644 --- a/Tests/Tests/STPPaymentCardTextFieldTest.m +++ b/Tests/Tests/STPPaymentCardTextFieldTest.m @@ -298,6 +298,9 @@ - (void)testSetCard_empty { XCTAssertFalse(sut.isValid); } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated" + - (void)testSetCard_addressFields { STPPaymentCardTextField *sut = [STPPaymentCardTextField new]; @@ -320,6 +323,8 @@ - (void)testSetCard_addressFields { XCTAssertEqualObjects(sut.cardParams.addressCountry, @"US"); } +#pragma clang diagnostic pop + - (void)testSettingTextUpdatesViewModelText { STPPaymentCardTextField *sut = [STPPaymentCardTextField new]; sut.numberField.text = @"4242424242424242"; diff --git a/Tests/Tests/STPSourceFunctionalTest.m b/Tests/Tests/STPSourceFunctionalTest.m index 3bc4d68b6ff..7fe1573bd76 100644 --- a/Tests/Tests/STPSourceFunctionalTest.m +++ b/Tests/Tests/STPSourceFunctionalTest.m @@ -78,12 +78,12 @@ - (void)testCreateSource_card { card.expYear = 2018; card.currency = @"usd"; card.name = @"Jenny Rosen"; - card.addressLine1 = @"123 Fake Street"; - card.addressLine2 = @"Apartment 4"; - card.addressCity = @"New York"; - card.addressState = @"NY"; - card.addressCountry = @"USA"; - card.addressZip = @"10002"; + card.address.line1 = @"123 Fake Street"; + card.address.line2 = @"Apartment 4"; + card.address.city = @"New York"; + card.address.state = @"NY"; + card.address.country = @"USA"; + card.address.postalCode = @"10002"; STPSourceParams *params = [STPSourceParams cardParamsWithCard:card]; params.metadata = @{@"foo": @"bar"}; @@ -98,12 +98,12 @@ - (void)testCreateSource_card { XCTAssertEqual(source.cardDetails.expYear, card.expYear); XCTAssertEqualObjects(source.owner.name, card.name); STPAddress *address = source.owner.address; - XCTAssertEqualObjects(address.line1, card.addressLine1); - XCTAssertEqualObjects(address.line2, card.addressLine2); - XCTAssertEqualObjects(address.city, card.addressCity); - XCTAssertEqualObjects(address.state, card.addressState); - XCTAssertEqualObjects(address.country, card.addressCountry); - XCTAssertEqualObjects(address.postalCode, card.addressZip); + XCTAssertEqualObjects(address.line1, card.address.line1); + XCTAssertEqualObjects(address.line2, card.address.line2); + XCTAssertEqualObjects(address.city, card.address.city); + XCTAssertEqualObjects(address.state, card.address.state); + XCTAssertEqualObjects(address.country, card.address.country); + XCTAssertEqualObjects(address.postalCode, card.address.postalCode); XCTAssertEqualObjects(source.metadata, params.metadata); [expectation fulfill]; @@ -257,12 +257,12 @@ - (void)testCreateSource_threeDSecure { card.expMonth = 6; card.expYear = 2018; card.currency = @"usd"; - card.addressLine1 = @"123 Fake Street"; - card.addressLine2 = @"Apartment 4"; - card.addressCity = @"New York"; - card.addressState = @"NY"; - card.addressCountry = @"USA"; - card.addressZip = @"10002"; + card.address.line1 = @"123 Fake Street"; + card.address.line2 = @"Apartment 4"; + card.address.city = @"New York"; + card.address.state = @"NY"; + card.address.country = @"USA"; + card.address.postalCode = @"10002"; STPSourceParams *cardParams = [STPSourceParams cardParamsWithCard:card]; STPAPIClient *client = [[STPAPIClient alloc] initWithPublishableKey:apiKey]; diff --git a/Tests/Tests/STPSourceParamsTest.m b/Tests/Tests/STPSourceParamsTest.m index e9129a55e03..37bbf7eb369 100644 --- a/Tests/Tests/STPSourceParamsTest.m +++ b/Tests/Tests/STPSourceParamsTest.m @@ -174,12 +174,12 @@ - (void)testCardParamsWithCard { card.expYear = 2018; card.currency = @"usd"; card.name = @"Jenny Rosen"; - card.addressLine1 = @"123 Fake Street"; - card.addressLine2 = @"Apartment 4"; - card.addressCity = @"New York"; - card.addressState = @"NY"; - card.addressCountry = @"USA"; - card.addressZip = @"10002"; + card.address.line1 = @"123 Fake Street"; + card.address.line2 = @"Apartment 4"; + card.address.city = @"New York"; + card.address.state = @"NY"; + card.address.country = @"USA"; + card.address.postalCode = @"10002"; STPSourceParams *source = [STPSourceParams cardParamsWithCard:card]; NSDictionary *sourceCard = source.additionalAPIParameters[@"card"]; @@ -189,14 +189,15 @@ - (void)testCardParamsWithCard { XCTAssertEqualObjects(sourceCard[@"exp_year"], @(card.expYear)); XCTAssertEqualObjects(source.owner[@"name"], card.name); NSDictionary *sourceAddress = source.owner[@"address"]; - XCTAssertEqualObjects(sourceAddress[@"line1"], card.addressLine1); - XCTAssertEqualObjects(sourceAddress[@"line2"], card.addressLine2); - XCTAssertEqualObjects(sourceAddress[@"city"], card.addressCity); - XCTAssertEqualObjects(sourceAddress[@"state"], card.addressState); - XCTAssertEqualObjects(sourceAddress[@"postal_code"], card.addressZip); - XCTAssertEqualObjects(sourceAddress[@"country"], card.addressCountry); + XCTAssertEqualObjects(sourceAddress[@"line1"], card.address.line1); + XCTAssertEqualObjects(sourceAddress[@"line2"], card.address.line2); + XCTAssertEqualObjects(sourceAddress[@"city"], card.address.city); + XCTAssertEqualObjects(sourceAddress[@"state"], card.address.state); + XCTAssertEqualObjects(sourceAddress[@"postal_code"], card.address.country); + XCTAssertEqualObjects(sourceAddress[@"country"], card.address.postalCode); } + #pragma mark - Redirect Dictionary Tests - (NSString *)redirectMerchantNameQueryItemValueFromURLString:(NSString *)urlString { From 4034caf7ed57b271434816b9d35e82c007b132bf Mon Sep 17 00:00:00 2001 From: Brian Dorfman Date: Wed, 2 Aug 2017 10:30:48 -0700 Subject: [PATCH 2/4] Updates based on pr feedback. Wrap all comments at 80 chars Assume nonnull in implementation Update property definitions to style guide --- Stripe/PublicHeaders/STPCard.h | 65 +++++++++++++++++++++------------- Stripe/STPCard.m | 47 +++++++++++++----------- 2 files changed, 67 insertions(+), 45 deletions(-) diff --git a/Stripe/PublicHeaders/STPCard.h b/Stripe/PublicHeaders/STPCard.h index a2bbbf1a4be..8ed485f9b69 100644 --- a/Stripe/PublicHeaders/STPCard.h +++ b/Stripe/PublicHeaders/STPCard.h @@ -27,16 +27,18 @@ typedef NS_ENUM(NSInteger, STPCardFundingType) { }; /** - Representation of a user's credit card details that have been tokenized with the Stripe API + Representation of a user's credit card details that have been tokenized with + the Stripe API @see https://stripe.com/docs/api#cards */ @interface STPCard : NSObject /** - You cannot directly instantiate an `STPCard`. You should only use one that has been returned from an `STPAPIClient` callback. + You cannot directly instantiate an `STPCard`. You should only use one that has + been returned from an `STPAPIClient` callback. */ -- (nonnull instancetype) init __attribute__((unavailable("You cannot directly instantiate an STPCard. You should only use one that has been returned from an STPAPIClient callback."))); +- (instancetype) init __attribute__((unavailable("You cannot directly instantiate an STPCard. You should only use one that has been returned from an STPAPIClient callback."))); /** The last 4 digits of the card. @@ -44,9 +46,11 @@ typedef NS_ENUM(NSInteger, STPCardFundingType) { @property (nonatomic, readonly) NSString *last4; /** - For cards made with Apple Pay, this refers to the last 4 digits of the "Device Account Number" for the tokenized card. For regular cards, it will be nil. + For cards made with Apple Pay, this refers to the last 4 digits of the + "Device Account Number" for the tokenized card. For regular cards, it will + be nil. */ -@property (nonatomic, readonly, nullable) NSString *dynamicLast4; +@property (nonatomic, nullable, readonly) NSString *dynamicLast4; /** Whether or not the card originated from Apple Pay. @@ -66,12 +70,12 @@ typedef NS_ENUM(NSInteger, STPCardFundingType) { /** The cardholder's name. */ -@property (nonatomic, copy, nullable, readonly) NSString *name; +@property (nonatomic, nullable, readonly) NSString *name; /** The cardholder's address. */ -@property (nonatomic, nonnull, readonly) STPAddress *address; +@property (nonatomic, readonly) STPAddress *address; /** The issuer of the card. @@ -89,12 +93,15 @@ typedef NS_ENUM(NSInteger, STPCardFundingType) { @property (nonatomic, nullable, readonly) NSString *country; /** - This is only applicable when tokenizing debit cards to issue payouts to managed accounts. You should not set it otherwise. The card can then be used as a transfer destination for funds in this currency. + This is only applicable when tokenizing debit cards to issue payouts to managed + accounts. You should not set it otherwise. The card can then be used as a + transfer destination for funds in this currency. */ @property (nonatomic, nullable, readonly) NSString *currency; /** - Returns a string representation for the provided card brand; i.e. `[NSString stringFromBrand:STPCardBrandVisa] == @"Visa"`. + Returns a string representation for the provided card brand; + i.e. `[NSString stringFromBrand:STPCardBrandVisa] == @"Visa"`. @param brand the brand you want to convert to a string @@ -108,47 +115,49 @@ typedef NS_ENUM(NSInteger, STPCardFundingType) { /** The Stripe ID for the card. */ -@property (nonatomic, nullable, readonly) NSString *cardId DEPRECATED_MSG_ATTRIBUTE("Use stripeID (defined in STPSourceProtocol)"); +@property (nonatomic, readonly) NSString *cardId DEPRECATED_MSG_ATTRIBUTE("Use stripeID (defined in STPSourceProtocol)"); /** The first line of the cardholder's address */ -@property (nonatomic, copy, nullable, readonly) NSString *addressLine1 DEPRECATED_MSG_ATTRIBUTE("Use address.line1"); +@property (nonatomic, nullable, readonly) NSString *addressLine1 DEPRECATED_MSG_ATTRIBUTE("Use address.line1"); /** The second line of the cardholder's address */ -@property (nonatomic, copy, nullable, readonly) NSString *addressLine2 DEPRECATED_MSG_ATTRIBUTE("Use address.line2"); +@property (nonatomic, nullable, readonly) NSString *addressLine2 DEPRECATED_MSG_ATTRIBUTE("Use address.line2"); /** The city of the cardholder's address */ -@property (nonatomic, copy, nullable, readonly) NSString *addressCity DEPRECATED_MSG_ATTRIBUTE("Use address.city"); +@property (nonatomic, nullable, readonly) NSString *addressCity DEPRECATED_MSG_ATTRIBUTE("Use address.city"); /** The state of the cardholder's address */ -@property (nonatomic, copy, nullable, readonly) NSString *addressState DEPRECATED_MSG_ATTRIBUTE("Use address.state"); +@property (nonatomic, nullable, readonly) NSString *addressState DEPRECATED_MSG_ATTRIBUTE("Use address.state"); /** The zip code of the cardholder's address */ -@property (nonatomic, copy, nullable, readonly) NSString *addressZip DEPRECATED_MSG_ATTRIBUTE("Use address.postalCode"); +@property (nonatomic, nullable, readonly) NSString *addressZip DEPRECATED_MSG_ATTRIBUTE("Use address.postalCode"); /** The country of the cardholder's address */ -@property (nonatomic, copy, nullable, readonly) NSString *addressCountry DEPRECATED_MSG_ATTRIBUTE("Use address.country"); +@property (nonatomic, nullable, readonly) NSString *addressCountry DEPRECATED_MSG_ATTRIBUTE("Use address.country"); /** Create an STPCard from a Stripe API response. @param cardID The Stripe ID of the card, e.g. `card_185iQx4JYtv6MPZKfcuXwkOx` - @param brand The brand of the card (e.g. "Visa". To obtain this enum value from a string, use `[STPCardBrand brandFromString:string]`; + @param brand The brand of the card (e.g. "Visa". To obtain this enum value + from a string, use `[STPCardBrand brandFromString:string]`; @param last4 The last 4 digits of the card, e.g. 4242 @param expMonth The card's expiration month, 1-indexed (i.e. 1 = January) @param expYear The card's expiration year - @param funding The card's funding type (credit, debit, or prepaid). To obtain this enum value from a string, use `[STPCardBrand fundingFromString:string]`. + @param funding The card's funding type (credit, debit, or prepaid). To obtain + this enum value from a string, use `[STPCardBrand fundingFromString:string]`. @return an STPCard instance populated with the provided values. */ @@ -160,20 +169,28 @@ typedef NS_ENUM(NSInteger, STPCardFundingType) { funding:(STPCardFundingType)funding DEPRECATED_MSG_ATTRIBUTE("You cannot directly instantiate an STPCard. You should only use one that has been returned from an STPAPIClient callback."); /** - This parses a string representing a card's funding type into the appropriate `STPCardFundingType` enum value, i.e. `[STPCard fundingFromString:@"prepaid"] == STPCardFundingTypePrepaid`. + This parses a string representing a card's funding type into the appropriate + `STPCardFundingType` enum value, + i.e. `[STPCard fundingFromString:@"prepaid"] == STPCardFundingTypePrepaid`. - @param string a string representing the card's funding type as returned from the Stripe API + @param string a string representing the card's funding type as returned from + the Stripe API - @return an enum value mapped to that string. If the string is unrecognized, returns `STPCardFundingTypeOther`. + @return an enum value mapped to that string. If the string is unrecognized, + returns `STPCardFundingTypeOther`. */ + (STPCardFundingType)fundingFromString:(NSString *)string DEPRECATED_ATTRIBUTE; /** - This parses a string representing a card's brand into the appropriate STPCardBrand enum value, i.e. `[STPCard brandFromString:@"American Express"] == STPCardBrandAmex` + This parses a string representing a card's brand into the appropriate + STPCardBrand enum value, + i.e. `[STPCard brandFromString:@"American Express"] == STPCardBrandAmex` - @param string a string representing the card's brand as returned from the Stripe API + @param string a string representing the card's brand as returned from + the Stripe API - @return an enum value mapped to that string. If the string is unrecognized, returns STPCardBrandUnknown. + @return an enum value mapped to that string. If the string is unrecognized, + returns STPCardBrandUnknown. */ + (STPCardBrand)brandFromString:(NSString *)string DEPRECATED_ATTRIBUTE; diff --git a/Stripe/STPCard.m b/Stripe/STPCard.m index 696b63f2588..63a36323f36 100644 --- a/Stripe/STPCard.m +++ b/Stripe/STPCard.m @@ -13,20 +13,23 @@ #import "STPImageLibrary+Private.h" #import "STPImageLibrary.h" +NS_ASSUME_NONNULL_BEGIN + @interface STPCard () -@property (nonatomic, nonnull) NSString *stripeID; -@property (nonatomic, readwrite) NSString *name; -@property (nonatomic, readwrite) NSString *last4; -@property (nonatomic, readwrite) NSString *dynamicLast4; -@property (nonatomic, readwrite) STPCardBrand brand; -@property (nonatomic, readwrite) STPCardFundingType funding; -@property (nonatomic, readwrite) NSString *country; -@property (nonatomic, readwrite) NSString *currency; -@property (nonatomic, readwrite) NSUInteger expMonth; -@property (nonatomic, readwrite) NSUInteger expYear; -@property (nonatomic, readwrite, nonnull, strong) STPAddress *address; -@property (nonatomic, readwrite, nonnull, copy) NSDictionary *allResponseFields; +@property (nonatomic, copy) NSString *stripeID; + +@property (nonatomic, copy, nullable, readwrite) NSString *name; +@property (nonatomic, copy, readwrite) NSString *last4; +@property (nonatomic, copy, nullable, readwrite) NSString *dynamicLast4; +@property (nonatomic, assign, readwrite) STPCardBrand brand; +@property (nonatomic, assign, readwrite) STPCardFundingType funding; +@property (nonatomic, copy, nullable, readwrite) NSString *country; +@property (nonatomic, copy, nullable, readwrite) NSString *currency; +@property (nonatomic, assign, readwrite) NSUInteger expMonth; +@property (nonatomic, assign, readwrite) NSUInteger expYear; +@property (nonatomic, strong, readwrite) STPAddress *address; +@property (nonatomic, copy, readwrite) NSDictionary *allResponseFields; // See STPCard+Private.h @@ -107,7 +110,7 @@ - (BOOL)isApplePayCard { #pragma mark - Equality -- (BOOL)isEqual:(id)other { +- (BOOL)isEqual:(nullable id)other { return [self isEqualToCard:other]; } @@ -115,7 +118,7 @@ - (NSUInteger)hash { return [self.stripeID hash]; } -- (BOOL)isEqualToCard:(STPCard *)other { +- (BOOL)isEqualToCard:(nullable STPCard *)other { if (self == other) { return YES; } @@ -168,7 +171,7 @@ + (NSArray *)requiredFields { return @[@"id", @"last4", @"brand", @"exp_month", @"exp_year"]; } -+ (instancetype)decodedObjectFromAPIResponse:(NSDictionary *)response { ++ (nullable instancetype)decodedObjectFromAPIResponse:(nullable NSDictionary *)response { NSDictionary *dict = [response stp_dictionaryByRemovingNullsValidatingRequiredFields:[self requiredFields]]; if (!dict) { return nil; @@ -247,28 +250,30 @@ - (NSString *)cardId { return self.stripeID; } -- (NSString *)addressLine1 { +- (nullable NSString *)addressLine1 { return self.address.line1; } -- (NSString *)addressLine2 { +- (nullable NSString *)addressLine2 { return self.address.line2; } -- (NSString *)addressZip { +- (nullable NSString *)addressZip { return self.address.postalCode; } -- (NSString *)addressCity { +- (nullable NSString *)addressCity { return self.address.city; } -- (NSString *)addressState { +- (nullable NSString *)addressState { return self.address.state; } -- (NSString *)addressCountry { +- (nullable NSString *)addressCountry { return self.address.country; } @end + +NS_ASSUME_NONNULL_END From 21e20b845363ec632615f98fd86c0db0fdbdd0f2 Mon Sep 17 00:00:00 2001 From: Brian Dorfman Date: Wed, 2 Aug 2017 15:27:04 -0700 Subject: [PATCH 3/4] Make changelog more declarative. --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index a914b08883d..902501916dc 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,5 @@ == X.Y.Z 2017-XX-YY -* Many methods on `STPCard` and `STPCardParams` have been deprecated or made readonly to bring card objects more in line with the rest of the API. See MIGRATING for further details. +* Fixes methods on `STPCard` and `STPCardParams` to bring card objects more in line with the rest of the API. See MIGRATING for further details. * Adds nullability annotations to `STPPaymentMethod` protocol * Improves the `[STPAPIResponseDecodable allResponseFields]` by removing all instances of `[NSNull null]` including ones that are nested. See MIGRATING.md. From 6cd1f329fcb34d18f9540106d9ad2840c783072a Mon Sep 17 00:00:00 2001 From: Brian Dorfman Date: Wed, 2 Aug 2017 16:22:04 -0700 Subject: [PATCH 4/4] Fix test --- Tests/Tests/STPSourceParamsTest.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/Tests/STPSourceParamsTest.m b/Tests/Tests/STPSourceParamsTest.m index 37bbf7eb369..3f64a32e17c 100644 --- a/Tests/Tests/STPSourceParamsTest.m +++ b/Tests/Tests/STPSourceParamsTest.m @@ -193,8 +193,8 @@ - (void)testCardParamsWithCard { XCTAssertEqualObjects(sourceAddress[@"line2"], card.address.line2); XCTAssertEqualObjects(sourceAddress[@"city"], card.address.city); XCTAssertEqualObjects(sourceAddress[@"state"], card.address.state); - XCTAssertEqualObjects(sourceAddress[@"postal_code"], card.address.country); - XCTAssertEqualObjects(sourceAddress[@"country"], card.address.postalCode); + XCTAssertEqualObjects(sourceAddress[@"postal_code"], card.address.postalCode); + XCTAssertEqualObjects(sourceAddress[@"country"], card.address.country); }