Adds support for Contacts framework
If you are on the appropriate ios version, does work using CNContact or PKContact in places instead of ABAddressRef
This commit is contained in:
parent
32d77727a2
commit
0e38aae137
|
@ -7,6 +7,7 @@ Pod::Spec.new do |s|
|
||||||
s.authors = { 'Jack Flintermann' => 'jack@stripe.com', 'Stripe' => 'support+github@stripe.com' }
|
s.authors = { 'Jack Flintermann' => 'jack@stripe.com', 'Stripe' => 'support+github@stripe.com' }
|
||||||
s.source = { :git => 'https://github.com/stripe/stripe-ios.git', :tag => "v#{s.version}" }
|
s.source = { :git => 'https://github.com/stripe/stripe-ios.git', :tag => "v#{s.version}" }
|
||||||
s.frameworks = 'Foundation', 'Security', 'WebKit', 'PassKit', 'AddressBook'
|
s.frameworks = 'Foundation', 'Security', 'WebKit', 'PassKit', 'AddressBook'
|
||||||
|
s.weak_frameworks = 'Contacts'
|
||||||
s.requires_arc = true
|
s.requires_arc = true
|
||||||
s.platform = :ios
|
s.platform = :ios
|
||||||
s.ios.deployment_target = '8.0'
|
s.ios.deployment_target = '8.0'
|
||||||
|
|
|
@ -596,6 +596,7 @@
|
||||||
F1510BBF1D5A8146000731AD /* stp_card_jcb_template.png in Resources */ = {isa = PBXBuildFile; fileRef = F1510BBC1D5A8146000731AD /* stp_card_jcb_template.png */; };
|
F1510BBF1D5A8146000731AD /* stp_card_jcb_template.png in Resources */ = {isa = PBXBuildFile; fileRef = F1510BBC1D5A8146000731AD /* stp_card_jcb_template.png */; };
|
||||||
F1510BC21D5A8146000731AD /* stp_card_jcb_template@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F1510BBD1D5A8146000731AD /* stp_card_jcb_template@2x.png */; };
|
F1510BC21D5A8146000731AD /* stp_card_jcb_template@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F1510BBD1D5A8146000731AD /* stp_card_jcb_template@2x.png */; };
|
||||||
F1510BC51D5A8146000731AD /* stp_card_jcb_template@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = F1510BBE1D5A8146000731AD /* stp_card_jcb_template@3x.png */; };
|
F1510BC51D5A8146000731AD /* stp_card_jcb_template@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = F1510BBE1D5A8146000731AD /* stp_card_jcb_template@3x.png */; };
|
||||||
|
F15232311EA93E6800D65C67 /* Contacts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F15232301EA93E6800D65C67 /* Contacts.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
|
||||||
F15675401DB544D3004468E3 /* STPAddCardViewControllerLocalizationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F156753F1DB544D3004468E3 /* STPAddCardViewControllerLocalizationTests.m */; };
|
F15675401DB544D3004468E3 /* STPAddCardViewControllerLocalizationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F156753F1DB544D3004468E3 /* STPAddCardViewControllerLocalizationTests.m */; };
|
||||||
F15AC18E1DBA9CA90009EADE /* FBSnapshotTestCase.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F15AC18D1DBA9CA90009EADE /* FBSnapshotTestCase.framework */; };
|
F15AC18E1DBA9CA90009EADE /* FBSnapshotTestCase.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F15AC18D1DBA9CA90009EADE /* FBSnapshotTestCase.framework */; };
|
||||||
F15AC1901DBA9CC60009EADE /* FBSnapshotTestCase.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = F15AC18D1DBA9CA90009EADE /* FBSnapshotTestCase.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
F15AC1901DBA9CC60009EADE /* FBSnapshotTestCase.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = F15AC18D1DBA9CA90009EADE /* FBSnapshotTestCase.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
|
@ -1048,6 +1049,7 @@
|
||||||
F1510BBC1D5A8146000731AD /* stp_card_jcb_template.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = stp_card_jcb_template.png; sourceTree = "<group>"; };
|
F1510BBC1D5A8146000731AD /* stp_card_jcb_template.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = stp_card_jcb_template.png; sourceTree = "<group>"; };
|
||||||
F1510BBD1D5A8146000731AD /* stp_card_jcb_template@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "stp_card_jcb_template@2x.png"; sourceTree = "<group>"; };
|
F1510BBD1D5A8146000731AD /* stp_card_jcb_template@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "stp_card_jcb_template@2x.png"; sourceTree = "<group>"; };
|
||||||
F1510BBE1D5A8146000731AD /* stp_card_jcb_template@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "stp_card_jcb_template@3x.png"; sourceTree = "<group>"; };
|
F1510BBE1D5A8146000731AD /* stp_card_jcb_template@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "stp_card_jcb_template@3x.png"; sourceTree = "<group>"; };
|
||||||
|
F15232301EA93E6800D65C67 /* Contacts.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Contacts.framework; path = System/Library/Frameworks/Contacts.framework; sourceTree = SDKROOT; };
|
||||||
F156753F1DB544D3004468E3 /* STPAddCardViewControllerLocalizationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STPAddCardViewControllerLocalizationTests.m; sourceTree = "<group>"; };
|
F156753F1DB544D3004468E3 /* STPAddCardViewControllerLocalizationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STPAddCardViewControllerLocalizationTests.m; sourceTree = "<group>"; };
|
||||||
F15AC18D1DBA9CA90009EADE /* FBSnapshotTestCase.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FBSnapshotTestCase.framework; path = Carthage/Build/iOS/FBSnapshotTestCase.framework; sourceTree = "<group>"; };
|
F15AC18D1DBA9CA90009EADE /* FBSnapshotTestCase.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FBSnapshotTestCase.framework; path = Carthage/Build/iOS/FBSnapshotTestCase.framework; sourceTree = "<group>"; };
|
||||||
F1852F911D80B6EC00367C86 /* STPStringUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STPStringUtils.h; sourceTree = "<group>"; };
|
F1852F911D80B6EC00367C86 /* STPStringUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STPStringUtils.h; sourceTree = "<group>"; };
|
||||||
|
@ -1109,11 +1111,12 @@
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
F1D64B2E1D87686E001CDB7C /* WebKit.framework in Frameworks */,
|
|
||||||
F116E94B1D83404D0026A52A /* AddressBook.framework in Frameworks */,
|
F116E94B1D83404D0026A52A /* AddressBook.framework in Frameworks */,
|
||||||
|
F15232311EA93E6800D65C67 /* Contacts.framework in Frameworks */,
|
||||||
F116E94C1D83405E0026A52A /* Foundation.framework in Frameworks */,
|
F116E94C1D83405E0026A52A /* Foundation.framework in Frameworks */,
|
||||||
04533E7D1A6877F400C7E52E /* PassKit.framework in Frameworks */,
|
04533E7D1A6877F400C7E52E /* PassKit.framework in Frameworks */,
|
||||||
F116E94D1D8340640026A52A /* Security.framework in Frameworks */,
|
F116E94D1D8340640026A52A /* Security.framework in Frameworks */,
|
||||||
|
F1D64B2E1D87686E001CDB7C /* WebKit.framework in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
@ -1451,6 +1454,7 @@
|
||||||
11C74B9A164043050071C2CA /* Frameworks */ = {
|
11C74B9A164043050071C2CA /* Frameworks */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
F15232301EA93E6800D65C67 /* Contacts.framework */,
|
||||||
C11B14961E8AE316000F760C /* OCMock.framework */,
|
C11B14961E8AE316000F760C /* OCMock.framework */,
|
||||||
F15AC18D1DBA9CA90009EADE /* FBSnapshotTestCase.framework */,
|
F15AC18D1DBA9CA90009EADE /* FBSnapshotTestCase.framework */,
|
||||||
F1D64B2D1D87686E001CDB7C /* WebKit.framework */,
|
F1D64B2D1D87686E001CDB7C /* WebKit.framework */,
|
||||||
|
|
|
@ -62,6 +62,20 @@ typedef void (^STPPaymentAuthorizationStatusCallback)(PKPaymentAuthorizationStat
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)paymentAuthorizationViewController:(__unused PKPaymentAuthorizationViewController *)controller
|
||||||
|
didSelectShippingContact:(PKContact *)contact
|
||||||
|
completion:(STPApplePayShippingAddressCompletionBlock)completion {
|
||||||
|
STPAddress *stpAddress = [[STPAddress alloc] initWithPKContact:contact];
|
||||||
|
self.onShippingAddressSelection(stpAddress, ^(STPShippingStatus status, NSArray<PKShippingMethod *>* shippingMethods, NSArray<PKPaymentSummaryItem*> *summaryItems) {
|
||||||
|
if (status == STPShippingStatusInvalid) {
|
||||||
|
completion(PKPaymentAuthorizationStatusInvalidShippingPostalAddress, shippingMethods, summaryItems);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
completion(PKPaymentAuthorizationStatusSuccess, shippingMethods, summaryItems);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
#pragma clang diagnostic ignored "-Wdeprecated"
|
#pragma clang diagnostic ignored "-Wdeprecated"
|
||||||
- (void)paymentAuthorizationViewController:(__unused PKPaymentAuthorizationViewController *)controller
|
- (void)paymentAuthorizationViewController:(__unused PKPaymentAuthorizationViewController *)controller
|
||||||
|
|
|
@ -6,21 +6,21 @@
|
||||||
// Copyright © 2016 Stripe, Inc. All rights reserved.
|
// Copyright © 2016 Stripe, Inc. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#define FAUXPAS_IGNORED_IN_FILE(...)
|
#define FAUXPAS_IGNORED_IN_METHOD(...)
|
||||||
FAUXPAS_IGNORED_IN_FILE(APIAvailability)
|
#define FAUXPAS_IGNORED_ON_LINE(...)
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <PassKit/PassKit.h>
|
||||||
|
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
#pragma clang diagnostic ignored "-Wdeprecated"
|
#pragma clang diagnostic ignored "-Wdeprecated"
|
||||||
#import <AddressBook/AddressBook.h>
|
#import <AddressBook/AddressBook.h>
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
#define FAUXPAS_IGNORED_IN_METHOD(...)
|
|
||||||
#define FAUXPAS_IGNORED_ON_LINE(...)
|
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
|
||||||
#import <PassKit/PassKit.h>
|
|
||||||
#import "STPAPIResponseDecodable.h"
|
#import "STPAPIResponseDecodable.h"
|
||||||
|
|
||||||
|
@class CNContact;
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -100,12 +100,16 @@ typedef NS_ENUM(NSUInteger, STPBillingAddressFields) {
|
||||||
- (instancetype)initWithABRecord:(ABRecordRef)record;
|
- (instancetype)initWithABRecord:(ABRecordRef)record;
|
||||||
- (ABRecordRef)ABRecordValue;
|
- (ABRecordRef)ABRecordValue;
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
- (PKContact *)PKContactValue NS_AVAILABLE_IOS(9.0);
|
|
||||||
|
- (instancetype)initWithPKContact:(PKContact *)contact NS_AVAILABLE_IOS(9_0); FAUXPAS_IGNORED_ON_LINE(APIAvailability);
|
||||||
|
- (PKContact *)PKContactValue NS_AVAILABLE_IOS(9_0); FAUXPAS_IGNORED_ON_LINE(APIAvailability);
|
||||||
|
|
||||||
|
- (instancetype)initWithCNContact:(CNContact *)contact NS_AVAILABLE_IOS(9_0); FAUXPAS_IGNORED_ON_LINE(APIAvailability);
|
||||||
|
|
||||||
- (BOOL)containsRequiredFields:(STPBillingAddressFields)requiredFields;
|
- (BOOL)containsRequiredFields:(STPBillingAddressFields)requiredFields;
|
||||||
- (BOOL)containsRequiredShippingAddressFields:(PKAddressField)requiredFields;
|
- (BOOL)containsRequiredShippingAddressFields:(PKAddressField)requiredFields;
|
||||||
|
|
||||||
+ (PKAddressField)applePayAddressFieldsFromBillingAddressFields:(STPBillingAddressFields)billingAddressFields; FAUXPAS_IGNORED_ON_LINE(APIAvailability);
|
+ (PKAddressField)applePayAddressFieldsFromBillingAddressFields:(STPBillingAddressFields)billingAddressFields;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
|
@ -24,14 +24,7 @@ FAUXPAS_IGNORED_IN_FILE(APIAvailability)
|
||||||
|
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
#pragma clang diagnostic ignored "-Wdeprecated"
|
#pragma clang diagnostic ignored "-Wdeprecated"
|
||||||
+ (NSDictionary *)parametersForPayment:(PKPayment *)payment {
|
+ (NSDictionary *)addressParamsFromABRecord:(ABRecordRef)billingAddress {
|
||||||
NSCAssert(payment != nil, @"Cannot create a token with a nil payment.");
|
|
||||||
NSString *paymentString =
|
|
||||||
[[NSString alloc] initWithData:payment.token.paymentData encoding:NSUTF8StringEncoding];
|
|
||||||
NSMutableDictionary *payload = [NSMutableDictionary new];
|
|
||||||
payload[@"pk_token"] = paymentString;
|
|
||||||
|
|
||||||
ABRecordRef billingAddress = payment.billingAddress;
|
|
||||||
if (billingAddress) {
|
if (billingAddress) {
|
||||||
NSMutableDictionary *params = [NSMutableDictionary dictionary];
|
NSMutableDictionary *params = [NSMutableDictionary dictionary];
|
||||||
|
|
||||||
|
@ -66,10 +59,58 @@ FAUXPAS_IGNORED_IN_FILE(APIAvailability)
|
||||||
params[@"address_country"] = country;
|
params[@"address_country"] = country;
|
||||||
}
|
}
|
||||||
CFRelease(dict);
|
CFRelease(dict);
|
||||||
payload[@"card"] = params;
|
|
||||||
}
|
}
|
||||||
CFRelease(addressValues);
|
CFRelease(addressValues);
|
||||||
}
|
}
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
|
+ (NSDictionary *)addressParamsFromPKContact:(PKContact *)billingContact {
|
||||||
|
if (billingContact) {
|
||||||
|
NSMutableDictionary *params = [NSMutableDictionary dictionary];
|
||||||
|
|
||||||
|
NSPersonNameComponents *nameComponents = billingContact.name;
|
||||||
|
if (nameComponents) {
|
||||||
|
params[@"name"] = [NSPersonNameComponentsFormatter localizedStringFromPersonNameComponents:nameComponents
|
||||||
|
style:NSPersonNameComponentsFormatterStyleDefault
|
||||||
|
options:(NSPersonNameComponentsFormatterOptions)0];
|
||||||
|
}
|
||||||
|
|
||||||
|
CNPostalAddress *address = billingContact.postalAddress;
|
||||||
|
if (address) {
|
||||||
|
params[@"address_line1"] = address.street;
|
||||||
|
params[@"address_city"] = address.city;
|
||||||
|
params[@"address_state"] = address.state;
|
||||||
|
params[@"address_zip"] = address.postalCode;
|
||||||
|
params[@"address_country"] = address.ISOCountryCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSDictionary *)parametersForPayment:(PKPayment *)payment {
|
||||||
|
NSCAssert(payment != nil, @"Cannot create a token with a nil payment.");
|
||||||
|
NSString *paymentString =
|
||||||
|
[[NSString alloc] initWithData:payment.token.paymentData encoding:NSUTF8StringEncoding];
|
||||||
|
NSMutableDictionary *payload = [NSMutableDictionary new];
|
||||||
|
payload[@"pk_token"] = paymentString;
|
||||||
|
|
||||||
|
if ([PKContact class]
|
||||||
|
&& [payment respondsToSelector:@selector(billingContact)]) {
|
||||||
|
payload[@"card"] = [self addressParamsFromPKContact:payment.billingContact];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
payload[@"card"] = [self addressParamsFromABRecord:payment.billingAddress];
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString *paymentInstrumentName = payment.token.paymentInstrumentName;
|
NSString *paymentInstrumentName = payment.token.paymentInstrumentName;
|
||||||
|
@ -93,7 +134,6 @@ FAUXPAS_IGNORED_IN_FILE(APIAvailability)
|
||||||
return payload;
|
return payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma clang diagnostic pop
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
|
@ -13,13 +13,18 @@
|
||||||
#import "STPPhoneNumberValidator.h"
|
#import "STPPhoneNumberValidator.h"
|
||||||
#import "STPPostalCodeValidator.h"
|
#import "STPPostalCodeValidator.h"
|
||||||
|
|
||||||
|
#import <Contacts/Contacts.h>
|
||||||
|
|
||||||
#define FAUXPAS_IGNORED_IN_FILE(...)
|
#define FAUXPAS_IGNORED_IN_FILE(...)
|
||||||
FAUXPAS_IGNORED_IN_FILE(APIAvailability)
|
FAUXPAS_IGNORED_IN_FILE(APIAvailability)
|
||||||
|
|
||||||
|
NSString *stringIfHasContentsElseNil(NSString *string);
|
||||||
|
|
||||||
@interface STPAddress ()
|
@interface STPAddress ()
|
||||||
|
|
||||||
@property (nonatomic, readwrite, nonnull, copy) NSDictionary *allResponseFields;
|
@property (nonatomic, readwrite, nonnull, copy) NSDictionary *allResponseFields;
|
||||||
|
@property (nonatomic, readwrite, nullable, copy) NSString *givenName;
|
||||||
|
@property (nonatomic, readwrite, nullable, copy) NSString *familyName;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation STPAddress
|
@implementation STPAddress
|
||||||
|
@ -126,6 +131,61 @@ FAUXPAS_IGNORED_IN_FILE(APIAvailability)
|
||||||
|
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
|
- (NSString *)sanitizedPhoneStringFromCNPhoneNumber:(CNPhoneNumber *)phoneNumber {
|
||||||
|
NSString *phone = phoneNumber.stringValue;
|
||||||
|
if (phone) {
|
||||||
|
phone = [STPCardValidator sanitizedNumericStringForString:phone];
|
||||||
|
}
|
||||||
|
|
||||||
|
return stringIfHasContentsElseNil(phone);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)initWithCNContact:(CNContact *)contact {
|
||||||
|
self = [super init];
|
||||||
|
if (self) {
|
||||||
|
|
||||||
|
_givenName = stringIfHasContentsElseNil(contact.givenName);
|
||||||
|
_familyName = stringIfHasContentsElseNil(contact.familyName);
|
||||||
|
_name = stringIfHasContentsElseNil([CNContactFormatter stringFromContact:contact
|
||||||
|
style:CNContactFormatterStyleFullName]);
|
||||||
|
_email = stringIfHasContentsElseNil([contact.emailAddresses firstObject].value);
|
||||||
|
_phone = [self sanitizedPhoneStringFromCNPhoneNumber:contact.phoneNumbers.firstObject.value];
|
||||||
|
|
||||||
|
|
||||||
|
[self setAddressFromCNPostalAddress:contact.postalAddresses.firstObject.value];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)initWithPKContact:(PKContact *)contact {
|
||||||
|
self = [super init];
|
||||||
|
if (self) {
|
||||||
|
NSPersonNameComponents *nameComponents = contact.name;
|
||||||
|
if (nameComponents) {
|
||||||
|
_givenName = stringIfHasContentsElseNil(nameComponents.givenName);
|
||||||
|
_familyName = stringIfHasContentsElseNil(nameComponents.familyName);
|
||||||
|
_name = stringIfHasContentsElseNil([NSPersonNameComponentsFormatter localizedStringFromPersonNameComponents:nameComponents
|
||||||
|
style:NSPersonNameComponentsFormatterStyleDefault
|
||||||
|
options:(NSPersonNameComponentsFormatterOptions)0]);
|
||||||
|
}
|
||||||
|
_email = stringIfHasContentsElseNil(contact.emailAddress);
|
||||||
|
_phone = [self sanitizedPhoneStringFromCNPhoneNumber:contact.phoneNumber];
|
||||||
|
[self setAddressFromCNPostalAddress:contact.postalAddress];
|
||||||
|
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setAddressFromCNPostalAddress:(CNPostalAddress *)address {
|
||||||
|
if (address) {
|
||||||
|
_line1 = stringIfHasContentsElseNil(address.street);
|
||||||
|
_city = stringIfHasContentsElseNil(address.city);
|
||||||
|
_state = stringIfHasContentsElseNil(address.state);
|
||||||
|
_postalCode = stringIfHasContentsElseNil(address.postalCode);
|
||||||
|
_country = stringIfHasContentsElseNil(address.ISOCountryCode.uppercaseString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (PKContact *)PKContactValue {
|
- (PKContact *)PKContactValue {
|
||||||
PKContact *contact = [PKContact new];
|
PKContact *contact = [PKContact new];
|
||||||
NSPersonNameComponents *name = [NSPersonNameComponents new];
|
NSPersonNameComponents *name = [NSPersonNameComponents new];
|
||||||
|
@ -145,19 +205,29 @@ FAUXPAS_IGNORED_IN_FILE(APIAvailability)
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)firstName {
|
- (NSString *)firstName {
|
||||||
NSArray<NSString *>*components = [self.name componentsSeparatedByString:@" "];
|
if (self.givenName) {
|
||||||
return [components firstObject];
|
return self.givenName;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
NSArray<NSString *>*components = [self.name componentsSeparatedByString:@" "];
|
||||||
|
return [components firstObject];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)lastName {
|
- (NSString *)lastName {
|
||||||
NSArray<NSString *>*components = [self.name componentsSeparatedByString:@" "];
|
if (self.familyName) {
|
||||||
NSString *firstName = [components firstObject];
|
return self.familyName;
|
||||||
NSString *lastName = [self.name stringByReplacingOccurrencesOfString:firstName withString:@""];
|
}
|
||||||
lastName = [lastName stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
else {
|
||||||
if ([lastName length] == 0) {
|
NSArray<NSString *>*components = [self.name componentsSeparatedByString:@" "];
|
||||||
lastName = nil;
|
NSString *firstName = [components firstObject];
|
||||||
|
NSString *lastName = [self.name stringByReplacingOccurrencesOfString:firstName withString:@""];
|
||||||
|
lastName = [lastName stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||||
|
if ([lastName length] == 0) {
|
||||||
|
lastName = nil;
|
||||||
|
}
|
||||||
|
return lastName;
|
||||||
}
|
}
|
||||||
return lastName;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)street {
|
- (NSString *)street {
|
||||||
|
@ -247,3 +317,12 @@ FAUXPAS_IGNORED_IN_FILE(APIAvailability)
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
NSString *stringIfHasContentsElseNil(NSString *string) {
|
||||||
|
if (string.length > 0) {
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
#import <XCTest/XCTest.h>
|
#import <XCTest/XCTest.h>
|
||||||
#import <AddressBook/AddressBook.h>
|
#import <AddressBook/AddressBook.h>
|
||||||
|
#import <PassKit/PassKit.h>
|
||||||
|
#import <Contacts/Contacts.h>
|
||||||
#import "STPAddress.h"
|
#import "STPAddress.h"
|
||||||
|
|
||||||
@interface STPAddressTests : XCTestCase
|
@interface STPAddressTests : XCTestCase
|
||||||
|
@ -16,7 +18,134 @@
|
||||||
|
|
||||||
@implementation STPAddressTests
|
@implementation STPAddressTests
|
||||||
|
|
||||||
- (void)testInit {
|
- (void)testInitWithPKContact_complete {
|
||||||
|
PKContact *contact = [PKContact new];
|
||||||
|
{
|
||||||
|
NSPersonNameComponents *name = [NSPersonNameComponents new];
|
||||||
|
name.givenName = @"John";
|
||||||
|
name.familyName = @"Doe";
|
||||||
|
contact.name = name;
|
||||||
|
|
||||||
|
contact.emailAddress = @"foo@example.com";
|
||||||
|
contact.phoneNumber = [CNPhoneNumber phoneNumberWithStringValue:@"888-555-1212"];
|
||||||
|
|
||||||
|
CNMutablePostalAddress *address = [CNMutablePostalAddress new];
|
||||||
|
address.street = @"55 John St";
|
||||||
|
address.city = @"New York";
|
||||||
|
address.state = @"NY";
|
||||||
|
address.postalCode = @"10002";
|
||||||
|
address.ISOCountryCode = @"US";
|
||||||
|
address.country = @"United States";
|
||||||
|
contact.postalAddress = address.copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
STPAddress *address = [[STPAddress alloc] initWithPKContact:contact];
|
||||||
|
XCTAssertEqualObjects(@"John Doe", address.name);
|
||||||
|
XCTAssertEqualObjects(@"8885551212", address.phone);
|
||||||
|
XCTAssertEqualObjects(@"foo@example.com", address.email);
|
||||||
|
XCTAssertEqualObjects(@"55 John St", address.line1);
|
||||||
|
XCTAssertEqualObjects(@"New York", address.city);
|
||||||
|
XCTAssertEqualObjects(@"NY", address.state);
|
||||||
|
XCTAssertEqualObjects(@"10002", address.postalCode);
|
||||||
|
XCTAssertEqualObjects(@"US", address.country);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testInitWithPKContact_partial {
|
||||||
|
PKContact *contact = [PKContact new];
|
||||||
|
{
|
||||||
|
NSPersonNameComponents *name = [NSPersonNameComponents new];
|
||||||
|
name.givenName = @"John";
|
||||||
|
contact.name = name;
|
||||||
|
|
||||||
|
CNMutablePostalAddress *address = [CNMutablePostalAddress new];
|
||||||
|
address.state = @"VA";
|
||||||
|
contact.postalAddress = address.copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
STPAddress *address = [[STPAddress alloc] initWithPKContact:contact];
|
||||||
|
XCTAssertEqualObjects(@"John", address.name);
|
||||||
|
XCTAssertNil(address.phone);
|
||||||
|
XCTAssertNil(address.email);
|
||||||
|
XCTAssertNil(address.line1);
|
||||||
|
XCTAssertNil(address.city);
|
||||||
|
XCTAssertEqualObjects(@"VA", address.state);
|
||||||
|
XCTAssertNil(address.postalCode);
|
||||||
|
XCTAssertNil(address.country);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testInitWithCNContact_complete {
|
||||||
|
CNMutableContact *contact = [CNMutableContact new];
|
||||||
|
{
|
||||||
|
contact.givenName = @"John";
|
||||||
|
contact.familyName = @"Doe";
|
||||||
|
|
||||||
|
contact.emailAddresses = @[
|
||||||
|
[CNLabeledValue labeledValueWithLabel:CNLabelHome
|
||||||
|
value:@"foo@example.com"],
|
||||||
|
[CNLabeledValue labeledValueWithLabel:CNLabelWork
|
||||||
|
value:@"bar@example.com"],
|
||||||
|
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
contact.phoneNumbers = @[
|
||||||
|
[CNLabeledValue labeledValueWithLabel:CNLabelHome
|
||||||
|
value:[CNPhoneNumber phoneNumberWithStringValue:@"888-555-1212"]],
|
||||||
|
[CNLabeledValue labeledValueWithLabel:CNLabelWork
|
||||||
|
value:[CNPhoneNumber phoneNumberWithStringValue:@"555-555-5555"]],
|
||||||
|
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
CNMutablePostalAddress *address = [CNMutablePostalAddress new];
|
||||||
|
address.street = @"55 John St";
|
||||||
|
address.city = @"New York";
|
||||||
|
address.state = @"NY";
|
||||||
|
address.postalCode = @"10002";
|
||||||
|
address.ISOCountryCode = @"US";
|
||||||
|
address.country = @"United States";
|
||||||
|
contact.postalAddresses = @[
|
||||||
|
[CNLabeledValue labeledValueWithLabel:CNLabelHome
|
||||||
|
value:address],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
STPAddress *address = [[STPAddress alloc] initWithCNContact:contact];
|
||||||
|
XCTAssertEqualObjects(@"John Doe", address.name);
|
||||||
|
XCTAssertEqualObjects(@"8885551212", address.phone);
|
||||||
|
XCTAssertEqualObjects(@"foo@example.com", address.email);
|
||||||
|
XCTAssertEqualObjects(@"55 John St", address.line1);
|
||||||
|
XCTAssertEqualObjects(@"New York", address.city);
|
||||||
|
XCTAssertEqualObjects(@"NY", address.state);
|
||||||
|
XCTAssertEqualObjects(@"10002", address.postalCode);
|
||||||
|
XCTAssertEqualObjects(@"US", address.country);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testInitWithCNContact_partial {
|
||||||
|
CNMutableContact *contact = [CNMutableContact new];
|
||||||
|
{
|
||||||
|
contact.givenName = @"John";
|
||||||
|
|
||||||
|
CNMutablePostalAddress *address = [CNMutablePostalAddress new];
|
||||||
|
address.state = @"VA";
|
||||||
|
contact.postalAddresses = @[
|
||||||
|
[CNLabeledValue labeledValueWithLabel:CNLabelHome
|
||||||
|
value:address],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
STPAddress *address = [[STPAddress alloc] initWithCNContact:contact];
|
||||||
|
XCTAssertEqualObjects(@"John", address.name);
|
||||||
|
XCTAssertNil(address.phone);
|
||||||
|
XCTAssertNil(address.email);
|
||||||
|
XCTAssertNil(address.line1);
|
||||||
|
XCTAssertNil(address.city);
|
||||||
|
XCTAssertEqualObjects(@"VA", address.state);
|
||||||
|
XCTAssertNil(address.postalCode);
|
||||||
|
XCTAssertNil(address.country);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)testInitWithABRecord_complete {
|
||||||
ABRecordRef record = ABPersonCreate();
|
ABRecordRef record = ABPersonCreate();
|
||||||
ABRecordSetValue(record, kABPersonFirstNameProperty, CFSTR("John"), nil);
|
ABRecordSetValue(record, kABPersonFirstNameProperty, CFSTR("John"), nil);
|
||||||
ABRecordSetValue(record, kABPersonLastNameProperty, CFSTR("Doe"), nil);
|
ABRecordSetValue(record, kABPersonLastNameProperty, CFSTR("Doe"), nil);
|
||||||
|
@ -50,7 +179,7 @@
|
||||||
XCTAssertEqualObjects(@"US", address.country);
|
XCTAssertEqualObjects(@"US", address.country);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)testInit_partial {
|
- (void)testInitWithABRecord_partial {
|
||||||
ABRecordRef record = ABPersonCreate();
|
ABRecordRef record = ABPersonCreate();
|
||||||
ABRecordSetValue(record, kABPersonFirstNameProperty, CFSTR("John"), nil);
|
ABRecordSetValue(record, kABPersonFirstNameProperty, CFSTR("John"), nil);
|
||||||
ABMutableMultiValueRef addressRef = ABMultiValueCreateMutable(kABMultiDictionaryPropertyType);
|
ABMutableMultiValueRef addressRef = ABMultiValueCreateMutable(kABMultiDictionaryPropertyType);
|
||||||
|
|
|
@ -26,11 +26,11 @@
|
||||||
@"address_city": @"New York",
|
@"address_city": @"New York",
|
||||||
@"address_state": @"NY",
|
@"address_state": @"NY",
|
||||||
@"address_zip": @"12345",
|
@"address_zip": @"12345",
|
||||||
@"address_country": @"USA",
|
@"address_country": @"US",
|
||||||
@"last4": @"1234",
|
@"last4": @"1234",
|
||||||
@"brand": @"Visa",
|
@"brand": @"Visa",
|
||||||
@"fingerprint": @"Fingolfin",
|
@"fingerprint": @"Fingolfin",
|
||||||
@"country": @"Japan",
|
@"country": @"JP",
|
||||||
};
|
};
|
||||||
|
|
||||||
NSDictionary *tokenDict = @{ @"id": @"id_for_token", @"object": @"token", @"livemode": @NO, @"created": @1353025450.0, @"used": @NO, @"card": cardDict };
|
NSDictionary *tokenDict = @{ @"id": @"id_for_token", @"object": @"token", @"livemode": @NO, @"created": @1353025450.0, @"used": @NO, @"card": cardDict };
|
||||||
|
|
Loading…
Reference in New Issue