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 shipping details to payment sheet #5419

Merged
merged 2 commits into from Aug 19, 2022

Conversation

jameswoo-stripe
Copy link
Contributor

Summary

  • Add shippingDetails to PaymentSheet.Configuration
  • Add SameAsShippingElement, a new checkbox element that will be shown below the AddressElement whenever the shippingDetails are supplied, default billing details is not enabled, and the merchant has configured for this checkbox

Shipping details is parsed into the initial values map to be used for the billing details. If customer requests same as shipping, then the billing details will be overwritten with the shipping information.

The checkbox is there if and only if the merchant has supplied the necessary configurations (shipping address config):

  • shipping details included, unchecked: billing details is empty
  • shipping details included, checked: billing details overwritten by shipping details
  • shipping details included, default billing address included: no check box is shown
  • shipping details not included: no checkbox is shown

This is enabled for Link add payment method screen and payment sheet, otherwise you should not see this new checkbox.

Motivation

Address Element private beta

Testing

  • Added tests
  • Modified tests
  • Manually verified

Screenshots

shippingdetails.mov

?.takeIf { loadFromArgs }
?.let { convertToFormValuesMap(it) }
?: emptyMap()
val initialValuesMap = args.initialValueMap
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should loadFromArgs be used here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

loadFromArgs exists because when you launch Link passing in the pre-filled card params, you'll want the form to be pre-filled with those values. But then if the user navigates within Link and ends up in this screen again, we won't want to load the values from the initial arguments. How does this logic apply to address?

CountryConfig(this.allowedCountryCodes),
initialValue = initialValues[this.apiPath]
)
): SectionElement {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Attempted to convert the AddressElement into a FormElement, but this became a problem when getting the hidden identifiers. FormElement doesn't have a way to access its children like SectionElement does. We should refactor the way elements works. Ideally, the Element itself always has access to its children.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, I am creating a new SectionElement with two fields: AddressElement and SameAsShippingElement

@@ -7,6 +7,8 @@ import kotlinx.coroutines.flow.Flow
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
sealed interface SectionFieldElement {
val identifier: IdentifierSpec
val shouldRenderOutsideCard: Boolean
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was needed for SectionElementUI, this lets the section know if this element should be rendered outside of the form card. Otherwise all elements get rendered in the card.

@@ -401,6 +402,21 @@ class PaymentSheetPlaygroundActivity : AppCompatActivity() {
customer = viewModel.customerConfig.value,
googlePay = googlePayConfig,
defaultBillingDetails = defaultBilling,
shippingDetails = if (viewModel.getSavedToggleState().setShippingAddress) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the shipping address toggle is enabled, you can test this feature without going through the autocomplete flow.

* The field is displayed and the customer is required to fill it in.
*/
REQUIRED
data class AdditionalFieldsConfiguration(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updating the structure of AddtionalFieldsConfiguration to match iOS

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need a @JvmOverloads for Java?

@github-actions
Copy link
Contributor

github-actions bot commented Aug 16, 2022

Diffuse output:

OLD: paymentsheet-example-release-master.apk (signature: none)
NEW: paymentsheet-example-release-pr.apk (signature: none)

          │            compressed            │           uncompressed            
          ├───────────┬───────────┬──────────┼───────────┬───────────┬───────────
 APK      │ old       │ new       │ diff     │ old       │ new       │ diff      
──────────┼───────────┼───────────┼──────────┼───────────┼───────────┼───────────
      dex │  15.4 MiB │  15.4 MiB │ +8.7 KiB │  51.9 MiB │  51.9 MiB │ +25.4 KiB 
     arsc │   1.8 MiB │   1.8 MiB │   +616 B │   1.8 MiB │   1.8 MiB │    +616 B 
 manifest │     4 KiB │     4 KiB │      0 B │  18.5 KiB │  18.5 KiB │       0 B 
      res │ 873.3 KiB │ 873.3 KiB │    +11 B │   1.4 MiB │   1.4 MiB │       0 B 
   native │   2.5 MiB │   2.5 MiB │      0 B │   5.9 MiB │   5.9 MiB │       0 B 
    asset │     3 MiB │     3 MiB │    -54 B │     3 MiB │     3 MiB │     -54 B 
    other │  81.7 KiB │  81.7 KiB │      0 B │ 155.6 KiB │ 155.6 KiB │       0 B 
──────────┼───────────┼───────────┼──────────┼───────────┼───────────┼───────────
    total │  23.6 MiB │  23.6 MiB │ +9.3 KiB │  64.1 MiB │  64.1 MiB │ +25.9 KiB 

         │          raw           │              unique               
         ├────────┬────────┬──────┼────────┬────────┬─────────────────
 DEX     │ old    │ new    │ diff │ old    │ new    │ diff            
─────────┼────────┼────────┼──────┼────────┼────────┼─────────────────
   files │      4 │      4 │    0 │        │        │                 
 strings │ 250865 │ 250968 │ +103 │ 213896 │ 213994 │  +98 (+165 -67) 
   types │  44261 │  44282 │  +21 │  40627 │  40648 │  +21 (+27 -6)   
 classes │  37828 │  37847 │  +19 │  37828 │  37847 │  +19 (+25 -6)   
 methods │ 221369 │ 221499 │ +130 │ 213377 │ 213505 │ +128 (+185 -57) 
  fields │ 162806 │ 162869 │  +63 │ 161766 │ 161828 │  +62 (+87 -25)  

 ARSC    │ old  │ new  │ diff       
─────────┼──────┼──────┼────────────
 configs │  292 │  292 │  0         
 entries │ 6231 │ 6232 │ +1 (+1 -0)
APK
     compressed     │     uncompressed     │                               
─────────┬──────────┼──────────┬───────────┤                               
 size    │ diff     │ size     │ diff      │ path                          
─────────┼──────────┼──────────┼───────────┼───────────────────────────────
 3.2 MiB │ +6.7 KiB │    9 MiB │ +18.4 KiB │ ∆ classes4.dex                
 2.2 MiB │ +2.1 KiB │  6.9 MiB │  +6.9 KiB │ ∆ classes3.dex                
 1.8 MiB │   +616 B │  1.8 MiB │    +616 B │ ∆ resources.arsc              
 8.6 KiB │    -54 B │  8.5 KiB │     -54 B │ ∆ assets/dexopt/baseline.prof 
   998 B │    +10 B │  2.8 KiB │       0 B │ ∆ res/AE.xml                  
   1 KiB │     +1 B │  3.1 KiB │       0 B │ ∆ res/Fs.xml                  
─────────┼──────────┼──────────┼───────────┼───────────────────────────────
 7.2 MiB │ +9.3 KiB │ 17.7 MiB │ +25.9 KiB │ (total)
DEX
STRINGS:

   old    │ new    │ diff           
  ────────┼────────┼────────────────
   213896 │ 213994 │ +98 (+165 -67) 
  + 
  
  
  ���
  �������0�8�X�T¢��
  �����0�8�X�T¢��
  �����0�8�X�T¢��
  �����0�X�T¢��
  �����0�8�X�T¢��
  ¨��
  +  
  
  ���
  ���
  
  ��_
  ���
  ���
  
  ���
  ����0�*�0�H�&��������0�������0�0�*�0�2
  ��������0�H¨�	
  + 
  ���
  ��
  
  ���
  
  ���
  ���
  ��_
  ���
  �g�2�0�JD����0�2�������0�2
  ��������0�2
  ��������0�2�����������0
  ������0���0	H&¨��
  + ,
  ���
  ��
  ���
  ���
  
  ���
  ���
  ��_
  ���
  ���
  ���
  ����2�0�B���¢����J�������0�2�����0�H�J�������0�2�����0�H�J ��������0
  ������0���0	2�����0�H�J�����0�2�����0�H�J����0
  2�����0�H�¨��
  + 8
  ���
  ��
  ���
  ���
  ���
  ��
  ���
  ���
  ���
  ��
  ���
  ���
  ���
  ������2�0�B�¢����J�����02�����0�J��	��02�	������0�0
  J�����02�����0�J��*��0+J�����02�������0�J��,��02�������0�J�����02�������0�J��_��02��_����0�J��'��02��'����0�R�������0�X��¢��
  �����������R �	������0�0
  X��¢��
  ����
  �����R�����0�X��¢��
  �����������R�������0�X��¢��
  �����������R�������0�X��¢��
  �����������R�������0�X��¢��
  ��� �!���#R��_����0�X��¢��
  ���%����&��R��'����0�X��¢��
  ���(����)��¨�-
  + :
  ���
  ���
  
  ���
  
  ���
  ��	
  ���
  
  ���
  
  ��
  ���
  ���
  
  ���
  �������2�0�:��B�����������0��
  ��������0�¢����J	����0�HÆ�J������0�HÆ�J��
  ��02�������0�2
  ��������0�HÆ�J	����0�HÖ�J�����0�2�������0�HÖ�J	����0�HÖ�J	����0�HÖ�J�����0�2�����0�2�����0�HÖ�R�������0�¢��
  ������R�����0�¢��
  ���	�
  ¨��
  + >
  ���
  ���
  
  ���
  
  ���
  ���
  ���
  ���
  ���
  ���
  ��
  ���
  ���
  
  ���
  ������� #2�0�:�#B5�
  ��������0��
  ��������0��
  ��������0��
  ��������0�¢���	J�������0�HÆ�J�������0�HÆ�J�������0�HÆ�J�������0�HÆ�¢���J>����02
  ��������0�2
  ��������0�2
  ��������0�2
  ��������0�HÆ�¢����J	����0�HÖ�J�����0�2�������0�HÖ�J	����0�HÖ�J	����0�HÖ�J�����0�2�� ��0!2����0�HÖ�R�������0�¢��
  ���
  ��R�������0�¢�
  
  ��
  �����R�������0�¢��
  ������R�������0�¢��
  ������¨�_
  + L
  ���
  ���
  
  ���
  
  ���
  
  ��
  ���
  ���
  ���
  ���
  ���
  
  ���
  
  ��
  ���
  ���
  
  ���
  �������2�0�:�3Bi����������0��
  ��������0�������������0�0��
  ���	����0��
  ���
  ����0��
  �������0��
  ���
  ����0��
  ��������0�¢����J	����0�HÆ�J�������0�HÆ�J���������0�0�HÆ�J�� ����0�HÆ�J��!����0�HÆ�J������0�HÆ�J��#����0�HÆ�J��_����0�HÆ�Jk�%��02�������0�2
  ��������0�2�����������0�0�2
  ���	����0�2
  ���
  ����0�2
  �������0�2
  ���
  ����0�2
  ��������0�H�J	�&��0'H�J��(��0)2��*����0+H�J	�,��0'H�J	�-��0�H�J��.��0/2��0��012��2��0'H�R��
  ����0�¢��
  ������R���������0�0�¢��
  ������R�����0�¢��
  ������R��	����0�¢��
  ������R�������0�¢��
  ������R�������0�¢��
  ������R��
  ����0�¢��
  ������R������0�¢��
  ������¨�4
  + R
  ���
  ���
  
  ���
  
  ���
  ���
  ��_
  ���
  
  ���
  
  ���
  ���
  ���
  
  ���
  
  ��
  ���
  ���
  
  ���
  ������� 82�0�:�89Ba�������0�������0��
  ��������0��
  ��������0�������������0
  ������0���0	�
  ��������0�
  ���
  ����0�¢����J�����0�HÀ�¢����J�����0�HÀ�¢����J�� ����0�HÀ�¢���!J������0�HÀ�¢���#J��_������0
  ������0���0	HÀ�¢���%J��&����0HÀ�¢���'J��(����0�HÀ�¢���)Jg�*��02�������0�2�������0�2
  ��������0�2
  ��������0�2�����������0
  ������0���0	2
  ��������02
  ���
  ����0�HÆ�J	�+��0,HÖ�J��-��0.2��/����00HÖ�J	�1��0,HÖ�J	�2��0�HÖ�J��3��042��5��062��7��0,HÖ�R�������0�X��¢��
  ������R�������0�X��¢��
  ������R_��������0
  ������0���0	X��¢��
  ������R��
  ����0�X��¢��
  ������R�����0�X��¢��
  ������R�������0X��¢��
  ������R�����0�X��¢��
  ������¨�:
  + V
  ���
  ���
  
  ���
  ���
  
  ���
  ���
  ���
  
  ���
  
  ���
  ���
  ���
  ���
  ���
  ���
  ��
  ���
  ���
  
  ���
  �������2�0�Bc�
  ����0�j��������0�������0�������0��
  ���	����0
  �
  ��������0�
  ���
  ����0���������0��
  ��������0�¢����J
  ���0�j��H�J	�#��0�H�J	�_��0�H�J	�%��0�H�J��&����0
  H�J��'����0H�J��(����0�H�J	�)��0�H�J��*����0�H�Jo�+��02������0�j��2�������0�2�������0�2�������0�2
  ���	����0
  2
  ��������02
  ���
  ����0�2�������0�2
  ��������0�H�J	�,��0-H�J��.��0�2��/����00H�J	�1��0-H�J	�2��0�H�J��3��042��5��062��7��0-H�R��	����0
  ¢��
  ������R�������0¢��
  ������R�������0�¢��
  ������R�����0�¢��
  ������R�����0�¢��
  ������R�����0�j��¢��
  ������R��
  ����0�¢��
  ������R�����0�¢��
  ����� R�����0�¢��
  ���!� ¨�8
  + l
  ���
  ��
  
  ���
  ���
  
  ���
  ���
  ���
  
  ���
  
...✂
ARSC
ENTRIES:

   old  │ new  │ diff       
  ──────┼──────┼────────────
   6231 │ 6232 │ +1 (+1 -0) 
  + string/stripe_paymentsheet_address_element_same_as_shipping

@jameswoo-stripe jameswoo-stripe force-pushed the jameswoo/shipping-address-element-interop branch from 0ba5b1d to 87daf10 Compare August 17, 2022 17:23
Copy link
Contributor

@brnunes-stripe brnunes-stripe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this change look like for a returning customer, where we would show the "Save for future use" checkbox? Does it show two checkboxes?

I'm also thinking if the checkbox being all the way in the bottom is the best UX. The user might start filling in the address and not be aware of the checkbox until the end.

@@ -11,6 +12,7 @@ interface LinkPaymentLauncherFactory {
fun create(
@Assisted(MERCHANT_NAME) merchantName: String,
@Assisted(CUSTOMER_EMAIL) customerEmail: String?,
@Assisted(CUSTOMER_PHONE) customerPhone: String?
@Assisted(CUSTOMER_PHONE) customerPhone: String?,
@Assisted(INITIAL_VALUES_MAP) initialValuesMap: Map<IdentifierSpec, String?>?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you make the names more descriptive? It's not clear what's in the map. Something like INITIAL_SHIPPING_ADDRESS_VALUES_MAP, initialShippingAddressValuesMap is clearer.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or if you're thinking of making this generic (not only for shipping address), maybe initialFormValuesMap

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I can make it less generic

I like initialFormValuesMap

} else {
emptyMap()
}
return@let it.create(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the return@let is not needed.

* The field is displayed and the customer is required to fill it in.
*/
REQUIRED
data class AdditionalFieldsConfiguration(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need a @JvmOverloads for Java?

brnunes-stripe
brnunes-stripe previously approved these changes Aug 18, 2022
@jameswoo-stripe jameswoo-stripe merged commit d76511a into master Aug 19, 2022
@jameswoo-stripe jameswoo-stripe deleted the jameswoo/shipping-address-element-interop branch August 19, 2022 18:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants