Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an option to STPPaymentConfiguration to filter the country list #1327

Merged
merged 3 commits into from
Sep 9, 2019
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Stripe/PublicHeaders/STPPaymentConfiguration.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,15 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (nonatomic, assign, readwrite) STPShippingType shippingType;

/**
The set of countries supported when entering an address. This property accepts
a set of ISO 2-character country codes.

The default value is nil, which will display all known countries. Setting this
property will limit the available countries to your selected set.
*/
@property (nonatomic, copy, nullable, readwrite) NSSet<NSString *> *availableCountries;
davidme-stripe marked this conversation as resolved.
Show resolved Hide resolved

/**
The name of your company, for displaying to the user during payment flows. For
example, when using Apple Pay, the payment sheet's final line item will read
Expand Down
2 changes: 1 addition & 1 deletion Stripe/STPAddCardViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ - (void)commonInitWithConfiguration:(STPPaymentConfiguration *)configuration {
_shippingAddress = nil;
_hasUsedShippingAddress = NO;
_apiClient = [[STPAPIClient alloc] initWithConfiguration:configuration];
_addressViewModel = [[STPAddressViewModel alloc] initWithRequiredBillingFields:configuration.requiredBillingAddressFields];
_addressViewModel = [[STPAddressViewModel alloc] initWithRequiredBillingFields:configuration.requiredBillingAddressFields availableCountries:configuration.availableCountries];
_addressViewModel.delegate = self;

self.title = STPLocalizedString(@"Add a Card", @"Title for Add a Card view");
Expand Down
1 change: 1 addition & 0 deletions Stripe/STPAddressFieldTableViewCell.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ typedef NS_ENUM(NSInteger, STPAddressFieldType) {
- (void)addressFieldTableViewCellDidReturn:(STPAddressFieldTableViewCell *)cell;
- (void)addressFieldTableViewCellDidEndEditing:(STPAddressFieldTableViewCell *)cell;
@property (nonatomic, copy) NSString *addressFieldTableViewCountryCode;
@property (nonatomic, copy) NSSet<NSString *> *availableCountries;

@end

Expand Down
18 changes: 16 additions & 2 deletions Stripe/STPAddressFieldTableViewCell.m
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,18 @@ - (instancetype)initWithType:(STPAddressFieldType)type
_inputAccessoryToolbar = toolbar;

NSString *countryCode = [[NSLocale autoupdatingCurrentLocale] objectForKey:NSLocaleCountryCode];
NSMutableArray *otherCountryCodes = [[NSLocale ISOCountryCodes] mutableCopy];
NSMutableArray *otherCountryCodes = [[self.delegate.availableCountries allObjects] mutableCopy];
if (otherCountryCodes == nil) {
otherCountryCodes = [[NSLocale ISOCountryCodes] mutableCopy];
}
if ([otherCountryCodes containsObject:countryCode]) {
// Remove the current country code to re-add it once we sort the list.
[otherCountryCodes removeObject:countryCode];
} else {
// If it isn't in the list (if we've been configured to not show that country), don't re-add it.
countryCode = nil;
}
NSLocale *locale = [NSLocale currentLocale];
[otherCountryCodes removeObject:countryCode];
[otherCountryCodes sortUsingComparator:^NSComparisonResult(NSString *code1, NSString *code2) {
NSString *localeID1 = [NSLocale localeIdentifierFromComponents:@{NSLocaleCountryCode: code1}];
NSString *localeID2 = [NSLocale localeIdentifierFromComponents:@{NSLocaleCountryCode: code2}];
Expand Down Expand Up @@ -179,6 +188,11 @@ - (void)updateTextFieldsAndCaptions {
self.textField.keyboardType = UIKeyboardTypeDefault;
// Don't set textContentType for Country, because we don't want iOS to skip the UIPickerView for input
self.textField.inputView = self.countryPickerView;

// If we're being set directly to a country we don't allow, add it to the allowed list
if (![self.countryCodes containsObject:self.contents] && [[NSLocale ISOCountryCodes] containsObject:self.contents]) {
self.countryCodes = [self.countryCodes arrayByAddingObject:self.contents];
}
NSInteger index = [self.countryCodes indexOfObject:self.contents];
if (index == NSNotFound) {
self.textField.text = @"";
Expand Down
3 changes: 3 additions & 0 deletions Stripe/STPAddressViewModel.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,13 @@
@property (nonatomic, readonly) NSArray<STPAddressFieldTableViewCell *> *addressCells;
@property (nonatomic, weak) id<STPAddressViewModelDelegate>delegate;
@property (nonatomic) STPAddress *address;
@property (nonatomic, copy, readwrite) NSSet<NSString *> *availableCountries;
@property (nonatomic, readonly) BOOL isValid;

- (instancetype)initWithRequiredBillingFields:(STPBillingAddressFields)requiredBillingAddressFields;
- (instancetype)initWithRequiredShippingFields:(NSSet<STPContactField> *)requiredShippingAddressFields;
- (instancetype)initWithRequiredBillingFields:(STPBillingAddressFields)requiredBillingAddressFields availableCountries:(NSSet<NSString *> *)availableCountries;
davidme-stripe marked this conversation as resolved.
Show resolved Hide resolved
- (instancetype)initWithRequiredShippingFields:(NSSet<STPContactField> *)requiredShippingAddressFields availableCountries:(NSSet<NSString *> *)availableCountries;
- (STPAddressFieldTableViewCell *)cellAtIndex:(NSInteger)index;

@end
14 changes: 12 additions & 2 deletions Stripe/STPAddressViewModel.m
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@ @interface STPAddressViewModel()<STPAddressFieldTableViewCellDelegate>
@implementation STPAddressViewModel

@synthesize addressFieldTableViewCountryCode = _addressFieldTableViewCountryCode;
@synthesize availableCountries = _availableCountries;

- (instancetype)initWithRequiredBillingFields:(STPBillingAddressFields)requiredBillingAddressFields {
- (instancetype)initWithRequiredBillingFields:(STPBillingAddressFields)requiredBillingAddressFields availableCountries:(NSSet<NSString *> *)availableCountries {
self = [super init];
if (self) {
_isBillingAddress = YES;
_availableCountries = [availableCountries copy];
_requiredBillingAddressFields = requiredBillingAddressFields;
switch (requiredBillingAddressFields) {
case STPBillingAddressFieldsNone:
Expand Down Expand Up @@ -63,10 +65,11 @@ - (instancetype)initWithRequiredBillingFields:(STPBillingAddressFields)requiredB
return self;
}

- (instancetype)initWithRequiredShippingFields:(NSSet<STPContactField> *)requiredShippingAddressFields {
- (instancetype)initWithRequiredShippingFields:(NSSet<STPContactField> *)requiredShippingAddressFields availableCountries:(NSSet<NSString *> *)availableCountries {
self = [super init];
if (self) {
_isBillingAddress = NO;
_availableCountries = [availableCountries copy];
_requiredShippingAddressFields = requiredShippingAddressFields;
NSMutableArray *cells = [NSMutableArray new];
if ([requiredShippingAddressFields containsObject:STPContactFieldName]) {
Expand Down Expand Up @@ -103,6 +106,13 @@ - (instancetype)initWithRequiredShippingFields:(NSSet<STPContactField> *)require
return self;
}

- (instancetype)initWithRequiredBillingFields:(STPBillingAddressFields)requiredBillingAddressFields {
return [self initWithRequiredBillingFields:requiredBillingAddressFields availableCountries:nil];
}
- (instancetype)initWithRequiredShippingFields:(NSSet<STPContactField> *)requiredShippingAddressFields {
return [self initWithRequiredShippingFields:requiredShippingAddressFields availableCountries:nil];
}

- (void)commonInit {
_addressFieldTableViewCountryCode = [[NSLocale autoupdatingCurrentLocale] objectForKey:NSLocaleCountryCode];
[self updatePostalCodeCellIfNecessary];
Expand Down
2 changes: 2 additions & 0 deletions Stripe/STPPaymentConfiguration.m
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ - (NSString *)description {
[NSString stringWithFormat:@"requiredShippingAddressFields = %@", requiredShippingAddressFieldsDescription],
[NSString stringWithFormat:@"verifyPrefilledShippingAddress = %@", (self.verifyPrefilledShippingAddress) ? @"YES" : @"NO"],
[NSString stringWithFormat:@"shippingType = %@", shippingTypeDescription],
[NSString stringWithFormat:@"availableCountries = %@", _availableCountries],

// Additional configuration
[NSString stringWithFormat:@"companyName = %@", self.companyName],
Expand All @@ -143,6 +144,7 @@ - (id)copyWithZone:(__unused NSZone *)zone {
copy.companyName = self.companyName;
copy.appleMerchantIdentifier = self.appleMerchantIdentifier;
copy.canDeletePaymentOptions = self.canDeletePaymentOptions;
copy.availableCountries = self.availableCountries;
return copy;
}

Expand Down
2 changes: 1 addition & 1 deletion Stripe/STPShippingAddressViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ - (instancetype)initWithConfiguration:(STPPaymentConfiguration *)configuration
_selectedShippingMethod = selectedShippingMethod;
_billingAddress = prefilledInformation.billingAddress;
_hasUsedBillingAddress = NO;
_addressViewModel = [[STPAddressViewModel alloc] initWithRequiredShippingFields:configuration.requiredShippingAddressFields];
_addressViewModel = [[STPAddressViewModel alloc] initWithRequiredShippingFields:configuration.requiredShippingAddressFields availableCountries:configuration.availableCountries];
_addressViewModel.delegate = self;
if (shippingAddress != nil) {
_addressViewModel.address = shippingAddress;
Expand Down
3 changes: 3 additions & 0 deletions Tests/Tests/STPPaymentConfigurationTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ - (void)testCopyWithZone {
paymentConfigurationA.requiredBillingAddressFields = STPBillingAddressFieldsFull;
paymentConfigurationA.requiredShippingAddressFields = allFields;
paymentConfigurationA.verifyPrefilledShippingAddress = NO;
paymentConfigurationA.availableCountries = [NSSet setWithArray:@[@"US", @"CA", @"BT"]];
paymentConfigurationA.shippingType = STPShippingTypeDelivery;
paymentConfigurationA.companyName = @"companyName";
paymentConfigurationA.appleMerchantIdentifier = @"appleMerchantIdentifier";
Expand All @@ -123,6 +124,8 @@ - (void)testCopyWithZone {
XCTAssertEqual(paymentConfigurationB.shippingType, STPShippingTypeDelivery);
XCTAssertEqualObjects(paymentConfigurationB.companyName, @"companyName");
XCTAssertEqualObjects(paymentConfigurationB.appleMerchantIdentifier, @"appleMerchantIdentifier");
NSSet *availableCountries = [NSSet setWithArray:@[@"US", @"CA", @"BT"]];
XCTAssertEqualObjects(paymentConfigurationB.availableCountries, availableCountries);
XCTAssertEqual(paymentConfigurationA.canDeletePaymentOptions, paymentConfigurationB.canDeletePaymentOptions);
}

Expand Down
32 changes: 32 additions & 0 deletions Tests/Tests/STPShippingAddressViewControllerTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,38 @@ - (void)testPrefilledBillingAddress_removeAddress {
XCTAssertNoThrow([sut viewDidLoad]);
}

- (void)testPrefilledBillingAddress_addAddressWithLimitedCountries {
[NSLocale stp_setCurrentLocale:[NSLocale localeWithLocaleIdentifier:@"en_ZW"]];
// Zimbabwe does not require zip codes, while the default locale for tests (US) does
// Sanity checks
XCTAssertFalse([STPPostalCodeValidator postalCodeIsRequiredForCountryCode:@"ZW"]);
XCTAssertTrue([STPPostalCodeValidator postalCodeIsRequiredForCountryCode:@"US"]);
STPPaymentConfiguration *config = [STPFixtures paymentConfiguration];
config.requiredShippingAddressFields = [NSSet setWithObject:STPContactFieldPostalAddress];
config.availableCountries = [[NSSet alloc] initWithArray:@[@"CA", @"BT"]];

STPAddress *address = [STPAddress new];
address.name = @"John Smith Doe";
address.phone = @"8885551212";
address.email = @"[email protected]";
address.line1 = @"55 John St";
address.city = @"New York";
address.state = @"NY";
address.postalCode = @"10002";
address.country = @"US";

STPShippingAddressViewController *sut = [[STPShippingAddressViewController alloc] initWithConfiguration:config
theme:[STPTheme defaultTheme]
currency:nil
shippingAddress:address
selectedShippingMethod:nil
prefilledInformation:nil];

XCTAssertNoThrow([sut loadView]);
XCTAssertNoThrow([sut viewDidLoad]);
[NSLocale stp_resetCurrentLocale];
}

- (void)testPrefilledBillingAddress_addAddress {
[NSLocale stp_setCurrentLocale:[NSLocale localeWithLocaleIdentifier:@"en_ZW"]];
// Zimbabwe does not require zip codes, while the default locale for tests (US) does
Expand Down