diff --git a/Stripe/PublicHeaders/STPAddress.h b/Stripe/PublicHeaders/STPAddress.h
index d62193db919..0e720efb473 100644
--- a/Stripe/PublicHeaders/STPAddress.h
+++ b/Stripe/PublicHeaders/STPAddress.h
@@ -166,6 +166,24 @@ typedef NS_ENUM(NSUInteger, STPBillingAddressFields) {
  */
 - (BOOL)containsRequiredFields:(STPBillingAddressFields)requiredFields;
 
+/**
+ Checks if this STPAddress has any content (possibly invalid) in any of the
+ desired billing address fields.
+
+ Where `containsRequiredFields:` validates that this STPAddress contains valid data in
+ all of the required fields, this method checks for the existence of *any* data.
+
+ For example, if `desiredFields` is `STPBillingAddressFieldsZip`, this will check
+ if the postalCode is empty.
+
+ Note: When `desiredFields == STPBillingAddressFieldsNone`, this method always returns
+ NO.
+
+ @parameter desiredFields The billing address information the caller is interested in.
+ @return YES if there is any data in this STPAddress that's relevant for those fields.
+ */
+- (BOOL)containsContentForBillingAddressFields:(STPBillingAddressFields)desiredFields;
+
 /**
  Checks if this STPAddress has the level of valid address information
  required by the passed in setting.
@@ -177,6 +195,22 @@ typedef NS_ENUM(NSUInteger, STPBillingAddressFields) {
  */
 - (BOOL)containsRequiredShippingAddressFields:(PKAddressField)requiredFields;
 
+/**
+ Checks if this STPAddress has any content (possibly invalid) in any of the
+ desired shipping address fields.
+
+ Where `containsRequiredShippingAddressFields:` validates that this STPAddress
+ contains valid data in all of the required fields, this method checks for the
+ existence of *any* data.
+
+ Note: When `desiredFields == PKAddressFieldNone`, this method always returns
+ NO.
+
+ @parameter desiredFields The shipping address information the caller is interested in.
+ @return YES if there is any data in this STPAddress that's relevant for those fields.
+ */
+- (BOOL)containsContentForShippingAddressFields:(PKAddressField)desiredFields;
+
 /**
  Converts an STPBillingAddressFields enum value into the closest equivalent
  representation of PKAddressField options
diff --git a/Stripe/STPAddCardViewController.m b/Stripe/STPAddCardViewController.m
index a54b3175c8b..c6e2b6ee4a1 100644
--- a/Stripe/STPAddCardViewController.m
+++ b/Stripe/STPAddCardViewController.m
@@ -145,8 +145,11 @@ - (void)createAndSetupViews {
     }
     [addressHeaderView.button addTarget:self action:@selector(useShippingAddress:)
                        forControlEvents:UIControlEventTouchUpInside];
-    BOOL needsAddress = self.configuration.requiredBillingAddressFields != STPBillingAddressFieldsNone && !self.addressViewModel.isValid;
-    BOOL buttonVisible = (needsAddress && self.shippingAddress != nil && !self.hasUsedShippingAddress);
+    STPBillingAddressFields requiredFields = self.configuration.requiredBillingAddressFields;
+    BOOL needsAddress = requiredFields != STPBillingAddressFieldsNone && !self.addressViewModel.isValid;
+    BOOL buttonVisible = (needsAddress &&
+                          [self.shippingAddress containsContentForBillingAddressFields:requiredFields]
+                          && !self.hasUsedShippingAddress);
     addressHeaderView.buttonHidden = !buttonVisible;
     [addressHeaderView setNeedsLayout];
     _addressHeaderView = addressHeaderView;
diff --git a/Stripe/STPAddress.m b/Stripe/STPAddress.m
index fc723c8c9ff..b8067716960 100644
--- a/Stripe/STPAddress.m
+++ b/Stripe/STPAddress.m
@@ -275,6 +275,19 @@ - (BOOL)containsRequiredFields:(STPBillingAddressFields)requiredFields {
     return containsFields;
 }
 
+- (BOOL)containsContentForBillingAddressFields:(STPBillingAddressFields)desiredFields {
+    switch (desiredFields) {
+        case STPBillingAddressFieldsNone:
+            return NO;
+        case STPBillingAddressFieldsZip:
+            return self.postalCode.length > 0;
+        case STPBillingAddressFieldsFull:
+            return [self hasPartialPostalAddress];
+    }
+
+    return NO;
+}
+
 - (BOOL)containsRequiredShippingAddressFields:(PKAddressField)requiredFields {
     BOOL containsFields = YES;
     if (requiredFields & PKAddressFieldName) {
@@ -292,6 +305,13 @@ - (BOOL)containsRequiredShippingAddressFields:(PKAddressField)requiredFields {
     return containsFields;
 }
 
+- (BOOL)containsContentForShippingAddressFields:(PKAddressField)desiredFields {
+    return (((desiredFields & PKAddressFieldName) && self.name.length > 0)
+            || ((desiredFields & PKAddressFieldEmail) && self.email.length > 0)
+            || ((desiredFields & PKAddressFieldPhone) && self.phone.length > 0)
+            || ((desiredFields & PKAddressFieldPostalAddress) && [self hasPartialPostalAddress]));
+}
+
 - (BOOL)hasValidPostalAddress {
     return (self.line1.length > 0 
             && self.city.length > 0 
@@ -301,6 +321,21 @@ - (BOOL)hasValidPostalAddress {
                                                          countryCode:self.country] == STPCardValidationStateValid));
 }
 
+/**
+ Does this STPAddress contain any data in the postal address fields?
+
+ If they are all empty or nil, returns NO. Even a single character in a
+ single field will return YES.
+ */
+- (BOOL)hasPartialPostalAddress {
+    return (self.line1.length > 0
+            || self.line2.length > 0
+            || self.city.length > 0
+            || self.country.length > 0
+            || self.state.length > 0
+            || self.postalCode.length > 0);
+}
+
 + (PKAddressField)applePayAddressFieldsFromBillingAddressFields:(STPBillingAddressFields)billingAddressFields {
     FAUXPAS_IGNORED_IN_METHOD(APIAvailability);
     switch (billingAddressFields) {
diff --git a/Stripe/STPShippingAddressViewController.m b/Stripe/STPShippingAddressViewController.m
index a6fe42f3b9b..91edd9642d0 100644
--- a/Stripe/STPShippingAddressViewController.m
+++ b/Stripe/STPShippingAddressViewController.m
@@ -137,8 +137,11 @@ - (void)createAndSetupViews {
                        forState:UIControlStateNormal];
     [headerView.button addTarget:self action:@selector(useBillingAddress:)
                 forControlEvents:UIControlEventTouchUpInside];
-    BOOL needsAddress = self.configuration.requiredShippingAddressFields & PKAddressFieldPostalAddress && !self.addressViewModel.isValid;
-    BOOL buttonVisible = (needsAddress && self.billingAddress != nil && !self.hasUsedBillingAddress);
+    PKAddressField requiredFields = self.configuration.requiredShippingAddressFields;
+    BOOL needsAddress = (requiredFields & PKAddressFieldPostalAddress) && !self.addressViewModel.isValid;
+    BOOL buttonVisible = (needsAddress
+                          && [self.billingAddress containsContentForShippingAddressFields:requiredFields]
+                          && !self.hasUsedBillingAddress);
     headerView.button.alpha = buttonVisible ? 1 : 0;
     [headerView setNeedsLayout];
     _addressHeaderView = headerView;
diff --git a/Tests/Tests/STPAddCardViewControllerLocalizationTests.m b/Tests/Tests/STPAddCardViewControllerLocalizationTests.m
index af62b6d5e32..9839a28b62f 100644
--- a/Tests/Tests/STPAddCardViewControllerLocalizationTests.m
+++ b/Tests/Tests/STPAddCardViewControllerLocalizationTests.m
@@ -51,6 +51,7 @@ - (void)performSnapshotTestForLanguage:(NSString *)language delivery:(BOOL)deliv
     STPAddCardViewController *addCardVC = [[STPAddCardViewController alloc] initWithConfiguration:config
                                                                                             theme:[STPTheme defaultTheme]];
     addCardVC.shippingAddress = [STPAddress new];
+    addCardVC.shippingAddress.line1 = @"1"; // trigger "use shipping address" button
     
     UINavigationController *navController = [UINavigationController new];
     navController.view.frame = CGRectMake(0, 0, 320, 750);
diff --git a/Tests/Tests/STPAddressTests.m b/Tests/Tests/STPAddressTests.m
index 999bef8adb6..85b9c459681 100644
--- a/Tests/Tests/STPAddressTests.m
+++ b/Tests/Tests/STPAddressTests.m
@@ -428,6 +428,51 @@ - (void)testContainsRequiredFieldsFull {
     XCTAssertTrue([address containsRequiredFields:STPBillingAddressFieldsFull]);
 }
 
+- (void)testContainsContentForBillingAddressFields {
+    STPAddress *address = [STPAddress new];
+
+    // Empty address should return false for everything
+    XCTAssertFalse([address containsContentForBillingAddressFields:STPBillingAddressFieldsNone]);
+    XCTAssertFalse([address containsContentForBillingAddressFields:STPBillingAddressFieldsZip]);
+    XCTAssertFalse([address containsContentForBillingAddressFields:STPBillingAddressFieldsFull]);
+
+    // 1+ characters in postalCode will return true for .Zip && .Full
+    address.postalCode = @"0";
+    XCTAssertFalse([address containsContentForBillingAddressFields:STPBillingAddressFieldsNone]);
+    XCTAssertTrue([address containsContentForBillingAddressFields:STPBillingAddressFieldsZip]);
+    XCTAssertTrue([address containsContentForBillingAddressFields:STPBillingAddressFieldsFull]);
+    // empty string returns false
+    address.postalCode = @"";
+    XCTAssertFalse([address containsContentForBillingAddressFields:STPBillingAddressFieldsNone]);
+    XCTAssertFalse([address containsContentForBillingAddressFields:STPBillingAddressFieldsZip]);
+    XCTAssertFalse([address containsContentForBillingAddressFields:STPBillingAddressFieldsFull]);
+    address.postalCode = nil;
+
+    // Test every other property that contributes to the full address, ensuring it returns True for .Full only
+    // This is *not* refactoring-safe, but I think it's better than a bunch of duplicated code
+    for (NSString *propertyName in @[@"line1", @"line2", @"city", @"state", @"country"]) {
+        for (NSString *testValue in @[@"a", @"0", @"Foo Bar"]) {
+            [address setValue:testValue forKey:propertyName];
+            XCTAssertFalse([address containsContentForBillingAddressFields:STPBillingAddressFieldsNone]);
+            XCTAssertFalse([address containsContentForBillingAddressFields:STPBillingAddressFieldsZip]);
+            XCTAssertTrue([address containsContentForBillingAddressFields:STPBillingAddressFieldsFull]);
+            [address setValue:nil forKey:propertyName];
+        }
+
+        // Make sure that empty string is treated like nil, and returns false for these properties
+        [address setValue:@"" forKey:propertyName];
+        XCTAssertFalse([address containsContentForBillingAddressFields:STPBillingAddressFieldsNone]);
+        XCTAssertFalse([address containsContentForBillingAddressFields:STPBillingAddressFieldsZip]);
+        XCTAssertFalse([address containsContentForBillingAddressFields:STPBillingAddressFieldsFull]);
+        [address setValue:nil forKey:propertyName];
+    }
+
+    // ensure it still returns false for everything since it has been cleared
+    XCTAssertFalse([address containsContentForBillingAddressFields:STPBillingAddressFieldsNone]);
+    XCTAssertFalse([address containsContentForBillingAddressFields:STPBillingAddressFieldsZip]);
+    XCTAssertFalse([address containsContentForBillingAddressFields:STPBillingAddressFieldsFull]);
+}
+
 - (void)testContainsRequiredShippingAddressFields {
     STPAddress *address = [STPAddress new];
     XCTAssertTrue([address containsRequiredShippingAddressFields:PKAddressFieldNone]);
@@ -458,6 +503,81 @@ - (void)testContainsRequiredShippingAddressFields {
     XCTAssertTrue([address containsRequiredShippingAddressFields:PKAddressFieldAll]);
 }
 
+- (void)testContainsContentForShippingAddressFields {
+    STPAddress *address = [STPAddress new];
+
+    // Empty address should return false for everything
+    XCTAssertFalse([address containsContentForShippingAddressFields:PKAddressFieldNone]);
+    XCTAssertFalse([address containsContentForShippingAddressFields:PKAddressFieldName]);
+    XCTAssertFalse([address containsContentForShippingAddressFields:PKAddressFieldPhone]);
+    XCTAssertFalse([address containsContentForShippingAddressFields:PKAddressFieldEmail]);
+    XCTAssertFalse([address containsContentForShippingAddressFields:PKAddressFieldPostalAddress]);
+
+    // Name
+    address.name = @"Smith";
+    XCTAssertFalse([address containsContentForShippingAddressFields:PKAddressFieldNone]);
+    XCTAssertTrue([address containsContentForShippingAddressFields:PKAddressFieldName]);
+    XCTAssertFalse([address containsContentForShippingAddressFields:PKAddressFieldPhone]);
+    XCTAssertFalse([address containsContentForShippingAddressFields:PKAddressFieldEmail]);
+    XCTAssertFalse([address containsContentForShippingAddressFields:PKAddressFieldPostalAddress]);
+    address.name = @"";
+
+    // Phone
+    address.phone = @"1";
+    XCTAssertFalse([address containsContentForShippingAddressFields:PKAddressFieldNone]);
+    XCTAssertFalse([address containsContentForShippingAddressFields:PKAddressFieldName]);
+    XCTAssertTrue([address containsContentForShippingAddressFields:PKAddressFieldPhone]);
+    XCTAssertFalse([address containsContentForShippingAddressFields:PKAddressFieldEmail]);
+    XCTAssertFalse([address containsContentForShippingAddressFields:PKAddressFieldPostalAddress]);
+    address.phone = @"";
+
+    // Email
+    address.email = @"f";
+    XCTAssertFalse([address containsContentForShippingAddressFields:PKAddressFieldNone]);
+    XCTAssertFalse([address containsContentForShippingAddressFields:PKAddressFieldName]);
+    XCTAssertFalse([address containsContentForShippingAddressFields:PKAddressFieldPhone]);
+    XCTAssertTrue([address containsContentForShippingAddressFields:PKAddressFieldEmail]);
+    XCTAssertFalse([address containsContentForShippingAddressFields:PKAddressFieldPostalAddress]);
+    address.email = @"";
+
+    // Test every property that contributes to the full address
+    // This is *not* refactoring-safe, but I think it's better than a bunch more duplicated code
+    for (NSString *propertyName in @[@"line1", @"line2", @"city", @"state", @"postalCode", @"country"]) {
+        for (NSString *testValue in @[@"a", @"0", @"Foo Bar"]) {
+            [address setValue:testValue forKey:propertyName];
+            XCTAssertFalse([address containsContentForShippingAddressFields:PKAddressFieldNone]);
+            XCTAssertFalse([address containsContentForShippingAddressFields:PKAddressFieldName]);
+            XCTAssertFalse([address containsContentForShippingAddressFields:PKAddressFieldPhone]);
+            XCTAssertFalse([address containsContentForShippingAddressFields:PKAddressFieldEmail]);
+            XCTAssertTrue([address containsContentForShippingAddressFields:PKAddressFieldPostalAddress]);
+            [address setValue:@"" forKey:propertyName];
+        }
+    }
+
+    // ensure it still returns false for everything with empty strings
+    XCTAssertFalse([address containsContentForShippingAddressFields:PKAddressFieldNone]);
+    XCTAssertFalse([address containsContentForShippingAddressFields:PKAddressFieldName]);
+    XCTAssertFalse([address containsContentForShippingAddressFields:PKAddressFieldPhone]);
+    XCTAssertFalse([address containsContentForShippingAddressFields:PKAddressFieldEmail]);
+    XCTAssertFalse([address containsContentForShippingAddressFields:PKAddressFieldPostalAddress]);
+
+    // Try a hybrid address, and make sure some bitwise combinations work
+    address.name = @"a";
+    address.phone = @"1";
+    address.line1 = @"_";
+    XCTAssertFalse([address containsContentForShippingAddressFields:PKAddressFieldNone]);
+    XCTAssertTrue([address containsContentForShippingAddressFields:PKAddressFieldName]);
+    XCTAssertTrue([address containsContentForShippingAddressFields:PKAddressFieldPhone]);
+    XCTAssertFalse([address containsContentForShippingAddressFields:PKAddressFieldEmail]);
+    XCTAssertTrue([address containsContentForShippingAddressFields:PKAddressFieldPostalAddress]);
+
+    XCTAssertTrue([address containsContentForShippingAddressFields:(PKAddressField)(PKAddressFieldName|PKAddressFieldEmail)]);
+    XCTAssertTrue([address containsContentForShippingAddressFields:(PKAddressField)(PKAddressFieldPhone|PKAddressFieldEmail)]);
+    XCTAssertTrue([address containsContentForShippingAddressFields:PKAddressFieldAll]);
+
+}
+
+
 - (void)testShippingInfoForCharge {
     STPAddress *address = [STPFixtures address];
     PKShippingMethod *method = [[PKShippingMethod alloc] init];
diff --git a/Tests/Tests/STPShippingAddressViewControllerLocalizationTests.m b/Tests/Tests/STPShippingAddressViewControllerLocalizationTests.m
index 57fdf2e54f6..01cd0058cca 100644
--- a/Tests/Tests/STPShippingAddressViewControllerLocalizationTests.m
+++ b/Tests/Tests/STPShippingAddressViewControllerLocalizationTests.m
@@ -47,6 +47,7 @@ - (void)performSnapshotTestForLanguage:(NSString *)language shippingType:(STPShi
     [STPLocalizationUtils overrideLanguageTo:language];
     STPUserInformation *info = [STPUserInformation new];
     info.billingAddress = [STPAddress new];
+    info.billingAddress.email = @"@"; // trigger "use billing address" button
 
     STPShippingAddressViewController *shippingVC = [[STPShippingAddressViewController alloc] initWithConfiguration:config
                                                                                                              theme:[STPTheme defaultTheme]