@@ -30,26 +30,20 @@ import com.stripe.android.uicore.utils.mapAsStateFlow
3030import kotlinx.coroutines.flow.StateFlow
3131
3232/* *
33- * This is a special type of AddressElement that
34- * removes fields from the address based on the country. It
35- * is only intended to be used with the card payment method.
33+ * An address element that dynamically removes fields based on the selected country and collection mode.
3634 */
3735@RestrictTo(RestrictTo .Scope .LIBRARY_GROUP )
38- class CardBillingAddressElement (
36+ open class BillingAddressElement (
3937 override val identifier : IdentifierSpec ,
40- rawValuesMap : Map <IdentifierSpec , String ?> = emptyMap(),
41- countryCodes : Set <String > = emptySet(),
42- countryDropdownFieldController : DropdownFieldController = DropdownFieldController (
43- CountryConfig (countryCodes),
44- rawValuesMap[IdentifierSpec .Country ]
45- ),
38+ rawValuesMap : Map <IdentifierSpec , String ?>,
39+ countryCodes : Set <String >,
40+ countryElement : CountryElement ,
4641 autocompleteAddressInteractorFactory : AutocompleteAddressInteractor .Factory ? ,
4742 sameAsShippingElement : SameAsShippingElement ? ,
4843 shippingValuesMap : Map <IdentifierSpec , String ?>? ,
49- private val collectionConfiguration : BillingDetailsCollectionConfiguration =
50- BillingDetailsCollectionConfiguration (),
51- private val shouldHideCountryOnNoAddressCollection : Boolean = true ,
52- private val requiresBillingAddressForAutomaticTax : Boolean = false ,
44+ private val collectionConfiguration : BillingDetailsCollectionConfiguration ,
45+ private val shouldHideCountryOnNoAddressCollection : Boolean ,
46+ private val requiresBillingAddressForAutomaticTax : Boolean ,
5347) : AddressFieldsElement {
5448 private val nameConfig = if (collectionConfiguration.collectName) {
5549 AddressFieldConfiguration .REQUIRED
@@ -80,7 +74,7 @@ class CardBillingAddressElement(
8074 nameConfig = nameConfig,
8175 phoneNumberConfig = phoneNumberConfig,
8276 emailConfig = emailConfig,
83- countryDropdownFieldController = countryDropdownFieldController ,
77+ countryDropdownFieldController = countryElement.controller ,
8478 interactorFactory = factory,
8579 shippingValuesMap = shippingValuesMap,
8680 sameAsShippingElement = sameAsShippingElement,
@@ -95,10 +89,7 @@ class CardBillingAddressElement(
9589 phoneNumberConfig = phoneNumberConfig,
9690 emailConfig = emailConfig,
9791 ),
98- countryElement = CountryElement (
99- identifier = IdentifierSpec .Country ,
100- controller = countryDropdownFieldController,
101- ),
92+ countryElement = countryElement,
10293 shippingValuesMap = shippingValuesMap,
10394 sameAsShippingElement = sameAsShippingElement,
10495 hideCountry = shouldHideCountryOnNoAddressCollection &&
@@ -107,7 +98,7 @@ class CardBillingAddressElement(
10798 }
10899
109100 private val addressElementSectionController = addressElement.sectionFieldErrorController()
110- private val cardBillingAddressElementSectionErrorController =
101+ private val billingAddressElementSectionErrorController =
111102 object : SectionFieldValidationController by addressElementSectionController, SectionFieldComposable {
112103 override val validationMessage: StateFlow <FieldValidationMessage ?> =
113104 addressElement.addressController
@@ -163,7 +154,7 @@ class CardBillingAddressElement(
163154 // Save for future use puts this in the controller rather than element
164155 // card and achv2 uses save for future use
165156 val hiddenIdentifiers: StateFlow <Set <IdentifierSpec >> =
166- countryDropdownFieldController .rawFieldValue.mapAsStateFlow { countryCode ->
157+ countryElement.controller .rawFieldValue.mapAsStateFlow { countryCode ->
167158 when (collectionConfiguration.address) {
168159 BillingDetailsCollectionConfiguration .AddressCollectionMode .Never -> {
169160 FieldType .entries
@@ -203,7 +194,7 @@ class CardBillingAddressElement(
203194 override fun getFormFieldValueFlow () = addressElement.getFormFieldValueFlow()
204195
205196 override fun sectionFieldErrorController (): SectionFieldValidationController =
206- cardBillingAddressElementSectionErrorController
197+ billingAddressElementSectionErrorController
207198
208199 override fun setRawValue (rawValuesMap : Map <IdentifierSpec , String ?>) = addressElement.setRawValue(rawValuesMap)
209200
@@ -215,23 +206,36 @@ class CardBillingAddressElement(
215206}
216207
217208/* *
218- * Billing address fields required in addition to the country, for a Checkout Session using
219- * automatic tax with the billing address as the tax source. Most countries only need the
220- * country. Source: https://docs.stripe.com/tax/customer-locations
221- *
222- * Billing only - shipping is out of scope, since it's always collected in full for delivery
223- * regardless of tax, so there's no omittable mode there for tax to rescue.
209+ * The card-specific name is retained for compatibility. New payment-method forms should use
210+ * [BillingAddressElement] directly.
224211 */
225- private val additionalAutomaticTaxFieldsByCountry: Map <String , Set <IdentifierSpec >> = mapOf (
226- " CA" to setOf (IdentifierSpec .PostalCode ),
227- " GB" to setOf (IdentifierSpec .PostalCode ),
228- " IN" to setOf (IdentifierSpec .PostalCode ),
229- " PR" to setOf (IdentifierSpec .Line1 , IdentifierSpec .City , IdentifierSpec .PostalCode ),
230- " US" to setOf (IdentifierSpec .Line1 , IdentifierSpec .City , IdentifierSpec .State , IdentifierSpec .PostalCode ),
212+ @RestrictTo(RestrictTo .Scope .LIBRARY_GROUP )
213+ class CardBillingAddressElement (
214+ identifier : IdentifierSpec ,
215+ rawValuesMap : Map <IdentifierSpec , String ?> = emptyMap(),
216+ countryCodes : Set <String > = emptySet(),
217+ countryDropdownFieldController : DropdownFieldController = DropdownFieldController (
218+ CountryConfig (countryCodes),
219+ rawValuesMap[IdentifierSpec .Country ]
220+ ),
221+ autocompleteAddressInteractorFactory : AutocompleteAddressInteractor .Factory ? ,
222+ sameAsShippingElement : SameAsShippingElement ? ,
223+ shippingValuesMap : Map <IdentifierSpec , String ?>? ,
224+ collectionConfiguration : BillingDetailsCollectionConfiguration = BillingDetailsCollectionConfiguration (),
225+ shouldHideCountryOnNoAddressCollection : Boolean = true ,
226+ requiresBillingAddressForAutomaticTax : Boolean = false ,
227+ ) : BillingAddressElement(
228+ identifier = identifier,
229+ rawValuesMap = rawValuesMap,
230+ countryCodes = countryCodes,
231+ countryElement = CountryElement (
232+ identifier = IdentifierSpec .Country ,
233+ controller = countryDropdownFieldController,
234+ ),
235+ autocompleteAddressInteractorFactory = autocompleteAddressInteractorFactory,
236+ sameAsShippingElement = sameAsShippingElement,
237+ shippingValuesMap = shippingValuesMap,
238+ collectionConfiguration = collectionConfiguration,
239+ shouldHideCountryOnNoAddressCollection = shouldHideCountryOnNoAddressCollection,
240+ requiresBillingAddressForAutomaticTax = requiresBillingAddressForAutomaticTax,
231241)
232-
233- private fun automaticTaxRequiredFields (countryCode : String ): Set <IdentifierSpec > {
234- // Matches the raw, non-uppercased comparison the AVS check above uses - countryCode is
235- // already an uppercase ISO code in practice (from CountryConfig).
236- return additionalAutomaticTaxFieldsByCountry[countryCode].orEmpty()
237- }
0 commit comments