Skip to content

Commit

Permalink
Merge pull request #808 from stripe/joey/addMetadataAccessors
Browse files Browse the repository at this point in the history
Add `metadata` accessors
  • Loading branch information
bdorfman-stripe authored Oct 4, 2017
2 parents 2154ceb + 1a59452 commit da8b1de
Show file tree
Hide file tree
Showing 16 changed files with 119 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## 11.x.x 2017-XX-XX

* Restores `[STPCard brandFromString:]` method which was marked as deprecated in a recent version [#801](https://github.com/stripe/stripe-ios/pull/801)
* Adds `[STPBankAccount metadata]` and `[STPCard metadata]` read-only accessors and improves annotation for `[STPSource metadata]` [#808](https://github.com/stripe/stripe-ios/pull/808)

## 11.3.0 2017-09-13
* Adds support for creating `STPSourceParams` for P24 source [#779](https://github.com/stripe/stripe-ios/pull/779)
Expand Down
2 changes: 2 additions & 0 deletions Stripe/NSDictionary+Stripe.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ NS_ASSUME_NONNULL_BEGIN

- (NSDictionary *)stp_dictionaryByRemovingNulls;

- (NSDictionary<NSString *, NSString *> *)stp_dictionaryByRemovingNonStrings;

@end

NS_ASSUME_NONNULL_END
Expand Down
18 changes: 18 additions & 0 deletions Stripe/NSDictionary+Stripe.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

#import "NSArray+Stripe.h"

NS_ASSUME_NONNULL_BEGIN

@implementation NSDictionary (Stripe)

- (nullable NSDictionary *)stp_dictionaryByRemovingNullsValidatingRequiredFields:(NSArray *)requiredFields {
Expand Down Expand Up @@ -50,6 +52,22 @@ - (NSDictionary *)stp_dictionaryByRemovingNulls {
return [result copy];
}

- (NSDictionary<NSString *, NSString *> *)stp_dictionaryByRemovingNonStrings {
NSMutableDictionary<NSString *, NSString *> *result = [[NSMutableDictionary alloc] init];

[self enumerateKeysAndObjectsUsingBlock:^(id key, id obj, __unused BOOL *stop) {
if ([key isKindOfClass:[NSString class]] && [obj isKindOfClass:[NSString class]]) {
// Save valid key/value pair
result[key] = obj;
}
}];

// Make immutable copy
return [result copy];
}

@end

void linkNSDictionaryCategory(void){}

NS_ASSUME_NONNULL_END
7 changes: 7 additions & 0 deletions Stripe/PublicHeaders/STPBankAccount.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,13 @@ typedef NS_ENUM(NSInteger, STPBankAccountStatus) {
*/
@property (nonatomic, nullable, readonly) NSString *fingerprint;

/**
A set of key/value pairs associated with the bank account object.
@see https://stripe.com/docs/api#metadata
*/
@property (nonatomic, copy, nullable, readonly) NSDictionary<NSString *, NSString *> *metadata;

/**
The validation status of the bank account. @see STPBankAccountStatus
*/
Expand Down
7 changes: 7 additions & 0 deletions Stripe/PublicHeaders/STPCard.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,13 @@ typedef NS_ENUM(NSInteger, STPCardFundingType) {
*/
@property (nonatomic, nullable, readonly) NSString *currency;

/**
A set of key/value pairs associated with the card object.
@see https://stripe.com/docs/api#metadata
*/
@property (nonatomic, copy, nullable, readonly) NSDictionary<NSString *, NSString *> *metadata;

/**
Returns a string representation for the provided card brand;
i.e. `[NSString stringFromBrand:STPCardBrandVisa] == @"Visa"`.
Expand Down
4 changes: 3 additions & 1 deletion Stripe/PublicHeaders/STPSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,10 @@ NS_ASSUME_NONNULL_BEGIN

/**
A set of key/value pairs associated with the source object.
@see https://stripe.com/docs/api#metadata
*/
@property (nonatomic, nullable, readonly) NSDictionary *metadata;
@property (nonatomic, copy, nullable, readonly) NSDictionary<NSString *, NSString *> *metadata;

/**
Information about the owner of the payment instrument.
Expand Down
3 changes: 3 additions & 0 deletions Stripe/STPBankAccount.m
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ @interface STPBankAccount ()
@property (nonatomic, copy, readwrite) NSString *bankName;
@property (nonatomic, copy, nullable, readwrite) NSString *accountHolderName;
@property (nonatomic, assign, readwrite) STPBankAccountHolderType accountHolderType;
@property (nonatomic, copy, nullable, readwrite) NSDictionary<NSString *, NSString *> *metadata;
@property (nonatomic, copy, nullable, readwrite) NSString *fingerprint;
@property (nonatomic, assign, readwrite) STPBankAccountStatus status;
@property (nonatomic, copy, readwrite) NSDictionary *allResponseFields;
Expand Down Expand Up @@ -101,6 +102,7 @@ - (NSString *)description {
[NSString stringWithFormat:@"country = %@", self.country],
[NSString stringWithFormat:@"currency = %@", self.currency],
[NSString stringWithFormat:@"fingerprint = %@", self.fingerprint],
[NSString stringWithFormat:@"metadata = %@", (self.metadata) ? @"<redacted>" : nil],
[NSString stringWithFormat:@"status = %@", [self.class stringFromStatus:self.status]],

// Owner details
Expand Down Expand Up @@ -144,6 +146,7 @@ + (nullable instancetype)decodedObjectFromAPIResponse:(nullable NSDictionary *)r
bankAccount.country = dict[@"country"];
bankAccount.currency = dict[@"currency"];
bankAccount.fingerprint = dict[@"fingerprint"];
bankAccount.metadata = [dict[@"metadata"] stp_dictionaryByRemovingNonStrings];
bankAccount.status = [self statusFromString:dict[@"status"]];

// Owner details
Expand Down
3 changes: 3 additions & 0 deletions Stripe/STPCard.m
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ @interface STPCard ()
@property (nonatomic, assign, readwrite) NSUInteger expMonth;
@property (nonatomic, assign, readwrite) NSUInteger expYear;
@property (nonatomic, strong, readwrite) STPAddress *address;
@property (nonatomic, copy, nullable, readwrite) NSDictionary<NSString *, NSString *> *metadata;
@property (nonatomic, copy, readwrite) NSDictionary *allResponseFields;

// See STPCard+Private.h
Expand Down Expand Up @@ -152,6 +153,7 @@ - (NSString *)description {
[NSString stringWithFormat:@"currency = %@", self.currency],
[NSString stringWithFormat:@"dynamicLast4 = %@", self.dynamicLast4],
[NSString stringWithFormat:@"isApplePayCard = %@", (self.isApplePayCard) ? @"YES" : @"NO"],
[NSString stringWithFormat:@"metadata = %@", (self.metadata) ? @"<redacted>" : nil],

// Cardholder details
[NSString stringWithFormat:@"name = %@", (self.name) ? @"<redacted>" : nil],
Expand Down Expand Up @@ -196,6 +198,7 @@ + (nullable instancetype)decodedObjectFromAPIResponse:(nullable NSDictionary *)r
card.currency = dict[@"currency"];
card.expMonth = [dict[@"exp_month"] intValue];
card.expYear = [dict[@"exp_year"] intValue];
card.metadata = [dict[@"metadata"] stp_dictionaryByRemovingNonStrings];

card.address.name = card.name;
card.address.line1 = dict[@"address_line1"];
Expand Down
4 changes: 2 additions & 2 deletions Stripe/STPSource.m
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ @interface STPSource ()
@property (nonatomic, nullable) NSString *currency;
@property (nonatomic) STPSourceFlow flow;
@property (nonatomic) BOOL livemode;
@property (nonatomic, nullable) NSDictionary *metadata;
@property (nonatomic, copy, nullable, readwrite) NSDictionary<NSString *, NSString *> *metadata;
@property (nonatomic, nullable) STPSourceOwner *owner;
@property (nonatomic, nullable) STPSourceReceiver *receiver;
@property (nonatomic, nullable) STPSourceRedirect *redirect;
Expand Down Expand Up @@ -230,7 +230,7 @@ + (instancetype)decodedObjectFromAPIResponse:(NSDictionary *)response {
source.currency = dict[@"currency"];
source.flow = [[self class] flowFromString:dict[@"flow"]];
source.livemode = [dict[@"livemode"] boolValue];
source.metadata = dict[@"metadata"];
source.metadata = [dict[@"metadata"] stp_dictionaryByRemovingNonStrings];
source.owner = [STPSourceOwner decodedObjectFromAPIResponse:dict[@"owner"]];
source.receiver = [STPSourceReceiver decodedObjectFromAPIResponse:dict[@"receiver"]];
source.redirect = [STPSourceRedirect decodedObjectFromAPIResponse:dict[@"redirect"]];
Expand Down
4 changes: 3 additions & 1 deletion Tests/Tests/BankAccount.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
"default_for_currency": false,
"fingerprint": "1JWtPxqbdX5Gamtc",
"last4": "6789",
"metadata": {},
"metadata": {
"order_id": "6735"
},
"routing_number": "110000000",
"status": "new"
}
4 changes: 3 additions & 1 deletion Tests/Tests/BitcoinSource.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
"currency": "usd",
"flow": "receiver",
"livemode": false,
"metadata": {},
"metadata": {
"order_id": "6735"
},
"owner": {
"address": {
"city": "Pittsburgh",
Expand Down
4 changes: 3 additions & 1 deletion Tests/Tests/Card.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
"fingerprint": "Xt5EWLLDS7FJjR1c",
"funding": "credit",
"last4": "4242",
"metadata": {},
"metadata": {
"order_id": "6735"
},
"name": "Jane Austen",
"tokenization_method": null
}
61 changes: 61 additions & 0 deletions Tests/Tests/NSDictionary+StripeTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ @interface NSDictionary_StripeTest : XCTestCase

@implementation NSDictionary_StripeTest

#pragma mark - dictionaryByRemovingNullsValidatingRequiredFields

- (void)test_dictionaryByRemovingNullsValidatingRequiredFields_removesNullsDeeply {
NSDictionary *dictionary = @{
@"id": @"card_123",
Expand Down Expand Up @@ -102,5 +104,64 @@ - (void)test_dictionaryByRemovingNullsValidatingRequiredFields_missingRequiredFi
XCTAssertNil([dictionary stp_dictionaryByRemovingNullsValidatingRequiredFields:requiredFields]);
}

#pragma mark - dictionaryByRemovingNonStrings

- (void)test_dictionaryByRemovingNonStrings_basicCases {
NSDictionary *dictionary;
NSDictionary *expected;
NSDictionary *result;

// Empty dictionary
dictionary = @{};
expected = @{};
result = [dictionary stp_dictionaryByRemovingNonStrings];
XCTAssertEqualObjects(result, expected);

// Regular case
dictionary = @{
@"user": @"user_123",
@"nicknames": @"John, Johnny",
};
expected = @{
@"user": @"user_123",
@"nicknames": @"John, Johnny",
};
result = [dictionary stp_dictionaryByRemovingNonStrings];
XCTAssertEqualObjects(result, expected);

// Strips non-NSString keys and values
dictionary = @{
@"user": @"user_123",
@"nicknames": @"John, Johnny",
@"profiles": [NSNull null],
[NSNull null]: @"San Francisco, CA",
[NSNull null]: [NSNull null],
@"age": @(21),
@(21): @"age",
@(21): @(21),
@"fees": @{
@"plan": @"monthly",
},
@"visits": @[
@"january",
@"february",
],
};
expected = @{
@"user": @"user_123",
@"nicknames": @"John, Johnny",
};
result = [dictionary stp_dictionaryByRemovingNonStrings];
XCTAssertEqualObjects(result, expected);
}

- (void)test_dictionaryByRemovingNonStrings_returnsImmutableCopy {
NSDictionary *dictionary = @{@"user": @"user_123"};
NSDictionary *result = [dictionary stp_dictionaryByRemovingNonStrings];

XCTAssert(result);
XCTAssertNotEqual(result, dictionary);
XCTAssertFalse([result isKindOfClass:[NSMutableDictionary class]]);
}

@end
1 change: 1 addition & 0 deletions Tests/Tests/STPBankAccountTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ - (void)testDecodedObjectFromAPIResponseMapping {
XCTAssertEqualObjects(bankAccount.currency, @"usd");
XCTAssertEqualObjects(bankAccount.fingerprint, @"1JWtPxqbdX5Gamtc");
XCTAssertEqualObjects(bankAccount.last4, @"6789");
XCTAssertEqualObjects(bankAccount.metadata, @{@"order_id": @"6735"});
XCTAssertEqualObjects(bankAccount.routingNumber, @"110000000");
XCTAssertEqual(bankAccount.status, STPBankAccountStatusNew);

Expand Down
1 change: 1 addition & 0 deletions Tests/Tests/STPCardTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ - (void)testDecodedObjectFromAPIResponseMapping {
XCTAssertEqual(card.expYear, (NSUInteger)2017);
XCTAssertEqual(card.funding, STPCardFundingTypeCredit);
XCTAssertEqualObjects(card.last4, @"4242");
XCTAssertEqualObjects(card.metadata, @{@"order_id": @"6735"});
XCTAssertEqualObjects(card.name, @"Jane Austen");

XCTAssertNotEqual(card.allResponseFields, response);
Expand Down
1 change: 1 addition & 0 deletions Tests/Tests/STPSourceTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ - (void)testDecodedObjectFromAPIResponseMapping {
XCTAssertEqualObjects(source.currency, @"usd");
XCTAssertEqual(source.flow, STPSourceFlowReceiver);
XCTAssertFalse(source.livemode);
XCTAssertEqualObjects(source.metadata, @{@"order_id": @"6735"});
XCTAssert(source.owner); // STPSourceOwnerTest
XCTAssert(source.receiver); // STPSourceReceiverTest
XCTAssertEqual(source.status, STPSourceStatusPending);
Expand Down

0 comments on commit da8b1de

Please sign in to comment.