From 3606eeb6be76ce3b11f785ff28956f9f41b63c1f Mon Sep 17 00:00:00 2001 From: joyceqin-stripe Date: Fri, 25 Oct 2024 13:59:07 -0700 Subject: [PATCH] Basic Integration Deprecation (#4069) ## Summary Document of all public APIs removed by basic integration deprecation: https://docs.google.com/document/d/170-0hg1SoSiNXOHiTuGST4b-tCJRzvNajST5Zeu11zA/edit?usp=sharing ## Motivation Basic integration deprecation ## Testing ## Changelog --------- Co-authored-by: Nick Porter <88012362+porter-stripe@users.noreply.github.com> --- .../project.pbxproj | 6 - .../BrowseExamplesViewController.m | 67 +- .../FPXExampleViewController.h | 17 - .../FPXExampleViewController.m | 144 -- .../AUBECSDebitFormViewController.swift | 8 +- .../Source/BrowseViewController.swift | 180 +-- .../Source/CardFieldViewController.swift | 8 - .../Source/MockCustomerContext.swift | 71 - ...PaymentMethodMessagingViewController.swift | 2 - .../Source/ThemeViewController.swift | 59 - Stripe/Stripe.xcodeproj/project.pbxproj | 424 +----- .../bg-BG.lproj/Localizable.strings | 39 - .../ca-ES.lproj/Localizable.strings | 39 - .../cs-CZ.lproj/Localizable.strings | 39 - .../da.lproj/Localizable.strings | 39 - .../de.lproj/Localizable.strings | 39 - .../el-GR.lproj/Localizable.strings | 39 - .../en-GB.lproj/Localizable.strings | 39 - .../en.lproj/Localizable.strings | 60 - .../es-419.lproj/Localizable.strings | 39 - .../es.lproj/Localizable.strings | 39 - .../et-EE.lproj/Localizable.strings | 39 - .../fi.lproj/Localizable.strings | 39 - .../fil.lproj/Localizable.strings | 39 - .../fr-CA.lproj/Localizable.strings | 39 - .../fr.lproj/Localizable.strings | 39 - .../hr.lproj/Localizable.strings | 39 - .../hu.lproj/Localizable.strings | 39 - .../id.lproj/Localizable.strings | 39 - .../it.lproj/Localizable.strings | 39 - .../ja.lproj/Localizable.strings | 39 - .../ko.lproj/Localizable.strings | 39 - .../lt-LT.lproj/Localizable.strings | 39 - .../lv-LV.lproj/Localizable.strings | 39 - .../ms-MY.lproj/Localizable.strings | 39 - .../mt.lproj/Localizable.strings | 39 - .../nb.lproj/Localizable.strings | 39 - .../nl.lproj/Localizable.strings | 39 - .../nn-NO.lproj/Localizable.strings | 39 - .../pl-PL.lproj/Localizable.strings | 39 - .../pt-BR.lproj/Localizable.strings | 39 - .../pt-PT.lproj/Localizable.strings | 39 - .../ro-RO.lproj/Localizable.strings | 39 - .../ru.lproj/Localizable.strings | 39 - .../sk-SK.lproj/Localizable.strings | 39 - .../sl-SI.lproj/Localizable.strings | 39 - .../sv.lproj/Localizable.strings | 39 - .../tk.lproj/Localizable.strings | 0 .../tr.lproj/Localizable.strings | 39 - .../vi.lproj/Localizable.strings | 39 - .../zh-HK.lproj/Localizable.strings | 39 - .../zh-Hans.lproj/Localizable.strings | 39 - .../zh-Hant.lproj/Localizable.strings | 39 - .../StripeiOS.xcassets/FPX/Contents.json | 6 - .../Contents.json | 23 - .../stp_bank_fpx_affin_bank.png | Bin 627 -> 0 bytes .../stp_bank_fpx_affin_bank@2x.png | Bin 1236 -> 0 bytes .../stp_bank_fpx_affin_bank@3x.png | Bin 1869 -> 0 bytes .../Contents.json | 23 - .../stp_bank_fpx_alliance_bank.png | Bin 514 -> 0 bytes .../stp_bank_fpx_alliance_bank@2x.png | Bin 806 -> 0 bytes .../stp_bank_fpx_alliance_bank@3x.png | Bin 1067 -> 0 bytes .../Contents.json | 23 - .../stp_bank_fpx_ambank.png | Bin 585 -> 0 bytes .../stp_bank_fpx_ambank@2x.png | Bin 1097 -> 0 bytes .../stp_bank_fpx_ambank@3x.png | Bin 1638 -> 0 bytes .../Contents.json | 23 - .../stp_bank_fpx_bank_islam.png | Bin 463 -> 0 bytes .../stp_bank_fpx_bank_islam@2x.png | Bin 992 -> 0 bytes .../stp_bank_fpx_bank_islam@3x.png | Bin 1488 -> 0 bytes .../Contents.json | 23 - .../stp_bank_fpx_bank_muamalat.png | Bin 718 -> 0 bytes .../stp_bank_fpx_bank_muamalat@2x.png | Bin 1812 -> 0 bytes .../stp_bank_fpx_bank_muamalat@3x.png | Bin 2204 -> 0 bytes .../Contents.json | 23 - .../stp_bank_fpx_bank_rakyat.png | Bin 595 -> 0 bytes .../stp_bank_fpx_bank_rakyat@2x.png | Bin 1098 -> 0 bytes .../stp_bank_fpx_bank_rakyat@3x.png | Bin 1583 -> 0 bytes .../stp_bank_fpx_bsn.imageset/Contents.json | 23 - .../stp_bank_fpx_bsn.png | Bin 885 -> 0 bytes .../stp_bank_fpx_bsn@2x.png | Bin 1874 -> 0 bytes .../stp_bank_fpx_bsn@3x.png | Bin 2235 -> 0 bytes .../stp_bank_fpx_cimb.imageset/Contents.json | 23 - .../stp_bank_fpx_cimb.png | Bin 305 -> 0 bytes .../stp_bank_fpx_cimb@2x.png | Bin 462 -> 0 bytes .../stp_bank_fpx_cimb@3x.png | Bin 622 -> 0 bytes .../Contents.json | 23 - .../stp_bank_fpx_hong_leong_bank.png | Bin 923 -> 0 bytes .../stp_bank_fpx_hong_leong_bank@2x.png | Bin 1835 -> 0 bytes .../stp_bank_fpx_hong_leong_bank@3x.png | Bin 2647 -> 0 bytes .../stp_bank_fpx_hsbc.imageset/Contents.json | 23 - .../stp_bank_fpx_hsbc.png | Bin 411 -> 0 bytes .../stp_bank_fpx_hsbc@2x.png | Bin 785 -> 0 bytes .../stp_bank_fpx_hsbc@3x.png | Bin 1205 -> 0 bytes .../stp_bank_fpx_kfh.imageset/Contents.json | 23 - .../stp_bank_fpx_kfh.png | Bin 1088 -> 0 bytes .../stp_bank_fpx_kfh@2x.png | Bin 1882 -> 0 bytes .../stp_bank_fpx_kfh@3x.png | Bin 2637 -> 0 bytes .../Contents.json | 23 - .../stp_bank_fpx_maybank2e.png | Bin 1376 -> 0 bytes .../stp_bank_fpx_maybank2e@2x.png | Bin 2377 -> 0 bytes .../stp_bank_fpx_maybank2e@3x.png | Bin 4570 -> 0 bytes .../Contents.json | 23 - .../stp_bank_fpx_maybank2u.png | Bin 1376 -> 0 bytes .../stp_bank_fpx_maybank2u@2x.png | Bin 2377 -> 0 bytes .../stp_bank_fpx_maybank2u@3x.png | Bin 4570 -> 0 bytes .../stp_bank_fpx_ocbc.imageset/Contents.json | 23 - .../stp_bank_fpx_ocbc.png | Bin 880 -> 0 bytes .../stp_bank_fpx_ocbc@2x.png | Bin 1770 -> 0 bytes .../stp_bank_fpx_ocbc@3x.png | Bin 2054 -> 0 bytes .../Contents.json | 23 - .../stp_bank_fpx_public_bank.png | Bin 505 -> 0 bytes .../stp_bank_fpx_public_bank@2x.png | Bin 927 -> 0 bytes .../stp_bank_fpx_public_bank@3x.png | Bin 1231 -> 0 bytes .../stp_bank_fpx_rhb.imageset/Contents.json | 23 - .../stp_bank_fpx_rhb.png | Bin 681 -> 0 bytes .../stp_bank_fpx_rhb@2x.png | Bin 1299 -> 0 bytes .../stp_bank_fpx_rhb@3x.png | Bin 1876 -> 0 bytes .../Contents.json | 23 - .../stp_bank_fpx_standard_chartered.png | Bin 890 -> 0 bytes .../stp_bank_fpx_standard_chartered@2x.png | Bin 1807 -> 0 bytes .../stp_bank_fpx_standard_chartered@3x.png | Bin 2596 -> 0 bytes .../stp_bank_fpx_uob.imageset/Contents.json | 23 - .../stp_bank_fpx_uob.png | Bin 323 -> 0 bytes .../stp_bank_fpx_uob@2x.png | Bin 560 -> 0 bytes .../stp_bank_fpx_uob@3x.png | Bin 757 -> 0 bytes .../stp_fpx_big_logo.imageset/Contents.json | 23 - .../stp_fpx_big_logo.png | Bin 3536 -> 0 bytes .../stp_fpx_big_logo@2x.png | Bin 7650 -> 0 bytes .../stp_fpx_big_logo@3x.png | Bin 12473 -> 0 bytes .../FPX/stp_fpx_logo.imageset/Contents.json | 23 - .../stp_fpx_logo.imageset/stp_fpx_logo.png | Bin 564 -> 0 bytes .../stp_fpx_logo.imageset/stp_fpx_logo@2x.png | Bin 1092 -> 0 bytes .../stp_fpx_logo.imageset/stp_fpx_logo@3x.png | Bin 1607 -> 0 bytes .../Enums+CustomStringConvertible.swift | 63 - ...rizationViewController+Stripe_Blocks.swift | 163 --- .../Source/STPAPIClient+BasicUI.swift | 178 --- .../STPAPIClient+PushProvisioning.swift | 6 + .../Source/STPAddCardViewController.swift | 1001 ------------- .../StripeiOS/Source/STPAddress+BasicUI.swift | 212 --- .../Source/STPAddressFieldTableViewCell.swift | 509 ------- .../Source/STPAddressViewModel.swift | 434 ------ .../Source/STPAnalyticsClient+BasicUI.swift | 160 --- .../Source/STPApplePayPaymentOption.swift | 51 - .../Source/STPBackendAPIAdapter.swift | 86 -- .../STPBankSelectionTableViewCell.swift | 124 -- .../STPBankSelectionViewController.swift | 300 ---- .../STPBasicUIAnalyticsSerializer.swift | 84 -- Stripe/StripeiOS/Source/STPBlocks.swift | 44 - Stripe/StripeiOS/Source/STPCameraView.swift | 77 - Stripe/StripeiOS/Source/STPCard+BasicUI.swift | 30 - Stripe/StripeiOS/Source/STPCardScanner.swift | 488 ------- .../Source/STPCardScannerTableViewCell.swift | 67 - .../Source/STPCardValidationState.swift | 9 - .../Source/STPCoreScrollViewController.swift | 62 - .../Source/STPCoreTableViewController.swift | 54 - .../Source/STPCoreViewController.swift | 162 --- .../StripeiOS/Source/STPCustomerContext.swift | 419 ------ Stripe/StripeiOS/Source/STPEphemeralKey.swift | 2 - .../Source/STPFPXBankStatusResponse.swift | 44 - Stripe/StripeiOS/Source/STPImageLibrary.swift | 94 -- ...PIntentActionLinkAuthenticateAccount.swift | 33 - .../StripeiOS/Source/STPLocalizedString.swift | 16 - .../STPPaymentActivityIndicatorView.swift | 135 -- .../Source/STPPaymentCardTextFieldCell.swift | 91 -- .../Source/STPPaymentConfiguration.swift | 244 ---- .../StripeiOS/Source/STPPaymentContext.swift | 1266 ----------------- .../Source/STPPaymentContextAmountModel.swift | 96 -- .../STPPaymentIntentParams+BasicUI.swift | 22 - .../Source/STPPaymentMethod+BasicUI.swift | 94 -- .../STPPaymentMethodParams+BasicUI.swift | 57 - .../StripeiOS/Source/STPPaymentOption.swift | 36 - .../STPPaymentOptionTableViewCell.swift | 326 ----- .../Source/STPPaymentOptionTuple.swift | 88 -- ...PaymentOptionsInternalViewController.swift | 593 -------- .../STPPaymentOptionsViewController.swift | 662 --------- .../StripeiOS/Source/STPPaymentResult.swift | 43 - .../Source/STPSectionHeaderView.swift | 161 --- .../STPShippingAddressViewController.swift | 674 --------- .../STPShippingMethodTableViewCell.swift | 147 -- .../STPShippingMethodsViewController.swift | 211 --- .../StripeiOS/Source/STPSource+BasicUI.swift | 74 - Stripe/StripeiOS/Source/STPTheme.swift | 212 --- .../StripeiOS/Source/STPUserInformation.swift | 42 - .../StripeiOS/Source/String+Localized.swift | 22 - .../Source/StripeBundleLocator.swift | 20 - .../Source/UIBarButtonItem+Stripe.swift | 54 - .../Source/UINavigationBar+Stripe_Theme.swift | 142 -- ...vigationController+Stripe_Completion.swift | 61 - .../UITableViewCell+Stripe_Borders.swift | 103 -- .../UIToolbar+Stripe_InputAccessory.swift | 38 - .../Source/UIView+Stripe_FirstResponder.swift | 24 - .../Source/UIView+Stripe_SafeAreaBounds.swift | 24 - ...ewController+Stripe_KeyboardAvoiding.swift | 166 --- ...ontroller+Stripe_NavigationItemProxy.swift | 38 - ...ntroller+Stripe_ParentViewController.swift | 50 - .../Source/UserDefaults+Stripe.swift | 29 - ...hotTestCase+STPViewControllerLoading.swift | 36 - .../NSDecimalNumber+StripeTest.swift | 23 - .../StripeiOSTests/PaymentAnalyticTest.swift | 30 - Stripe/StripeiOSTests/STPAPIClientTest.swift | 20 +- .../STPAPISettingsObjCBridgeTest.m | 84 -- ...wControllerLocalizationSnapshotTests.swift | 101 -- .../STPAddCardViewControllerTest.swift | 290 ---- Stripe/StripeiOSTests/STPAddressTests.swift | 281 ---- .../STPAddressViewModelTest.swift | 205 --- .../STPAnalyticsClientPaymentsTest.swift | 85 -- .../STPApplePayPaymentOptionTest.swift | 40 - Stripe/StripeiOSTests/STPBlocks.h | 49 - Stripe/StripeiOSTests/STPCardTest.swift | 6 - .../STPCustomerContextTest.swift | 671 --------- .../StripeiOSTests/STPEphemeralKeyTest.swift | 1 - .../StripeiOSTests/STPImageLibraryTest.swift | 124 -- Stripe/StripeiOSTests/STPMocks.h | 34 - Stripe/StripeiOSTests/STPMocks.m | 55 - .../STPPaymentConfigurationTest.m | 141 -- .../STPPaymentContextApplePayTest.swift | 204 --- .../STPPaymentContextSnapshotTests.swift | 84 -- ...wControllerLocalizationSnapshotTests.swift | 102 -- .../STPPaymentOptionsViewControllerTest.swift | 351 ----- .../STPPhoneNumberValidatorTest.swift | 45 - ...wControllerLocalizationSnapshotTests.swift | 113 -- ...STPShippingAddressViewControllerTest.swift | 114 -- ...wControllerLocalizationSnapshotTests.swift | 76 - Stripe/StripeiOSTests/STPSourceTest.swift | 66 - Stripe/StripeiOSTests/STPSwiftFixtures.swift | 73 - ...PUIVCStripeParentViewControllerTests.swift | 39 - .../StripeiOS Tests-Bridging-Header.h | 2 - .../UINavigationBar+StripeTest.m | 52 - .../UserDefaults+StripeTest.swift | 6 - .../Source/Helpers/PaymentsSDKVariant.swift | 4 - .../PaymentSheet/PaymentMethodType.swift | 18 +- .../STPPaymentMethodParams.swift | 28 - .../en.lproj/Localizable.strings | 3 - .../Helpers/STPPhoneNumberValidator.swift | 20 - .../Source/Helpers/STPPromise.swift | 12 - .../Source/Helpers/String+Localized.swift | 4 - .../en.lproj/Localizable.strings | 3 - .../Source/Helpers/String+Localized.swift | 4 - .../Common/IntegrationMethods.swift | 5 - .../project.pbxproj | 8 +- .../IntegrationTester/Source/MainMenu.swift | 2 - .../Source/Views/FPXView.swift | 81 -- .../IntegrationTesterUITests.swift | 23 +- modules.yaml | 1 - 245 files changed, 70 insertions(+), 17838 deletions(-) delete mode 100644 Example/Non-Card Payment Examples/Non-Card Payment Examples/FPXExampleViewController.h delete mode 100644 Example/Non-Card Payment Examples/Non-Card Payment Examples/FPXExampleViewController.m delete mode 100644 Stripe/StripeiOS/Resources/Localizations/bg-BG.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/ca-ES.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/cs-CZ.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/da.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/de.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/el-GR.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/en-GB.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/en.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/es-419.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/es.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/et-EE.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/fi.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/fil.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/fr-CA.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/fr.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/hr.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/hu.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/id.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/it.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/ja.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/ko.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/lt-LT.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/lv-LV.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/ms-MY.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/mt.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/nb.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/nl.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/nn-NO.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/pl-PL.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/pt-BR.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/pt-PT.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/ro-RO.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/ru.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/sk-SK.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/sl-SI.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/sv.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/tk.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/tr.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/vi.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/zh-HK.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/zh-Hans.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/Localizations/zh-Hant.lproj/Localizable.strings delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/Contents.json delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_affin_bank.imageset/Contents.json delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_affin_bank.imageset/stp_bank_fpx_affin_bank.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_affin_bank.imageset/stp_bank_fpx_affin_bank@2x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_affin_bank.imageset/stp_bank_fpx_affin_bank@3x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_alliance_bank.imageset/Contents.json delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_alliance_bank.imageset/stp_bank_fpx_alliance_bank.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_alliance_bank.imageset/stp_bank_fpx_alliance_bank@2x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_alliance_bank.imageset/stp_bank_fpx_alliance_bank@3x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_ambank.imageset/Contents.json delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_ambank.imageset/stp_bank_fpx_ambank.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_ambank.imageset/stp_bank_fpx_ambank@2x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_ambank.imageset/stp_bank_fpx_ambank@3x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bank_islam.imageset/Contents.json delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bank_islam.imageset/stp_bank_fpx_bank_islam.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bank_islam.imageset/stp_bank_fpx_bank_islam@2x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bank_islam.imageset/stp_bank_fpx_bank_islam@3x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bank_muamalat.imageset/Contents.json delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bank_muamalat.imageset/stp_bank_fpx_bank_muamalat.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bank_muamalat.imageset/stp_bank_fpx_bank_muamalat@2x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bank_muamalat.imageset/stp_bank_fpx_bank_muamalat@3x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bank_rakyat.imageset/Contents.json delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bank_rakyat.imageset/stp_bank_fpx_bank_rakyat.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bank_rakyat.imageset/stp_bank_fpx_bank_rakyat@2x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bank_rakyat.imageset/stp_bank_fpx_bank_rakyat@3x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bsn.imageset/Contents.json delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bsn.imageset/stp_bank_fpx_bsn.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bsn.imageset/stp_bank_fpx_bsn@2x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bsn.imageset/stp_bank_fpx_bsn@3x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_cimb.imageset/Contents.json delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_cimb.imageset/stp_bank_fpx_cimb.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_cimb.imageset/stp_bank_fpx_cimb@2x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_cimb.imageset/stp_bank_fpx_cimb@3x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_hong_leong_bank.imageset/Contents.json delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_hong_leong_bank.imageset/stp_bank_fpx_hong_leong_bank.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_hong_leong_bank.imageset/stp_bank_fpx_hong_leong_bank@2x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_hong_leong_bank.imageset/stp_bank_fpx_hong_leong_bank@3x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_hsbc.imageset/Contents.json delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_hsbc.imageset/stp_bank_fpx_hsbc.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_hsbc.imageset/stp_bank_fpx_hsbc@2x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_hsbc.imageset/stp_bank_fpx_hsbc@3x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_kfh.imageset/Contents.json delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_kfh.imageset/stp_bank_fpx_kfh.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_kfh.imageset/stp_bank_fpx_kfh@2x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_kfh.imageset/stp_bank_fpx_kfh@3x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_maybank2e.imageset/Contents.json delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_maybank2e.imageset/stp_bank_fpx_maybank2e.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_maybank2e.imageset/stp_bank_fpx_maybank2e@2x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_maybank2e.imageset/stp_bank_fpx_maybank2e@3x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_maybank2u.imageset/Contents.json delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_maybank2u.imageset/stp_bank_fpx_maybank2u.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_maybank2u.imageset/stp_bank_fpx_maybank2u@2x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_maybank2u.imageset/stp_bank_fpx_maybank2u@3x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_ocbc.imageset/Contents.json delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_ocbc.imageset/stp_bank_fpx_ocbc.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_ocbc.imageset/stp_bank_fpx_ocbc@2x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_ocbc.imageset/stp_bank_fpx_ocbc@3x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_public_bank.imageset/Contents.json delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_public_bank.imageset/stp_bank_fpx_public_bank.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_public_bank.imageset/stp_bank_fpx_public_bank@2x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_public_bank.imageset/stp_bank_fpx_public_bank@3x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_rhb.imageset/Contents.json delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_rhb.imageset/stp_bank_fpx_rhb.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_rhb.imageset/stp_bank_fpx_rhb@2x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_rhb.imageset/stp_bank_fpx_rhb@3x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_standard_chartered.imageset/Contents.json delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_standard_chartered.imageset/stp_bank_fpx_standard_chartered.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_standard_chartered.imageset/stp_bank_fpx_standard_chartered@2x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_standard_chartered.imageset/stp_bank_fpx_standard_chartered@3x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_uob.imageset/Contents.json delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_uob.imageset/stp_bank_fpx_uob.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_uob.imageset/stp_bank_fpx_uob@2x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_uob.imageset/stp_bank_fpx_uob@3x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_fpx_big_logo.imageset/Contents.json delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_fpx_big_logo.imageset/stp_fpx_big_logo.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_fpx_big_logo.imageset/stp_fpx_big_logo@2x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_fpx_big_logo.imageset/stp_fpx_big_logo@3x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_fpx_logo.imageset/Contents.json delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_fpx_logo.imageset/stp_fpx_logo.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_fpx_logo.imageset/stp_fpx_logo@2x.png delete mode 100644 Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_fpx_logo.imageset/stp_fpx_logo@3x.png delete mode 100644 Stripe/StripeiOS/Source/Enums+CustomStringConvertible.swift delete mode 100644 Stripe/StripeiOS/Source/STPAPIClient+BasicUI.swift delete mode 100644 Stripe/StripeiOS/Source/STPAddCardViewController.swift delete mode 100644 Stripe/StripeiOS/Source/STPAddress+BasicUI.swift delete mode 100644 Stripe/StripeiOS/Source/STPAddressFieldTableViewCell.swift delete mode 100644 Stripe/StripeiOS/Source/STPAddressViewModel.swift delete mode 100644 Stripe/StripeiOS/Source/STPAnalyticsClient+BasicUI.swift delete mode 100644 Stripe/StripeiOS/Source/STPApplePayPaymentOption.swift delete mode 100644 Stripe/StripeiOS/Source/STPBackendAPIAdapter.swift delete mode 100644 Stripe/StripeiOS/Source/STPBankSelectionTableViewCell.swift delete mode 100644 Stripe/StripeiOS/Source/STPBankSelectionViewController.swift delete mode 100644 Stripe/StripeiOS/Source/STPBasicUIAnalyticsSerializer.swift delete mode 100644 Stripe/StripeiOS/Source/STPBlocks.swift delete mode 100644 Stripe/StripeiOS/Source/STPCameraView.swift delete mode 100644 Stripe/StripeiOS/Source/STPCard+BasicUI.swift delete mode 100644 Stripe/StripeiOS/Source/STPCardScanner.swift delete mode 100644 Stripe/StripeiOS/Source/STPCardScannerTableViewCell.swift delete mode 100644 Stripe/StripeiOS/Source/STPCardValidationState.swift delete mode 100644 Stripe/StripeiOS/Source/STPCoreScrollViewController.swift delete mode 100644 Stripe/StripeiOS/Source/STPCoreTableViewController.swift delete mode 100644 Stripe/StripeiOS/Source/STPCoreViewController.swift delete mode 100644 Stripe/StripeiOS/Source/STPCustomerContext.swift delete mode 100644 Stripe/StripeiOS/Source/STPFPXBankStatusResponse.swift delete mode 100644 Stripe/StripeiOS/Source/STPImageLibrary.swift delete mode 100644 Stripe/StripeiOS/Source/STPIntentActionLinkAuthenticateAccount.swift delete mode 100644 Stripe/StripeiOS/Source/STPLocalizedString.swift delete mode 100644 Stripe/StripeiOS/Source/STPPaymentActivityIndicatorView.swift delete mode 100644 Stripe/StripeiOS/Source/STPPaymentCardTextFieldCell.swift delete mode 100644 Stripe/StripeiOS/Source/STPPaymentConfiguration.swift delete mode 100644 Stripe/StripeiOS/Source/STPPaymentContext.swift delete mode 100644 Stripe/StripeiOS/Source/STPPaymentContextAmountModel.swift delete mode 100644 Stripe/StripeiOS/Source/STPPaymentIntentParams+BasicUI.swift delete mode 100644 Stripe/StripeiOS/Source/STPPaymentMethod+BasicUI.swift delete mode 100644 Stripe/StripeiOS/Source/STPPaymentMethodParams+BasicUI.swift delete mode 100644 Stripe/StripeiOS/Source/STPPaymentOption.swift delete mode 100644 Stripe/StripeiOS/Source/STPPaymentOptionTableViewCell.swift delete mode 100644 Stripe/StripeiOS/Source/STPPaymentOptionTuple.swift delete mode 100644 Stripe/StripeiOS/Source/STPPaymentOptionsInternalViewController.swift delete mode 100644 Stripe/StripeiOS/Source/STPPaymentOptionsViewController.swift delete mode 100644 Stripe/StripeiOS/Source/STPPaymentResult.swift delete mode 100644 Stripe/StripeiOS/Source/STPSectionHeaderView.swift delete mode 100644 Stripe/StripeiOS/Source/STPShippingAddressViewController.swift delete mode 100644 Stripe/StripeiOS/Source/STPShippingMethodTableViewCell.swift delete mode 100644 Stripe/StripeiOS/Source/STPShippingMethodsViewController.swift delete mode 100644 Stripe/StripeiOS/Source/STPSource+BasicUI.swift delete mode 100644 Stripe/StripeiOS/Source/STPTheme.swift delete mode 100644 Stripe/StripeiOS/Source/STPUserInformation.swift delete mode 100644 Stripe/StripeiOS/Source/String+Localized.swift delete mode 100644 Stripe/StripeiOS/Source/StripeBundleLocator.swift delete mode 100644 Stripe/StripeiOS/Source/UIBarButtonItem+Stripe.swift delete mode 100644 Stripe/StripeiOS/Source/UINavigationBar+Stripe_Theme.swift delete mode 100644 Stripe/StripeiOS/Source/UINavigationController+Stripe_Completion.swift delete mode 100644 Stripe/StripeiOS/Source/UITableViewCell+Stripe_Borders.swift delete mode 100644 Stripe/StripeiOS/Source/UIToolbar+Stripe_InputAccessory.swift delete mode 100644 Stripe/StripeiOS/Source/UIView+Stripe_FirstResponder.swift delete mode 100644 Stripe/StripeiOS/Source/UIView+Stripe_SafeAreaBounds.swift delete mode 100644 Stripe/StripeiOS/Source/UIViewController+Stripe_KeyboardAvoiding.swift delete mode 100644 Stripe/StripeiOS/Source/UIViewController+Stripe_NavigationItemProxy.swift delete mode 100644 Stripe/StripeiOS/Source/UIViewController+Stripe_ParentViewController.swift delete mode 100644 Stripe/StripeiOS/Source/UserDefaults+Stripe.swift delete mode 100644 Stripe/StripeiOSTests/PaymentAnalyticTest.swift delete mode 100644 Stripe/StripeiOSTests/STPAPISettingsObjCBridgeTest.m delete mode 100644 Stripe/StripeiOSTests/STPAddCardViewControllerLocalizationSnapshotTests.swift delete mode 100644 Stripe/StripeiOSTests/STPAddCardViewControllerTest.swift delete mode 100644 Stripe/StripeiOSTests/STPAddressViewModelTest.swift delete mode 100644 Stripe/StripeiOSTests/STPApplePayPaymentOptionTest.swift delete mode 100644 Stripe/StripeiOSTests/STPCustomerContextTest.swift delete mode 100644 Stripe/StripeiOSTests/STPMocks.h delete mode 100644 Stripe/StripeiOSTests/STPMocks.m delete mode 100644 Stripe/StripeiOSTests/STPPaymentConfigurationTest.m delete mode 100644 Stripe/StripeiOSTests/STPPaymentContextApplePayTest.swift delete mode 100644 Stripe/StripeiOSTests/STPPaymentContextSnapshotTests.swift delete mode 100644 Stripe/StripeiOSTests/STPPaymentOptionsViewControllerLocalizationSnapshotTests.swift delete mode 100644 Stripe/StripeiOSTests/STPPaymentOptionsViewControllerTest.swift delete mode 100644 Stripe/StripeiOSTests/STPShippingAddressViewControllerLocalizationSnapshotTests.swift delete mode 100644 Stripe/StripeiOSTests/STPShippingAddressViewControllerTest.swift delete mode 100644 Stripe/StripeiOSTests/STPShippingMethodsViewControllerLocalizationSnapshotTests.swift delete mode 100644 Stripe/StripeiOSTests/STPUIVCStripeParentViewControllerTests.swift delete mode 100644 Stripe/StripeiOSTests/UINavigationBar+StripeTest.m delete mode 100644 Testers/IntegrationTester/IntegrationTester/Source/Views/FPXView.swift diff --git a/Example/Non-Card Payment Examples/Non-Card Payment Examples.xcodeproj/project.pbxproj b/Example/Non-Card Payment Examples/Non-Card Payment Examples.xcodeproj/project.pbxproj index 6973176de72..503a57fae73 100644 --- a/Example/Non-Card Payment Examples/Non-Card Payment Examples.xcodeproj/project.pbxproj +++ b/Example/Non-Card Payment Examples/Non-Card Payment Examples.xcodeproj/project.pbxproj @@ -61,7 +61,6 @@ CAC3A0322C2F1184007BC888 /* SunbitExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAC3A0312C2F1184007BC888 /* SunbitExampleViewController.swift */; }; CAC3A03A2C2F2AB5007BC888 /* BillieExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAC3A0392C2F2AB5007BC888 /* BillieExampleViewController.swift */; }; CAC80EBB2C333164001E3D0D /* SatispayExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAC80EBA2C333164001E3D0D /* SatispayExampleViewController.swift */; }; - CD7FC52A94895E322DB5B3D9 /* FPXExampleViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4387CA3F60553DB73F05BDC9 /* FPXExampleViewController.m */; }; CF0983C679CA4196DF4DA37D /* PayPalExampleViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B0D62F7B5288E04FB14DBFFF /* PayPalExampleViewController.m */; }; D46A05D88420B85C1B275640 /* MyAPIClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 0AA7CAC14165BD4EFB39E7C5 /* MyAPIClient.m */; }; D9507571006167E5188CA5BD /* GiropayExampleViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D896A3BF93A934C07AB388E /* GiropayExampleViewController.m */; }; @@ -114,7 +113,6 @@ 32C7B53B74E206CF2A2DF38C /* USBankAccountConnectionsExampleViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = USBankAccountConnectionsExampleViewController.swift; sourceTree = ""; }; 3300883AEEEF23265C6CA4BE /* Stripe3DS2.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Stripe3DS2.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 39FD1595EB5ACDAB0DFB4A7E /* NonCardPaymentExamples.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NonCardPaymentExamples.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 4387CA3F60553DB73F05BDC9 /* FPXExampleViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FPXExampleViewController.m; sourceTree = ""; }; 479C1F3AC76FF0DAF749DA69 /* Non-Card Payment Examples.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Non-Card Payment Examples.entitlements"; sourceTree = ""; }; 4C003C0154CCBA34AF5CAC43 /* EPSExampleViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EPSExampleViewController.m; sourceTree = ""; }; 4C7C09286B3FF62A1562B3FB /* KlarnaExampleViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KlarnaExampleViewController.swift; sourceTree = ""; }; @@ -138,7 +136,6 @@ 86A1A58725F3254624BE3C0B /* GiropayExampleViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GiropayExampleViewController.h; sourceTree = ""; }; 8B425785CB5AE1A15209D100 /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/Localizable.strings; sourceTree = ""; }; 8B4FE9E774494C148EBFDD0F /* Non-Card-Payment-Examples-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Non-Card-Payment-Examples-Debug.xcconfig"; sourceTree = ""; }; - 8E672E24890CD3B941069941 /* FPXExampleViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FPXExampleViewController.h; sourceTree = ""; }; 90081BE52D2A12E3C962E386 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; 934226D0B321DB46199AF4F2 /* BrowseExamplesViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BrowseExamplesViewController.h; sourceTree = ""; }; 951B76B22A5088E944157C23 /* StripeApplePay.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = StripeApplePay.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -276,8 +273,6 @@ BC2E15A342CA3A2EA76EE1D6 /* Constants.m */, 8246202E37E84C97DB160C87 /* EPSExampleViewController.h */, 4C003C0154CCBA34AF5CAC43 /* EPSExampleViewController.m */, - 8E672E24890CD3B941069941 /* FPXExampleViewController.h */, - 4387CA3F60553DB73F05BDC9 /* FPXExampleViewController.m */, 86A1A58725F3254624BE3C0B /* GiropayExampleViewController.h */, 2D896A3BF93A934C07AB388E /* GiropayExampleViewController.m */, 311E3343A1F8432A0B56CEA5 /* GrabPayExampleViewController.swift */, @@ -444,7 +439,6 @@ 0AC26F0F597E114044E9A15A /* Constants.m in Sources */, 2965738ADB4C4325D7BDEB97 /* EPSExampleViewController.m in Sources */, CAC80EBB2C333164001E3D0D /* SatispayExampleViewController.swift in Sources */, - CD7FC52A94895E322DB5B3D9 /* FPXExampleViewController.m in Sources */, D9507571006167E5188CA5BD /* GiropayExampleViewController.m in Sources */, 80466B86A1F4896FE7811E9D /* GrabPayExampleViewController.swift in Sources */, 61951FBB2B8674EC005F90BE /* AmazonPayExampleViewController.swift in Sources */, diff --git a/Example/Non-Card Payment Examples/Non-Card Payment Examples/BrowseExamplesViewController.m b/Example/Non-Card Payment Examples/Non-Card Payment Examples/BrowseExamplesViewController.m index dc9d4b80f5c..d7f3f970e4b 100644 --- a/Example/Non-Card Payment Examples/Non-Card Payment Examples/BrowseExamplesViewController.m +++ b/Example/Non-Card Payment Examples/Non-Card Payment Examples/BrowseExamplesViewController.m @@ -15,7 +15,6 @@ #import "ApplePayExampleViewController.h" #import "AUBECSDebitExampleViewController.h" #import "BancontactExampleViewController.h" -#import "FPXExampleViewController.h" #import "GiropayExampleViewController.h" #import "iDEALExampleViewController.h" #import "Przelewy24ExampleViewController.h" @@ -191,192 +190,186 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath break; } case 3: { - FPXExampleViewController *exampleVC = [FPXExampleViewController new]; - exampleVC.delegate = self; - viewController = exampleVC; - break; - } - case 4: { SEPADebitExampleViewController *exampleVC = [SEPADebitExampleViewController new]; exampleVC.delegate = self; viewController = exampleVC; break; } - case 5: { + case 4: { iDEALExampleViewController *exampleVC = [iDEALExampleViewController new]; exampleVC.delegate = self; viewController = exampleVC; break; } - case 6: { + case 5: { AlipayExampleViewController *exampleVC = [AlipayExampleViewController new]; exampleVC.delegate = self; viewController = exampleVC; break; } - case 7: { + case 6: { KlarnaSourcesExampleViewController *exampleVC = [KlarnaSourcesExampleViewController new]; exampleVC.delegate = self; viewController = exampleVC; break; } - case 8: { + case 7: { BacsDebitExampleViewController *exampleVC = [BacsDebitExampleViewController new]; exampleVC.delegate = self; viewController = exampleVC; break; } - case 9: { + case 8: { AUBECSDebitExampleViewController *exampleVC = [AUBECSDebitExampleViewController new]; exampleVC.delegate = self; viewController = exampleVC; break; } - case 10: { + case 9: { GiropayExampleViewController *exampleVC = [GiropayExampleViewController new]; exampleVC.delegate = self; viewController = exampleVC; break; } - case 11: { + case 10: { Przelewy24ExampleViewController *exampleVC = [Przelewy24ExampleViewController new]; exampleVC.delegate = self; viewController = exampleVC; break; } - case 12: { + case 11: { BancontactExampleViewController *exampleVC = [BancontactExampleViewController new]; exampleVC.delegate = self; viewController = exampleVC; break; } - case 13: { + case 12: { EPSExampleViewController *exampleVC = [EPSExampleViewController new]; exampleVC.delegate = self; viewController = exampleVC; break; } - case 14: { + case 13: { SofortExampleViewController *exampleVC = [SofortExampleViewController new]; exampleVC.delegate = self; viewController = exampleVC; break; } - case 15: { + case 14: { GrabPayExampleViewController *exampleVC = [GrabPayExampleViewController new]; exampleVC.delegate = self; viewController = exampleVC; break; } - case 16: { + case 15: { OXXOExampleViewController *exampleVC = [OXXOExampleViewController new]; exampleVC.delegate = self; viewController = exampleVC; break; } - case 17: { + case 16: { AfterpayClearpayExampleViewController *exampleVC = [AfterpayClearpayExampleViewController new]; exampleVC.delegate = self; viewController = exampleVC; break; } - case 18: { + case 17: { BoletoExampleViewController *exampleVC = [BoletoExampleViewController new]; exampleVC.delegate = self; viewController = exampleVC; break; } - case 19: { + case 18: { KlarnaExampleViewController *exampleVC = [KlarnaExampleViewController new]; exampleVC.delegate = self; viewController = exampleVC; break; } - case 20: { + case 19: { AffirmExampleViewController *exampleVC = [AffirmExampleViewController new]; exampleVC.delegate = self; viewController = exampleVC; break; } - case 21: { + case 20: { USBankAccountExampleViewController *exampleVC = [USBankAccountExampleViewController new]; exampleVC.delegate = self; viewController = exampleVC; break; } - case 22: { + case 21: { USBankAccountFinancialConnectionsExampleViewController *exampleVC = [USBankAccountFinancialConnectionsExampleViewController new]; exampleVC.delegate = self; viewController = exampleVC; break; } - case 23: { + case 22: { CashAppExampleViewController *exampleVC = [CashAppExampleViewController new]; exampleVC.delegate = self; viewController = exampleVC; break; } - case 24: { + case 23: { BlikExampleViewController *exampleVC = [BlikExampleViewController new]; exampleVC.delegate = self; viewController = exampleVC; break; } - case 25: { + case 24: { PayPalExampleViewController *exampleVC = [PayPalExampleViewController new]; exampleVC.delegate = self; viewController = exampleVC; break; } - case 26: { + case 25: { RevolutPayExampleViewController *exampleVC = [RevolutPayExampleViewController new]; exampleVC.delegate = self; viewController = exampleVC; break; } - case 27: { + case 26: { SwishExampleViewController *exampleVC = [SwishExampleViewController new]; exampleVC.delegate = self; viewController = exampleVC; break; } - case 28: { + case 27: { AmazonPayExampleViewController *exampleVC = [AmazonPayExampleViewController new]; exampleVC.delegate = self; viewController = exampleVC; break; } - case 29: { + case 28: { AlmaExampleViewController *exampleVC = [AlmaExampleViewController new]; exampleVC.delegate = self; viewController = exampleVC; break; } - case 30: { + case 29: { MultibancoExampleViewController *exampleVC = [MultibancoExampleViewController new]; exampleVC.delegate = self; viewController = exampleVC; break; } - case 31: { + case 30: { MobilePayExampleViewController *exampleVC = [MobilePayExampleViewController new]; exampleVC.delegate = self; viewController = exampleVC; break; } - case 32: { + case 31: { SunbitExampleViewController *exampleVC = [SunbitExampleViewController new]; exampleVC.delegate = self; viewController = exampleVC; break; } - case 33: { + case 32: { BillieExampleViewController *exampleVC = [BillieExampleViewController new]; exampleVC.delegate = self; viewController = exampleVC; break; } - case 34: { + case 33: { SatispayExampleViewController *exampleVC = [SatispayExampleViewController new]; exampleVC.delegate = self; viewController = exampleVC; diff --git a/Example/Non-Card Payment Examples/Non-Card Payment Examples/FPXExampleViewController.h b/Example/Non-Card Payment Examples/Non-Card Payment Examples/FPXExampleViewController.h deleted file mode 100644 index e06a9124969..00000000000 --- a/Example/Non-Card Payment Examples/Non-Card Payment Examples/FPXExampleViewController.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// FPXExampleViewController.h -// Non-Card Payment Examples -// -// Created by David Estes on 8/26/19. -// Copyright © 2019 Stripe. All rights reserved. -// - -#import - -@protocol ExampleViewControllerDelegate; - -@interface FPXExampleViewController : UIViewController - -@property (nonatomic, weak) id delegate; - -@end diff --git a/Example/Non-Card Payment Examples/Non-Card Payment Examples/FPXExampleViewController.m b/Example/Non-Card Payment Examples/Non-Card Payment Examples/FPXExampleViewController.m deleted file mode 100644 index 8ca6ec3e525..00000000000 --- a/Example/Non-Card Payment Examples/Non-Card Payment Examples/FPXExampleViewController.m +++ /dev/null @@ -1,144 +0,0 @@ -// -// FPXExampleViewController.m -// Non-Card Payment Examples -// -// Created by David Estes on 8/26/19. -// Copyright © 2019 Stripe. All rights reserved. -// - -@import Stripe; -@import StripeCore; -#import "FPXExampleViewController.h" -#import "BrowseExamplesViewController.h" -#import "MyAPIClient.h" - -/** - This example demonstrates using PaymentIntents to accept payments using FPX, a popular - payment method in Malaysia. - First, we ask our server to set up a PaymentIntent. We create a PaymentMethodParams with the - details of our selected FPX-supporting bank, then call STPPaymentHandler to confirm the PaymentIntent - using the Stripe API. - */ -@interface FPXExampleViewController () -@property (nonatomic, weak) UIButton *payButton; -@property (nonatomic, weak) UILabel *waitingLabel; -@property (nonatomic, weak) UIActivityIndicatorView *activityIndicator; -@end - -@implementation FPXExampleViewController - -- (void)viewDidLoad { - [super viewDidLoad]; - self.view.backgroundColor = [UIColor systemBackgroundColor]; - self.title = @"FPX"; - self.edgesForExtendedLayout = UIRectEdgeNone; - - UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; - [button setTitle:@"Pay RM2.34 with Bank Account (FPX)" forState:UIControlStateNormal]; - [button sizeToFit]; - [button addTarget:self action:@selector(selectBank) forControlEvents:UIControlEventTouchUpInside]; - self.payButton = button; - [self.view addSubview:button]; - - UILabel *label = [UILabel new]; - label.text = @"Waiting for payment authorization"; - [label sizeToFit]; - label.textColor = [UIColor secondaryLabelColor]; - label.alpha = 0; - [self.view addSubview:label]; - self.waitingLabel = label; - - UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleMedium]; - activityIndicator.hidesWhenStopped = YES; - self.activityIndicator = activityIndicator; - [self.view addSubview:activityIndicator]; -} - -- (void)viewDidLayoutSubviews { - [super viewDidLayoutSubviews]; - CGFloat padding = 15; - CGRect bounds = self.view.bounds; - self.payButton.center = CGPointMake(CGRectGetMidX(bounds), 100); - self.activityIndicator.center = CGPointMake(CGRectGetMidX(bounds), - CGRectGetMaxY(self.payButton.frame) + padding*2); - self.waitingLabel.center = CGPointMake(CGRectGetMidX(bounds), - CGRectGetMaxY(self.activityIndicator.frame) + padding*2); -} - -- (void)updateUIForPaymentInProgress:(BOOL)paymentInProgress { - self.navigationController.navigationBar.userInteractionEnabled = !paymentInProgress; - self.payButton.enabled = !paymentInProgress; - [UIView animateWithDuration:0.2 animations:^{ - self.waitingLabel.alpha = paymentInProgress ? 1 : 0; - }]; - if (paymentInProgress) { - [self.activityIndicator startAnimating]; - } else { - [self.activityIndicator stopAnimating]; - } -} - -- (void)selectBank { - STPBankSelectionViewController *vc = [[STPBankSelectionViewController alloc] initWithBankMethod:STPBankSelectionMethodFPX]; - vc.delegate = self; - - [self.navigationController pushViewController:vc animated:YES]; -} - -- (void)payWithBankAccount:(STPPaymentMethodParams *)paymentMethodParams { - if (![StripeAPI defaultPublishableKey]) { - [self.delegate exampleViewController:self didFinishWithMessage:@"Please set a Stripe Publishable Key in Constants.m"]; - return; - } - [self updateUIForPaymentInProgress:YES]; - - [[MyAPIClient sharedClient] createPaymentIntentWithCompletion:^(MyAPIClientResult status, NSString *clientSecret, NSError *error) { - if (status == MyAPIClientResultFailure || clientSecret == nil) { - [self.delegate exampleViewController:self didFinishWithError:error]; - return; - } - - STPPaymentIntentParams *paymentIntentParams = [[STPPaymentIntentParams alloc] initWithClientSecret:clientSecret]; - paymentIntentParams.paymentMethodParams = paymentMethodParams; - paymentIntentParams.returnURL = @"payments-example://stripe-redirect"; - [[STPPaymentHandler sharedHandler] confirmPayment:paymentIntentParams - withAuthenticationContext:self - completion:^(STPPaymentHandlerActionStatus handlerStatus, STPPaymentIntent * handledIntent, NSError * _Nullable handlerError) { - switch (handlerStatus) { - case STPPaymentHandlerActionStatusFailed: - [self.delegate exampleViewController:self didFinishWithError:handlerError]; - break; - case STPPaymentHandlerActionStatusCanceled: - [self.delegate exampleViewController:self didFinishWithMessage:@"Canceled"]; - break; - case STPPaymentHandlerActionStatusSucceeded: - [self.delegate exampleViewController:self didFinishWithMessage:@"Payment successfully created"]; - break; - } - }]; - } additionalParameters:@"country=my"]; -} - -- (void)bankSelectionViewController:(nonnull STPBankSelectionViewController *)bankViewController didCreatePaymentMethodParams:(STPPaymentMethodParams *)paymentMethodParams { - [self payWithBankAccount:paymentMethodParams]; -} - -#pragma mark - STPAuthenticationContext - -- (UIViewController *)authenticationPresentingViewController { - return self.navigationController.topViewController; -} - -- (void)authenticationContextWillDismissViewController:(UIViewController *)viewController { - // Remove the bank selector from the view controller stack so that we pop directly - // back to FPXExampleViewController. This provides a better experience vs sending the user back to the bank selector list. - NSMutableArray *vcs = [self.navigationController.viewControllers mutableCopy]; - for (UIViewController *vc in self.navigationController.viewControllers) { - if ([vc isKindOfClass:[STPBankSelectionViewController class]]) { - [vcs removeObject:vc]; - } - } - self.navigationController.viewControllers = vcs; -} - -@end diff --git a/Example/UI Examples/UI Examples/Source/AUBECSDebitFormViewController.swift b/Example/UI Examples/UI Examples/Source/AUBECSDebitFormViewController.swift index 3ff3936b033..d44dae7e278 100644 --- a/Example/UI Examples/UI Examples/Source/AUBECSDebitFormViewController.swift +++ b/Example/UI Examples/UI Examples/Source/AUBECSDebitFormViewController.swift @@ -12,21 +12,15 @@ import UIKit class AUBECSDebitFormViewController: UIViewController { let becsFormView = STPAUBECSDebitFormView(companyName: "Great Company Inc.") - var theme = STPTheme.defaultTheme - + override func viewDidLoad() { super.viewDidLoad() title = "BECS Debit Form" view.backgroundColor = UIColor.white view.addSubview(becsFormView) edgesForExtendedLayout = [] - view.backgroundColor = theme.primaryBackgroundColor - becsFormView.formTextColor = theme.primaryForegroundColor - becsFormView.formPlaceholderColor = theme.secondaryForegroundColor - becsFormView.formTextErrorColor = theme.errorColor navigationItem.leftBarButtonItem = UIBarButtonItem( barButtonSystemItem: .done, target: self, action: #selector(done)) - navigationController?.navigationBar.stp_theme = theme becsFormView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ diff --git a/Example/UI Examples/UI Examples/Source/BrowseViewController.swift b/Example/UI Examples/UI Examples/Source/BrowseViewController.swift index a9ada5fcbdf..e33cf44bf92 100644 --- a/Example/UI Examples/UI Examples/Source/BrowseViewController.swift +++ b/Example/UI Examples/UI Examples/Source/BrowseViewController.swift @@ -13,38 +13,29 @@ import UIKit @testable import Stripe @_spi(STP) import StripePaymentsUI -class BrowseViewController: UITableViewController, STPAddCardViewControllerDelegate, - STPPaymentOptionsViewControllerDelegate, STPShippingAddressViewControllerDelegate +class BrowseViewController: UITableViewController { enum Demo: Int { - static var count: Int = 11 + static var count: Int = 8 case STPPaymentCardTextField case STPPaymentCardTextFieldWithCBC - case STPPaymentOptionsViewController - case STPPaymentOptionsFPXViewController - case STPShippingInfoViewController case STPAUBECSFormViewController case STPCardFormViewController case STPCardFormViewControllerCBC case SwiftUICardFormViewController case PaymentMethodMessagingView - case ChangeTheme var title: String { switch self { case .STPPaymentCardTextField: return "Card Field" case .STPPaymentCardTextFieldWithCBC: return "Card Field (CBC)" - case .STPPaymentOptionsViewController: return "Payment Option Picker" - case .STPPaymentOptionsFPXViewController: return "Payment Option Picker (With FPX)" - case .STPShippingInfoViewController: return "Shipping Info Form" case .STPAUBECSFormViewController: return "AU BECS Form" case .STPCardFormViewController: return "Card Form" case .STPCardFormViewControllerCBC: return "Card Form (CBC)" case .SwiftUICardFormViewController: return "Card Form (SwiftUI)" case .PaymentMethodMessagingView: return "Payment Method Messaging View" - case .ChangeTheme: return "Change Theme" } } @@ -52,33 +43,28 @@ class BrowseViewController: UITableViewController, STPAddCardViewControllerDeleg switch self { case .STPPaymentCardTextField: return "STPPaymentCardTextField" case .STPPaymentCardTextFieldWithCBC: return "STPPaymentCardTextField" - case .STPPaymentOptionsViewController: return "STPPaymentOptionsViewController" - case .STPPaymentOptionsFPXViewController: return "STPPaymentOptionsViewController" - case .STPShippingInfoViewController: return "STPShippingInfoViewController" case .STPAUBECSFormViewController: return "STPAUBECSFormViewController" case .STPCardFormViewController: return "STPCardFormViewController" case .STPCardFormViewControllerCBC: return "STPCardFormViewController (CBC)" case .SwiftUICardFormViewController: return "STPCardFormView.Representable" case .PaymentMethodMessagingView: return "PaymentMethodMessagingView" - case .ChangeTheme: return "" } } } - let customerContext: MockCustomerContext = { - let keyManager = STPEphemeralKeyManager( - keyProvider: MockKeyProvider(), - apiVersion: STPAPIClient.apiVersion, - performsEagerFetching: true) - return MockCustomerContext(keyManager: keyManager, apiClient: .shared) - }() - let themeViewController = ThemeViewController() - override func viewDidLoad() { super.viewDidLoad() title = "Stripe UI Examples" tableView.tableFooterView = UIView() tableView.rowHeight = 60 + switch traitCollection.userInterfaceStyle { + case .light, .unspecified: + UINavigationBar.appearance().backgroundColor = .white + case .dark: + UINavigationBar.appearance().backgroundColor = .black + @unknown default: + fatalError() + } } // MARK: UITableViewDelegate @@ -105,83 +91,28 @@ class BrowseViewController: UITableViewController, STPAddCardViewControllerDeleg override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) guard let example = Demo(rawValue: indexPath.row) else { return } - let theme = themeViewController.theme.stpTheme - switch example { case .STPPaymentCardTextField: let viewController = CardFieldViewController() - viewController.theme = theme let navigationController = UINavigationController(rootViewController: viewController) - navigationController.navigationBar.stp_theme = theme present(navigationController, animated: true, completion: nil) case .STPPaymentCardTextFieldWithCBC: let viewController = CardFieldViewController() - viewController.theme = theme viewController.alwaysEnableCBC = true let navigationController = UINavigationController(rootViewController: viewController) - navigationController.navigationBar.stp_theme = theme - present(navigationController, animated: true, completion: nil) - case .STPPaymentOptionsFPXViewController: - let config = STPPaymentConfiguration() - config.fpxEnabled = true - config.requiredBillingAddressFields = .none - config.appleMerchantIdentifier = "dummy-merchant-id" - config.cardScanningEnabled = true - let viewController = STPPaymentOptionsViewController( - configuration: config, - theme: theme, - customerContext: self.customerContext, - delegate: self) - let navigationController = UINavigationController(rootViewController: viewController) - navigationController.navigationBar.stp_theme = theme - present(navigationController, animated: true, completion: nil) - case .STPPaymentOptionsViewController: - let config = STPPaymentConfiguration() - config.requiredBillingAddressFields = .none - config.appleMerchantIdentifier = "dummy-merchant-id" - config.cardScanningEnabled = true - let viewController = STPPaymentOptionsViewController( - configuration: config, - theme: theme, - customerContext: self.customerContext, - delegate: self) - let navigationController = UINavigationController(rootViewController: viewController) - navigationController.navigationBar.stp_theme = theme - present(navigationController, animated: true, completion: nil) - case .STPShippingInfoViewController: - let config = STPPaymentConfiguration() - config.requiredShippingAddressFields = [.postalAddress] - let viewController = STPShippingAddressViewController( - configuration: config, - theme: theme, - currency: "usd", - shippingAddress: nil, - selectedShippingMethod: nil, - prefilledInformation: nil) - viewController.delegate = self - let navigationController = UINavigationController(rootViewController: viewController) - navigationController.navigationBar.stp_theme = theme present(navigationController, animated: true, completion: nil) case .STPAUBECSFormViewController: let viewController = AUBECSDebitFormViewController() - viewController.theme = theme let navigationController = UINavigationController(rootViewController: viewController) - navigationController.navigationBar.stp_theme = theme present(navigationController, animated: true, completion: nil) case .STPCardFormViewController: let viewController = CardFormViewController() let navigationController = UINavigationController(rootViewController: viewController) - navigationController.navigationBar.stp_theme = theme present(navigationController, animated: true, completion: nil) case .STPCardFormViewControllerCBC: let viewController = CardFormViewController() viewController.alwaysEnableCBC = true let navigationController = UINavigationController(rootViewController: viewController) - navigationController.navigationBar.stp_theme = theme - present(navigationController, animated: true, completion: nil) - case .ChangeTheme: - let navigationController = UINavigationController( - rootViewController: self.themeViewController) present(navigationController, animated: true, completion: nil) case .SwiftUICardFormViewController: let controller = UIHostingController(rootView: SwiftUICardFormView()) @@ -193,95 +124,4 @@ class BrowseViewController: UITableViewController, STPAddCardViewControllerDeleg } } - // MARK: STPAddCardViewControllerDelegate - - func addCardViewControllerDidCancel(_ addCardViewController: STPAddCardViewController) { - dismiss(animated: true, completion: nil) - } - - func addCardViewController( - _ addCardViewController: STPAddCardViewController, - didCreatePaymentMethod paymentMethod: STPPaymentMethod, - completion: @escaping STPErrorBlock - ) { - dismiss(animated: true, completion: nil) - } - - // MARK: STPPaymentOptionsViewControllerDelegate - - func paymentOptionsViewControllerDidCancel( - _ paymentOptionsViewController: STPPaymentOptionsViewController - ) { - dismiss(animated: true, completion: nil) - } - - func paymentOptionsViewControllerDidFinish( - _ paymentOptionsViewController: STPPaymentOptionsViewController - ) { - dismiss(animated: true, completion: nil) - } - - func paymentOptionsViewController( - _ paymentOptionsViewController: STPPaymentOptionsViewController, - didFailToLoadWithError error: Error - ) { - dismiss(animated: true, completion: nil) - } - - // MARK: STPShippingAddressViewControllerDelegate - - func shippingAddressViewControllerDidCancel( - _ addressViewController: STPShippingAddressViewController - ) { - dismiss(animated: true, completion: nil) - } - - func shippingAddressViewController( - _ addressViewController: STPShippingAddressViewController, - didFinishWith address: STPAddress, - shippingMethod method: PKShippingMethod? - ) { - self.customerContext.updateCustomer(withShippingAddress: address, completion: nil) - dismiss(animated: true, completion: nil) - } - - func shippingAddressViewController( - _ addressViewController: STPShippingAddressViewController, - didEnter address: STPAddress, - completion: @escaping STPShippingMethodsCompletionBlock - ) { - let upsGround = PKShippingMethod() - upsGround.amount = 0 - upsGround.label = "UPS Ground" - upsGround.detail = "Arrives in 3-5 days" - upsGround.identifier = "ups_ground" - let upsWorldwide = PKShippingMethod() - upsWorldwide.amount = 10.99 - upsWorldwide.label = "UPS Worldwide Express" - upsWorldwide.detail = "Arrives in 1-3 days" - upsWorldwide.identifier = "ups_worldwide" - let fedEx = PKShippingMethod() - fedEx.amount = 5.99 - fedEx.label = "FedEx" - fedEx.detail = "Arrives tomorrow" - fedEx.identifier = "fedex" - - DispatchQueue.main.asyncAfter(deadline: .now() + 0.6) { - if address.country == nil || address.country == "US" { - completion(.valid, nil, [upsGround, fedEx], fedEx) - } else if address.country == "AQ" { - let error = NSError( - domain: "ShippingError", code: 123, - userInfo: [ - NSLocalizedDescriptionKey: "Invalid Shipping Address", - NSLocalizedFailureReasonErrorKey: "We can't ship to this country.", - ]) - completion(.invalid, error, nil, nil) - } else { - fedEx.amount = 20.99 - completion(.valid, nil, [upsWorldwide, fedEx], fedEx) - } - } - } - } diff --git a/Example/UI Examples/UI Examples/Source/CardFieldViewController.swift b/Example/UI Examples/UI Examples/Source/CardFieldViewController.swift index da4f4ee8a6d..bd59b3eaaa0 100644 --- a/Example/UI Examples/UI Examples/Source/CardFieldViewController.swift +++ b/Example/UI Examples/UI Examples/Source/CardFieldViewController.swift @@ -14,7 +14,6 @@ class CardFieldViewController: UIViewController { let cardField = STPPaymentCardTextField() - var theme = STPTheme.defaultTheme var alwaysEnableCBC = false override func viewDidLoad() { @@ -23,20 +22,13 @@ class CardFieldViewController: UIViewController { view.backgroundColor = UIColor.white view.addSubview(cardField) edgesForExtendedLayout = [] - view.backgroundColor = theme.primaryBackgroundColor - cardField.backgroundColor = theme.secondaryBackgroundColor - cardField.textColor = theme.primaryForegroundColor - cardField.placeholderColor = theme.secondaryForegroundColor - cardField.borderColor = theme.accentColor cardField.borderWidth = 1.0 - cardField.textErrorColor = theme.errorColor cardField.postalCodeEntryEnabled = true if alwaysEnableCBC { cardField.cbcEnabledOverride = true } navigationItem.leftBarButtonItem = UIBarButtonItem( barButtonSystemItem: .done, target: self, action: #selector(done)) - navigationController?.navigationBar.stp_theme = theme } @objc func done() { diff --git a/Example/UI Examples/UI Examples/Source/MockCustomerContext.swift b/Example/UI Examples/UI Examples/Source/MockCustomerContext.swift index 68095395ff3..311995e6a54 100644 --- a/Example/UI Examples/UI Examples/Source/MockCustomerContext.swift +++ b/Example/UI Examples/UI Examples/Source/MockCustomerContext.swift @@ -110,74 +110,3 @@ class MockKeyProvider: NSObject, STPCustomerEphemeralKeyProvider { completion(nil, NSError.stp_ephemeralKeyDecodingError()) } } - -class MockCustomerContext: STPCustomerContext { - - let customer = MockCustomer() - - override func retrieveCustomer(_ completion: STPCustomerCompletionBlock? = nil) { - if let completion = completion { - completion(customer, nil) - } - } - - override func attachPaymentMethod( - toCustomer paymentMethod: STPPaymentMethod, completion: STPErrorBlock? = nil - ) { - customer.paymentMethods.append(paymentMethod) - if let completion = completion { - completion(nil) - } - } - - override func detachPaymentMethod( - fromCustomer paymentMethod: STPPaymentMethod, completion: STPErrorBlock? = nil - ) { - if let index = customer.paymentMethods.firstIndex(where: { - $0.stripeId == paymentMethod.stripeId - }) { - customer.paymentMethods.remove(at: index) - } - if let completion = completion { - completion(nil) - } - } - - override func listPaymentMethodsForCustomer(completion: STPPaymentMethodsCompletionBlock? = nil) - { - if let completion = completion { - completion(customer.paymentMethods, nil) - } - } - - func selectDefaultCustomerPaymentMethod( - _ paymentMethod: STPPaymentMethod, completion: @escaping STPErrorBlock - ) { - if customer.paymentMethods.contains(where: { $0.stripeId == paymentMethod.stripeId }) { - customer.defaultPaymentMethod = paymentMethod - } - completion(nil) - } - - override func updateCustomer( - withShippingAddress shipping: STPAddress, completion: STPErrorBlock? - ) { - customer.shippingAddress = shipping - if let completion = completion { - completion(nil) - } - } - - override func retrieveLastSelectedPaymentMethodIDForCustomer( - completion: @escaping (String?, Error?) -> Void - ) { - completion(nil, nil) - } - override func saveLastSelectedPaymentMethodID( - forCustomer paymentMethodID: String?, completion: STPErrorBlock? - ) { - if let completion = completion { - completion(nil) - } - } -} diff --git a/Example/UI Examples/UI Examples/Source/PaymentMethodMessagingViewController.swift b/Example/UI Examples/UI Examples/Source/PaymentMethodMessagingViewController.swift index 15baa3a5d9b..086c9e09782 100644 --- a/Example/UI Examples/UI Examples/Source/PaymentMethodMessagingViewController.swift +++ b/Example/UI Examples/UI Examples/Source/PaymentMethodMessagingViewController.swift @@ -15,8 +15,6 @@ import UIKit class PaymentMethodMessagingViewController: UIViewController { - var theme = STPTheme.defaultTheme - override func viewDidLoad() { super.viewDidLoad() title = "PaymentMethodMessagingView Demo" diff --git a/Example/UI Examples/UI Examples/Source/ThemeViewController.swift b/Example/UI Examples/UI Examples/Source/ThemeViewController.swift index d248e288595..cc90cf3b9d9 100644 --- a/Example/UI Examples/UI Examples/Source/ThemeViewController.swift +++ b/Example/UI Examples/UI Examples/Source/ThemeViewController.swift @@ -24,65 +24,6 @@ class ThemeViewController: UITableViewController { } } - var stpTheme: STPTheme { - switch self { - case .Default: - return STPTheme.defaultTheme - case .Custom: - let theme = STPTheme.init() - theme.primaryBackgroundColor = UIColor.init(dynamicProvider: { - (tc) -> UIColor in - return (tc.userInterfaceStyle == .light) - ? UIColor( - red: 230.0 / 255.0, green: 235.0 / 255.0, blue: 241.0 / 255.0, - alpha: 255.0 / 255.0) - : UIColor( - red: 66.0 / 255.0, green: 69.0 / 255.0, blue: 112.0 / 255.0, - alpha: 255.0 / 255.0) - }) - theme.secondaryBackgroundColor = UIColor.init(dynamicProvider: { - (tc) -> UIColor in - return (tc.userInterfaceStyle == .light) - ? .white : theme.primaryBackgroundColor - }) - theme.primaryForegroundColor = UIColor.init(dynamicProvider: { - (tc) -> UIColor in - return (tc.userInterfaceStyle == .light) - ? UIColor( - red: 55.0 / 255.0, green: 53.0 / 255.0, blue: 100.0 / 255.0, - alpha: 255.0 / 255.0) : .white - }) - theme.secondaryForegroundColor = UIColor.init(dynamicProvider: { - (tc) -> UIColor in - return (tc.userInterfaceStyle == .light) - ? UIColor( - red: 148.0 / 255.0, green: 163.0 / 255.0, blue: 179.0 / 255.0, - alpha: 255.0 / 255.0) - : UIColor( - red: 130.0 / 255.0, green: 147.0 / 255.0, blue: 168.0 / 255.0, - alpha: 255.0 / 255.0) - }) - theme.accentColor = UIColor.init(dynamicProvider: { (tc) -> UIColor in - return (tc.userInterfaceStyle == .light) - ? UIColor( - red: 101.0 / 255.0, green: 101.0 / 255.0, blue: 232.0 / 255.0, - alpha: 255.0 / 255.0) - : UIColor( - red: 14.0 / 255.0, green: 211.0 / 255.0, blue: 140.0 / 255.0, - alpha: 255.0 / 255.0) - }) - theme.errorColor = UIColor.init(dynamicProvider: { (tc) -> UIColor in - return (tc.userInterfaceStyle == .light) - ? UIColor( - red: 240.0 / 255.0, green: 2.0 / 255.0, blue: 36.0 / 255.0, - alpha: 255.0 / 255.0) - : UIColor( - red: 237.0 / 255.0, green: 83.0 / 255.0, blue: 69.0 / 255.0, - alpha: 255.0 / 255.0) - }) - return theme - } - } } var theme: Theme = .Default diff --git a/Stripe/Stripe.xcodeproj/project.pbxproj b/Stripe/Stripe.xcodeproj/project.pbxproj index 80c06670b8a..4b328982c46 100644 --- a/Stripe/Stripe.xcodeproj/project.pbxproj +++ b/Stripe/Stripe.xcodeproj/project.pbxproj @@ -16,17 +16,12 @@ 07A5CDBFDF2340BAD99D6EB3 /* STPCardFormViewSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D983E089196152DA1C69469 /* STPCardFormViewSnapshotTests.swift */; }; 07BF3CF1656AF5F5A0678873 /* STPPhoneNumberValidatorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 924E878428D15506711CA628 /* STPPhoneNumberValidatorTest.swift */; }; 08111F4AD3CA0755420E05F7 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 147D2DC1FFDFC99269039377 /* LaunchScreen.storyboard */; }; - 08ED7A4EB7E64FDAED2C2D39 /* STPShippingAddressViewControllerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 789D0B49B0788794739E3DD4 /* STPShippingAddressViewControllerTest.swift */; }; - 093FE3D65978E3DB6B79AE05 /* UIToolbar+Stripe_InputAccessory.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2307F2C5E53540D4ACAA1F6 /* UIToolbar+Stripe_InputAccessory.swift */; }; 0B9C0E9A7A750607413C9E53 /* STPFakeAddPaymentPassViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0669B4CA326CE74D125C789C /* STPFakeAddPaymentPassViewController.swift */; }; - 0C5F4AE769D95AA921F61084 /* STPApplePayPaymentOptionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00985EFC6CB7B912FDBF3813 /* STPApplePayPaymentOptionTest.swift */; }; 0DFA17378D894C70D72C9F62 /* Error+PaymentSheetTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CE85C770AEEDBE4AEC93EAA /* Error+PaymentSheetTests.swift */; }; 0FA3C1494BA57884B5DE3B20 /* Stripe.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4259421D2CD26E37B96F97B2 /* Stripe.framework */; }; 10342D659764A88A695EF38B /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DFA7A75BA785EBBE4C05DAA3 /* Images.xcassets */; }; - 124D43C1A633922B1DA3E1E7 /* STPShippingAddressViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71711FC8E2FB66E52A5FDD9A /* STPShippingAddressViewController.swift */; }; 14656D177E67594B8C75A9FE /* STPConnectAccountParamsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 195DEC752CC82CC4BA1E2351 /* STPConnectAccountParamsTest.swift */; }; 162C101E57D66F0051164C4A /* Stripe.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 4259421D2CD26E37B96F97B2 /* Stripe.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 172D96526023A80534D54CC0 /* STPBankSelectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81352A0CBE46A59E6B1A712E /* STPBankSelectionViewController.swift */; }; 17BD7C0391F3182E32A63D6B /* STPAUBECSDebitFormViewSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCBEA9E4823F08C1F5057B5A /* STPAUBECSDebitFormViewSnapshotTests.swift */; }; 194154708E1A9E013DCE2C72 /* STPPaymentHandlerStubbedMockedFilesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF48EC440E1ED5D6BAA567FF /* STPPaymentHandlerStubbedMockedFilesTests.swift */; }; 1948544E75A2E16E46CBA00E /* STPRedirectContextTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFCF9EB77A45F3E9E83F5D8B /* STPRedirectContextTest.swift */; }; @@ -35,37 +30,26 @@ 1CCFC43F7FCD273E2100D321 /* STPPaymentMethodBancontactTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4E5416F6AE8BED88980D6F8 /* STPPaymentMethodBancontactTests.swift */; }; 1CD3AB315580606AF87A7B1F /* STPPaymentCardTextFieldKVOTest.m in Sources */ = {isa = PBXBuildFile; fileRef = BB08D2AC882B21C8ADD76B92 /* STPPaymentCardTextFieldKVOTest.m */; }; 1E8D8E2494062262A332879C /* STPCardValidatorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1644AA33E81233EF33022BA /* STPCardValidatorTest.swift */; }; - 1F432D0B37949217E4299A20 /* STPPaymentOptionsInternalViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5C4A4CC7D2E9B5AB3EC3B79 /* STPPaymentOptionsInternalViewController.swift */; }; 225140E0BD9C0630116DDE4A /* STPPaymentMethodUSBankAccountTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B112FFF3FCA82094281493F /* STPPaymentMethodUSBankAccountTest.swift */; }; - 22BE2ABB29F77362FF16D945 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = C2427C1CDFA85BFC6570F1E9 /* Localizable.strings */; }; 234C71F480318E9062075924 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BBCE3A905041A709E8F279A /* AppDelegate.swift */; }; 23CF725CFAB2ABED416BF416 /* STPApplePayContextFunctionalTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CE268457D21A7209862E004 /* STPApplePayContextFunctionalTest.swift */; }; - 23D1246A5DAB5333650F104F /* STPSectionHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96E1FED5CE5974C9C1162E93 /* STPSectionHeaderView.swift */; }; 240993144289CD0DEC2C73C7 /* STPConfirmPaymentMethodOptionsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05FE1BA89B80336F16924FA2 /* STPConfirmPaymentMethodOptionsTest.swift */; }; 246920234EE8382FB4E56516 /* STPCardFormViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF5E08A1651D9DFE502DA021 /* STPCardFormViewTests.swift */; }; - 26F38A2A57FDDC12926BE044 /* STPAddCardViewControllerLocalizationSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26E5C1DABAA63F07F0C6AE37 /* STPAddCardViewControllerLocalizationSnapshotTests.swift */; }; - 279D2BA91198E18730626CE6 /* STPUserInformation.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1217AD643A9E8F88B60F645 /* STPUserInformation.swift */; }; 27F1783CBFEC06BFD6C114F6 /* STPPaymentMethodKlarnaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FD94FF270165D699DA89B24 /* STPPaymentMethodKlarnaTests.swift */; }; 28538CD5885636DC523E8751 /* STPSourceRedirectTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0436A8574E7D0730641407A /* STPSourceRedirectTest.swift */; }; 29428CDB658E6F504402D844 /* STPPaymentMethodBillingDetailsTests+Link.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AC0A18C441FCA394BEF6A3D /* STPPaymentMethodBillingDetailsTests+Link.swift */; }; 2A528B7B2579E5F977797822 /* STPPaymentHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC30E6129279F14506219E98 /* STPPaymentHandlerTests.swift */; }; 2AC91F23CF3949ADC60D27F7 /* STPThreeDSTextFieldCustomizationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A583966A33DCDCF04322A592 /* STPThreeDSTextFieldCustomizationTest.swift */; }; 2AE9ABA774B430E174279FEA /* stp_test_upload_image.jpeg in Resources */ = {isa = PBXBuildFile; fileRef = FD3398E2352CEA0264F20AEA /* stp_test_upload_image.jpeg */; }; - 2BD45625F6F665B60C6CAD30 /* STPAddressViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28A50AFA4603E488FF3D82D0 /* STPAddressViewModel.swift */; }; 2C6DC246DD12FE0D87156A4D /* STPPaymentMethodPayPalTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A63AC868755CB4745E7458E /* STPPaymentMethodPayPalTests.swift */; }; - 2C7991FDF7B374E0E65E253F /* STPPaymentOptionsViewControllerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2922A32A754CFC9AB8B48AE /* STPPaymentOptionsViewControllerTest.swift */; }; 2C9F69E4A384C5743F4EAF69 /* STPPaymentMethodSwishParamsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9631915F03F157A1CC3FEFFE /* STPPaymentMethodSwishParamsTests.swift */; }; 2CD7968DA48F7129E16EA0CB /* OHHTTPStubsSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 911CA85A1610303FA0AF0643 /* OHHTTPStubsSwift */; }; 2E35B0FB60FCBE7608080642 /* STPPushProvisioningContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6887F19BB9804BF45FD703FF /* STPPushProvisioningContext.swift */; }; 2EB68A59660A4D1E14799DA4 /* OHHTTPStubs in Frameworks */ = {isa = PBXBuildFile; productRef = 62887B4538E4E41E735685E1 /* OHHTTPStubs */; }; 2F0FC4E67BE577AD66CD1475 /* StripePaymentSheet.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDC55CC034022DFAC9366E2E /* StripePaymentSheet.framework */; }; - 2F18A1903244E144C7802E09 /* STPCardValidationState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A9E7B637A8747431B38FD1D /* STPCardValidationState.swift */; }; 2F9FA9CBCA3C0CE52FAC9B6B /* ConfirmButtonSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 806124200E77795DCFC8418E /* ConfirmButtonSnapshotTests.swift */; }; - 2FFA7C2D1C7337FDB4C608A5 /* STPCardScannerTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B91C4D5B93FF71C61B140F1 /* STPCardScannerTableViewCell.swift */; }; - 307FD6A103EF7AF3CE451598 /* STPPaymentResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D964D9E01627B419B4BD23C /* STPPaymentResult.swift */; }; 30D48C62B2FA6B28EC23A5BB /* Stripe-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = A8598727045C6268B57A5FC7 /* Stripe-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 313F5F792B0BE59100BD98A9 /* Docs.docc in Sources */ = {isa = PBXBuildFile; fileRef = 313F5F782B0BE59000BD98A9 /* Docs.docc */; }; - 315713352C770DA3ED9CBDCD /* Enums+CustomStringConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F7E3CE2105E4A39032CD919 /* Enums+CustomStringConvertible.swift */; }; 3172C789DF2CE133ECA359D7 /* STPPushProvisioningDetailsFunctionalTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A8A6B88797870BC71CCB3AF /* STPPushProvisioningDetailsFunctionalTest.swift */; }; 319899DEC91B3F88D380DB47 /* STPPaymentMethodGrabPayParamsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A8FF64CA314F909D7EC82FE /* STPPaymentMethodGrabPayParamsTest.swift */; }; 31CDFC2E2BA3708000B3DD91 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 31CDFC2D2BA3708000B3DD91 /* PrivacyInfo.xcprivacy */; }; @@ -79,27 +63,19 @@ 37E9160706C9EEEFEF133617 /* STPPaymentIntentFunctionalTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDDEAB86BE4711841D426F3B /* STPPaymentIntentFunctionalTest.swift */; }; 37FBCED5F71F03483EA73F27 /* STPPaymentMethodOXXOTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80BBCC4D386EE44E809A591C /* STPPaymentMethodOXXOTests.swift */; }; 385CAC4D2FF119D2E925916B /* STPPostalCodeInputTextFieldFormatterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 917154477796779ECFA1334A /* STPPostalCodeInputTextFieldFormatterTests.swift */; }; - 3930ECBEE003772C1245D25B /* UIViewController+Stripe_ParentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5804C2B9C0704E386B3D25A4 /* UIViewController+Stripe_ParentViewController.swift */; }; 39B1B88B8506BE4574E6B376 /* STPBankAccountFunctionalTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 989411FA3CD0CCC38BC227F4 /* STPBankAccountFunctionalTest.swift */; }; - 3AAE488F2461A46143B3A687 /* STPPaymentConfigurationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 79ABE6A14AF9D14103050876 /* STPPaymentConfigurationTest.m */; }; 3AD22E0BD44B02D968C6569A /* STPImageLibraryTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = F546088BA4F763334CFD3D34 /* STPImageLibraryTest.swift */; }; 3B237145902E3DB07E747E32 /* TextFieldElement+IBANTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BD2CE41E4F0CF648F44E4A /* TextFieldElement+IBANTest.swift */; }; 3C1A7B9810B038177FF1CF52 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F29C15B47C7CB0941CD4C9E /* ViewController.swift */; }; 3C1E9069CD03ED9981D7F3E2 /* ConfirmButtonTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CFFE40AD9D875709F643D2E5 /* ConfirmButtonTests.swift */; }; - 3CE88568CB9648D6F1503B88 /* STPSource+BasicUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3B75875C55D2C2723DC5090 /* STPSource+BasicUI.swift */; }; 3EA9D509E59DA65EE4EDF98D /* STPAddressTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A39580123A4F1EA96F91768A /* STPAddressTests.swift */; }; 3EB3745F556EA12AB27A8545 /* APIRequestTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85AAB72218409F85FE29E69E /* APIRequestTest.swift */; }; - 3FA556CF8B11E2486F505161 /* UIViewController+Stripe_NavigationItemProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F017A08C7E633FB4297D274 /* UIViewController+Stripe_NavigationItemProxy.swift */; }; 3FD5ABC45AF3A03F4EFE196F /* STPSourceFunctionalTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17013F78CE3F9662029FEF5B /* STPSourceFunctionalTest.swift */; }; 4059301B0365BD4220E591FB /* STPPaymentMethodSwishTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DE9F0BAC35EA14579775033 /* STPPaymentMethodSwishTests.swift */; }; 420F8CAB4FAD6D9AF4AF25C0 /* StripePaymentSheet.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDC55CC034022DFAC9366E2E /* StripePaymentSheet.framework */; }; 42395EF962DB8AD6A094630B /* StripePaymentSheet.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DDC55CC034022DFAC9366E2E /* StripePaymentSheet.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 429DBA641E926EBC2D049FE7 /* STPCustomerContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB8FCDBC63A79CD1571A2DFB /* STPCustomerContext.swift */; }; 42F18560F3DC6980408AF051 /* STPPaymentMethodPayPalParamsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE2A766FB355DD9C461939C1 /* STPPaymentMethodPayPalParamsTests.swift */; }; 43FFF2881D4EFA7B57A60E09 /* STPPaymentMethodCardTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BD02D8298877F10F2EF2A9D /* STPPaymentMethodCardTest.swift */; }; - 44672917D3AC4B83F9EC3BC3 /* UIView+Stripe_SafeAreaBounds.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86798C95A778362EF815B4C6 /* UIView+Stripe_SafeAreaBounds.swift */; }; - 446A108C8EB6C338A1D774F8 /* STPPaymentConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18FCB69CD3B8C3DAB216A5F0 /* STPPaymentConfiguration.swift */; }; - 447C19BDB2CF5445045F81F7 /* STPPaymentContextAmountModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1C876DC7F3E31D7189506A8 /* STPPaymentContextAmountModel.swift */; }; 450FAE41FB4538462D05F2E4 /* LinkSignupViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7C7D85A7FAAFDF4F59BA85E /* LinkSignupViewModelTests.swift */; }; 45FA9B8CC2D18E29BE81CF8F /* STPIntentActionAlipayHandleRedirectTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD06AED0AF8A9A7FB4A2E66F /* STPIntentActionAlipayHandleRedirectTest.swift */; }; 460B31EDB22BD6B912567363 /* STPSourceVerificationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E89551702F1F9A3AFF1ED676 /* STPSourceVerificationTest.swift */; }; @@ -110,11 +86,8 @@ 4A61DC36F10B9C9C24345613 /* STPRadarSessionFunctionalTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D878F923A1F69B58D6B2812 /* STPRadarSessionFunctionalTest.swift */; }; 4AAA2CD5AEF1F913395B3B95 /* STPPaymentMethodUSBankAccountParamsStubbedTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF13BAEF86594C9CABD4F42A /* STPPaymentMethodUSBankAccountParamsStubbedTest.swift */; }; 4B0917FC15BF56D0100E0ED1 /* STPGenericInputTextFieldSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58A53F005EA8FDDAA66126BA /* STPGenericInputTextFieldSnapshotTests.swift */; }; - 4C3B161481D11385352B06D4 /* STPCustomerContextTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CC4B06AB5C02FF54091E5A8 /* STPCustomerContextTest.swift */; }; 4E09E54E7FEC35C49C59A379 /* STPPushProvisioningDetailsParams.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B28B8A547CD846277ECD578 /* STPPushProvisioningDetailsParams.swift */; }; 4E31B1864DA407598FB1BBC6 /* STPPostalCodeInputTextFieldTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6618739767139C25C05B3631 /* STPPostalCodeInputTextFieldTests.swift */; }; - 4ED44ACF24949F516867235C /* STPPaymentOptionTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6215A9BF343775B1BD0F62AF /* STPPaymentOptionTableViewCell.swift */; }; - 4EFF8B46B12DA4D9AAB22523 /* STPPaymentCardTextFieldCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01B42BE6FB5EC1F708875AB8 /* STPPaymentCardTextFieldCell.swift */; }; 4FB67F10A0B7106A8142B842 /* STPEphemeralKeyManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 588C260880FFC584A00A89F5 /* STPEphemeralKeyManager.swift */; }; 51044B947A7FDB99451466D8 /* STPGenericInputPickerFieldSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 284C67269D2606DA147AE01D /* STPGenericInputPickerFieldSnapshotTests.swift */; }; 5170651536332C4842E9D009 /* STPPaymentMethodBoletoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E371E9B3B2E343FE954531C /* STPPaymentMethodBoletoTests.swift */; }; @@ -123,9 +96,6 @@ 524AE1978E0A4490D1C390C5 /* CustomerAdapterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11C866064B3482878A69892F /* CustomerAdapterTests.swift */; }; 5302F9246A4A6381CB4FB874 /* StripePaymentsTestUtils.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 77247622AB08FEF48CA0DC26 /* StripePaymentsTestUtils.framework */; }; 5370700ED1F630E8261507D3 /* STPBankAccountParamsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 967C784618A074FF021B3089 /* STPBankAccountParamsTest.swift */; }; - 542610492B38FEB652C6823E /* String+Localized.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5398E1156E0BFEBBF56FD2F /* String+Localized.swift */; }; - 54331380F5AC68846DBE94D5 /* UITableViewCell+Stripe_Borders.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5476BD87E0480A93958F0328 /* UITableViewCell+Stripe_Borders.swift */; }; - 58240AA66FAE55131268E4A0 /* STPAddressFieldTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72903593DC432D01720DC9D9 /* STPAddressFieldTableViewCell.swift */; }; 583DE9869C885BA02E0A071E /* STPAUBECSFormViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AAE5EE11611F9F7762B64C6 /* STPAUBECSFormViewModelTests.swift */; }; 58A8B3F57FE98C22D8F90C77 /* STPThreeDSButtonCustomizationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6F3B966470A530E0DC53F8C /* STPThreeDSButtonCustomizationTest.swift */; }; 590DB84AC15709E3C6F1FC3B /* STPThreeDSNavigationBarCustomizationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51408DE266D0345784ADD4FA /* STPThreeDSNavigationBarCustomizationTest.swift */; }; @@ -133,15 +103,10 @@ 5B6F1BF973FC2D8DD6127B7F /* StripePaymentsUI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = E136A967522048B313E3C62F /* StripePaymentsUI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 5C51167CC14F653E7117BA61 /* OCMock in Frameworks */ = {isa = PBXBuildFile; productRef = E804AA8C4156CC85FFD9595F /* OCMock */; }; 5C5E1CE53D89DE8F0B867115 /* STPPaymentMethodSofortTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8063E8073A32E0B081A1DFA /* STPPaymentMethodSofortTests.swift */; }; - 5D6B52EB4D7258129F134D07 /* STPImageLibrary.swift in Sources */ = {isa = PBXBuildFile; fileRef = D93C23F55BEADF9BC74DFBDB /* STPImageLibrary.swift */; }; 5D7F632025C261B88F0C2016 /* STPFPXBankBrandTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85C29AE44D809CD677B5E52B /* STPFPXBankBrandTest.swift */; }; 5D9EB3E2725C38D7098B9965 /* STPPaymentMethodParamsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4002981AC12687681616D21E /* STPPaymentMethodParamsTest.swift */; }; 5E498CDA0115CF9F8463C566 /* STPPaymentMethodAUBECSDebitParamsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FF2B9FF57E100301B5C38DB /* STPPaymentMethodAUBECSDebitParamsTests.swift */; }; - 5E5EE69D140F6FEDA5F0A346 /* STPAPIClientTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8DD70E5ED8E9DE8E9752C9E /* STPAPIClientTest.swift */; }; - 5ECED204FD22CFEA3A806767 /* STPPaymentOptionTuple.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDD30E5DB8DB3AA3567F5C20 /* STPPaymentOptionTuple.swift */; }; - 605EFBDD21426FD30581563F /* STPAnalyticsClient+BasicUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12DBB3F72AEFB52DE27C27ED /* STPAnalyticsClient+BasicUI.swift */; }; 609C2C8F10AFAA2711639CD0 /* NSArray+StripeTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C17799DC7FA54E758EED31A6 /* NSArray+StripeTest.swift */; }; - 609E4D384B75F6A111DC0E27 /* STPPaymentActivityIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FFBAA4B44967B157A4F4E91 /* STPPaymentActivityIndicatorView.swift */; }; 610DF5DC2B33597500DA6AAA /* HostedSurfaceTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 610DF5DB2B33597500DA6AAA /* HostedSurfaceTest.swift */; }; 61152B4F2B866827003B69A0 /* STPPaymentMethodAmazonPayParamsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61152B4E2B866827003B69A0 /* STPPaymentMethodAmazonPayParamsTests.swift */; }; 617C1C882BB4992400B10AC5 /* STPPaymentMethodAlmaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 617C1C872BB4992400B10AC5 /* STPPaymentMethodAlmaTests.swift */; }; @@ -152,15 +117,12 @@ 61E1CA212BD6B78500A421AE /* STPPaymentMethodMultibancoParamsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61E1CA202BD6B78500A421AE /* STPPaymentMethodMultibancoParamsTests.swift */; }; 61E1CA272BD6BED600A421AE /* STPIntentActionMultibancoDisplayDetailsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61E1CA262BD6BED600A421AE /* STPIntentActionMultibancoDisplayDetailsTest.swift */; }; 62B91808A088C4F9FDB62C53 /* STPEphemeralKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 890660C21E3666CE7B82695B /* STPEphemeralKey.swift */; }; - 66065B1D65D7D5502D4E2F2B /* STPCard+BasicUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E5FB20B2BEFC00D54FDD87D /* STPCard+BasicUI.swift */; }; 66B7EF2DC1CBF813707C767C /* STPBSBNumberValidatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3C732C25FD961631BD44FDD /* STPBSBNumberValidatorTests.swift */; }; 68318DB86DFCD19505FC47BA /* NSURLComponents_StripeTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1CD20E00EAD41091B71ABD5 /* NSURLComponents_StripeTest.swift */; }; 687517E7FE02FFB96DCE2328 /* STPEphemeralKeyManagerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C645F78B3EFFAA083B6FD3E9 /* STPEphemeralKeyManagerTest.swift */; }; - 69AC1EDE2A3C03B1D980CA54 /* STPPaymentOptionsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9A1BB31C7B514984231125B /* STPPaymentOptionsViewController.swift */; }; 6BA4B91A2BF433B200D1F21D /* STPPaymentMethodMobilePayParamsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BA4B9192BF433B200D1F21D /* STPPaymentMethodMobilePayParamsTests.swift */; }; 6BA4B91C2BF4343B00D1F21D /* STPPaymentMethodMobilePayTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BA4B91B2BF4343B00D1F21D /* STPPaymentMethodMobilePayTests.swift */; }; 6BC5EC2D2B4609FF00CC75E8 /* LinkInlineSignupElementSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BC5EC2C2B4609FF00CC75E8 /* LinkInlineSignupElementSnapshotTests.swift */; }; - 6BF6ECC4A4E61E2FFC3EA20B /* STPAPIClient+BasicUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8AFAE24610EC983727F860 /* STPAPIClient+BasicUI.swift */; }; 6E7AD3CCC966A7F34922B172 /* NSDictionary+StripeTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D07275F94914B7E7937D24FE /* NSDictionary+StripeTest.swift */; }; 6EDFC83541EED9E361B71C02 /* STPCustomerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAB817ED5B5DB87AE1290894 /* STPCustomerTest.swift */; }; 6EF3F611E6EA3CB479D62450 /* AfterpayPriceBreakdownViewSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C742844915B96CFD25BFFF9 /* AfterpayPriceBreakdownViewSnapshotTests.swift */; }; @@ -169,7 +131,6 @@ 6FCA954C32AB351F902BA876 /* STPPostalCodeValidatorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDF7394DDD552EDE996EAD8E /* STPPostalCodeValidatorTest.swift */; }; 701C464523173C6809544935 /* STPThreeDSUICustomizationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ED44491EB0AC72B1B1A773C /* STPThreeDSUICustomizationTest.swift */; }; 71116C2D5831E271E12DB059 /* ServerErrorMapperTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20879436DCFB1F03BE1608B3 /* ServerErrorMapperTest.swift */; }; - 724429607B2741CF44D9C2E5 /* STPShippingMethodsViewControllerLocalizationSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 661976D1296DFA48A25E0493 /* STPShippingMethodsViewControllerLocalizationSnapshotTests.swift */; }; 73AFE2A8839EFAB8330F6CF0 /* STPPaymentIntentTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACE8998EAF997A78759E49B5 /* STPPaymentIntentTest.swift */; }; 7435E6BB6971012A9B0DB52E /* STPErrorBridgeTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EAE9A2AE65771403CE57C11 /* STPErrorBridgeTest.m */; }; 7589E37795D21AB818B0C333 /* STPAnalyticsClient+Payments.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD89580A3E41D7167C30B287 /* STPAnalyticsClient+Payments.swift */; }; @@ -183,21 +144,14 @@ 78B70C2EE8334F0FA91439CA /* Stripe.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4259421D2CD26E37B96F97B2 /* Stripe.framework */; }; 795F3783D62AB8E2A00DCD05 /* ConsumerSessionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6312182B5BCAB940D216650 /* ConsumerSessionTests.swift */; }; 7A9D7D156B5053638F9B21E1 /* STPPaymentMethodThreeDSecureUsageTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 916DB8789F65D3C1BCB510C0 /* STPPaymentMethodThreeDSecureUsageTest.swift */; }; - 7B9C0D039EA9EF593AEC682D /* STPShippingMethodTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98544B08552407D41D398C68 /* STPShippingMethodTableViewCell.swift */; }; - 7BC98BE168781C5B3EC8A8DB /* STPPaymentMethod+BasicUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35C1E9B0EE03825DABF6471A /* STPPaymentMethod+BasicUI.swift */; }; 7D251ABF1EBF65ACA8A4BDD4 /* STPPaymentMethodUSBankAccountParamsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74FDEF9F687C63BADFB96480 /* STPPaymentMethodUSBankAccountParamsTest.swift */; }; 7D2C0D1BF455625997CBC33B /* STPAPIClientNetworkBridgeTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9BA8D8467218C7E691C9FAE /* STPAPIClientNetworkBridgeTest.swift */; }; 7EAA7334372DBC38DF8FA0AA /* STPPinManagementService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EBB07171F6FDCE6E20C454A /* STPPinManagementService.swift */; }; - 7F235CD649F6E97E4E7DD180 /* UIView+Stripe_FirstResponder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B76DF0FE363F59BF0940A8B /* UIView+Stripe_FirstResponder.swift */; }; - 7F9D08AC5A448C7693162D7D /* STPShippingMethodsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21E4B84223DDA131544DBBA7 /* STPShippingMethodsViewController.swift */; }; 801F417CE53689B95C4A098B /* STPBankAccountTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D103BC590F1E0EC0C31C7B5F /* STPBankAccountTest.swift */; }; - 812682EA323986B8F698FF3C /* STPPaymentMethodParams+BasicUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53C5AB22D6328E85A6DDF663 /* STPPaymentMethodParams+BasicUI.swift */; }; - 829D43B6705D125FEC9926DA /* STPPaymentContextApplePayTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C995125252BED1EEC018B9D /* STPPaymentContextApplePayTest.swift */; }; 8378F2A4B0796819BB1C6C54 /* STPPaymentMethodCardParamsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1671EC46C713D51013AD7D8B /* STPPaymentMethodCardParamsTest.swift */; }; 8520A27C204A068C43592024 /* StripeApplePay.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52F8AEC50D4623F80F04A533 /* StripeApplePay.framework */; }; 8532FEBF4F2E0EB282D466CE /* STPGenericInputPickerFieldValidatorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D63B73C5773432CA134D1FC /* STPGenericInputPickerFieldValidatorTest.swift */; }; 86BAF121184D71F5F4FFAD7B /* STPPaymentCardTextFieldTestsSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F16C36797D978E72E612100 /* STPPaymentCardTextFieldTestsSwift.swift */; }; - 8AA84A3A52A3D79BCA8C8994 /* STPUIVCStripeParentViewControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88639E3C3AC622B5EF475538 /* STPUIVCStripeParentViewControllerTests.swift */; }; 8B80FB6FC88D411A90E9D487 /* WalletHeaderViewSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DB03E83746FE78361831546 /* WalletHeaderViewSnapshotTests.swift */; }; 8C977F8D224A7360AE8E15A7 /* STPPaymentMethodBoletoParamsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1C67AC5D415615E9F27D3E3 /* STPPaymentMethodBoletoParamsTests.swift */; }; 8E423294AB602BF25DB11D8E /* OperationDebouncerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A61763BA2CCA86F9B8FD4F1F /* OperationDebouncerTests.swift */; }; @@ -213,47 +167,33 @@ 951344464ACF84F0F6D43D10 /* OneTimeCodeTextFieldTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98F9CB667BC68767DFB5FACD /* OneTimeCodeTextFieldTests.swift */; }; 9535CADFFBC9E1FA291E947E /* STPPIIFunctionalTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1645D9793463E266501B74FD /* STPPIIFunctionalTest.swift */; }; 96098727EFA6A72087A35A52 /* STPFormTextFieldTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E1862744F23286D1FB9D4AE /* STPFormTextFieldTest.swift */; }; - 97756805F41DDB51B3ED0326 /* STPPaymentContextSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5B86F3355E44DF4A980B82C /* STPPaymentContextSnapshotTests.swift */; }; - 98E2332DE7F54E970BE5EEF7 /* UIBarButtonItem+Stripe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B3000668A75E095B514241F /* UIBarButtonItem+Stripe.swift */; }; - 98EE8326C1D133E1C998114F /* STPLocalizedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFF957F38AABE5F748C38C0B /* STPLocalizedString.swift */; }; 9A24970C5FB6D3F7314AE550 /* STPAPIClientStubbedTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4194E605BB5F31E9CBB8F96 /* STPAPIClientStubbedTest.swift */; }; - 9A57C50938A66604FF16A882 /* STPPaymentOptionsViewControllerLocalizationSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5062915D961C1BCAFD641FFE /* STPPaymentOptionsViewControllerLocalizationSnapshotTests.swift */; }; 9B149DA42FB38C3542E0CB4B /* STPApplePayFunctionalTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C77C7BC4BA57EC296CF2F1C /* STPApplePayFunctionalTest.swift */; }; 9B1AC278FDCDABF26C5E468C /* STPPostalCodeInputTextFieldSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 090EF7D598B8DE779C275395 /* STPPostalCodeInputTextFieldSnapshotTests.swift */; }; - 9C13E8A017A4E23BCCDE618B /* UINavigationController+Stripe_Completion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C078573F46762353664AC92 /* UINavigationController+Stripe_Completion.swift */; }; 9D464A252FBD0D4E2A0A7398 /* STPCountryPickerInputFieldSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D49257A97E71A475A9F6E08 /* STPCountryPickerInputFieldSnapshotTests.swift */; }; 9D8354BDB04CEC5D1EFCF54F /* STPSwiftFixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = E315168EF07F52B733EA77F8 /* STPSwiftFixtures.swift */; }; - 9D9692DFC4F06F8C70145000 /* UINavigationBar+Stripe_Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7E369CEC9F5B3758F78E88F /* UINavigationBar+Stripe_Theme.swift */; }; 9FB20E559379F468070C7B50 /* STPLabeledFormTextFieldViewSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78D1EEABBAE5BD5615486B0F /* STPLabeledFormTextFieldViewSnapshotTests.swift */; }; - 9FD92B3ADEBEC96660B70409 /* STPMocks.m in Sources */ = {isa = PBXBuildFile; fileRef = 88AEABC15CCBB9EA393C175F /* STPMocks.m */; }; A01BB7F09134F7081679F9C4 /* STPPaymentMethodUPIParamsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47E5E1173A37AABB07FB68AB /* STPPaymentMethodUPIParamsTest.swift */; }; A08C2F0E7F642515B1D263ED /* STPPaymentMethodTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 148C1D7D1BBBC6B74894A869 /* STPPaymentMethodTest.swift */; }; - A0AA0B8AEF5B429858D71F6B /* STPBlocks.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3B42EBAC0DC7ED0D9200DB7 /* STPBlocks.swift */; }; A12CFA90DAE8BBB39A8C7AA1 /* STPCardFunctionalTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D38184A7CD27B978DFA30E69 /* STPCardFunctionalTest.swift */; }; A22D548084E7DE1FE5ABE8E7 /* STPLabeledMultiFormTextFieldViewSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F68637E75142DCD46710796 /* STPLabeledMultiFormTextFieldViewSnapshotTests.swift */; }; + A30CD9DA2CCC2DFE00EA22D3 /* STPAPIClientTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A30CD9D92CCC2DFE00EA22D3 /* STPAPIClientTest.swift */; }; A66C279957B6AC8F72DE05C7 /* STPCardExpiryInputTextFieldSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C75157665428685C7A4FD20 /* STPCardExpiryInputTextFieldSnapshotTests.swift */; }; A77C5769B20D7884FC8FC4FB /* STPNumericDigitInputTextFormatterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6223E57D3A198F956A37ED89 /* STPNumericDigitInputTextFormatterTests.swift */; }; A781FB0F586B26655FAEC3C0 /* STPCertTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D51B04D83D4FEF7F90DF16A /* STPCertTest.swift */; }; A8B0DB753CAA2223C8BED099 /* StripeErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC3AD586DDED620B9E68F461 /* StripeErrorTest.swift */; }; - A930DF2880EAD0CB9096E49E /* STPShippingAddressViewControllerLocalizationSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ED6BAC91E8A827DCDB38B15 /* STPShippingAddressViewControllerLocalizationSnapshotTests.swift */; }; AC35943F1EAD50E9D5D509B3 /* STPCardExpiryInputTextFieldFormatterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40BB87E28719FE0C6B946BB5 /* STPCardExpiryInputTextFieldFormatterTests.swift */; }; AC7C127B11A60222465F4696 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 005650A59D692F820EF20F5F /* XCTest.framework */; }; ACC1B91FC687AFD0DFD27CD4 /* STPIntentActionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33B9D01D037909D1C9C0B617 /* STPIntentActionTest.swift */; }; ACF6CFE0F8B88FDBBB16968C /* FraudDetectionDataTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45FF7A07CFC3B9B7AD6B49EE /* FraudDetectionDataTest.swift */; }; - AD09F2ACD0CDCBD414AC30AD /* STPAPISettingsObjCBridgeTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B669C53A601CD3CB0203A4B9 /* STPAPISettingsObjCBridgeTest.m */; }; - AD9B9F3FF697D4A3892E86F2 /* PaymentAnalyticTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8F8FCC84601E4ADC6B7F3CE /* PaymentAnalyticTest.swift */; }; AE747ADA2841AA06F32558D8 /* STPSourceCardDetailsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63114D0EAAE2606732DF5AA0 /* STPSourceCardDetailsTest.swift */; }; AF18D569B296BFC1EB5A7338 /* ImageTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAF368BCD5990EE5DC17D299 /* ImageTest.swift */; }; - AF23CB4EF17E87007CFC3E96 /* STPFPXBankStatusResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA08DCDD421CE92ECB61EF5C /* STPFPXBankStatusResponse.swift */; }; AF44725558E654548FED2A2B /* STPPaymentMethodUPITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 940209E5D30E86E856016906 /* STPPaymentMethodUPITests.swift */; }; - B00F7FC372E376C6B2170D37 /* STPPaymentContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = C750C2C4AB33BC232D1592BA /* STPPaymentContext.swift */; }; - B1BF689B91D538BDCA4C8578 /* STPCoreViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02FC9ED423D40C88D5A24441 /* STPCoreViewController.swift */; }; B359F6DCB31EAD0814AD9AFD /* STPPaymentMethodSEPADebitTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A41F721AEBB942BB81408A59 /* STPPaymentMethodSEPADebitTest.swift */; }; B44E4CF6C65522F80C946775 /* STPPaymentMethodFunctionalTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8192839B0F1AE9D9F2A94504 /* STPPaymentMethodFunctionalTest.swift */; }; B4719234E4BBDAD260E31373 /* STPPaymentCardTextFieldViewModelTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6DEE912364C9F4B51B374D0 /* STPPaymentCardTextFieldViewModelTest.swift */; }; B6656829DEC006DBEED2AA0E /* STPEphemeralKeyTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5BEAA15B53AC5662A33D0E1 /* STPEphemeralKeyTest.swift */; }; B6784B7F4B9B04617C0EE510 /* PKAddPaymentPassRequest+Stripe_Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 273EE407039913F0B644172B /* PKAddPaymentPassRequest+Stripe_Error.swift */; }; - B6EC2F572B618A3D00FF72A2 /* STPBasicUIAnalyticsSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6EC2F562B618A3D00FF72A2 /* STPBasicUIAnalyticsSerializer.swift */; }; B71F04D02538FA1723558C48 /* STPPaymentMethodiDEALTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B83930B631CF8EADFB606D6 /* STPPaymentMethodiDEALTest.swift */; }; B795A5EB8FDECA1060A9655C /* iOSSnapshotTestCase in Frameworks */ = {isa = PBXBuildFile; productRef = C55551F29B99CF6D6DD9EE2F /* iOSSnapshotTestCase */; }; B82859A4444B9F735720F232 /* STPMandateOnlineParamsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB58AC5E2E0A68221260FD44 /* STPMandateOnlineParamsTest.swift */; }; @@ -262,20 +202,16 @@ B8ED1F697519A6FCD3D79431 /* STPPaymentMethodGiropayTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 583DB466066B47C0F716E474 /* STPPaymentMethodGiropayTests.swift */; }; B917BF282C84507292112B9D /* STPCardBINMetadataTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E1C5E08678292561255B1C5 /* STPCardBINMetadataTests.swift */; }; B98D71ED9ACC2E1B47372F53 /* NSDecimalNumber+StripeTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20552E792B8E7BA15821AB5D /* NSDecimalNumber+StripeTest.swift */; }; - BAFD06E994739E1C38DFFBBC /* STPCardScanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69BD038947E8E2376A0D240B /* STPCardScanner.swift */; }; - BB46077C256C26418420F240 /* STPAddCardViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA793904C7B2D3AA0A4D5EFB /* STPAddCardViewController.swift */; }; BBB734F006FAD749678B87D1 /* STPPaymentMethodRevolutPayParamsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AE7BEADD3824A06C2994854 /* STPPaymentMethodRevolutPayParamsTests.swift */; }; BC6912C0DE15008C8D8C303C /* STPFloatingPlaceholderTextFieldSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7385193226663A5B79E69ED /* STPFloatingPlaceholderTextFieldSnapshotTests.swift */; }; BC694A1642DC30D530B60635 /* RotatingCardBrandsViewSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDA32D0C9E8A7A69F4899EDC /* RotatingCardBrandsViewSnapshotTests.swift */; }; BEC0435570B9199B918ED4DA /* STPAPIClient+LinkAccountSessionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E956CFA6317CAA8B41E217CA /* STPAPIClient+LinkAccountSessionTest.swift */; }; BEC5B2ACC54FB72DEBFB70AB /* STPPaymentMethodBancontactParamsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 655209238C85F466F9F14F14 /* STPPaymentMethodBancontactParamsTests.swift */; }; BF4A92064926FD7B0E3E92F7 /* StripePayments.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 22D1C6EB5826E2D7C80B6CF3 /* StripePayments.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - BF4ED4828114E2E89A3D4AB7 /* StripeBundleLocator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4D31B0D7BD9F97AF3BB61E6 /* StripeBundleLocator.swift */; }; C035D82D7096E3005858848C /* StripeCore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 43B4E4B85C598D7A9AFCB4D4 /* StripeCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; C0688E067AE4FFDFFDDC03BB /* PKPaymentAuthorizationViewController+Stripe_Blocks.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5D9F97ABC88302478220267 /* PKPaymentAuthorizationViewController+Stripe_Blocks.swift */; }; C0B59D0A7025A55ECD948D47 /* STPPaymentMethodNetBankingParamsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D41081066DC4465734F7FCD7 /* STPPaymentMethodNetBankingParamsTest.swift */; }; C1E70FD29BBE36D76A7E6929 /* CardExpiryDateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 153071C69A0BEE033E035DCF /* CardExpiryDateTests.swift */; }; - C314A5C55064C51C2B999E6B /* STPBackendAPIAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B782E1D974A4C131E60E2BD /* STPBackendAPIAdapter.swift */; }; C32D7ACEBC852CBC295BBEF2 /* STPSetupIntentFunctionalTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49AA313E068FB99CEAA5F7D3 /* STPSetupIntentFunctionalTest.swift */; }; C34D0BBDF6553ACF85204ACD /* STPPaymentMethodAfterpayClearpayTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CDD1E823223F450193E8746 /* STPPaymentMethodAfterpayClearpayTest.swift */; }; C35CF837D67AE8DB7CBDAD98 /* STPThreeDSLabelCustomizationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FDD4956E0A04D33F0856F31 /* STPThreeDSLabelCustomizationTest.swift */; }; @@ -297,9 +233,6 @@ CB5AADE45B7B7A40514C054B /* StripeApplePay.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 52F8AEC50D4623F80F04A533 /* StripeApplePay.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; CBAF9C6F87F746F17495ADC2 /* STPPaymentMethodCashAppTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7DDE50CBC86AD77084C877B6 /* STPPaymentMethodCashAppTests.swift */; }; CBCA59D39B30D869B4FDC04B /* STPE2ETest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C1548BA518F7AC2A9ECF9D5 /* STPE2ETest.swift */; }; - CC072EBAD035AA54A2AD3ABC /* UIViewController+Stripe_KeyboardAvoiding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F08757CA6F6B2DA65C14E0A /* UIViewController+Stripe_KeyboardAvoiding.swift */; }; - CEE483EB7B06B3C607BC755C /* UINavigationBar+StripeTest.m in Sources */ = {isa = PBXBuildFile; fileRef = E68F6B90F3BC61A49570FAF4 /* UINavigationBar+StripeTest.m */; }; - CEF318C74D2E44C78EF85306 /* STPBankSelectionTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 458F8576215E0F8ECE1D74CE /* STPBankSelectionTableViewCell.swift */; }; CF2E17AC77EB08393B8A3F98 /* STPCardNumberInputTextFieldFormatterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3803D0DED98501AA26B2EAC /* STPCardNumberInputTextFieldFormatterTests.swift */; }; CFC1F2B8D48FFF7B0F81B5A0 /* STPPaymentMethodAddressTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEB3F9F0228008BE213706DF /* STPPaymentMethodAddressTest.swift */; }; CFDD431A9A8A82BAA11AE5BF /* Stripe3DS2.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 33FDC634FD5D79E824240DDC /* Stripe3DS2.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; @@ -307,7 +240,6 @@ D0C81317E0AA8EB0370B1BA1 /* LinkLegalTermsViewSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 835CB781FBC19773ACC20676 /* LinkLegalTermsViewSnapshotTests.swift */; }; D15160C0F0763078DBB434E4 /* STPCardTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D575C31524E596E9C1A8E9B /* STPCardTest.swift */; }; D151C8724925DCBA4BA4F46A /* StripeCoreTestUtils.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 512A0E7C246D5F044245E069 /* StripeCoreTestUtils.framework */; }; - D2869246B446B8B31F1CD368 /* STPIntentActionLinkAuthenticateAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EB24EC81CE2C8D1C863B044 /* STPIntentActionLinkAuthenticateAccount.swift */; }; D2C062CE4E54094B1AC33E78 /* STPCardCVCInputTextFieldValidatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D42F83F785EAF24F5DC7ED1A /* STPCardCVCInputTextFieldValidatorTests.swift */; }; D375ADBD1F4B48380D5347D1 /* CircularButtonSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46AC0B5EC7433E081825D31B /* CircularButtonSnapshotTests.swift */; }; D3D654D8376AAA634466D31D /* STPSourceTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05AA6A1B2A462F1CE2F537C5 /* STPSourceTest.swift */; }; @@ -322,21 +254,17 @@ D7C555B36C282B99E22B8D45 /* STPInputTextFieldFormatterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A22E5B87755C1F05C3DB438C /* STPInputTextFieldFormatterTests.swift */; }; D7D24DCC9402153965AF7F1B /* STPPaymentMethodPrzelewy24Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6558C62376C2397030BD4A6 /* STPPaymentMethodPrzelewy24Tests.swift */; }; D83F76F584BC345CFBA71CF8 /* OneTimeCodeTextFieldSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D85FA7B714BDD8D1FD83B75 /* OneTimeCodeTextFieldSnapshotTests.swift */; }; - D85C432B241FDE23875037F9 /* UserDefaults+Stripe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26302721419496F37DE91DF8 /* UserDefaults+Stripe.swift */; }; D8BECFB70834CC42BA6706D8 /* STPSourceParamsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F6CB4B8FAD14B4D70A63595 /* STPSourceParamsTest.swift */; }; DC57D2DC40C6BA0C9CF7EC92 /* PayWithLinkButtonSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF342CBC167F9CAB5B49CC32 /* PayWithLinkButtonSnapshotTests.swift */; }; DCF615643A22D0A7B739547C /* Stripe+Exports.swift in Sources */ = {isa = PBXBuildFile; fileRef = B70DF0B659009041F485EE0F /* Stripe+Exports.swift */; }; DD16FC7ABCA7817794ECC407 /* STPThreeDSSelectionCustomizationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C23D612FD5AD7772E1B30DCC /* STPThreeDSSelectionCustomizationTest.swift */; }; DD8E2B99BAE917F83258DC35 /* STPPaymentMethodOptionsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E2638F7AA0906914117C2D5 /* STPPaymentMethodOptionsTest.swift */; }; - DDBF5AAE607C698618DDE865 /* STPCameraView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61F8308B7250B642D19827D8 /* STPCameraView.swift */; }; DE23FEF74E860620A334FDF5 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 884C01B087B4D820395BD374 /* Main.storyboard */; }; - DF73457BF349BC962A6AC502 /* STPCoreScrollViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D1525AF65BDEF691F8BCBE8 /* STPCoreScrollViewController.swift */; }; DF85F5EC6E16CAD21491891A /* AnalyticsHelperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61AF6E95FE0DD913204CAB32 /* AnalyticsHelperTests.swift */; }; E0F011E9C6CA368EF87F8E28 /* STPPaymentMethodBillingDetailsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0E24B5689732EB9106DA232 /* STPPaymentMethodBillingDetailsTest.swift */; }; E2790AB17C8C65CDE1E81532 /* STPPaymentMethodPrzelewy24ParamsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6269E77F81C32A5EC8BE412 /* STPPaymentMethodPrzelewy24ParamsTests.swift */; }; E3E916EB10E19727D6B33081 /* STPPaymentMethodOXXOParamsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBC9D4B0158266B01840AD9A /* STPPaymentMethodOXXOParamsTests.swift */; }; E3F1BAD22CC6E90B761B0502 /* STPTextFieldDelegateProxyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A8A2CD759D465290066EF65 /* STPTextFieldDelegateProxyTests.swift */; }; - E63B5BAF6B5645C979BFBA71 /* STPAddress+BasicUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 498C3FB07CFD532779C755D3 /* STPAddress+BasicUI.swift */; }; E699508F4DB4D9D4666BAA08 /* STPSetupIntentLastSetupErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01B057D99A14E5BA6019C349 /* STPSetupIntentLastSetupErrorTest.swift */; }; E6F428CFAD64979A8874B00B /* STPAnalyticsClientPaymentsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7ACB4FAFAD33296DE34D036 /* STPAnalyticsClientPaymentsTest.swift */; }; E97168F37D769524B58461B6 /* StripeCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43B4E4B85C598D7A9AFCB4D4 /* StripeCore.framework */; }; @@ -344,29 +272,22 @@ E9C690F3629C0AC3CD0260AF /* StripePaymentsObjcTestUtils.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D237177A7F99EB0F5F4F5E4 /* StripePaymentsObjcTestUtils.framework */; }; EA34719659CB9F1A269FECC7 /* StripeUICore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D794C5E6396B4A19DC4F6921 /* StripeUICore.framework */; }; EA571ECEFDDF10AF87CE2B74 /* STPThreeDSFooterCustomizationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 483B243268646AE65B06E98C /* STPThreeDSFooterCustomizationTest.swift */; }; - EA7FEC518AA07BA59405A5E3 /* STPPaymentIntentParams+BasicUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F01150CD0255164FE2CF3A4 /* STPPaymentIntentParams+BasicUI.swift */; }; EA80A8DB806DEF4F519059CB /* STPSourceSEPADebitDetailsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21780C410D22264B7C299520 /* STPSourceSEPADebitDetailsTest.swift */; }; EBD436689635CC28A24DECD4 /* STPPinManagementServiceFunctionalTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 336CC555B845DED30208D39D /* STPPinManagementServiceFunctionalTest.swift */; }; EC4DC8E386544959E1AA9355 /* STPSetupIntentTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA8B8F540CD05B3DC2C5EEA6 /* STPSetupIntentTest.swift */; }; EEA502DF8809B8FD0D00785E /* StripePayments.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 22D1C6EB5826E2D7C80B6CF3 /* StripePayments.framework */; }; EEB5E5E9C4E06B148A91C7BD /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6955B3A3353F8442E4FBBBF6 /* Assets.xcassets */; }; EEBA9A95E8057A06E5E7C103 /* STPCardNumberInputTextFieldSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD289E1EA9F0CE1C848AC0BB /* STPCardNumberInputTextFieldSnapshotTests.swift */; }; - EEFFE199D9769FF449BFD7FF /* STPCoreTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B78C72B0DB434EC7F700FDE0 /* STPCoreTableViewController.swift */; }; F06EAD0F48302B061ED29E61 /* STPPaymentMethodCardWalletMasterpassTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 533538E3EB92E326CCB95506 /* STPPaymentMethodCardWalletMasterpassTest.swift */; }; - F10FC337254A34ED8F13E341 /* STPPaymentOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30B694A39D54886392AA5DE3 /* STPPaymentOption.swift */; }; F2655328479314A9C8718DE4 /* STPApplePayContextTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F7AB40A5A10C2D267323ABE /* STPApplePayContextTest.swift */; }; F35E090A607EB5F86FFC3D31 /* STPCardCVCInputTextFieldTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94A7104C1C470515616E4D2B /* STPCardCVCInputTextFieldTests.swift */; }; F49D9C4030829D13A6EB45BE /* MockFiles in Resources */ = {isa = PBXBuildFile; fileRef = FE2DED6ABA7407C17C1391B6 /* MockFiles */; }; - F53E04785DB804EA5C2AAC18 /* STPAddressViewModelTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3D2DB08C335695B705F544C /* STPAddressViewModelTest.swift */; }; F550D4EB3DCFE03D6FC8F023 /* STPIntentActionPayNowDisplayQrCodeTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A517686D4D12691351311CA /* STPIntentActionPayNowDisplayQrCodeTest.swift */; }; F5CC4F320D09A06F0B21ABE6 /* STPPaymentMethodAffirmTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0DF2ED9232A7CC51F5FCB1 /* STPPaymentMethodAffirmTests.swift */; }; F729E784CFFC1F79EF5F2ABE /* STPPaymentIntentLastPaymentErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C7B8DACB0A7294BC235E3BC /* STPPaymentIntentLastPaymentErrorTest.swift */; }; - F835CEC935464FF32726A0A0 /* STPTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E8CA4361964E1BA400EFC89 /* STPTheme.swift */; }; F86F2DF6E46EFABE23AD5D27 /* STPApplePayContextDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E452877E5D11120B1E28A6E7 /* STPApplePayContextDelegate.swift */; }; F975CE029DF30419B8DB0D8F /* STPNumericStringValidatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AA36705DED9164663A98B6A /* STPNumericStringValidatorTests.swift */; }; - FB34906C9215D0E03850064B /* STPAddCardViewControllerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8704ABFA91A5226847F4A69A /* STPAddCardViewControllerTest.swift */; }; FBBA3B39598BBECB664C5E7F /* STPApplePayTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = CFC4BC1AB047ED88C4D13C89 /* STPApplePayTest.swift */; }; - FC166455478EAF51F7C34E68 /* STPApplePayPaymentOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03ACDC7EEC28D1FE50008F65 /* STPApplePayPaymentOption.swift */; }; FDADE3E36804A8AD82301BF3 /* STPPaymentMethodAfterpayClearpayParamsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECBA5B09A3FD875C93218573 /* STPPaymentMethodAfterpayClearpayParamsTest.swift */; }; FDD1858CAEFCEBB22BEC9BBC /* MKPlacemark+PaymentSheetTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DCCA0E8A02B4F4B23837FB4 /* MKPlacemark+PaymentSheetTests.swift */; }; FE6647242714D9BEA1EBC055 /* STPCardCVCInputTextFieldFormatterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E1F6514E7530C2A3478B2F5 /* STPCardCVCInputTextFieldFormatterTests.swift */; }; @@ -452,49 +373,29 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 002634603200AABECC9686B1 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/Localizable.strings"; sourceTree = ""; }; 005650A59D692F820EF20F5F /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/iPhoneOS.platform/Developer/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; - 00985EFC6CB7B912FDBF3813 /* STPApplePayPaymentOptionTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPApplePayPaymentOptionTest.swift; sourceTree = ""; }; 01B057D99A14E5BA6019C349 /* STPSetupIntentLastSetupErrorTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPSetupIntentLastSetupErrorTest.swift; sourceTree = ""; }; - 01B42BE6FB5EC1F708875AB8 /* STPPaymentCardTextFieldCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentCardTextFieldCell.swift; sourceTree = ""; }; - 02FC9ED423D40C88D5A24441 /* STPCoreViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPCoreViewController.swift; sourceTree = ""; }; - 03ACDC7EEC28D1FE50008F65 /* STPApplePayPaymentOption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPApplePayPaymentOption.swift; sourceTree = ""; }; - 04838ACE779F5CC949C276CB /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = ""; }; - 04FE0C74090AE8A871CCE5EC /* mt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = mt; path = mt.lproj/Localizable.strings; sourceTree = ""; }; 05AA6A1B2A462F1CE2F537C5 /* STPSourceTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPSourceTest.swift; sourceTree = ""; }; 05FE1BA89B80336F16924FA2 /* STPConfirmPaymentMethodOptionsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPConfirmPaymentMethodOptionsTest.swift; sourceTree = ""; }; - 064CFCA8FCEA9E4BAB3547D0 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/Localizable.strings; sourceTree = ""; }; 0669B4CA326CE74D125C789C /* STPFakeAddPaymentPassViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPFakeAddPaymentPassViewController.swift; sourceTree = ""; }; - 084B1B9FCCF4AB727B4ECFB2 /* id */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = id; path = id.lproj/Localizable.strings; sourceTree = ""; }; 090EF7D598B8DE779C275395 /* STPPostalCodeInputTextFieldSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPostalCodeInputTextFieldSnapshotTests.swift; sourceTree = ""; }; 095EBF095BA2BC8D299547DB /* STPSourceOwnerTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPSourceOwnerTest.swift; sourceTree = ""; }; - 0A16326394D71637A2CF68C3 /* fil */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fil; path = fil.lproj/Localizable.strings; sourceTree = ""; }; 0A8FF64CA314F909D7EC82FE /* STPPaymentMethodGrabPayParamsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodGrabPayParamsTest.swift; sourceTree = ""; }; 0ABB2CA7E96BE249CE8C0566 /* STPPaymentMethodCashAppParamsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodCashAppParamsTests.swift; sourceTree = ""; }; - 0B91C4D5B93FF71C61B140F1 /* STPCardScannerTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPCardScannerTableViewCell.swift; sourceTree = ""; }; 0C44B4366D6C4FD4B11662C8 /* STPPaymentMethodEPSTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodEPSTests.swift; sourceTree = ""; }; 0C75157665428685C7A4FD20 /* STPCardExpiryInputTextFieldSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPCardExpiryInputTextFieldSnapshotTests.swift; sourceTree = ""; }; - 0C9D6F99E303A17A91101723 /* pl-PL */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pl-PL"; path = "pl-PL.lproj/Localizable.strings"; sourceTree = ""; }; 0DB03E83746FE78361831546 /* WalletHeaderViewSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletHeaderViewSnapshotTests.swift; sourceTree = ""; }; 0E10C4D64477638398251FFB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; - 0F735744F27D46F005BB5D67 /* sk-SK */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "sk-SK"; path = "sk-SK.lproj/Localizable.strings"; sourceTree = ""; }; - 1007571188950D7FBF745A4E /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/Localizable.strings; sourceTree = ""; }; 11C866064B3482878A69892F /* CustomerAdapterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomerAdapterTests.swift; sourceTree = ""; }; - 121B7EDCCD0957C9A444A8E3 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = ""; }; 12632E6710DE8861CAF1BAA4 /* RotatingCardBrandsViewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RotatingCardBrandsViewTests.swift; sourceTree = ""; }; - 12D757B36030685C401A6990 /* et-EE */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "et-EE"; path = "et-EE.lproj/Localizable.strings"; sourceTree = ""; }; - 12DBB3F72AEFB52DE27C27ED /* STPAnalyticsClient+BasicUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "STPAnalyticsClient+BasicUI.swift"; sourceTree = ""; }; - 13DDBEA7D444A8AC14E0F1C8 /* lv-LV */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "lv-LV"; path = "lv-LV.lproj/Localizable.strings"; sourceTree = ""; }; 148C1D7D1BBBC6B74894A869 /* STPPaymentMethodTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodTest.swift; sourceTree = ""; }; 153071C69A0BEE033E035DCF /* CardExpiryDateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardExpiryDateTests.swift; sourceTree = ""; }; 1645D9793463E266501B74FD /* STPPIIFunctionalTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPIIFunctionalTest.swift; sourceTree = ""; }; 1671EC46C713D51013AD7D8B /* STPPaymentMethodCardParamsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodCardParamsTest.swift; sourceTree = ""; }; 17013F78CE3F9662029FEF5B /* STPSourceFunctionalTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPSourceFunctionalTest.swift; sourceTree = ""; }; 180CF848E3ABF0236C494D8B /* FBSnapshotTestCase+STPViewControllerLoading.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FBSnapshotTestCase+STPViewControllerLoading.swift"; sourceTree = ""; }; - 18FCB69CD3B8C3DAB216A5F0 /* STPPaymentConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentConfiguration.swift; sourceTree = ""; }; 195DEC752CC82CC4BA1E2351 /* STPConnectAccountParamsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPConnectAccountParamsTest.swift; sourceTree = ""; }; 1A8A6B88797870BC71CCB3AF /* STPPushProvisioningDetailsFunctionalTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPushProvisioningDetailsFunctionalTest.swift; sourceTree = ""; }; - 1B76DF0FE363F59BF0940A8B /* UIView+Stripe_FirstResponder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Stripe_FirstResponder.swift"; sourceTree = ""; }; 1C1548BA518F7AC2A9ECF9D5 /* STPE2ETest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPE2ETest.swift; sourceTree = ""; }; 1CE268457D21A7209862E004 /* STPApplePayContextFunctionalTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPApplePayContextFunctionalTest.swift; sourceTree = ""; }; 1D23EB567F573612E0794B3A /* Stripe Tests-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Stripe Tests-Debug.xcconfig"; sourceTree = ""; }; @@ -503,101 +404,69 @@ 1D983E089196152DA1C69469 /* STPCardFormViewSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPCardFormViewSnapshotTests.swift; sourceTree = ""; }; 1DD6897858F46976A946394E /* StripeiOSAppHostedTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = StripeiOSAppHostedTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 1E2638F7AA0906914117C2D5 /* STPPaymentMethodOptionsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodOptionsTest.swift; sourceTree = ""; }; - 1E8AFAE24610EC983727F860 /* STPAPIClient+BasicUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "STPAPIClient+BasicUI.swift"; sourceTree = ""; }; - 1ED6BAC91E8A827DCDB38B15 /* STPShippingAddressViewControllerLocalizationSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPShippingAddressViewControllerLocalizationSnapshotTests.swift; sourceTree = ""; }; 1F0DF2ED9232A7CC51F5FCB1 /* STPPaymentMethodAffirmTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodAffirmTests.swift; sourceTree = ""; }; 1F16C36797D978E72E612100 /* STPPaymentCardTextFieldTestsSwift.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentCardTextFieldTestsSwift.swift; sourceTree = ""; }; 1F29C15B47C7CB0941CD4C9E /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 1F6CB4B8FAD14B4D70A63595 /* STPSourceParamsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPSourceParamsTest.swift; sourceTree = ""; }; - 1FFBAA4B44967B157A4F4E91 /* STPPaymentActivityIndicatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentActivityIndicatorView.swift; sourceTree = ""; }; 20552E792B8E7BA15821AB5D /* NSDecimalNumber+StripeTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSDecimalNumber+StripeTest.swift"; sourceTree = ""; }; 207677E2A0DBC04C88139372 /* STPPaymentMethodSofortParamsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodSofortParamsTests.swift; sourceTree = ""; }; 20879436DCFB1F03BE1608B3 /* ServerErrorMapperTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerErrorMapperTest.swift; sourceTree = ""; }; 21780C410D22264B7C299520 /* STPSourceSEPADebitDetailsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPSourceSEPADebitDetailsTest.swift; sourceTree = ""; }; - 21E4B84223DDA131544DBBA7 /* STPShippingMethodsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPShippingMethodsViewController.swift; sourceTree = ""; }; 22D1C6EB5826E2D7C80B6CF3 /* StripePayments.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = StripePayments.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 23997D61DF41CA84BFC33080 /* STPBECSDebitAccountNumberValidatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPBECSDebitAccountNumberValidatorTests.swift; sourceTree = ""; }; - 2560B4EEE60D40FB31B8552F /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; - 26302721419496F37DE91DF8 /* UserDefaults+Stripe.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserDefaults+Stripe.swift"; sourceTree = ""; }; - 26E5C1DABAA63F07F0C6AE37 /* STPAddCardViewControllerLocalizationSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPAddCardViewControllerLocalizationSnapshotTests.swift; sourceTree = ""; }; - 26E70469F4032553B4BB62DA /* ca-ES */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ca-ES"; path = "ca-ES.lproj/Localizable.strings"; sourceTree = ""; }; 273EE407039913F0B644172B /* PKAddPaymentPassRequest+Stripe_Error.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PKAddPaymentPassRequest+Stripe_Error.swift"; sourceTree = ""; }; - 27A4D83C0E7D4AE0CCD38B89 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/Localizable.strings; sourceTree = ""; }; 284C67269D2606DA147AE01D /* STPGenericInputPickerFieldSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPGenericInputPickerFieldSnapshotTests.swift; sourceTree = ""; }; - 28A50AFA4603E488FF3D82D0 /* STPAddressViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPAddressViewModel.swift; sourceTree = ""; }; 294CD46E24BB2743042872D7 /* StripeiOSTestHostApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = StripeiOSTestHostApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; 2A63AC868755CB4745E7458E /* STPPaymentMethodPayPalTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodPayPalTests.swift; sourceTree = ""; }; 2A8A2CD759D465290066EF65 /* STPTextFieldDelegateProxyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPTextFieldDelegateProxyTests.swift; sourceTree = ""; }; 2B28B8A547CD846277ECD578 /* STPPushProvisioningDetailsParams.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPushProvisioningDetailsParams.swift; sourceTree = ""; }; - 2C078573F46762353664AC92 /* UINavigationController+Stripe_Completion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UINavigationController+Stripe_Completion.swift"; sourceTree = ""; }; - 2CC4B06AB5C02FF54091E5A8 /* STPCustomerContextTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPCustomerContextTest.swift; sourceTree = ""; }; - 2D1525AF65BDEF691F8BCBE8 /* STPCoreScrollViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPCoreScrollViewController.swift; sourceTree = ""; }; 2D63B73C5773432CA134D1FC /* STPGenericInputPickerFieldValidatorTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPGenericInputPickerFieldValidatorTest.swift; sourceTree = ""; }; 2D878F923A1F69B58D6B2812 /* STPRadarSessionFunctionalTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPRadarSessionFunctionalTest.swift; sourceTree = ""; }; 2DC4B62C336EAA05A33FC384 /* STPPaymentMethodCardWalletTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodCardWalletTest.swift; sourceTree = ""; }; 2E1862744F23286D1FB9D4AE /* STPFormTextFieldTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPFormTextFieldTest.swift; sourceTree = ""; }; - 2F08757CA6F6B2DA65C14E0A /* UIViewController+Stripe_KeyboardAvoiding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Stripe_KeyboardAvoiding.swift"; sourceTree = ""; }; 30964128998473CAA9F2DD7E /* STPFormEncoderTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPFormEncoderTest.swift; sourceTree = ""; }; - 30B694A39D54886392AA5DE3 /* STPPaymentOption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentOption.swift; sourceTree = ""; }; - 313263D9DC0629C5EE279FEB /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/Localizable.strings; sourceTree = ""; }; 313F5F782B0BE59000BD98A9 /* Docs.docc */ = {isa = PBXFileReference; lastKnownFileType = folder.documentationcatalog; path = Docs.docc; sourceTree = ""; }; 31CDFC2D2BA3708000B3DD91 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; 336CC555B845DED30208D39D /* STPPinManagementServiceFunctionalTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPinManagementServiceFunctionalTest.swift; sourceTree = ""; }; 33B9D01D037909D1C9C0B617 /* STPIntentActionTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPIntentActionTest.swift; sourceTree = ""; }; 33FDC634FD5D79E824240DDC /* Stripe3DS2.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Stripe3DS2.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 35ABE696542469B79A9D52E6 /* tk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tk; path = tk.lproj/Localizable.strings; sourceTree = ""; }; - 35C1E9B0EE03825DABF6471A /* STPPaymentMethod+BasicUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "STPPaymentMethod+BasicUI.swift"; sourceTree = ""; }; 3AE7BEADD3824A06C2994854 /* STPPaymentMethodRevolutPayParamsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodRevolutPayParamsTests.swift; sourceTree = ""; }; 3B0E131538728BC4802627B1 /* UserDefaults+StripeTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserDefaults+StripeTest.swift"; sourceTree = ""; }; 3B112FFF3FCA82094281493F /* STPPaymentMethodUSBankAccountTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodUSBankAccountTest.swift; sourceTree = ""; }; - 3B3000668A75E095B514241F /* UIBarButtonItem+Stripe.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIBarButtonItem+Stripe.swift"; sourceTree = ""; }; 3C742844915B96CFD25BFFF9 /* AfterpayPriceBreakdownViewSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AfterpayPriceBreakdownViewSnapshotTests.swift; sourceTree = ""; }; 3C77C7BC4BA57EC296CF2F1C /* STPApplePayFunctionalTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPApplePayFunctionalTest.swift; sourceTree = ""; }; - 3C995125252BED1EEC018B9D /* STPPaymentContextApplePayTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentContextApplePayTest.swift; sourceTree = ""; }; 3CDD1E823223F450193E8746 /* STPPaymentMethodAfterpayClearpayTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodAfterpayClearpayTest.swift; sourceTree = ""; }; 3E1C5E08678292561255B1C5 /* STPCardBINMetadataTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPCardBINMetadataTests.swift; sourceTree = ""; }; - 3E5FB20B2BEFC00D54FDD87D /* STPCard+BasicUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "STPCard+BasicUI.swift"; sourceTree = ""; }; 3EBB07171F6FDCE6E20C454A /* STPPinManagementService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPinManagementService.swift; sourceTree = ""; }; 3ED44491EB0AC72B1B1A773C /* STPThreeDSUICustomizationTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPThreeDSUICustomizationTest.swift; sourceTree = ""; }; 3FC0560A312147C37CFE6CF9 /* STPBinRangeTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPBinRangeTest.swift; sourceTree = ""; }; 4002981AC12687681616D21E /* STPPaymentMethodParamsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodParamsTest.swift; sourceTree = ""; }; - 4077600B9B3C1ABFF38383BE /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/Localizable.strings; sourceTree = ""; }; 40BB87E28719FE0C6B946BB5 /* STPCardExpiryInputTextFieldFormatterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPCardExpiryInputTextFieldFormatterTests.swift; sourceTree = ""; }; 4259421D2CD26E37B96F97B2 /* Stripe.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Stripe.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 43ADFC4EF612D7C4A46E81B9 /* lt-LT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "lt-LT"; path = "lt-LT.lproj/Localizable.strings"; sourceTree = ""; }; 43B4E4B85C598D7A9AFCB4D4 /* StripeCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = StripeCore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 4418164D75002AE6A0273176 /* STPCardExpiryInputTextFieldValidatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPCardExpiryInputTextFieldValidatorTests.swift; sourceTree = ""; }; - 458F8576215E0F8ECE1D74CE /* STPBankSelectionTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPBankSelectionTableViewCell.swift; sourceTree = ""; }; 45FF7A07CFC3B9B7AD6B49EE /* FraudDetectionDataTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FraudDetectionDataTest.swift; sourceTree = ""; }; 46AC0B5EC7433E081825D31B /* CircularButtonSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircularButtonSnapshotTests.swift; sourceTree = ""; }; 46C31CAD0FA74B58BA2B8530 /* STPPaymentIntentEnumsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentIntentEnumsTest.swift; sourceTree = ""; }; 47E12A0CBFA259A032F7AF0C /* STPPaymentMethodKlarnaParamsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodKlarnaParamsTests.swift; sourceTree = ""; }; 47E5E1173A37AABB07FB68AB /* STPPaymentMethodUPIParamsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodUPIParamsTest.swift; sourceTree = ""; }; - 482693A3D9A527B0E671F757 /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/Localizable.strings; sourceTree = ""; }; 483B243268646AE65B06E98C /* STPThreeDSFooterCustomizationTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPThreeDSFooterCustomizationTest.swift; sourceTree = ""; }; 485E747DA1F72F091986787B /* STPEphemeralKeyProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPEphemeralKeyProvider.swift; sourceTree = ""; }; - 498C3FB07CFD532779C755D3 /* STPAddress+BasicUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "STPAddress+BasicUI.swift"; sourceTree = ""; }; 49AA313E068FB99CEAA5F7D3 /* STPSetupIntentFunctionalTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPSetupIntentFunctionalTest.swift; sourceTree = ""; }; 4AA36705DED9164663A98B6A /* STPNumericStringValidatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPNumericStringValidatorTests.swift; sourceTree = ""; }; 4AAE5EE11611F9F7762B64C6 /* STPAUBECSFormViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPAUBECSFormViewModelTests.swift; sourceTree = ""; }; 4CA5D11C977A95B8E936E907 /* STPIntentActionWeChatPayRedirectToAppTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPIntentActionWeChatPayRedirectToAppTest.swift; sourceTree = ""; }; - 4DFDFC019C67AFF7C0F7630B /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/Localizable.strings"; sourceTree = ""; }; 4E29B46F2C940E0A21734E09 /* StripeiOSTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = StripeiOSTests.xctestplan; sourceTree = ""; }; 4E371E9B3B2E343FE954531C /* STPPaymentMethodBoletoTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodBoletoTests.swift; sourceTree = ""; }; 4FD94FF270165D699DA89B24 /* STPPaymentMethodKlarnaTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodKlarnaTests.swift; sourceTree = ""; }; 4FFA8B446217CDE678D7287F /* STPBlocks.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = STPBlocks.h; sourceTree = ""; }; - 5062915D961C1BCAFD641FFE /* STPPaymentOptionsViewControllerLocalizationSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentOptionsViewControllerLocalizationSnapshotTests.swift; sourceTree = ""; }; 512A0E7C246D5F044245E069 /* StripeCoreTestUtils.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = StripeCoreTestUtils.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 51408DE266D0345784ADD4FA /* STPThreeDSNavigationBarCustomizationTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPThreeDSNavigationBarCustomizationTest.swift; sourceTree = ""; }; 51BD2CE41E4F0CF648F44E4A /* TextFieldElement+IBANTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TextFieldElement+IBANTest.swift"; sourceTree = ""; }; 51E62BB62EA9B782778CA880 /* STPStackViewWithSeparatorSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPStackViewWithSeparatorSnapshotTests.swift; sourceTree = ""; }; 52F8AEC50D4623F80F04A533 /* StripeApplePay.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = StripeApplePay.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 533538E3EB92E326CCB95506 /* STPPaymentMethodCardWalletMasterpassTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodCardWalletMasterpassTest.swift; sourceTree = ""; }; - 53C5AB22D6328E85A6DDF663 /* STPPaymentMethodParams+BasicUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "STPPaymentMethodParams+BasicUI.swift"; sourceTree = ""; }; 54426CBF6F77ABEFBDFDA8C4 /* STPPaymentMethodAUBECSDebitTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodAUBECSDebitTests.swift; sourceTree = ""; }; - 5476BD87E0480A93958F0328 /* UITableViewCell+Stripe_Borders.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITableViewCell+Stripe_Borders.swift"; sourceTree = ""; }; - 5804C2B9C0704E386B3D25A4 /* UIViewController+Stripe_ParentViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Stripe_ParentViewController.swift"; sourceTree = ""; }; - 58158E8A117299834246100F /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Localizable.strings; sourceTree = ""; }; 583DB466066B47C0F716E474 /* STPPaymentMethodGiropayTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodGiropayTests.swift; sourceTree = ""; }; 588C260880FFC584A00A89F5 /* STPEphemeralKeyManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPEphemeralKeyManager.swift; sourceTree = ""; }; 58A53F005EA8FDDAA66126BA /* STPGenericInputTextFieldSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPGenericInputTextFieldSnapshotTests.swift; sourceTree = ""; }; @@ -610,27 +479,21 @@ 61152B4E2B866827003B69A0 /* STPPaymentMethodAmazonPayParamsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodAmazonPayParamsTests.swift; sourceTree = ""; }; 617C1C872BB4992400B10AC5 /* STPPaymentMethodAlmaTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodAlmaTests.swift; sourceTree = ""; }; 617C1C892BB4998C00B10AC5 /* STPPaymentMethodAlmaParamsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodAlmaParamsTests.swift; sourceTree = ""; }; - 618DE183886175AF23C4E668 /* sl-SI */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "sl-SI"; path = "sl-SI.lproj/Localizable.strings"; sourceTree = ""; }; 61951FB82B866BA1005F90BE /* STPPaymentMethodAmazonPayTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodAmazonPayTests.swift; sourceTree = ""; }; 61AF6E95FE0DD913204CAB32 /* AnalyticsHelperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsHelperTests.swift; sourceTree = ""; }; 61E0A0C42BF31D3C00C89786 /* STPPaymentHandlerRefreshTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentHandlerRefreshTests.swift; sourceTree = ""; }; 61E1CA1E2BD6B72800A421AE /* STPPaymentMethodMultibancoTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodMultibancoTests.swift; sourceTree = ""; }; 61E1CA202BD6B78500A421AE /* STPPaymentMethodMultibancoParamsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodMultibancoParamsTests.swift; sourceTree = ""; }; 61E1CA262BD6BED600A421AE /* STPIntentActionMultibancoDisplayDetailsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPIntentActionMultibancoDisplayDetailsTest.swift; sourceTree = ""; }; - 61F8308B7250B642D19827D8 /* STPCameraView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPCameraView.swift; sourceTree = ""; }; - 6215A9BF343775B1BD0F62AF /* STPPaymentOptionTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentOptionTableViewCell.swift; sourceTree = ""; }; 6223E57D3A198F956A37ED89 /* STPNumericDigitInputTextFormatterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPNumericDigitInputTextFormatterTests.swift; sourceTree = ""; }; 63114D0EAAE2606732DF5AA0 /* STPSourceCardDetailsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPSourceCardDetailsTest.swift; sourceTree = ""; }; 63F5F35DB97D8A176FB6ED24 /* NSString+StripeTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSString+StripeTest.swift"; sourceTree = ""; }; 655209238C85F466F9F14F14 /* STPPaymentMethodBancontactParamsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodBancontactParamsTests.swift; sourceTree = ""; }; 65DCC9BDA647E58D3882C698 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; 6618739767139C25C05B3631 /* STPPostalCodeInputTextFieldTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPostalCodeInputTextFieldTests.swift; sourceTree = ""; }; - 661976D1296DFA48A25E0493 /* STPShippingMethodsViewControllerLocalizationSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPShippingMethodsViewControllerLocalizationSnapshotTests.swift; sourceTree = ""; }; 683F7735569D22CBEC9CA2E6 /* STPPaymentHandlerFunctionalTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = STPPaymentHandlerFunctionalTest.m; sourceTree = ""; }; 6887F19BB9804BF45FD703FF /* STPPushProvisioningContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPushProvisioningContext.swift; sourceTree = ""; }; 6955B3A3353F8442E4FBBBF6 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 69BD038947E8E2376A0D240B /* STPCardScanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPCardScanner.swift; sourceTree = ""; }; - 6A9E7B637A8747431B38FD1D /* STPCardValidationState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPCardValidationState.swift; sourceTree = ""; }; 6B7A947152A728EB2CBC4DB2 /* STPSourceReceiverTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPSourceReceiverTest.swift; sourceTree = ""; }; 6BA4B9192BF433B200D1F21D /* STPPaymentMethodMobilePayParamsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodMobilePayParamsTests.swift; sourceTree = ""; }; 6BA4B91B2BF4343B00D1F21D /* STPPaymentMethodMobilePayTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodMobilePayTests.swift; sourceTree = ""; }; @@ -638,26 +501,16 @@ 6C7B8DACB0A7294BC235E3BC /* STPPaymentIntentLastPaymentErrorTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentIntentLastPaymentErrorTest.swift; sourceTree = ""; }; 6CC0B1FC92A573AAEA4F4E94 /* STPSetupIntentConfirmParamsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPSetupIntentConfirmParamsTest.swift; sourceTree = ""; }; 6E1F6514E7530C2A3478B2F5 /* STPCardCVCInputTextFieldFormatterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPCardCVCInputTextFieldFormatterTests.swift; sourceTree = ""; }; - 6F01150CD0255164FE2CF3A4 /* STPPaymentIntentParams+BasicUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "STPPaymentIntentParams+BasicUI.swift"; sourceTree = ""; }; - 6F017A08C7E633FB4297D274 /* UIViewController+Stripe_NavigationItemProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Stripe_NavigationItemProxy.swift"; sourceTree = ""; }; - 71711FC8E2FB66E52A5FDD9A /* STPShippingAddressViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPShippingAddressViewController.swift; sourceTree = ""; }; - 72903593DC432D01720DC9D9 /* STPAddressFieldTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPAddressFieldTableViewCell.swift; sourceTree = ""; }; 739934737B9A09775CD278C9 /* STPPaymentMethodNetBankingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodNetBankingTests.swift; sourceTree = ""; }; 74FDEF9F687C63BADFB96480 /* STPPaymentMethodUSBankAccountParamsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodUSBankAccountParamsTest.swift; sourceTree = ""; }; 77247622AB08FEF48CA0DC26 /* StripePaymentsTestUtils.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = StripePaymentsTestUtils.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 77E846CD56018D8417A3AB95 /* StripeiOS.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = StripeiOS.xcassets; sourceTree = ""; }; - 789D0B49B0788794739E3DD4 /* STPShippingAddressViewControllerTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPShippingAddressViewControllerTest.swift; sourceTree = ""; }; 78D1EEABBAE5BD5615486B0F /* STPLabeledFormTextFieldViewSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPLabeledFormTextFieldViewSnapshotTests.swift; sourceTree = ""; }; - 79ABE6A14AF9D14103050876 /* STPPaymentConfigurationTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = STPPaymentConfigurationTest.m; sourceTree = ""; }; 7A517686D4D12691351311CA /* STPIntentActionPayNowDisplayQrCodeTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPIntentActionPayNowDisplayQrCodeTest.swift; sourceTree = ""; }; 7A7963CC618A1A1346EC20C7 /* STPPaymentMethodRevolutPayTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodRevolutPayTests.swift; sourceTree = ""; }; 7AC0A18C441FCA394BEF6A3D /* STPPaymentMethodBillingDetailsTests+Link.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "STPPaymentMethodBillingDetailsTests+Link.swift"; sourceTree = ""; }; - 7B10B1A15063FEDBA4A59953 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; - 7B8ADF2EA2D5C4C90BCDDDD5 /* bg-BG */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "bg-BG"; path = "bg-BG.lproj/Localizable.strings"; sourceTree = ""; }; 7B9A4A2B0FB9F8C743BBED48 /* PaymentTypeCellSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaymentTypeCellSnapshotTests.swift; sourceTree = ""; }; 7C04AFC9CDE50D09D38A3232 /* FormSpecProviderTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormSpecProviderTest.swift; sourceTree = ""; }; - 7CAE7444CEFE1D1EFB888996 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/Localizable.strings; sourceTree = ""; }; - 7D964D9E01627B419B4BD23C /* STPPaymentResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentResult.swift; sourceTree = ""; }; 7DDE50CBC86AD77084C877B6 /* STPPaymentMethodCashAppTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodCashAppTests.swift; sourceTree = ""; }; 7F090B8D315E7FD12A5F9C09 /* STPTokenTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPTokenTest.swift; sourceTree = ""; }; 7F68637E75142DCD46710796 /* STPLabeledMultiFormTextFieldViewSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPLabeledMultiFormTextFieldViewSnapshotTests.swift; sourceTree = ""; }; @@ -665,28 +518,19 @@ 806124200E77795DCFC8418E /* ConfirmButtonSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfirmButtonSnapshotTests.swift; sourceTree = ""; }; 807FF966F1DE05F3496B817B /* STPAPIClient+PushProvisioning.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "STPAPIClient+PushProvisioning.swift"; sourceTree = ""; }; 80BBCC4D386EE44E809A591C /* STPPaymentMethodOXXOTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodOXXOTests.swift; sourceTree = ""; }; - 81352A0CBE46A59E6B1A712E /* STPBankSelectionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPBankSelectionViewController.swift; sourceTree = ""; }; 8192839B0F1AE9D9F2A94504 /* STPPaymentMethodFunctionalTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodFunctionalTest.swift; sourceTree = ""; }; 82E46B18CDDC191934F3D4BE /* STPPaymentMethodCardWalletVisaCheckoutTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodCardWalletVisaCheckoutTest.swift; sourceTree = ""; }; 835CB781FBC19773ACC20676 /* LinkLegalTermsViewSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkLegalTermsViewSnapshotTests.swift; sourceTree = ""; }; 85AAB72218409F85FE29E69E /* APIRequestTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APIRequestTest.swift; sourceTree = ""; }; 85C29AE44D809CD677B5E52B /* STPFPXBankBrandTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPFPXBankBrandTest.swift; sourceTree = ""; }; - 86798C95A778362EF815B4C6 /* UIView+Stripe_SafeAreaBounds.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Stripe_SafeAreaBounds.swift"; sourceTree = ""; }; 86983B09A1712944EC012AD4 /* STPViewWithSeparatorSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPViewWithSeparatorSnapshotTests.swift; sourceTree = ""; }; - 8704ABFA91A5226847F4A69A /* STPAddCardViewControllerTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPAddCardViewControllerTest.swift; sourceTree = ""; }; - 88639E3C3AC622B5EF475538 /* STPUIVCStripeParentViewControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPUIVCStripeParentViewControllerTests.swift; sourceTree = ""; }; - 88AEABC15CCBB9EA393C175F /* STPMocks.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = STPMocks.m; sourceTree = ""; }; 890660C21E3666CE7B82695B /* STPEphemeralKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPEphemeralKey.swift; sourceTree = ""; }; 89E5DA3029F141B5111A5B2C /* STPPushProvisioningDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPushProvisioningDetails.swift; sourceTree = ""; }; 8A3F2B714DB3D1DED561A7EF /* STPCardParamsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPCardParamsTest.swift; sourceTree = ""; }; 8BD02D8298877F10F2EF2A9D /* STPPaymentMethodCardTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodCardTest.swift; sourceTree = ""; }; 8CE85C770AEEDBE4AEC93EAA /* Error+PaymentSheetTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Error+PaymentSheetTests.swift"; sourceTree = ""; }; 8D49257A97E71A475A9F6E08 /* STPCountryPickerInputFieldSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPCountryPickerInputFieldSnapshotTests.swift; sourceTree = ""; }; - 8E8CA4361964E1BA400EFC89 /* STPTheme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPTheme.swift; sourceTree = ""; }; - 8ED737CB1253C3C5704B6C05 /* cs-CZ */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "cs-CZ"; path = "cs-CZ.lproj/Localizable.strings"; sourceTree = ""; }; - 8F7E3CE2105E4A39032CD919 /* Enums+CustomStringConvertible.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Enums+CustomStringConvertible.swift"; sourceTree = ""; }; 901BE31021AF27DB5D326327 /* STPCardBrandTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPCardBrandTest.swift; sourceTree = ""; }; - 90D0900C5FDBB7952BCF2C3A /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/Localizable.strings"; sourceTree = ""; }; 916DB8789F65D3C1BCB510C0 /* STPPaymentMethodThreeDSecureUsageTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodThreeDSecureUsageTest.swift; sourceTree = ""; }; 917154477796779ECFA1334A /* STPPostalCodeInputTextFieldFormatterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPostalCodeInputTextFieldFormatterTests.swift; sourceTree = ""; }; 924E878428D15506711CA628 /* STPPhoneNumberValidatorTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPhoneNumberValidatorTest.swift; sourceTree = ""; }; @@ -698,83 +542,53 @@ 967C784618A074FF021B3089 /* STPBankAccountParamsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPBankAccountParamsTest.swift; sourceTree = ""; }; 967DDC94B687B14E07842CC8 /* STPConnectAccountAddressTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPConnectAccountAddressTest.swift; sourceTree = ""; }; 969E196AB597EEF68C38103E /* Project-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Project-Release.xcconfig"; sourceTree = ""; }; - 96E1FED5CE5974C9C1162E93 /* STPSectionHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPSectionHeaderView.swift; sourceTree = ""; }; - 98544B08552407D41D398C68 /* STPShippingMethodTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPShippingMethodTableViewCell.swift; sourceTree = ""; }; 989411FA3CD0CCC38BC227F4 /* STPBankAccountFunctionalTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPBankAccountFunctionalTest.swift; sourceTree = ""; }; 98F9CB667BC68767DFB5FACD /* OneTimeCodeTextFieldTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OneTimeCodeTextFieldTests.swift; sourceTree = ""; }; - 9B782E1D974A4C131E60E2BD /* STPBackendAPIAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPBackendAPIAdapter.swift; sourceTree = ""; }; 9B83930B631CF8EADFB606D6 /* STPPaymentMethodiDEALTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodiDEALTest.swift; sourceTree = ""; }; 9BBCE3A905041A709E8F279A /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 9D3BBCE8C46A38D0E20DBF4E /* ms-MY */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ms-MY"; path = "ms-MY.lproj/Localizable.strings"; sourceTree = ""; }; 9D85FA7B714BDD8D1FD83B75 /* OneTimeCodeTextFieldSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OneTimeCodeTextFieldSnapshotTests.swift; sourceTree = ""; }; 9DCCA0E8A02B4F4B23837FB4 /* MKPlacemark+PaymentSheetTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MKPlacemark+PaymentSheetTests.swift"; sourceTree = ""; }; 9EAE9A2AE65771403CE57C11 /* STPErrorBridgeTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = STPErrorBridgeTest.m; sourceTree = ""; }; - 9EB24EC81CE2C8D1C863B044 /* STPIntentActionLinkAuthenticateAccount.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPIntentActionLinkAuthenticateAccount.swift; sourceTree = ""; }; 9FEE395C4DD0E0112AF3720C /* STPInputTextFieldValidatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPInputTextFieldValidatorTests.swift; sourceTree = ""; }; A0E24B5689732EB9106DA232 /* STPPaymentMethodBillingDetailsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodBillingDetailsTest.swift; sourceTree = ""; }; A1272F2E05A0E294DD9ECA26 /* STPApplePayContextFunctionalTestExtras.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPApplePayContextFunctionalTestExtras.swift; sourceTree = ""; }; A15BBFFA401852A8719E3DDD /* STPPaymentMethodCardChecksTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodCardChecksTest.swift; sourceTree = ""; }; A1C67AC5D415615E9F27D3E3 /* STPPaymentMethodBoletoParamsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodBoletoParamsTests.swift; sourceTree = ""; }; - A1C876DC7F3E31D7189506A8 /* STPPaymentContextAmountModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentContextAmountModel.swift; sourceTree = ""; }; A22E5B87755C1F05C3DB438C /* STPInputTextFieldFormatterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPInputTextFieldFormatterTests.swift; sourceTree = ""; }; - A2922A32A754CFC9AB8B48AE /* STPPaymentOptionsViewControllerTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentOptionsViewControllerTest.swift; sourceTree = ""; }; + A30CD9D92CCC2DFE00EA22D3 /* STPAPIClientTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = STPAPIClientTest.swift; sourceTree = ""; }; A39580123A4F1EA96F91768A /* STPAddressTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPAddressTests.swift; sourceTree = ""; }; A41F721AEBB942BB81408A59 /* STPPaymentMethodSEPADebitTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodSEPADebitTest.swift; sourceTree = ""; }; - A5398E1156E0BFEBBF56FD2F /* String+Localized.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Localized.swift"; sourceTree = ""; }; A583966A33DCDCF04322A592 /* STPThreeDSTextFieldCustomizationTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPThreeDSTextFieldCustomizationTest.swift; sourceTree = ""; }; A61763BA2CCA86F9B8FD4F1F /* OperationDebouncerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OperationDebouncerTests.swift; sourceTree = ""; }; A6269E77F81C32A5EC8BE412 /* STPPaymentMethodPrzelewy24ParamsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodPrzelewy24ParamsTests.swift; sourceTree = ""; }; - A6F6634AD12771A9BB100DD3 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = ""; }; - A7E369CEC9F5B3758F78E88F /* UINavigationBar+Stripe_Theme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UINavigationBar+Stripe_Theme.swift"; sourceTree = ""; }; A8598727045C6268B57A5FC7 /* Stripe-umbrella.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Stripe-umbrella.h"; sourceTree = ""; }; - A9A1BB31C7B514984231125B /* STPPaymentOptionsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentOptionsViewController.swift; sourceTree = ""; }; - AA3CA5B4B91838CC7ED4D5EB /* ro-RO */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ro-RO"; path = "ro-RO.lproj/Localizable.strings"; sourceTree = ""; }; AAF368BCD5990EE5DC17D299 /* ImageTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageTest.swift; sourceTree = ""; }; - AB1A92C77AC61335184BBDBC /* es-419 */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-419"; path = "es-419.lproj/Localizable.strings"; sourceTree = ""; }; - ABAABB969BFB7102D5AA5598 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Localizable.strings; sourceTree = ""; }; ACE8998EAF997A78759E49B5 /* STPPaymentIntentTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentIntentTest.swift; sourceTree = ""; }; ACF450AD17FF7BCE5916DDF1 /* STPPaymentHandlerFunctionalTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentHandlerFunctionalTest.swift; sourceTree = ""; }; AD06AED0AF8A9A7FB4A2E66F /* STPIntentActionAlipayHandleRedirectTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPIntentActionAlipayHandleRedirectTest.swift; sourceTree = ""; }; AD8BED2A6066514B51693172 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; AF342CBC167F9CAB5B49CC32 /* PayWithLinkButtonSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayWithLinkButtonSnapshotTests.swift; sourceTree = ""; }; - AFF957F38AABE5F748C38C0B /* STPLocalizedString.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPLocalizedString.swift; sourceTree = ""; }; - B1217AD643A9E8F88B60F645 /* STPUserInformation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPUserInformation.swift; sourceTree = ""; }; - B334078D1C3E629BEB498BAB /* nn-NO */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "nn-NO"; path = "nn-NO.lproj/Localizable.strings"; sourceTree = ""; }; B3E0745D13EB19BAA24F3BA3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; B407FE2D39775902A95B1118 /* StripeiOS Tests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "StripeiOS Tests-Bridging-Header.h"; sourceTree = ""; }; B4D12508C2F1056A7EAFEC86 /* PKPayment+StripeTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PKPayment+StripeTest.swift"; sourceTree = ""; }; - B4D31B0D7BD9F97AF3BB61E6 /* StripeBundleLocator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StripeBundleLocator.swift; sourceTree = ""; }; - B5B86F3355E44DF4A980B82C /* STPPaymentContextSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentContextSnapshotTests.swift; sourceTree = ""; }; - B669C53A601CD3CB0203A4B9 /* STPAPISettingsObjCBridgeTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = STPAPISettingsObjCBridgeTest.m; sourceTree = ""; }; - B6EC2F562B618A3D00FF72A2 /* STPBasicUIAnalyticsSerializer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPBasicUIAnalyticsSerializer.swift; sourceTree = ""; }; B6F3B966470A530E0DC53F8C /* STPThreeDSButtonCustomizationTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPThreeDSButtonCustomizationTest.swift; sourceTree = ""; }; B70DF0B659009041F485EE0F /* Stripe+Exports.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Stripe+Exports.swift"; sourceTree = ""; }; - B78C72B0DB434EC7F700FDE0 /* STPCoreTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPCoreTableViewController.swift; sourceTree = ""; }; B7F7AA0B7B86BA5BB2FE92CE /* STPMandateDataParamsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPMandateDataParamsTest.swift; sourceTree = ""; }; - B8DD70E5ED8E9DE8E9752C9E /* STPAPIClientTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPAPIClientTest.swift; sourceTree = ""; }; B9BA8D8467218C7E691C9FAE /* STPAPIClientNetworkBridgeTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPAPIClientNetworkBridgeTest.swift; sourceTree = ""; }; - BA08DCDD421CE92ECB61EF5C /* STPFPXBankStatusResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPFPXBankStatusResponse.swift; sourceTree = ""; }; - BAFD938F3A149A56CC99FE96 /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = fi.lproj/Localizable.strings; sourceTree = ""; }; BB08D2AC882B21C8ADD76B92 /* STPPaymentCardTextFieldKVOTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = STPPaymentCardTextFieldKVOTest.m; sourceTree = ""; }; - BB8FCDBC63A79CD1571A2DFB /* STPCustomerContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPCustomerContext.swift; sourceTree = ""; }; BCBEA9E4823F08C1F5057B5A /* STPAUBECSDebitFormViewSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPAUBECSDebitFormViewSnapshotTests.swift; sourceTree = ""; }; BD77D4B1C5B64E45F9DA09B5 /* STPConfirmCardOptionsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPConfirmCardOptionsTest.swift; sourceTree = ""; }; BD89580A3E41D7167C30B287 /* STPAnalyticsClient+Payments.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "STPAnalyticsClient+Payments.swift"; sourceTree = ""; }; BEB3F9F0228008BE213706DF /* STPPaymentMethodAddressTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodAddressTest.swift; sourceTree = ""; }; BF1CF8FB0100664A02468FBC /* STPPaymentMethodBacsDebitTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodBacsDebitTest.swift; sourceTree = ""; }; - BFB4A210A30D1D4F3D3100E5 /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/Localizable.strings; sourceTree = ""; }; C0436A8574E7D0730641407A /* STPSourceRedirectTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPSourceRedirectTest.swift; sourceTree = ""; }; C17799DC7FA54E758EED31A6 /* NSArray+StripeTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSArray+StripeTest.swift"; sourceTree = ""; }; C23D612FD5AD7772E1B30DCC /* STPThreeDSSelectionCustomizationTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPThreeDSSelectionCustomizationTest.swift; sourceTree = ""; }; - C3B75875C55D2C2723DC5090 /* STPSource+BasicUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "STPSource+BasicUI.swift"; sourceTree = ""; }; - C45852D37E323E65C47348B0 /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/Localizable.strings"; sourceTree = ""; }; C5923A4DD3CD39CB64B8A8C9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; C5BEAA15B53AC5662A33D0E1 /* STPEphemeralKeyTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPEphemeralKeyTest.swift; sourceTree = ""; }; C641A744CCEA67C07E9BFE05 /* NSLocale+STPSwizzling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSLocale+STPSwizzling.swift"; sourceTree = ""; }; C645F78B3EFFAA083B6FD3E9 /* STPEphemeralKeyManagerTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPEphemeralKeyManagerTest.swift; sourceTree = ""; }; C713F58BC61A962C720AE0AE /* STPMandateCustomerAcceptanceParamsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPMandateCustomerAcceptanceParamsTest.swift; sourceTree = ""; }; - C750C2C4AB33BC232D1592BA /* STPPaymentContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentContext.swift; sourceTree = ""; }; - C8F8FCC84601E4ADC6B7F3CE /* PaymentAnalyticTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaymentAnalyticTest.swift; sourceTree = ""; }; C980D24DDC884FECCE39139F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; CA8B8F540CD05B3DC2C5EEA6 /* STPSetupIntentTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPSetupIntentTest.swift; sourceTree = ""; }; CAC3A0332C2F176A007BC888 /* STPPaymentMethodSunbitTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodSunbitTests.swift; sourceTree = ""; }; @@ -791,42 +605,33 @@ D103BC590F1E0EC0C31C7B5F /* STPBankAccountTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPBankAccountTest.swift; sourceTree = ""; }; D1859673CAD068B345F5DD7D /* STPCardCVCInputTextFieldSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPCardCVCInputTextFieldSnapshotTests.swift; sourceTree = ""; }; D2F205F920E971DEA59E3C31 /* STPIntentActionTypeTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPIntentActionTypeTest.swift; sourceTree = ""; }; - D3667F97B7665F699D6704BE /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = ""; }; D3803D0DED98501AA26B2EAC /* STPCardNumberInputTextFieldFormatterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPCardNumberInputTextFieldFormatterTests.swift; sourceTree = ""; }; D38184A7CD27B978DFA30E69 /* STPCardFunctionalTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPCardFunctionalTest.swift; sourceTree = ""; }; - D3D2DB08C335695B705F544C /* STPAddressViewModelTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPAddressViewModelTest.swift; sourceTree = ""; }; D3E0CA28591EB0748C64D1FA /* STPFileTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPFileTest.swift; sourceTree = ""; }; D41081066DC4465734F7FCD7 /* STPPaymentMethodNetBankingParamsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodNetBankingParamsTest.swift; sourceTree = ""; }; D42F83F785EAF24F5DC7ED1A /* STPCardCVCInputTextFieldValidatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPCardCVCInputTextFieldValidatorTests.swift; sourceTree = ""; }; - D5C4A4CC7D2E9B5AB3EC3B79 /* STPPaymentOptionsInternalViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentOptionsInternalViewController.swift; sourceTree = ""; }; D609FFD051FC01BF566665A0 /* StripeiOS Tests-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "StripeiOS Tests-Debug.xcconfig"; sourceTree = ""; }; D794C5E6396B4A19DC4F6921 /* StripeUICore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = StripeUICore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D7C4773C2D193BEDF1CBB530 /* STPCardNumberInputTextFieldValidatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPCardNumberInputTextFieldValidatorTests.swift; sourceTree = ""; }; D87817A1D3D213AA4ADF6A4C /* STPPaymentMethodAffirmParamsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodAffirmParamsTest.swift; sourceTree = ""; }; - D93C23F55BEADF9BC74DFBDB /* STPImageLibrary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPImageLibrary.swift; sourceTree = ""; }; DA82BB67D434E76B9ABA4CEC /* Stripe-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Stripe-Release.xcconfig"; sourceTree = ""; }; DAB817ED5B5DB87AE1290894 /* STPCustomerTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPCustomerTest.swift; sourceTree = ""; }; DB58AC5E2E0A68221260FD44 /* STPMandateOnlineParamsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPMandateOnlineParamsTest.swift; sourceTree = ""; }; DC3AD586DDED620B9E68F461 /* StripeErrorTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StripeErrorTest.swift; sourceTree = ""; }; DDC55CC034022DFAC9366E2E /* StripePaymentSheet.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = StripePaymentSheet.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - DE24B3BAD7E890661CCA817D /* el-GR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "el-GR"; path = "el-GR.lproj/Localizable.strings"; sourceTree = ""; }; DE2A766FB355DD9C461939C1 /* STPPaymentMethodPayPalParamsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodPayPalParamsTests.swift; sourceTree = ""; }; - DFA4E34E459EA612E065DE64 /* fr-CA */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "fr-CA"; path = "fr-CA.lproj/Localizable.strings"; sourceTree = ""; }; DFA7A75BA785EBBE4C05DAA3 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; E1264C4DCB32B1FA5CE19201 /* STPFileFunctionalTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPFileFunctionalTest.swift; sourceTree = ""; }; E136A967522048B313E3C62F /* StripePaymentsUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = StripePaymentsUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; E1644AA33E81233EF33022BA /* STPCardValidatorTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPCardValidatorTest.swift; sourceTree = ""; }; E1A2173E0891B7138687D544 /* Stripe-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Stripe-Debug.xcconfig"; sourceTree = ""; }; E1CD20E00EAD41091B71ABD5 /* NSURLComponents_StripeTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSURLComponents_StripeTest.swift; sourceTree = ""; }; - E2307F2C5E53540D4ACAA1F6 /* UIToolbar+Stripe_InputAccessory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIToolbar+Stripe_InputAccessory.swift"; sourceTree = ""; }; E315168EF07F52B733EA77F8 /* STPSwiftFixtures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPSwiftFixtures.swift; sourceTree = ""; }; - E3B42EBAC0DC7ED0D9200DB7 /* STPBlocks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPBlocks.swift; sourceTree = ""; }; E3C8833E7EBA7A1EBF349D19 /* StripeiOS Tests-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "StripeiOS Tests-Release.xcconfig"; sourceTree = ""; }; E4194E605BB5F31E9CBB8F96 /* STPAPIClientStubbedTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPAPIClientStubbedTest.swift; sourceTree = ""; }; E452877E5D11120B1E28A6E7 /* STPApplePayContextDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPApplePayContextDelegate.swift; sourceTree = ""; }; E5D9F97ABC88302478220267 /* PKPaymentAuthorizationViewController+Stripe_Blocks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PKPaymentAuthorizationViewController+Stripe_Blocks.swift"; sourceTree = ""; }; E6312182B5BCAB940D216650 /* ConsumerSessionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConsumerSessionTests.swift; sourceTree = ""; }; - E68F6B90F3BC61A49570FAF4 /* UINavigationBar+StripeTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UINavigationBar+StripeTest.m"; sourceTree = ""; }; E6DEE912364C9F4B51B374D0 /* STPPaymentCardTextFieldViewModelTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentCardTextFieldViewModelTest.swift; sourceTree = ""; }; E7ACB4FAFAD33296DE34D036 /* STPAnalyticsClientPaymentsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPAnalyticsClientPaymentsTest.swift; sourceTree = ""; }; E7C7D85A7FAAFDF4F59BA85E /* LinkSignupViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkSignupViewModelTests.swift; sourceTree = ""; }; @@ -834,17 +639,13 @@ E89551702F1F9A3AFF1ED676 /* STPSourceVerificationTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPSourceVerificationTest.swift; sourceTree = ""; }; E956CFA6317CAA8B41E217CA /* STPAPIClient+LinkAccountSessionTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "STPAPIClient+LinkAccountSessionTest.swift"; sourceTree = ""; }; E97018A201D01A8FA59999C2 /* STPConnectAccountFunctionalTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPConnectAccountFunctionalTest.swift; sourceTree = ""; }; - EA20E0E29EDC1F61ADA226A2 /* zh-HK */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-HK"; path = "zh-HK.lproj/Localizable.strings"; sourceTree = ""; }; EA9975553E669AF69F3CE437 /* STPPostalCodeInputTextFieldValidatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPostalCodeInputTextFieldValidatorTests.swift; sourceTree = ""; }; EAEE347A6372AAE2735FAD6F /* STPPaymentMethodFPXTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodFPXTest.swift; sourceTree = ""; }; EB6AE83989B0596F0C111E13 /* STPStringUtilsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPStringUtilsTest.swift; sourceTree = ""; }; EB71A4A2762CF864DB198BCF /* Project-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Project-Debug.xcconfig"; sourceTree = ""; }; ECBA5B09A3FD875C93218573 /* STPPaymentMethodAfterpayClearpayParamsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodAfterpayClearpayParamsTest.swift; sourceTree = ""; }; - EDD30E5DB8DB3AA3567F5C20 /* STPPaymentOptionTuple.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentOptionTuple.swift; sourceTree = ""; }; EF48EC440E1ED5D6BAA567FF /* STPPaymentHandlerStubbedMockedFilesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentHandlerStubbedMockedFilesTests.swift; sourceTree = ""; }; EFD2F6A5A046A620BAB75B41 /* AutoCompleteViewControllerSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoCompleteViewControllerSnapshotTests.swift; sourceTree = ""; }; - F13E3DE09A463B4501733B87 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = ""; }; - F153420EA142B5CA76E89A04 /* STPMocks.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = STPMocks.h; sourceTree = ""; }; F372EDF9C2C45E1CA2C76866 /* STPPaymentMethodGiropayParamsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodGiropayParamsTests.swift; sourceTree = ""; }; F3C732C25FD961631BD44FDD /* STPBSBNumberValidatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPBSBNumberValidatorTests.swift; sourceTree = ""; }; F44327A2B2C9483F52EE343B /* STPFormViewSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPFormViewSnapshotTests.swift; sourceTree = ""; }; @@ -852,7 +653,6 @@ F546088BA4F763334CFD3D34 /* STPImageLibraryTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPImageLibraryTest.swift; sourceTree = ""; }; F6558C62376C2397030BD4A6 /* STPPaymentMethodPrzelewy24Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentMethodPrzelewy24Tests.swift; sourceTree = ""; }; F7385193226663A5B79E69ED /* STPFloatingPlaceholderTextFieldSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPFloatingPlaceholderTextFieldSnapshotTests.swift; sourceTree = ""; }; - FA793904C7B2D3AA0A4D5EFB /* STPAddCardViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPAddCardViewController.swift; sourceTree = ""; }; FC30E6129279F14506219E98 /* STPPaymentHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPPaymentHandlerTests.swift; sourceTree = ""; }; FD289E1EA9F0CE1C848AC0BB /* STPCardNumberInputTextFieldSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STPCardNumberInputTextFieldSnapshotTests.swift; sourceTree = ""; }; FD3398E2352CEA0264F20AEA /* stp_test_upload_image.jpeg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = stp_test_upload_image.jpeg; sourceTree = ""; }; @@ -944,80 +744,20 @@ 7EA3633D452F7A9C017F4D52 /* Source */ = { isa = PBXGroup; children = ( - 8F7E3CE2105E4A39032CD919 /* Enums+CustomStringConvertible.swift */, 273EE407039913F0B644172B /* PKAddPaymentPassRequest+Stripe_Error.swift */, E5D9F97ABC88302478220267 /* PKPaymentAuthorizationViewController+Stripe_Blocks.swift */, - FA793904C7B2D3AA0A4D5EFB /* STPAddCardViewController.swift */, - 498C3FB07CFD532779C755D3 /* STPAddress+BasicUI.swift */, - 72903593DC432D01720DC9D9 /* STPAddressFieldTableViewCell.swift */, - 28A50AFA4603E488FF3D82D0 /* STPAddressViewModel.swift */, - 12DBB3F72AEFB52DE27C27ED /* STPAnalyticsClient+BasicUI.swift */, - B6EC2F562B618A3D00FF72A2 /* STPBasicUIAnalyticsSerializer.swift */, BD89580A3E41D7167C30B287 /* STPAnalyticsClient+Payments.swift */, - 1E8AFAE24610EC983727F860 /* STPAPIClient+BasicUI.swift */, 807FF966F1DE05F3496B817B /* STPAPIClient+PushProvisioning.swift */, E452877E5D11120B1E28A6E7 /* STPApplePayContextDelegate.swift */, - 03ACDC7EEC28D1FE50008F65 /* STPApplePayPaymentOption.swift */, - 9B782E1D974A4C131E60E2BD /* STPBackendAPIAdapter.swift */, - 458F8576215E0F8ECE1D74CE /* STPBankSelectionTableViewCell.swift */, - 81352A0CBE46A59E6B1A712E /* STPBankSelectionViewController.swift */, - E3B42EBAC0DC7ED0D9200DB7 /* STPBlocks.swift */, - 61F8308B7250B642D19827D8 /* STPCameraView.swift */, - 3E5FB20B2BEFC00D54FDD87D /* STPCard+BasicUI.swift */, - 69BD038947E8E2376A0D240B /* STPCardScanner.swift */, - 0B91C4D5B93FF71C61B140F1 /* STPCardScannerTableViewCell.swift */, - 6A9E7B637A8747431B38FD1D /* STPCardValidationState.swift */, - 2D1525AF65BDEF691F8BCBE8 /* STPCoreScrollViewController.swift */, - B78C72B0DB434EC7F700FDE0 /* STPCoreTableViewController.swift */, - 02FC9ED423D40C88D5A24441 /* STPCoreViewController.swift */, - BB8FCDBC63A79CD1571A2DFB /* STPCustomerContext.swift */, 890660C21E3666CE7B82695B /* STPEphemeralKey.swift */, 588C260880FFC584A00A89F5 /* STPEphemeralKeyManager.swift */, 485E747DA1F72F091986787B /* STPEphemeralKeyProvider.swift */, 0669B4CA326CE74D125C789C /* STPFakeAddPaymentPassViewController.swift */, - BA08DCDD421CE92ECB61EF5C /* STPFPXBankStatusResponse.swift */, - D93C23F55BEADF9BC74DFBDB /* STPImageLibrary.swift */, - 9EB24EC81CE2C8D1C863B044 /* STPIntentActionLinkAuthenticateAccount.swift */, - AFF957F38AABE5F748C38C0B /* STPLocalizedString.swift */, - 1FFBAA4B44967B157A4F4E91 /* STPPaymentActivityIndicatorView.swift */, - 01B42BE6FB5EC1F708875AB8 /* STPPaymentCardTextFieldCell.swift */, - 18FCB69CD3B8C3DAB216A5F0 /* STPPaymentConfiguration.swift */, - C750C2C4AB33BC232D1592BA /* STPPaymentContext.swift */, - A1C876DC7F3E31D7189506A8 /* STPPaymentContextAmountModel.swift */, - 6F01150CD0255164FE2CF3A4 /* STPPaymentIntentParams+BasicUI.swift */, - 35C1E9B0EE03825DABF6471A /* STPPaymentMethod+BasicUI.swift */, - 53C5AB22D6328E85A6DDF663 /* STPPaymentMethodParams+BasicUI.swift */, - 30B694A39D54886392AA5DE3 /* STPPaymentOption.swift */, - D5C4A4CC7D2E9B5AB3EC3B79 /* STPPaymentOptionsInternalViewController.swift */, - A9A1BB31C7B514984231125B /* STPPaymentOptionsViewController.swift */, - 6215A9BF343775B1BD0F62AF /* STPPaymentOptionTableViewCell.swift */, - EDD30E5DB8DB3AA3567F5C20 /* STPPaymentOptionTuple.swift */, - 7D964D9E01627B419B4BD23C /* STPPaymentResult.swift */, 3EBB07171F6FDCE6E20C454A /* STPPinManagementService.swift */, 6887F19BB9804BF45FD703FF /* STPPushProvisioningContext.swift */, 89E5DA3029F141B5111A5B2C /* STPPushProvisioningDetails.swift */, 2B28B8A547CD846277ECD578 /* STPPushProvisioningDetailsParams.swift */, - 96E1FED5CE5974C9C1162E93 /* STPSectionHeaderView.swift */, - 71711FC8E2FB66E52A5FDD9A /* STPShippingAddressViewController.swift */, - 21E4B84223DDA131544DBBA7 /* STPShippingMethodsViewController.swift */, - 98544B08552407D41D398C68 /* STPShippingMethodTableViewCell.swift */, - C3B75875C55D2C2723DC5090 /* STPSource+BasicUI.swift */, - 8E8CA4361964E1BA400EFC89 /* STPTheme.swift */, - B1217AD643A9E8F88B60F645 /* STPUserInformation.swift */, - A5398E1156E0BFEBBF56FD2F /* String+Localized.swift */, B70DF0B659009041F485EE0F /* Stripe+Exports.swift */, - B4D31B0D7BD9F97AF3BB61E6 /* StripeBundleLocator.swift */, - 3B3000668A75E095B514241F /* UIBarButtonItem+Stripe.swift */, - A7E369CEC9F5B3758F78E88F /* UINavigationBar+Stripe_Theme.swift */, - 2C078573F46762353664AC92 /* UINavigationController+Stripe_Completion.swift */, - 5476BD87E0480A93958F0328 /* UITableViewCell+Stripe_Borders.swift */, - E2307F2C5E53540D4ACAA1F6 /* UIToolbar+Stripe_InputAccessory.swift */, - 1B76DF0FE363F59BF0940A8B /* UIView+Stripe_FirstResponder.swift */, - 86798C95A778362EF815B4C6 /* UIView+Stripe_SafeAreaBounds.swift */, - 2F08757CA6F6B2DA65C14E0A /* UIViewController+Stripe_KeyboardAvoiding.swift */, - 6F017A08C7E633FB4297D274 /* UIViewController+Stripe_NavigationItemProxy.swift */, - 5804C2B9C0704E386B3D25A4 /* UIViewController+Stripe_ParentViewController.swift */, - 26302721419496F37DE91DF8 /* UserDefaults+Stripe.swift */, ); path = Source; sourceTree = ""; @@ -1063,14 +803,6 @@ path = StripeiOSAppHostedTests; sourceTree = ""; }; - AF41AE099441C2A09DECC1AC /* Localizations */ = { - isa = PBXGroup; - children = ( - C2427C1CDFA85BFC6570F1E9 /* Localizable.strings */, - ); - path = Localizations; - sourceTree = ""; - }; B035E857851EAF160C88DC2B /* StripeiOS */ = { isa = PBXGroup; children = ( @@ -1157,28 +889,22 @@ 9D85FA7B714BDD8D1FD83B75 /* OneTimeCodeTextFieldSnapshotTests.swift */, 98F9CB667BC68767DFB5FACD /* OneTimeCodeTextFieldTests.swift */, A61763BA2CCA86F9B8FD4F1F /* OperationDebouncerTests.swift */, - C8F8FCC84601E4ADC6B7F3CE /* PaymentAnalyticTest.swift */, 7B9A4A2B0FB9F8C743BBED48 /* PaymentTypeCellSnapshotTests.swift */, AF342CBC167F9CAB5B49CC32 /* PayWithLinkButtonSnapshotTests.swift */, B4D12508C2F1056A7EAFEC86 /* PKPayment+StripeTest.swift */, FDA32D0C9E8A7A69F4899EDC /* RotatingCardBrandsViewSnapshotTests.swift */, 12632E6710DE8861CAF1BAA4 /* RotatingCardBrandsViewTests.swift */, 20879436DCFB1F03BE1608B3 /* ServerErrorMapperTest.swift */, - 26E5C1DABAA63F07F0C6AE37 /* STPAddCardViewControllerLocalizationSnapshotTests.swift */, - 8704ABFA91A5226847F4A69A /* STPAddCardViewControllerTest.swift */, + A30CD9D92CCC2DFE00EA22D3 /* STPAPIClientTest.swift */, A39580123A4F1EA96F91768A /* STPAddressTests.swift */, - D3D2DB08C335695B705F544C /* STPAddressViewModelTest.swift */, E7ACB4FAFAD33296DE34D036 /* STPAnalyticsClientPaymentsTest.swift */, E956CFA6317CAA8B41E217CA /* STPAPIClient+LinkAccountSessionTest.swift */, B9BA8D8467218C7E691C9FAE /* STPAPIClientNetworkBridgeTest.swift */, E4194E605BB5F31E9CBB8F96 /* STPAPIClientStubbedTest.swift */, - B8DD70E5ED8E9DE8E9752C9E /* STPAPIClientTest.swift */, - B669C53A601CD3CB0203A4B9 /* STPAPISettingsObjCBridgeTest.m */, 1CE268457D21A7209862E004 /* STPApplePayContextFunctionalTest.swift */, A1272F2E05A0E294DD9ECA26 /* STPApplePayContextFunctionalTestExtras.swift */, 5F7AB40A5A10C2D267323ABE /* STPApplePayContextTest.swift */, 3C77C7BC4BA57EC296CF2F1C /* STPApplePayFunctionalTest.swift */, - 00985EFC6CB7B912FDBF3813 /* STPApplePayPaymentOptionTest.swift */, CFC4BC1AB047ED88C4D13C89 /* STPApplePayTest.swift */, BCBEA9E4823F08C1F5057B5A /* STPAUBECSDebitFormViewSnapshotTests.swift */, 4AAE5EE11611F9F7762B64C6 /* STPAUBECSFormViewModelTests.swift */, @@ -1214,7 +940,6 @@ E97018A201D01A8FA59999C2 /* STPConnectAccountFunctionalTest.swift */, 195DEC752CC82CC4BA1E2351 /* STPConnectAccountParamsTest.swift */, 8D49257A97E71A475A9F6E08 /* STPCountryPickerInputFieldSnapshotTests.swift */, - 2CC4B06AB5C02FF54091E5A8 /* STPCustomerContextTest.swift */, DAB817ED5B5DB87AE1290894 /* STPCustomerTest.swift */, 1C1548BA518F7AC2A9ECF9D5 /* STPE2ETest.swift */, C645F78B3EFFAA083B6FD3E9 /* STPEphemeralKeyManagerTest.swift */, @@ -1245,17 +970,12 @@ C713F58BC61A962C720AE0AE /* STPMandateCustomerAcceptanceParamsTest.swift */, B7F7AA0B7B86BA5BB2FE92CE /* STPMandateDataParamsTest.swift */, DB58AC5E2E0A68221260FD44 /* STPMandateOnlineParamsTest.swift */, - F153420EA142B5CA76E89A04 /* STPMocks.h */, - 88AEABC15CCBB9EA393C175F /* STPMocks.m */, 6223E57D3A198F956A37ED89 /* STPNumericDigitInputTextFormatterTests.swift */, 4AA36705DED9164663A98B6A /* STPNumericStringValidatorTests.swift */, BB08D2AC882B21C8ADD76B92 /* STPPaymentCardTextFieldKVOTest.m */, 939360978872BBE4334215B1 /* STPPaymentCardTextFieldTest.swift */, 1F16C36797D978E72E612100 /* STPPaymentCardTextFieldTestsSwift.swift */, E6DEE912364C9F4B51B374D0 /* STPPaymentCardTextFieldViewModelTest.swift */, - 79ABE6A14AF9D14103050876 /* STPPaymentConfigurationTest.m */, - 3C995125252BED1EEC018B9D /* STPPaymentContextApplePayTest.swift */, - B5B86F3355E44DF4A980B82C /* STPPaymentContextSnapshotTests.swift */, 683F7735569D22CBEC9CA2E6 /* STPPaymentHandlerFunctionalTest.m */, ACF450AD17FF7BCE5916DDF1 /* STPPaymentHandlerFunctionalTest.swift */, EF48EC440E1ED5D6BAA567FF /* STPPaymentHandlerStubbedMockedFilesTests.swift */, @@ -1330,8 +1050,6 @@ CF13BAEF86594C9CABD4F42A /* STPPaymentMethodUSBankAccountParamsStubbedTest.swift */, 74FDEF9F687C63BADFB96480 /* STPPaymentMethodUSBankAccountParamsTest.swift */, 3B112FFF3FCA82094281493F /* STPPaymentMethodUSBankAccountTest.swift */, - 5062915D961C1BCAFD641FFE /* STPPaymentOptionsViewControllerLocalizationSnapshotTests.swift */, - A2922A32A754CFC9AB8B48AE /* STPPaymentOptionsViewControllerTest.swift */, 924E878428D15506711CA628 /* STPPhoneNumberValidatorTest.swift */, 1645D9793463E266501B74FD /* STPPIIFunctionalTest.swift */, 336CC555B845DED30208D39D /* STPPinManagementServiceFunctionalTest.swift */, @@ -1347,9 +1065,6 @@ 49AA313E068FB99CEAA5F7D3 /* STPSetupIntentFunctionalTest.swift */, 01B057D99A14E5BA6019C349 /* STPSetupIntentLastSetupErrorTest.swift */, CA8B8F540CD05B3DC2C5EEA6 /* STPSetupIntentTest.swift */, - 1ED6BAC91E8A827DCDB38B15 /* STPShippingAddressViewControllerLocalizationSnapshotTests.swift */, - 789D0B49B0788794739E3DD4 /* STPShippingAddressViewControllerTest.swift */, - 661976D1296DFA48A25E0493 /* STPShippingMethodsViewControllerLocalizationSnapshotTests.swift */, 63114D0EAAE2606732DF5AA0 /* STPSourceCardDetailsTest.swift */, 17013F78CE3F9662029FEF5B /* STPSourceFunctionalTest.swift */, 095EBF095BA2BC8D299547DB /* STPSourceOwnerTest.swift */, @@ -1371,12 +1086,10 @@ A583966A33DCDCF04322A592 /* STPThreeDSTextFieldCustomizationTest.swift */, 3ED44491EB0AC72B1B1A773C /* STPThreeDSUICustomizationTest.swift */, 7F090B8D315E7FD12A5F9C09 /* STPTokenTest.swift */, - 88639E3C3AC622B5EF475538 /* STPUIVCStripeParentViewControllerTests.swift */, 86983B09A1712944EC012AD4 /* STPViewWithSeparatorSnapshotTests.swift */, DC3AD586DDED620B9E68F461 /* StripeErrorTest.swift */, B407FE2D39775902A95B1118 /* StripeiOS Tests-Bridging-Header.h */, 51BD2CE41E4F0CF648F44E4A /* TextFieldElement+IBANTest.swift */, - E68F6B90F3BC61A49570FAF4 /* UINavigationBar+StripeTest.m */, 3B0E131538728BC4802627B1 /* UserDefaults+StripeTest.swift */, 0DB03E83746FE78361831546 /* WalletHeaderViewSnapshotTests.swift */, CAC3A0332C2F176A007BC888 /* STPPaymentMethodSunbitTests.swift */, @@ -1399,7 +1112,6 @@ FBC7A77342A98B1DE8E416B7 /* Resources */ = { isa = PBXGroup; children = ( - AF41AE099441C2A09DECC1AC /* Localizations */, 77E846CD56018D8417A3AB95 /* StripeiOS.xcassets */, ); path = Resources; @@ -1586,7 +1298,6 @@ buildActionMask = 2147483647; files = ( 31CDFC2E2BA3708000B3DD91 /* PrivacyInfo.xcprivacy in Resources */, - 22BE2ABB29F77362FF16D945 /* Localizable.strings in Resources */, 76BC927BC7A591601C1DAB18 /* StripeiOS.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1625,81 +1336,21 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 315713352C770DA3ED9CBDCD /* Enums+CustomStringConvertible.swift in Sources */, B6784B7F4B9B04617C0EE510 /* PKAddPaymentPassRequest+Stripe_Error.swift in Sources */, C0688E067AE4FFDFFDDC03BB /* PKPaymentAuthorizationViewController+Stripe_Blocks.swift in Sources */, - 6BF6ECC4A4E61E2FFC3EA20B /* STPAPIClient+BasicUI.swift in Sources */, 5212C7875C07F9BF16AFD98D /* STPAPIClient+PushProvisioning.swift in Sources */, - BB46077C256C26418420F240 /* STPAddCardViewController.swift in Sources */, - E63B5BAF6B5645C979BFBA71 /* STPAddress+BasicUI.swift in Sources */, - 58240AA66FAE55131268E4A0 /* STPAddressFieldTableViewCell.swift in Sources */, 313F5F792B0BE59100BD98A9 /* Docs.docc in Sources */, - 2BD45625F6F665B60C6CAD30 /* STPAddressViewModel.swift in Sources */, - 605EFBDD21426FD30581563F /* STPAnalyticsClient+BasicUI.swift in Sources */, 7589E37795D21AB818B0C333 /* STPAnalyticsClient+Payments.swift in Sources */, F86F2DF6E46EFABE23AD5D27 /* STPApplePayContextDelegate.swift in Sources */, - FC166455478EAF51F7C34E68 /* STPApplePayPaymentOption.swift in Sources */, - C314A5C55064C51C2B999E6B /* STPBackendAPIAdapter.swift in Sources */, - CEF318C74D2E44C78EF85306 /* STPBankSelectionTableViewCell.swift in Sources */, - 172D96526023A80534D54CC0 /* STPBankSelectionViewController.swift in Sources */, - A0AA0B8AEF5B429858D71F6B /* STPBlocks.swift in Sources */, - DDBF5AAE607C698618DDE865 /* STPCameraView.swift in Sources */, - 66065B1D65D7D5502D4E2F2B /* STPCard+BasicUI.swift in Sources */, - BAFD06E994739E1C38DFFBBC /* STPCardScanner.swift in Sources */, - 2FFA7C2D1C7337FDB4C608A5 /* STPCardScannerTableViewCell.swift in Sources */, - 2F18A1903244E144C7802E09 /* STPCardValidationState.swift in Sources */, - DF73457BF349BC962A6AC502 /* STPCoreScrollViewController.swift in Sources */, - EEFFE199D9769FF449BFD7FF /* STPCoreTableViewController.swift in Sources */, - B1BF689B91D538BDCA4C8578 /* STPCoreViewController.swift in Sources */, - 429DBA641E926EBC2D049FE7 /* STPCustomerContext.swift in Sources */, 62B91808A088C4F9FDB62C53 /* STPEphemeralKey.swift in Sources */, 4FB67F10A0B7106A8142B842 /* STPEphemeralKeyManager.swift in Sources */, B8385576DC25BDEEB92D812F /* STPEphemeralKeyProvider.swift in Sources */, - AF23CB4EF17E87007CFC3E96 /* STPFPXBankStatusResponse.swift in Sources */, - B6EC2F572B618A3D00FF72A2 /* STPBasicUIAnalyticsSerializer.swift in Sources */, 0B9C0E9A7A750607413C9E53 /* STPFakeAddPaymentPassViewController.swift in Sources */, - 5D6B52EB4D7258129F134D07 /* STPImageLibrary.swift in Sources */, - D2869246B446B8B31F1CD368 /* STPIntentActionLinkAuthenticateAccount.swift in Sources */, - 98EE8326C1D133E1C998114F /* STPLocalizedString.swift in Sources */, - 609E4D384B75F6A111DC0E27 /* STPPaymentActivityIndicatorView.swift in Sources */, - 4EFF8B46B12DA4D9AAB22523 /* STPPaymentCardTextFieldCell.swift in Sources */, - 446A108C8EB6C338A1D774F8 /* STPPaymentConfiguration.swift in Sources */, - B00F7FC372E376C6B2170D37 /* STPPaymentContext.swift in Sources */, - 447C19BDB2CF5445045F81F7 /* STPPaymentContextAmountModel.swift in Sources */, - EA7FEC518AA07BA59405A5E3 /* STPPaymentIntentParams+BasicUI.swift in Sources */, - 7BC98BE168781C5B3EC8A8DB /* STPPaymentMethod+BasicUI.swift in Sources */, - 812682EA323986B8F698FF3C /* STPPaymentMethodParams+BasicUI.swift in Sources */, - F10FC337254A34ED8F13E341 /* STPPaymentOption.swift in Sources */, - 4ED44ACF24949F516867235C /* STPPaymentOptionTableViewCell.swift in Sources */, - 5ECED204FD22CFEA3A806767 /* STPPaymentOptionTuple.swift in Sources */, - 1F432D0B37949217E4299A20 /* STPPaymentOptionsInternalViewController.swift in Sources */, - 69AC1EDE2A3C03B1D980CA54 /* STPPaymentOptionsViewController.swift in Sources */, - 307FD6A103EF7AF3CE451598 /* STPPaymentResult.swift in Sources */, 7EAA7334372DBC38DF8FA0AA /* STPPinManagementService.swift in Sources */, 2E35B0FB60FCBE7608080642 /* STPPushProvisioningContext.swift in Sources */, FEE74744B657F86873EA2F3D /* STPPushProvisioningDetails.swift in Sources */, 4E09E54E7FEC35C49C59A379 /* STPPushProvisioningDetailsParams.swift in Sources */, - 23D1246A5DAB5333650F104F /* STPSectionHeaderView.swift in Sources */, - 124D43C1A633922B1DA3E1E7 /* STPShippingAddressViewController.swift in Sources */, - 7B9C0D039EA9EF593AEC682D /* STPShippingMethodTableViewCell.swift in Sources */, - 7F9D08AC5A448C7693162D7D /* STPShippingMethodsViewController.swift in Sources */, - 3CE88568CB9648D6F1503B88 /* STPSource+BasicUI.swift in Sources */, - F835CEC935464FF32726A0A0 /* STPTheme.swift in Sources */, - 279D2BA91198E18730626CE6 /* STPUserInformation.swift in Sources */, - 542610492B38FEB652C6823E /* String+Localized.swift in Sources */, DCF615643A22D0A7B739547C /* Stripe+Exports.swift in Sources */, - BF4ED4828114E2E89A3D4AB7 /* StripeBundleLocator.swift in Sources */, - 98E2332DE7F54E970BE5EEF7 /* UIBarButtonItem+Stripe.swift in Sources */, - 9D9692DFC4F06F8C70145000 /* UINavigationBar+Stripe_Theme.swift in Sources */, - 9C13E8A017A4E23BCCDE618B /* UINavigationController+Stripe_Completion.swift in Sources */, - 54331380F5AC68846DBE94D5 /* UITableViewCell+Stripe_Borders.swift in Sources */, - 093FE3D65978E3DB6B79AE05 /* UIToolbar+Stripe_InputAccessory.swift in Sources */, - 7F235CD649F6E97E4E7DD180 /* UIView+Stripe_FirstResponder.swift in Sources */, - 44672917D3AC4B83F9EC3BC3 /* UIView+Stripe_SafeAreaBounds.swift in Sources */, - CC072EBAD035AA54A2AD3ABC /* UIViewController+Stripe_KeyboardAvoiding.swift in Sources */, - 3FA556CF8B11E2486F505161 /* UIViewController+Stripe_NavigationItemProxy.swift in Sources */, - 3930ECBEE003772C1245D25B /* UIViewController+Stripe_ParentViewController.swift in Sources */, - D85C432B241FDE23875037F9 /* UserDefaults+Stripe.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1754,7 +1405,6 @@ 8E423294AB602BF25DB11D8E /* OperationDebouncerTests.swift in Sources */, C4DC3F4FA93A3BAF6EE782A0 /* PKPayment+StripeTest.swift in Sources */, DC57D2DC40C6BA0C9CF7EC92 /* PayWithLinkButtonSnapshotTests.swift in Sources */, - AD9B9F3FF697D4A3892E86F2 /* PaymentAnalyticTest.swift in Sources */, C861BB9EAAD04949E338D7FF /* PaymentTypeCellSnapshotTests.swift in Sources */, BC694A1642DC30D530B60635 /* RotatingCardBrandsViewSnapshotTests.swift in Sources */, 6BA4B91C2BF4343B00D1F21D /* STPPaymentMethodMobilePayTests.swift in Sources */, @@ -1762,21 +1412,15 @@ BEC0435570B9199B918ED4DA /* STPAPIClient+LinkAccountSessionTest.swift in Sources */, 7D2C0D1BF455625997CBC33B /* STPAPIClientNetworkBridgeTest.swift in Sources */, 9A24970C5FB6D3F7314AE550 /* STPAPIClientStubbedTest.swift in Sources */, - 5E5EE69D140F6FEDA5F0A346 /* STPAPIClientTest.swift in Sources */, - AD09F2ACD0CDCBD414AC30AD /* STPAPISettingsObjCBridgeTest.m in Sources */, 17BD7C0391F3182E32A63D6B /* STPAUBECSDebitFormViewSnapshotTests.swift in Sources */, 583DE9869C885BA02E0A071E /* STPAUBECSFormViewModelTests.swift in Sources */, - 26F38A2A57FDDC12926BE044 /* STPAddCardViewControllerLocalizationSnapshotTests.swift in Sources */, - FB34906C9215D0E03850064B /* STPAddCardViewControllerTest.swift in Sources */, 3EA9D509E59DA65EE4EDF98D /* STPAddressTests.swift in Sources */, - F53E04785DB804EA5C2AAC18 /* STPAddressViewModelTest.swift in Sources */, CAC3A0342C2F176A007BC888 /* STPPaymentMethodSunbitTests.swift in Sources */, E6F428CFAD64979A8874B00B /* STPAnalyticsClientPaymentsTest.swift in Sources */, 23CF725CFAB2ABED416BF416 /* STPApplePayContextFunctionalTest.swift in Sources */, 6F9525063D76A9F86A10CCBF /* STPApplePayContextFunctionalTestExtras.swift in Sources */, F2655328479314A9C8718DE4 /* STPApplePayContextTest.swift in Sources */, 9B149DA42FB38C3542E0CB4B /* STPApplePayFunctionalTest.swift in Sources */, - 0C5F4AE769D95AA921F61084 /* STPApplePayPaymentOptionTest.swift in Sources */, FBBA3B39598BBECB664C5E7F /* STPApplePayTest.swift in Sources */, D0342D50F9AC319919D93D59 /* STPBECSDebitAccountNumberValidatorTests.swift in Sources */, 66B7EF2DC1CBF813707C767C /* STPBSBNumberValidatorTests.swift in Sources */, @@ -1811,7 +1455,6 @@ 14656D177E67594B8C75A9FE /* STPConnectAccountParamsTest.swift in Sources */, 610DF5DC2B33597500DA6AAA /* HostedSurfaceTest.swift in Sources */, 9D464A252FBD0D4E2A0A7398 /* STPCountryPickerInputFieldSnapshotTests.swift in Sources */, - 4C3B161481D11385352B06D4 /* STPCustomerContextTest.swift in Sources */, 6EDFC83541EED9E361B71C02 /* STPCustomerTest.swift in Sources */, CBCA59D39B30D869B4FDC04B /* STPE2ETest.swift in Sources */, 687517E7FE02FFB96DCE2328 /* STPEphemeralKeyManagerTest.swift in Sources */, @@ -1843,7 +1486,6 @@ 331924F0801287BAD413FDCB /* STPMandateCustomerAcceptanceParamsTest.swift in Sources */, 781EC0163AC001C6A66045B6 /* STPMandateDataParamsTest.swift in Sources */, B82859A4444B9F735720F232 /* STPMandateOnlineParamsTest.swift in Sources */, - 9FD92B3ADEBEC96660B70409 /* STPMocks.m in Sources */, A77C5769B20D7884FC8FC4FB /* STPNumericDigitInputTextFormatterTests.swift in Sources */, F975CE029DF30419B8DB0D8F /* STPNumericStringValidatorTests.swift in Sources */, 9535CADFFBC9E1FA291E947E /* STPPIIFunctionalTest.swift in Sources */, @@ -1852,10 +1494,8 @@ 77C0FD1BCDA7BBFB88559B44 /* STPPaymentCardTextFieldTest.swift in Sources */, 86BAF121184D71F5F4FFAD7B /* STPPaymentCardTextFieldTestsSwift.swift in Sources */, B4719234E4BBDAD260E31373 /* STPPaymentCardTextFieldViewModelTest.swift in Sources */, - 3AAE488F2461A46143B3A687 /* STPPaymentConfigurationTest.m in Sources */, CAC80EBF2C33339D001E3D0D /* STPPaymentMethodSatispayTests.swift in Sources */, - 829D43B6705D125FEC9926DA /* STPPaymentContextApplePayTest.swift in Sources */, - 97756805F41DDB51B3ED0326 /* STPPaymentContextSnapshotTests.swift in Sources */, + A30CD9DA2CCC2DFE00EA22D3 /* STPAPIClientTest.swift in Sources */, FEF2E0DAC862FF42B814AFCA /* STPPaymentHandlerFunctionalTest.m in Sources */, 8F5AF9D3566B8DBCA5AB5188 /* STPPaymentHandlerFunctionalTest.swift in Sources */, 194154708E1A9E013DCE2C72 /* STPPaymentHandlerStubbedMockedFilesTests.swift in Sources */, @@ -1923,8 +1563,6 @@ 7D251ABF1EBF65ACA8A4BDD4 /* STPPaymentMethodUSBankAccountParamsTest.swift in Sources */, 225140E0BD9C0630116DDE4A /* STPPaymentMethodUSBankAccountTest.swift in Sources */, B71F04D02538FA1723558C48 /* STPPaymentMethodiDEALTest.swift in Sources */, - 9A57C50938A66604FF16A882 /* STPPaymentOptionsViewControllerLocalizationSnapshotTests.swift in Sources */, - 2C7991FDF7B374E0E65E253F /* STPPaymentOptionsViewControllerTest.swift in Sources */, 07BF3CF1656AF5F5A0678873 /* STPPhoneNumberValidatorTest.swift in Sources */, EBD436689635CC28A24DECD4 /* STPPinManagementServiceFunctionalTest.swift in Sources */, 385CAC4D2FF119D2E925916B /* STPPostalCodeInputTextFieldFormatterTests.swift in Sources */, @@ -1940,9 +1578,6 @@ C32D7ACEBC852CBC295BBEF2 /* STPSetupIntentFunctionalTest.swift in Sources */, E699508F4DB4D9D4666BAA08 /* STPSetupIntentLastSetupErrorTest.swift in Sources */, EC4DC8E386544959E1AA9355 /* STPSetupIntentTest.swift in Sources */, - A930DF2880EAD0CB9096E49E /* STPShippingAddressViewControllerLocalizationSnapshotTests.swift in Sources */, - 08ED7A4EB7E64FDAED2C2D39 /* STPShippingAddressViewControllerTest.swift in Sources */, - 724429607B2741CF44D9C2E5 /* STPShippingMethodsViewControllerLocalizationSnapshotTests.swift in Sources */, AE747ADA2841AA06F32558D8 /* STPSourceCardDetailsTest.swift in Sources */, 3FD5ABC45AF3A03F4EFE196F /* STPSourceFunctionalTest.swift in Sources */, 922C0DF37F5AAA29375A5454 /* STPSourceOwnerTest.swift in Sources */, @@ -1966,12 +1601,10 @@ 2AC91F23CF3949ADC60D27F7 /* STPThreeDSTextFieldCustomizationTest.swift in Sources */, 701C464523173C6809544935 /* STPThreeDSUICustomizationTest.swift in Sources */, B86EE8C85E6AB6B0A34C1887 /* STPTokenTest.swift in Sources */, - 8AA84A3A52A3D79BCA8C8994 /* STPUIVCStripeParentViewControllerTests.swift in Sources */, 35E05040EA813C3B9C8EF054 /* STPViewWithSeparatorSnapshotTests.swift in Sources */, 71116C2D5831E271E12DB059 /* ServerErrorMapperTest.swift in Sources */, A8B0DB753CAA2223C8BED099 /* StripeErrorTest.swift in Sources */, 3B237145902E3DB07E747E32 /* TextFieldElement+IBANTest.swift in Sources */, - CEE483EB7B06B3C607BC755C /* UINavigationBar+StripeTest.m in Sources */, 51D515315F02D4C03BA12366 /* UserDefaults+StripeTest.swift in Sources */, 8B80FB6FC88D411A90E9D487 /* WalletHeaderViewSnapshotTests.swift in Sources */, ); @@ -2017,55 +1650,6 @@ name = Main.storyboard; sourceTree = ""; }; - C2427C1CDFA85BFC6570F1E9 /* Localizable.strings */ = { - isa = PBXVariantGroup; - children = ( - 7B8ADF2EA2D5C4C90BCDDDD5 /* bg-BG */, - 26E70469F4032553B4BB62DA /* ca-ES */, - 8ED737CB1253C3C5704B6C05 /* cs-CZ */, - 27A4D83C0E7D4AE0CCD38B89 /* da */, - 2560B4EEE60D40FB31B8552F /* de */, - DE24B3BAD7E890661CCA817D /* el-GR */, - 7B10B1A15063FEDBA4A59953 /* en */, - 90D0900C5FDBB7952BCF2C3A /* en-GB */, - A6F6634AD12771A9BB100DD3 /* es */, - AB1A92C77AC61335184BBDBC /* es-419 */, - 12D757B36030685C401A6990 /* et-EE */, - BAFD938F3A149A56CC99FE96 /* fi */, - 0A16326394D71637A2CF68C3 /* fil */, - 04838ACE779F5CC949C276CB /* fr */, - DFA4E34E459EA612E065DE64 /* fr-CA */, - 7CAE7444CEFE1D1EFB888996 /* hr */, - BFB4A210A30D1D4F3D3100E5 /* hu */, - 084B1B9FCCF4AB727B4ECFB2 /* id */, - ABAABB969BFB7102D5AA5598 /* it */, - 064CFCA8FCEA9E4BAB3547D0 /* ja */, - 1007571188950D7FBF745A4E /* ko */, - 43ADFC4EF612D7C4A46E81B9 /* lt-LT */, - 13DDBEA7D444A8AC14E0F1C8 /* lv-LV */, - 9D3BBCE8C46A38D0E20DBF4E /* ms-MY */, - 04FE0C74090AE8A871CCE5EC /* mt */, - 482693A3D9A527B0E671F757 /* nb */, - D3667F97B7665F699D6704BE /* nl */, - B334078D1C3E629BEB498BAB /* nn-NO */, - 0C9D6F99E303A17A91101723 /* pl-PL */, - 002634603200AABECC9686B1 /* pt-BR */, - C45852D37E323E65C47348B0 /* pt-PT */, - AA3CA5B4B91838CC7ED4D5EB /* ro-RO */, - 121B7EDCCD0957C9A444A8E3 /* ru */, - 0F735744F27D46F005BB5D67 /* sk-SK */, - 618DE183886175AF23C4E668 /* sl-SI */, - 58158E8A117299834246100F /* sv */, - 35ABE696542469B79A9D52E6 /* tk */, - 313263D9DC0629C5EE279FEB /* tr */, - 4077600B9B3C1ABFF38383BE /* vi */, - F13E3DE09A463B4501733B87 /* zh-Hans */, - 4DFDFC019C67AFF7C0F7630B /* zh-Hant */, - EA20E0E29EDC1F61ADA226A2 /* zh-HK */, - ); - name = Localizable.strings; - sourceTree = ""; - }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ diff --git a/Stripe/StripeiOS/Resources/Localizations/bg-BG.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/bg-BG.lproj/Localizable.strings deleted file mode 100644 index 9b4e5b1903f..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/bg-BG.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ - Офлайн"; - -"3D Secure" = "3D Secure удостоверяване"; - -"Add New Card…" = "Добавяне на нова карта..."; - -"Add a Card" = "Добавяне на карта"; - -"Apt." = "Aп."; - -"Contact" = "Контакт"; - -"Delivery" = "Доставка"; - -"Delivery Address" = "Адрес за доставка"; - -"Free" = "Безплатно"; - -"Invalid Shipping Address" = "Невалиден адрес за доставка"; - -"Loading…" = "Зареждане..."; - -"Multibanco" = "Multibanco"; - -"Next" = "Следващо"; - -"Online Banking (FPX)" = "Онлайн банкиране (FPX)"; - -"Payment Method" = "Метод на плащане"; - -"Shipping" = "Доставка"; - -"Shipping Method" = "Метод на доставка"; - -"Use Billing" = "Да се използва адреса за фактуриране"; - -"Use Delivery" = "Да се използва адреса за доставка"; - -"Use Shipping" = "Да се използва адреса за изпращане"; diff --git a/Stripe/StripeiOS/Resources/Localizations/ca-ES.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/ca-ES.lproj/Localizable.strings deleted file mode 100644 index b7979c0aa2c..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/ca-ES.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ - Fora de línia"; - -"3D Secure" = "3D Segur"; - -"Add New Card…" = "Afegir nova targeta..."; - -"Add a Card" = "Afegir una targeta"; - -"Apt." = "Apt."; - -"Contact" = "Contacte"; - -"Delivery" = "Lliurament"; - -"Delivery Address" = "Adreça de lliurament"; - -"Free" = "Sense cost"; - -"Invalid Shipping Address" = "Adreça d'enviament invàlida"; - -"Loading…" = "Carregant..."; - -"Multibanco" = "Multibanco"; - -"Next" = "Següent"; - -"Online Banking (FPX)" = "Banca Online (FPX)"; - -"Payment Method" = "Mètode de pagament"; - -"Shipping" = "Enviament"; - -"Shipping Method" = "Mètode d'enviament"; - -"Use Billing" = "Fer servir Facturació"; - -"Use Delivery" = "Fer servir Lliurament"; - -"Use Shipping" = "Fes servir Enviament"; diff --git a/Stripe/StripeiOS/Resources/Localizations/cs-CZ.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/cs-CZ.lproj/Localizable.strings deleted file mode 100644 index a0a89390b08..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/cs-CZ.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ - Offline"; - -"3D Secure" = "3D Secure"; - -"Add New Card…" = "Přidat novou kartu"; - -"Add a Card" = "Přidat kartu"; - -"Apt." = "Byt"; - -"Contact" = "Kontakt"; - -"Delivery" = "Dodávka"; - -"Delivery Address" = "Dodací adresa"; - -"Free" = "Zdarma"; - -"Invalid Shipping Address" = "Neplatná dodací adresa"; - -"Loading…" = "Načítání..."; - -"Multibanco" = "Multibanco"; - -"Next" = "Další"; - -"Online Banking (FPX)" = "Online bankovnictví (FPX)"; - -"Payment Method" = "Způsob platby"; - -"Shipping" = "Doprava"; - -"Shipping Method" = "Způsob dopravy"; - -"Use Billing" = "Použít fakturaci"; - -"Use Delivery" = "Použít dodání"; - -"Use Shipping" = "Použít dopravu"; diff --git a/Stripe/StripeiOS/Resources/Localizations/da.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/da.lproj/Localizable.strings deleted file mode 100644 index 8415e65b008..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/da.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ - Offline"; - -"3D Secure" = "3D Secure"; - -"Add New Card…" = "Tilføj nyt kort …"; - -"Add a Card" = "Tilføj et kort"; - -"Apt." = "Lejlighed"; - -"Contact" = "Kontaktperson"; - -"Delivery" = "Levering"; - -"Delivery Address" = "Leveringsadresse"; - -"Free" = "Gratis"; - -"Invalid Shipping Address" = "Ugyldig forsendelsesadresse"; - -"Loading…" = "Indlæser ..."; - -"Multibanco" = "Multibanco"; - -"Next" = "Næste"; - -"Online Banking (FPX)" = "Onlinebanking (FPX)"; - -"Payment Method" = "Betalingsmetode"; - -"Shipping" = "Forsendelse"; - -"Shipping Method" = "Forsendelsesmetode"; - -"Use Billing" = "Brug faktureringsadresse"; - -"Use Delivery" = "Brug leveringsadresse"; - -"Use Shipping" = "Brug forsendelsesadresse"; diff --git a/Stripe/StripeiOS/Resources/Localizations/de.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/de.lproj/Localizable.strings deleted file mode 100644 index 1818eb8542b..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/de.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ – offline"; - -"3D Secure" = "Secure"; - -"Add New Card…" = "Neue Karte hinzufügen…"; - -"Add a Card" = "Karte hinzufügen"; - -"Apt." = "Adresszeile 2"; - -"Contact" = "Kontakt"; - -"Delivery" = "Lieferinformationen"; - -"Delivery Address" = "Lieferadresse"; - -"Free" = "Kostenlos"; - -"Invalid Shipping Address" = "Ungültige Versandadresse"; - -"Loading…" = "Wird geladen..."; - -"Multibanco" = "Multibanco"; - -"Next" = "Weiter"; - -"Online Banking (FPX)" = "Online-Banking (FPX)"; - -"Payment Method" = "Zahlungsmethode"; - -"Shipping" = "Versand"; - -"Shipping Method" = "Versandmethode"; - -"Use Billing" = "Rechnungsadresse verwenden"; - -"Use Delivery" = "Lieferadresse verwenden"; - -"Use Shipping" = "Versandadresse verwenden"; diff --git a/Stripe/StripeiOS/Resources/Localizations/el-GR.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/el-GR.lproj/Localizable.strings deleted file mode 100644 index a95851a2384..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/el-GR.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ - Εκτός σύνδεσης"; - -"3D Secure" = "3D Secure"; - -"Add New Card…" = "Προσθήκη νέας κάρτας…"; - -"Add a Card" = "Προσθήκη κάρτας"; - -"Apt." = "Διαμ."; - -"Contact" = "Επικοινωνία"; - -"Delivery" = "Παράδοση"; - -"Delivery Address" = "Διεύθυνση παράδοσης"; - -"Free" = "Δωρεάν"; - -"Invalid Shipping Address" = "Μη έγκυρη διεύθυνση αποστολής"; - -"Loading…" = "Φόρτωση…"; - -"Multibanco" = "Multibanco"; - -"Next" = "Επόμενο"; - -"Online Banking (FPX)" = "Τραπεζικές υπηρεσίες μέσω διαδικτύου (FPX)"; - -"Payment Method" = "Μέθοδος πληρωμής"; - -"Shipping" = "Αποστολή"; - -"Shipping Method" = "Μέθοδος αποστολής"; - -"Use Billing" = "Χρήση χρέωσης"; - -"Use Delivery" = "Χρήση παράδοσης"; - -"Use Shipping" = "Χρήση αποστολής"; diff --git a/Stripe/StripeiOS/Resources/Localizations/en-GB.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/en-GB.lproj/Localizable.strings deleted file mode 100644 index 6d515362825..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/en-GB.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ — Offline"; - -"3D Secure" = "3D Secure"; - -"Add New Card…" = "Add New Card…"; - -"Add a Card" = "Add a Card"; - -"Apt." = "Apt."; - -"Contact" = "Contact"; - -"Delivery" = "Delivery"; - -"Delivery Address" = "Delivery Address"; - -"Free" = "Free"; - -"Invalid Shipping Address" = "Invalid Shipping Address"; - -"Loading…" = "Loading…"; - -"Multibanco" = "Multibanco"; - -"Next" = "Next"; - -"Online Banking (FPX)" = "Online Banking (FPX)"; - -"Payment Method" = "Payment Method"; - -"Shipping" = "Shipping"; - -"Shipping Method" = "Shipping Method"; - -"Use Billing" = "Use Billing"; - -"Use Delivery" = "Use Delivery"; - -"Use Shipping" = "Use Shipping"; diff --git a/Stripe/StripeiOS/Resources/Localizations/en.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/en.lproj/Localizable.strings deleted file mode 100644 index 40b3a29493a..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/en.lproj/Localizable.strings +++ /dev/null @@ -1,60 +0,0 @@ -/* Bank name when bank is offline for maintenance. */ -"%@ - Offline" = "%@ - Offline"; - -/* Source type brand name */ -"3D Secure" = "3D Secure"; - -/* Title for Add a Card view */ -"Add a Card" = "Add a Card"; - -/* Button to add a new credit card. */ -"Add New Card…" = "Add New Card…"; - -/* Caption for Apartment/Address line 2 field on address form */ -"Apt." = "Apt."; - -/* Title for contact info form */ -"Contact" = "Contact"; - -/* Title for delivery info form */ -"Delivery" = "Delivery"; - -/* Title for delivery address entry section */ -"Delivery Address" = "Delivery Address"; - -/* Label for free shipping method */ -"Free" = "Free"; - -/* Shipping form error message */ -"Invalid Shipping Address" = "Invalid Shipping Address"; - -/* Title for screen when data is still loading from the network. */ -"Loading…" = "Loading…"; - -/* Source type brand name */ -"Multibanco" = "Multibanco"; - -/* Button to move to the next text entry field */ -"Next" = "Next"; - -/* Button to pay with a Bank Account (using FPX). */ -"Online Banking (FPX)" = "Online Banking (FPX)"; - -/* Title for Payment Method screen */ -"Payment Method" = "Payment Method"; - -/* Title for shipping info form */ -"Shipping" = "Shipping"; - -/* Label for shipping method form */ -"Shipping Method" = "Shipping Method"; - -/* Button to fill shipping address from billing address. */ -"Use Billing" = "Use Billing"; - -/* Button to fill billing address from delivery address. */ -"Use Delivery" = "Use Delivery"; - -/* Button to fill billing address from shipping address. */ -"Use Shipping" = "Use Shipping"; - diff --git a/Stripe/StripeiOS/Resources/Localizations/es-419.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/es-419.lproj/Localizable.strings deleted file mode 100644 index 0ff4ff68235..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/es-419.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ - Fuera de línea"; - -"3D Secure" = "3D Secure"; - -"Add New Card…" = "Agregar nueva tarjeta..."; - -"Add a Card" = "Agrega una tarjeta"; - -"Apt." = "Apto."; - -"Contact" = "Contacto"; - -"Delivery" = "Entrega"; - -"Delivery Address" = "Dirección de entrega"; - -"Free" = "Gratis"; - -"Invalid Shipping Address" = "Dirección de envío inválida"; - -"Loading…" = "Cargando..."; - -"Multibanco" = "Multibanco"; - -"Next" = "Siguiente"; - -"Online Banking (FPX)" = "Banca electrónica (FPX)"; - -"Payment Method" = "Método de pago"; - -"Shipping" = "Envío"; - -"Shipping Method" = "Método de envío"; - -"Use Billing" = "Usar la de facturación"; - -"Use Delivery" = "Usar la de entrega"; - -"Use Shipping" = "Usar la de envío"; diff --git a/Stripe/StripeiOS/Resources/Localizations/es.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/es.lproj/Localizable.strings deleted file mode 100644 index 133110153a3..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/es.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ - Fuera de línea"; - -"3D Secure" = "3D Secure"; - -"Add New Card…" = "Añadir tarjeta nueva…"; - -"Add a Card" = "Añade una tarjeta"; - -"Apt." = "Piso"; - -"Contact" = "Contacto"; - -"Delivery" = "Entrega"; - -"Delivery Address" = "Dirección de entrega"; - -"Free" = "Gratuito"; - -"Invalid Shipping Address" = "Dirección de envío no válida"; - -"Loading…" = "Cargando…"; - -"Multibanco" = "Multibanco"; - -"Next" = "Siguiente"; - -"Online Banking (FPX)" = "Banca electrónica (FPX)"; - -"Payment Method" = "Método de pago"; - -"Shipping" = "Envío"; - -"Shipping Method" = "Método de envío"; - -"Use Billing" = "Usar la de facturación"; - -"Use Delivery" = "Usar la de entrega"; - -"Use Shipping" = "Usar la de envío"; diff --git a/Stripe/StripeiOS/Resources/Localizations/et-EE.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/et-EE.lproj/Localizable.strings deleted file mode 100644 index afe2d85c878..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/et-EE.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ - Võrguühenduseta"; - -"3D Secure" = "3D Secure"; - -"Add New Card…" = "Lisa uus kaart ..."; - -"Add a Card" = "Kaardi lisamine"; - -"Apt." = "Korter"; - -"Contact" = "Kontakt"; - -"Delivery" = "Tarnimine"; - -"Delivery Address" = "Tarneaadress"; - -"Free" = "Tasuta"; - -"Invalid Shipping Address" = "Kehtetu tarneaadress"; - -"Loading…" = "Laadimine ..."; - -"Multibanco" = "Multibanco"; - -"Next" = "Järgmine"; - -"Online Banking (FPX)" = "Internetipank (FPX)"; - -"Payment Method" = "Makseviis"; - -"Shipping" = "Tarnimine"; - -"Shipping Method" = "Tarneviis"; - -"Use Billing" = "Kasuta arveldusaadressi"; - -"Use Delivery" = "Kasuta saaja aadressi"; - -"Use Shipping" = "Kasuta tarneaadressi"; diff --git a/Stripe/StripeiOS/Resources/Localizations/fi.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/fi.lproj/Localizable.strings deleted file mode 100644 index 710969798e3..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/fi.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ Offline-tila"; - -"3D Secure" = "3D Secure"; - -"Add New Card…" = "Lisää uusi kortti..."; - -"Add a Card" = "Lisää kortti"; - -"Apt." = "Asunto"; - -"Contact" = "Yhteystiedot"; - -"Delivery" = "Toimitus"; - -"Delivery Address" = "Toimitusosoite"; - -"Free" = "Maksuton"; - -"Invalid Shipping Address" = "Toimitusosoite ei kelpaa"; - -"Loading…" = "Lataa..."; - -"Multibanco" = "Multibanco"; - -"Next" = "Seuraava"; - -"Online Banking (FPX)" = "Verkkopankki (FPX)"; - -"Payment Method" = "Maksutapa"; - -"Shipping" = "Toimitus"; - -"Shipping Method" = "Toimitustapa"; - -"Use Billing" = "Käytä laskutusosoitetta"; - -"Use Delivery" = "Käytä toimitusosoitetta"; - -"Use Shipping" = "Käytä lähetysosoitetta"; diff --git a/Stripe/StripeiOS/Resources/Localizations/fil.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/fil.lproj/Localizable.strings deleted file mode 100644 index a4252268985..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/fil.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ - Offline"; - -"3D Secure" = "3D Secure"; - -"Add New Card…" = "Magdagdag ng Bagong Kard..."; - -"Add a Card" = "Magdagdag ng isang Kard"; - -"Apt." = "Apt."; - -"Contact" = "Kontak"; - -"Delivery" = "Pagpapadala"; - -"Delivery Address" = "Adres ng Paghahatarin"; - -"Free" = "Libre"; - -"Invalid Shipping Address" = "Adres ng Nagpadala ay di balido"; - -"Loading…" = "Naglo-load..."; - -"Multibanco" = "Multibanco"; - -"Next" = "Susunod"; - -"Online Banking (FPX)" = "Online Banking (FPX)"; - -"Payment Method" = "Paraan ng Pagbabayad"; - -"Shipping" = "Pagpapadala"; - -"Shipping Method" = "Paraan ng Pagpapadala"; - -"Use Billing" = "Gamitin ang Billing"; - -"Use Delivery" = "Gamitin ang Padadalhan"; - -"Use Shipping" = "Gamitin ang Nagpadala"; diff --git a/Stripe/StripeiOS/Resources/Localizations/fr-CA.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/fr-CA.lproj/Localizable.strings deleted file mode 100644 index 8ba185a4633..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/fr-CA.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ - Hors ligne"; - -"3D Secure" = "3D Secure"; - -"Add New Card…" = "Ajouter une carte…"; - -"Add a Card" = "Ajouter une carte"; - -"Apt." = "Nº d'app."; - -"Contact" = "Contact"; - -"Delivery" = "Livraison"; - -"Delivery Address" = "Adresse de livraison"; - -"Free" = "Gratuit"; - -"Invalid Shipping Address" = "Adresse de livraison non valide"; - -"Loading…" = "Chargement…"; - -"Multibanco" = "Multibanco"; - -"Next" = "Suivant"; - -"Online Banking (FPX)" = "Services bancaires en ligne (FPX)"; - -"Payment Method" = "Moyen de paiement"; - -"Shipping" = "Livraison"; - -"Shipping Method" = "Mode de livraison"; - -"Use Billing" = "Utiliser l'adresse de facturation"; - -"Use Delivery" = "Utiliser l'adresse de livraison"; - -"Use Shipping" = "Utiliser l'adresse de livraison"; diff --git a/Stripe/StripeiOS/Resources/Localizations/fr.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/fr.lproj/Localizable.strings deleted file mode 100644 index 191697b3e51..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/fr.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ - Hors ligne"; - -"3D Secure" = "3D Secure"; - -"Add New Card…" = "Ajouter une nouvelle carte..."; - -"Add a Card" = "Ajouter une carte"; - -"Apt." = "Numéro d'appartement"; - -"Contact" = "Contact"; - -"Delivery" = "Livraison"; - -"Delivery Address" = "Adresse de livraison"; - -"Free" = "Gratuit"; - -"Invalid Shipping Address" = "Adresse de livraison incorrecte"; - -"Loading…" = "Chargement en cours..."; - -"Multibanco" = "Multibanco"; - -"Next" = "Suivant"; - -"Online Banking (FPX)" = "Compte bancaire (FPX)"; - -"Payment Method" = "Moyen de paiement"; - -"Shipping" = "Expédition"; - -"Shipping Method" = "Mode de livraison"; - -"Use Billing" = "Utiliser l'adresse de facturation"; - -"Use Delivery" = "Utiliser l'adresse de livraison"; - -"Use Shipping" = "Utiliser l'adresse de livraison"; diff --git a/Stripe/StripeiOS/Resources/Localizations/hr.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/hr.lproj/Localizable.strings deleted file mode 100644 index 6f9a9a4b020..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/hr.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ - Izvan mreže"; - -"3D Secure" = "3D Secure"; - -"Add New Card…" = "Dodaj novu karticu..."; - -"Add a Card" = "Dodaj karticu"; - -"Apt." = "Stan br."; - -"Contact" = "Kontakt"; - -"Delivery" = "Dostava"; - -"Delivery Address" = "Adresa za dostavu"; - -"Free" = "Besplatno"; - -"Invalid Shipping Address" = "Adresa za otpremu nije valjana"; - -"Loading…" = "Učitava se..."; - -"Multibanco" = "Multibanco"; - -"Next" = "Sljedeće"; - -"Online Banking (FPX)" = "Online Banking (FPX)"; - -"Payment Method" = "Način plaćanja"; - -"Shipping" = "Otprema"; - -"Shipping Method" = "Način otpreme"; - -"Use Billing" = "Koristi istu adresu kao i za naplatu"; - -"Use Delivery" = "Koristi istu adresu kao i za dostavu"; - -"Use Shipping" = "Koristi istu adresu kao i za otpremu"; diff --git a/Stripe/StripeiOS/Resources/Localizations/hu.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/hu.lproj/Localizable.strings deleted file mode 100644 index 355f47cddcc..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/hu.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ - offline"; - -"3D Secure" = "3D Secure"; - -"Add New Card…" = "Új kártya hozzáadása..."; - -"Add a Card" = "Kártya hozzáadása"; - -"Apt." = "Házszám"; - -"Contact" = "Kapcsolat"; - -"Delivery" = "Szállítás"; - -"Delivery Address" = "Szállítási cím"; - -"Free" = "Ingyenes"; - -"Invalid Shipping Address" = "Érvénytelen szállítási cím"; - -"Loading…" = "Betöltés..."; - -"Multibanco" = "Multibanco"; - -"Next" = "Tovább"; - -"Online Banking (FPX)" = "Online bankolás (FPX)"; - -"Payment Method" = "Fizetési mód"; - -"Shipping" = "Szállítás"; - -"Shipping Method" = "Szállítási mód"; - -"Use Billing" = "Számlázási használata"; - -"Use Delivery" = "Szállítási használata"; - -"Use Shipping" = "Szállítási használata"; diff --git a/Stripe/StripeiOS/Resources/Localizations/id.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/id.lproj/Localizable.strings deleted file mode 100644 index c53fed579c4..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/id.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ - Offline"; - -"3D Secure" = "3D Secure"; - -"Add New Card…" = "Tambahkan Kartu Baru..."; - -"Add a Card" = "Tambahkan sebuah Kartu"; - -"Apt." = "Apt."; - -"Contact" = "Kontak"; - -"Delivery" = "Pengiriman"; - -"Delivery Address" = "Alamat Pengiriman"; - -"Free" = "Gratis"; - -"Invalid Shipping Address" = "Alamat Pengiriman Tidak Valid"; - -"Loading…" = "Memuat…"; - -"Multibanco" = "Multibanco"; - -"Next" = "Berikutnya"; - -"Online Banking (FPX)" = "Perbankan Online (FPX)"; - -"Payment Method" = "Metode Pembayaran"; - -"Shipping" = "Pengiriman"; - -"Shipping Method" = "Metode Pengiriman"; - -"Use Billing" = "Gunakan Tagihan"; - -"Use Delivery" = "Gunakan Pengiriman"; - -"Use Shipping" = "Gunakan Pengiriman"; diff --git a/Stripe/StripeiOS/Resources/Localizations/it.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/it.lproj/Localizable.strings deleted file mode 100644 index e59f1ff5be8..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/it.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ - Offline"; - -"3D Secure" = "3D Secure"; - -"Add New Card…" = "Aggiungi nuova carta…"; - -"Add a Card" = "Aggiungi una carta"; - -"Apt." = "Int."; - -"Contact" = "Contatto"; - -"Delivery" = "Consegna"; - -"Delivery Address" = "Indirizzo di consegna"; - -"Free" = "Gratuita"; - -"Invalid Shipping Address" = "Indirizzo di spedizione non valido"; - -"Loading…" = "Caricamento..."; - -"Multibanco" = "Multibanco"; - -"Next" = "Avanti"; - -"Online Banking (FPX)" = "Online Banking (FPX)"; - -"Payment Method" = "Modalità di pagamento"; - -"Shipping" = "Spedizione"; - -"Shipping Method" = "Modalità di spedizione"; - -"Use Billing" = "Usa indirizzo di fatturazione"; - -"Use Delivery" = "Usa indirizzo di consegna"; - -"Use Shipping" = "Usa indirizzo di spedizione"; diff --git a/Stripe/StripeiOS/Resources/Localizations/ja.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/ja.lproj/Localizable.strings deleted file mode 100644 index 4b98d6cc875..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/ja.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ - オフライン"; - -"3D Secure" = "3D セキュア"; - -"Add New Card…" = "新しいクレジットカードを追加..."; - -"Add a Card" = "カードを追加"; - -"Apt." = "建物名"; - -"Contact" = "連絡先"; - -"Delivery" = "配達先情報"; - -"Delivery Address" = "配達先住所"; - -"Free" = "無料"; - -"Invalid Shipping Address" = "配送先住所が無効です"; - -"Loading…" = "ロード中..."; - -"Multibanco" = "Multibanco"; - -"Next" = "次へ"; - -"Online Banking (FPX)" = "オンラインバンキング (FPX)"; - -"Payment Method" = "お支払い方法"; - -"Shipping" = "配送先情報"; - -"Shipping Method" = "配送方法"; - -"Use Billing" = "請求先を使用"; - -"Use Delivery" = "配達先を使用"; - -"Use Shipping" = "配送先を使用"; diff --git a/Stripe/StripeiOS/Resources/Localizations/ko.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/ko.lproj/Localizable.strings deleted file mode 100644 index 2e2e2d7933d..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/ko.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ - 오프라인"; - -"3D Secure" = "3D Secure"; - -"Add New Card…" = "새 카드 추가..."; - -"Add a Card" = "카드 추가"; - -"Apt." = "아파트"; - -"Contact" = "연락처"; - -"Delivery" = "배달"; - -"Delivery Address" = "배달 주소"; - -"Free" = "무료"; - -"Invalid Shipping Address" = "잘못된 배송 주소"; - -"Loading…" = "로드 중..."; - -"Multibanco" = "Multibanco"; - -"Next" = "다음"; - -"Online Banking (FPX)" = "온라인 뱅킹(FPX)"; - -"Payment Method" = "결제 수단"; - -"Shipping" = "배송"; - -"Shipping Method" = "배송 방법"; - -"Use Billing" = "청구 사용"; - -"Use Delivery" = "배달 사용"; - -"Use Shipping" = "배송 사용"; diff --git a/Stripe/StripeiOS/Resources/Localizations/lt-LT.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/lt-LT.lproj/Localizable.strings deleted file mode 100644 index 83a835e9d42..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/lt-LT.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ – neprisijungęs"; - -"3D Secure" = "3D saugi"; - -"Add New Card…" = "Pridėti naują kortelę..."; - -"Add a Card" = "Pridėti kortelę"; - -"Apt." = "But."; - -"Contact" = "Susisiekti"; - -"Delivery" = "Pristatymas"; - -"Delivery Address" = "Pristatymo adresas"; - -"Free" = "Nemokamai"; - -"Invalid Shipping Address" = "Netinkamas siuntimo adresas"; - -"Loading…" = "Įkeliama..."; - -"Multibanco" = "„Multibanco“"; - -"Next" = "Toliau"; - -"Online Banking (FPX)" = "Interneto banko paslaugos (FPX)"; - -"Payment Method" = "Mokėjimo būdas"; - -"Shipping" = "Siuntimas"; - -"Shipping Method" = "Siuntimo būdas"; - -"Use Billing" = "Naudoti sąskaitų siuntimo adresą"; - -"Use Delivery" = "Naudoti pristatymo adresą"; - -"Use Shipping" = "Naudoti siuntimo adresą"; diff --git a/Stripe/StripeiOS/Resources/Localizations/lv-LV.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/lv-LV.lproj/Localizable.strings deleted file mode 100644 index c06a34814a9..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/lv-LV.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ — bezsaistē"; - -"3D Secure" = "3D Secure"; - -"Add New Card…" = "Pievienot jaunu karti…"; - -"Add a Card" = "Kartes pievienošana"; - -"Apt." = "Dzīv."; - -"Contact" = "Kontaktinformācija"; - -"Delivery" = "Piegāde"; - -"Delivery Address" = "Piegādes adrese"; - -"Free" = "Bezmaksas"; - -"Invalid Shipping Address" = "Nederīga piegādes adrese"; - -"Loading…" = "Ielādē…"; - -"Multibanco" = "Multibanco"; - -"Next" = "Tālāk"; - -"Online Banking (FPX)" = "Internetbanka (FPX)"; - -"Payment Method" = "Maksājuma metode"; - -"Shipping" = "Piegāde"; - -"Shipping Method" = "Piegādes metode"; - -"Use Billing" = "Izmantot norēķinu adresi"; - -"Use Delivery" = "Izmantot piegādes adresi"; - -"Use Shipping" = "Izmantot piegādes adresi"; diff --git a/Stripe/StripeiOS/Resources/Localizations/ms-MY.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/ms-MY.lproj/Localizable.strings deleted file mode 100644 index a4c59d97a06..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/ms-MY.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ – Luar Talian"; - -"3D Secure" = "3D Secure"; - -"Add New Card…" = "Tambah Kad Baharu..."; - -"Add a Card" = "Tambah Kad"; - -"Apt." = "Apt."; - -"Contact" = "Maklumat Hubungan"; - -"Delivery" = "Penghantaran"; - -"Delivery Address" = "Alamat Penghantaran"; - -"Free" = "Percuma"; - -"Invalid Shipping Address" = "Alamat Pengiriman Tidak Sah"; - -"Loading…" = "Sedang dimuatkan..."; - -"Multibanco" = "Multibanco"; - -"Next" = "Seterusnya"; - -"Online Banking (FPX)" = "Perbankan Dalam Talian (FPX)"; - -"Payment Method" = "Kaedah Pembayaran"; - -"Shipping" = "Pengiriman"; - -"Shipping Method" = "Kaedah Pengiriman"; - -"Use Billing" = "Gunakan Alamat Pengebilan"; - -"Use Delivery" = "Gunakan Alamat Penghantaran"; - -"Use Shipping" = "Gunakan Alamat Pengiriman"; diff --git a/Stripe/StripeiOS/Resources/Localizations/mt.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/mt.lproj/Localizable.strings deleted file mode 100644 index d7513a3cdb4..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/mt.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@- Offline"; - -"3D Secure" = "3D Secure"; - -"Add New Card…" = "Żid Kard Ġdida…"; - -"Add a Card" = "Żid Kard"; - -"Apt." = "Appartament"; - -"Contact" = "Kuntatt"; - -"Delivery" = "Kunsinna"; - -"Delivery Address" = "Indirizz tal-Kunsinna"; - -"Free" = "Bla ħlas"; - -"Invalid Shipping Address" = "L-Indirizz għat-Trasport tal-Merkanzija Mhux Validu"; - -"Loading…" = "Qed jillowdja…"; - -"Multibanco" = "Multibanco"; - -"Next" = "Li jmiss"; - -"Online Banking (FPX)" = "Bankar online"; - -"Payment Method" = "Metodu tal-Ħlas"; - -"Shipping" = "Trasport tal-Merkanzija"; - -"Shipping Method" = "Il-Mod tat-Trasport tal-Merkanzija"; - -"Use Billing" = "Uża tal-Kont"; - -"Use Delivery" = "Uża tal-Kunsinna"; - -"Use Shipping" = "Uża tat-Trasport tal-Merkanzija"; diff --git a/Stripe/StripeiOS/Resources/Localizations/nb.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/nb.lproj/Localizable.strings deleted file mode 100644 index 336da04f97e..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/nb.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ – frakoblet"; - -"3D Secure" = "3D Secure"; - -"Add New Card…" = "Legg til nytt kort…"; - -"Add a Card" = "Legg til kort"; - -"Apt." = "Leil."; - -"Contact" = "Kontakt"; - -"Delivery" = "Leveranse"; - -"Delivery Address" = "Leveringsadresse"; - -"Free" = "Gratis"; - -"Invalid Shipping Address" = "Ugyldig leveringsadresse"; - -"Loading…" = "Laster ..."; - -"Multibanco" = "Multibanco"; - -"Next" = "Neste"; - -"Online Banking (FPX)" = "Banktjenester på nett (FPX)"; - -"Payment Method" = "Betalingsmåte"; - -"Shipping" = "Frakt"; - -"Shipping Method" = "Forsendelsesmetode"; - -"Use Billing" = "Bruk fakturaadresse"; - -"Use Delivery" = "Bruk leveringsadresse"; - -"Use Shipping" = "Bruk forsendelsesadresse"; diff --git a/Stripe/StripeiOS/Resources/Localizations/nl.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/nl.lproj/Localizable.strings deleted file mode 100644 index d31b0f2fce7..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/nl.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ - offline"; - -"3D Secure" = "3D Secure"; - -"Add New Card…" = "Nieuwe kaart toevoegen…"; - -"Add a Card" = "Een kaart toevoegen"; - -"Apt." = "Adresregel 2"; - -"Contact" = "Contact"; - -"Delivery" = "Bezorging"; - -"Delivery Address" = "Bezorgadres"; - -"Free" = "Gratis"; - -"Invalid Shipping Address" = "Ongeldig verzendadres"; - -"Loading…" = "Laden…"; - -"Multibanco" = "Multibanco"; - -"Next" = "Volgende"; - -"Online Banking (FPX)" = "Online bankieren (FPX)"; - -"Payment Method" = "Betaalmethode"; - -"Shipping" = "Verzending"; - -"Shipping Method" = "Verzendmethode"; - -"Use Billing" = "Factuuradres gebruiken"; - -"Use Delivery" = "Bezorgadres gebruiken"; - -"Use Shipping" = "Verzendadres gebruiken"; diff --git a/Stripe/StripeiOS/Resources/Localizations/nn-NO.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/nn-NO.lproj/Localizable.strings deleted file mode 100644 index 559c25ddd2e..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/nn-NO.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ - Fråkopla"; - -"3D Secure" = "3D Secure"; - -"Add New Card…" = "Legg til nytt kort …"; - -"Add a Card" = "Legg til kort"; - -"Apt." = "Leilegheit"; - -"Contact" = "Kontakt"; - -"Delivery" = "Leveranse"; - -"Delivery Address" = "Leveringsadresse"; - -"Free" = "Gratis"; - -"Invalid Shipping Address" = "Ugyldig sendingsadresse"; - -"Loading…" = "Lastar …"; - -"Multibanco" = "Multibanco"; - -"Next" = "Neste"; - -"Online Banking (FPX)" = "Nettbank (FPX)"; - -"Payment Method" = "Betalingsmetode"; - -"Shipping" = "Sending"; - -"Shipping Method" = "Sendingsmåte"; - -"Use Billing" = "Bruk fakturering"; - -"Use Delivery" = "Bruk leveringsadressa"; - -"Use Shipping" = "Bruk sendingsadressa"; diff --git a/Stripe/StripeiOS/Resources/Localizations/pl-PL.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/pl-PL.lproj/Localizable.strings deleted file mode 100644 index a594607034d..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/pl-PL.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ — offline"; - -"3D Secure" = "3D Secure"; - -"Add New Card…" = "Dodaj nową kartę…"; - -"Add a Card" = "Dodaj kartę"; - -"Apt." = "Nr lokalu"; - -"Contact" = "Kontakt"; - -"Delivery" = "Dostawa"; - -"Delivery Address" = "Adres dostawy"; - -"Free" = "Bezpłatnie"; - -"Invalid Shipping Address" = "Nieprawidłowy adres dostawy"; - -"Loading…" = "Ładowanie…"; - -"Multibanco" = "Multibanco"; - -"Next" = "Dalej"; - -"Online Banking (FPX)" = "Bankowość elektroniczna (FPX)"; - -"Payment Method" = "Metoda płatności"; - -"Shipping" = "Dostawa"; - -"Shipping Method" = "Metoda dostawy"; - -"Use Billing" = "Użyj adresu płatności"; - -"Use Delivery" = "Użyj adresu dostawy"; - -"Use Shipping" = "Użyj adresu dostawy"; diff --git a/Stripe/StripeiOS/Resources/Localizations/pt-BR.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/pt-BR.lproj/Localizable.strings deleted file mode 100644 index 7cdcc17ea9e..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/pt-BR.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ – Offline"; - -"3D Secure" = "3D Secure"; - -"Add New Card…" = "Adicionar novo cartão..."; - -"Add a Card" = "Adicionar um cartão"; - -"Apt." = "Apt."; - -"Contact" = "Contato"; - -"Delivery" = "Entrega"; - -"Delivery Address" = "Endereço de entrega"; - -"Free" = "Grátis"; - -"Invalid Shipping Address" = "Endereço de envio inválido"; - -"Loading…" = "Carregando..."; - -"Multibanco" = "Multibanco"; - -"Next" = "Próximo"; - -"Online Banking (FPX)" = "Online Banking (FPX)"; - -"Payment Method" = "Forma de pagamento"; - -"Shipping" = "Dados de entrega"; - -"Shipping Method" = "Método de entrega"; - -"Use Billing" = "Usar cobrança"; - -"Use Delivery" = "Usar entrega"; - -"Use Shipping" = "Usar envio"; diff --git a/Stripe/StripeiOS/Resources/Localizations/pt-PT.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/pt-PT.lproj/Localizable.strings deleted file mode 100644 index 0b428ecc0ca..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/pt-PT.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ - Offline"; - -"3D Secure" = "3D Secure"; - -"Add New Card…" = "Adicionar Novo Cartão..."; - -"Add a Card" = "Adicionar um cartão"; - -"Apt." = "Apt."; - -"Contact" = "Contacto"; - -"Delivery" = "Entrega"; - -"Delivery Address" = "Endereço de entrega"; - -"Free" = "Gratuito"; - -"Invalid Shipping Address" = "Endereço de envio inválido"; - -"Loading…" = "A carregar..."; - -"Multibanco" = "Multibanco"; - -"Next" = "Seguinte"; - -"Online Banking (FPX)" = "Serviços bancários online (FPX)"; - -"Payment Method" = "Método de Pagamento"; - -"Shipping" = "Envio"; - -"Shipping Method" = "Método de envio"; - -"Use Billing" = "Utilizar endereço de faturação"; - -"Use Delivery" = "Utilizar endereço de entrega"; - -"Use Shipping" = "Utilizar endereço de envio"; diff --git a/Stripe/StripeiOS/Resources/Localizations/ro-RO.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/ro-RO.lproj/Localizable.strings deleted file mode 100644 index 666d8c8ae80..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/ro-RO.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ - Offline"; - -"3D Secure" = "3D Secure"; - -"Add New Card…" = "Adăugare card nou..."; - -"Add a Card" = "Adăugare card"; - -"Apt." = "Apartament"; - -"Contact" = "Detalii de contact"; - -"Delivery" = "Informații privind livrarea"; - -"Delivery Address" = "Adresa de livrare"; - -"Free" = "Expediere gratuită"; - -"Invalid Shipping Address" = "Adresa de expediere nu este validă"; - -"Loading…" = "Se încarcă..."; - -"Multibanco" = "Multibanco"; - -"Next" = "Următorul"; - -"Online Banking (FPX)" = "Servicii bancare electronice (FPX)"; - -"Payment Method" = "Metoda de plată"; - -"Shipping" = "Expediere"; - -"Shipping Method" = "Metoda de expediere"; - -"Use Billing" = "Utilizare adresă de facturare"; - -"Use Delivery" = "Utilizare adresă de livrare"; - -"Use Shipping" = "Utilizare adresă de expediere"; diff --git a/Stripe/StripeiOS/Resources/Localizations/ru.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/ru.lproj/Localizable.strings deleted file mode 100644 index 9a9d68d5ea6..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/ru.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ - не в сети"; - -"3D Secure" = "Метод 3D Secure"; - -"Add New Card…" = "Добавить новую карту..."; - -"Add a Card" = "Добавить карту"; - -"Apt." = "Кв."; - -"Contact" = "Контактные данные"; - -"Delivery" = "Доставка"; - -"Delivery Address" = "Адрес доставки"; - -"Free" = "Бесплатно"; - -"Invalid Shipping Address" = "Ошибочный адрес доставки"; - -"Loading…" = "Идет загрузка..."; - -"Multibanco" = "Multibanco"; - -"Next" = "Далее"; - -"Online Banking (FPX)" = "Онлайн-банкинг (FPX)"; - -"Payment Method" = "Метод оплаты"; - -"Shipping" = "Доставка"; - -"Shipping Method" = "Метод доставки"; - -"Use Billing" = "Использовать адрес выставления счетов"; - -"Use Delivery" = "Использовать адрес доставки"; - -"Use Shipping" = "Использовать адрес доставки"; diff --git a/Stripe/StripeiOS/Resources/Localizations/sk-SK.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/sk-SK.lproj/Localizable.strings deleted file mode 100644 index fb8fa880ef9..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/sk-SK.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ – Offline"; - -"3D Secure" = "3D Secure"; - -"Add New Card…" = "Pridať novú kartu..."; - -"Add a Card" = "Pridať kartu"; - -"Apt." = "Byt"; - -"Contact" = "Kontakt"; - -"Delivery" = "Dodanie"; - -"Delivery Address" = "Dodacia adresa"; - -"Free" = "Zdarma"; - -"Invalid Shipping Address" = "Neplatná dodacia adresa"; - -"Loading…" = "Nahrávanie..."; - -"Multibanco" = "Multibanco"; - -"Next" = "Ďalej"; - -"Online Banking (FPX)" = "Online bankovníctvo (FPX)"; - -"Payment Method" = "Spôsob platby"; - -"Shipping" = "Dodanie"; - -"Shipping Method" = "Spôsob dodania"; - -"Use Billing" = "Použiť fakturačnú adresu"; - -"Use Delivery" = "Použiť adresu doručenia"; - -"Use Shipping" = "Použiť dodaciu adresu"; diff --git a/Stripe/StripeiOS/Resources/Localizations/sl-SI.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/sl-SI.lproj/Localizable.strings deleted file mode 100644 index 77eccc7da4b..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/sl-SI.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ – ni dosegljiva"; - -"3D Secure" = "3D Secure"; - -"Add New Card…" = "Dodaj novo kartico ..."; - -"Add a Card" = "Dodajte kartico"; - -"Apt." = "Stanovanje"; - -"Contact" = "Stik"; - -"Delivery" = "Dostava"; - -"Delivery Address" = "Dostavni naslov"; - -"Free" = "Brezplačno"; - -"Invalid Shipping Address" = "Neveljaven dostavni naslov"; - -"Loading…" = "Nalaganje ..."; - -"Multibanco" = "Multibanco"; - -"Next" = "Naprej"; - -"Online Banking (FPX)" = "Spletno bančništvo (FPX)"; - -"Payment Method" = "Načina plačila"; - -"Shipping" = "Dostava"; - -"Shipping Method" = "Način dostave"; - -"Use Billing" = "Uporabi naslov plačnika računa"; - -"Use Delivery" = "Uporabi dostavo"; - -"Use Shipping" = "Uporabi dostavo"; diff --git a/Stripe/StripeiOS/Resources/Localizations/sv.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/sv.lproj/Localizable.strings deleted file mode 100644 index 77af2122d33..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/sv.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ – Offline"; - -"3D Secure" = "3D Secure"; - -"Add New Card…" = "Lägg till nytt kort …"; - -"Add a Card" = "Lägg till kort"; - -"Apt." = "Lägenhetsnr."; - -"Contact" = "Kontaktinformation"; - -"Delivery" = "Leverans"; - -"Delivery Address" = "Leveransadress"; - -"Free" = "Gratis"; - -"Invalid Shipping Address" = "Ogiltig leveransadress"; - -"Loading…" = "Laddar ..."; - -"Multibanco" = "Multibanco"; - -"Next" = "Nästa"; - -"Online Banking (FPX)" = "Internetbank (FPX)"; - -"Payment Method" = "Betalningsmetod"; - -"Shipping" = "Frakt"; - -"Shipping Method" = "Leveransmetod"; - -"Use Billing" = "Använd faktureringsadress"; - -"Use Delivery" = "Använd leveransadress"; - -"Use Shipping" = "Använd fraktadress"; diff --git a/Stripe/StripeiOS/Resources/Localizations/tk.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/tk.lproj/Localizable.strings deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/Stripe/StripeiOS/Resources/Localizations/tr.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/tr.lproj/Localizable.strings deleted file mode 100644 index f660bf8daf4..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/tr.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ - Çevrimdışı"; - -"3D Secure" = "3D Güvenli"; - -"Add New Card…" = "Yeni Kart Ekle..."; - -"Add a Card" = "Kart Ekle"; - -"Apt." = "Apt."; - -"Contact" = "İletişim"; - -"Delivery" = "Teslimat"; - -"Delivery Address" = "Teslimat Adresi"; - -"Free" = "Ücretsiz"; - -"Invalid Shipping Address" = "Geçersiz Gönderi Adresi"; - -"Loading…" = "Yükleniyor..."; - -"Multibanco" = "Multibanco"; - -"Next" = "İleri"; - -"Online Banking (FPX)" = "Çevrimiçi Bankacılık (FPX)"; - -"Payment Method" = "Ödeme Metodu"; - -"Shipping" = "Gönderi"; - -"Shipping Method" = "Gönderi Metodu"; - -"Use Billing" = "Fatura Adresini Kullan"; - -"Use Delivery" = "Teslimat Adresini Kullan"; - -"Use Shipping" = "Gönderi Adresini Kullan"; diff --git a/Stripe/StripeiOS/Resources/Localizations/vi.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/vi.lproj/Localizable.strings deleted file mode 100644 index 3234969e9bd..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/vi.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ - Ngoại tuyến"; - -"3D Secure" = "Bảo mật 3D"; - -"Add New Card…" = "Thêm thẻ mới..."; - -"Add a Card" = "Thêm thẻ"; - -"Apt." = "Căn hộ"; - -"Contact" = "Liên hệ"; - -"Delivery" = "Giao hàng"; - -"Delivery Address" = "Địa chỉ giao hàng"; - -"Free" = "Miễn phí"; - -"Invalid Shipping Address" = "Địa chỉ vận chuyển không hợp lệ"; - -"Loading…" = "Đang tải..."; - -"Multibanco" = "Multibanco"; - -"Next" = "Tiếp"; - -"Online Banking (FPX)" = "Ngân hàng Trực tuyến (FPX)"; - -"Payment Method" = "Phương thức thanh toán"; - -"Shipping" = "Vận chuyển"; - -"Shipping Method" = "Phương thức vận chuyển"; - -"Use Billing" = "Sử dụng Hóa đơn"; - -"Use Delivery" = "Sử dụng Giao hàng"; - -"Use Shipping" = "Chọn Vận chuyển"; diff --git a/Stripe/StripeiOS/Resources/Localizations/zh-HK.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/zh-HK.lproj/Localizable.strings deleted file mode 100644 index 9e17b1dcf7e..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/zh-HK.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ - 離線"; - -"3D Secure" = "3DS 驗證"; - -"Add New Card…" = "添加新卡…"; - -"Add a Card" = "添加卡"; - -"Apt." = "公寓"; - -"Contact" = "聯絡資訊"; - -"Delivery" = "收貨"; - -"Delivery Address" = "收貨地址"; - -"Free" = "免費"; - -"Invalid Shipping Address" = "收貨地址無效"; - -"Loading…" = "正在載入..."; - -"Multibanco" = "Multibanco"; - -"Next" = "下一步"; - -"Online Banking (FPX)" = "網上銀行 (FPX)"; - -"Payment Method" = "支付方式"; - -"Shipping" = "配送"; - -"Shipping Method" = "配送方式"; - -"Use Billing" = "使用賬單地址"; - -"Use Delivery" = "使用收貨地址"; - -"Use Shipping" = "使用收貨地址"; diff --git a/Stripe/StripeiOS/Resources/Localizations/zh-Hans.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/zh-Hans.lproj/Localizable.strings deleted file mode 100644 index 6b428ddb4fa..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/zh-Hans.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ - 离线"; - -"3D Secure" = "3DS 验证"; - -"Add New Card…" = "添加新卡……"; - -"Add a Card" = "添加卡"; - -"Apt." = "公寓"; - -"Contact" = "联系信息"; - -"Delivery" = "收货信息"; - -"Delivery Address" = "收货地址"; - -"Free" = "免费"; - -"Invalid Shipping Address" = "收货地址无效"; - -"Loading…" = "正在加载……"; - -"Multibanco" = "Multibanco"; - -"Next" = "下一步"; - -"Online Banking (FPX)" = "网上银行 (FPX)"; - -"Payment Method" = "支付方式"; - -"Shipping" = "配送"; - -"Shipping Method" = "配送方式"; - -"Use Billing" = "使用账单地址"; - -"Use Delivery" = "使用收货地址"; - -"Use Shipping" = "使用收货地址"; diff --git a/Stripe/StripeiOS/Resources/Localizations/zh-Hant.lproj/Localizable.strings b/Stripe/StripeiOS/Resources/Localizations/zh-Hant.lproj/Localizable.strings deleted file mode 100644 index 400a7f1c6e6..00000000000 --- a/Stripe/StripeiOS/Resources/Localizations/zh-Hant.lproj/Localizable.strings +++ /dev/null @@ -1,39 +0,0 @@ -"%@ - Offline" = "%@ - 離線"; - -"3D Secure" = "3DS 驗證"; - -"Add New Card…" = "添加新卡..."; - -"Add a Card" = "新增卡"; - -"Apt." = "公寓"; - -"Contact" = "聯絡資訊"; - -"Delivery" = "寄送"; - -"Delivery Address" = "寄送地址"; - -"Free" = "免費"; - -"Invalid Shipping Address" = "收貨地址無效"; - -"Loading…" = "正在載入..."; - -"Multibanco" = "Multibanco"; - -"Next" = "下一步"; - -"Online Banking (FPX)" = "網上銀行 (FPX)"; - -"Payment Method" = "支付方式"; - -"Shipping" = "送貨"; - -"Shipping Method" = "送貨方式"; - -"Use Billing" = "使用帳單地址"; - -"Use Delivery" = "使用寄送地址"; - -"Use Shipping" = "使用收貨地址"; diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/Contents.json b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/Contents.json deleted file mode 100644 index 73c00596a7f..00000000000 --- a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_affin_bank.imageset/Contents.json b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_affin_bank.imageset/Contents.json deleted file mode 100644 index 182babd3b08..00000000000 --- a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_affin_bank.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "filename" : "stp_bank_fpx_affin_bank.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "stp_bank_fpx_affin_bank@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "stp_bank_fpx_affin_bank@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_affin_bank.imageset/stp_bank_fpx_affin_bank.png b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_affin_bank.imageset/stp_bank_fpx_affin_bank.png deleted file mode 100644 index c55aad7c142b023a95a8d59ba46b972dc444c094..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 627 zcmV-(0*w8MP)Px%ElET{R7l6|l-W-cQ51*yyWHZFTcQt`pa?Mp`(R6rI_fUAl1X*$5p8S^*q7^l8PwswmBV&AfRlfMNlI+#73 znvVVtvUzL7a`ckEXV3%z_}uM<6ITuARVIkV$;6UHi-XB|gU+=Sq6VKVA>?EqHBASb z14L5qxJD!C{;nB9b~-(N#W3`2dBvUh9!?82a-e%g{l;bUB*M|0#HADC6Q>4fzFb2? z2hYwzVksUZcYtdSK)>KKsUn=B@dBGELpgjwckHtM(QAhR?+K2 znfto5bEa^1yNbN%FTs@%_;AeL9N>>+lj)Ld`!_O}4+e@s?K(wb+h8{c5eyVetYmFH zQ!LfWRS_GKcNY4QL*QRMG|}y8RD~A400001b5ch_0Itp) z=>Px(j!8s8RA}Dqn2%3WR}{zntCmH_nA2@ek{S2Ipr}kyac)k>gyD4RvShO11_9Zo z#El=0P=2={AhcM(BJ!jBPzGfbX!%v3^e43MweLOlZBBVKrAzE$GMe0*ljgp2&b{w_ z?mg$+_qt;}#@h}CzyKHk17H9QfB`T72EYIq00UqE41fVJfS1@LtJT-0^%VT(zI@g7 z$$59?m9<+r-akrsWxcPxQ+Pfit*mTE0Aa%D`Q?r?@t7@sulvidI7Ou}I<_u~+kOXl z9!u*ye$w`8oI5Sur+Ku_@i7uYg1}W&+4mo?y}oBHH&0x!#8M9U9_t(j582}0^yKDC zHv3CX;3L@98knb1VUlpRj^hOkw^-NU`TqHOwW@FB zm0bv!>3+jU7aJhy*&Xs-lx;?ub8^P=CpD^DZnu-`oOCoq9rco1Sx#+l|{#aQVjZO1~gR4Z!=v4?eG#Cq4B| zYpC`2>Jids{?wU$uTPeOvO!qCxT%HdwIoGWVQ;7?HAWh)AD;Jc{@!O6b(e`WH}Cey z_qwAPCS_83)7D$RC_r)DUo_o^7aH*Uc1lgC_0o?W@_KI_yYF-jOh-1>JFIclwf^p& z@K$4O^cT(M+40 zQ>2&WasM1lGYf9=M?mKk>t!*T198k%R-;Ph6$G{@{#Y!AZxK$-1=Si5TKd9aFHj=u8o<<^?zZu+_FR-cnLYnv|=-*ccjH zCXK4i`0klnbbcu8McE)Fkw*bAK5a+%Vq{*ap7#kl{akP*+Na3j(bE~yymwBCyp#n= z32SbNo~%fr#Iy$_h!C9oDDz-w?FtfN(`Z6PQ*e_fXPr=@^UkT7j9Z=PAP^)e$};-t zcWn`u@YnJoa=88HVA!67w$$rtiY}jjvvf!fhdto{UJB69zdsnZBG>Z+)#j~}foC;L z*~m%>aQ22Kx^n;p?%(R;m0VpYA)?mH3E@YoDD6(Jg7wTbb*SE*@%36(HucYatDy-^ z8|CuQ#Xz0Fv~-!AxtY*;r2|m_V9jW*gw(oW!}92)4WiS}(_9DxazjN5y$lP#V0aYk zH!E_B+Le-u_l3Y#Nb7q}R8d)@*l@b}uxG7o9+v^+I{QKZ_f^5XDQg&$ZK5QhTtK-y zIS>FiWyl9rf9pi3^khXU2UT9LBk`!XxJXwxQ_11N_gd0)Z=8uZH%S8|x+7%P;*J6U z1*@WI96|@a+)x})wjqKb%`dHz&qSo+fUF>^Tys5z_jpx?L780P*W?M=o+i44o#46o$PEpiKMVeX5_vMGtmYKS+CG#*LLvL^Np zEAf&$ExFEZS{gADMZ9u4=Q-!s^PC^P-_P^;3qIMN?k-RnO&I_H0Chd-w~r{@*&A?YMWC(fTI;%g#<|sb5=}@Ntev%PsWujYg#D#jL~i~3 z&crlr!ZyOf)hS$3`w$v@8=!PZ!YN%^5eV1*e{FmGbz}qE{Yn0G{YzK1t9|Y%BnFlSHN1*{-}EFybimugN-`v`;Bt0tZs5dM(8%bC3ATX?hDO=9_#fV{Vl1=9O+X#vuTqm<%1YOzKTw1vl@-nytu-{ zI)uFqlaCDR2XyWXmAobH)NTJou_NrmcNzI`hLbNYUzRTvEo7md0>j#3*1@JPg2!?t z=eWIfWFl@O9jN*1iTC3U=PfPzJ?c2*^8U^8skG-_pM*cKY%Ci%I+ie{AJY zN#!>`2NeL7jm+vKK~88rNjy9fLE@d_)CXwW8 zJe-=d+NEu`Y+URXBFzN3Y$dNZ^U)g#pc{c^=>zYf(%ZL2ezD*-wwqrEZ!{8M_QIkq z?;IiKul0oE6K?F*A3L`(PqWxE)2VLd3NszcJJUMLU1*U+@O}M+cW;->8SUDE&}B>H zHAf&p>$x2r`oTb*&tlZxiU!})rLXZsiChVYKJMA!hRv6r!1Ce`(S|iqzN}82XV9y* zE5$=)f)Jy8N)U54Ed{<_*NS+TTt&&5rh8|xO{5qT6#?oXYgrq!z0DGFO1YZ6_2}q~ zA6U-Qxd669J%~@qze``dR%_^6nf+8Pu z;j8ee`8te&0*_-4yIKAm-eJG?!LK0|dot3`El>?(Y=fj!*+_n}M{`@JQr^Z>choPL zjYoNB{H%Ezay*OW6iBS^bqv}pxOtgxZIXa?sb#aauqG_VL7H-(O3tW*>tv;$|Ch1X zs10RuhNcF3f0p+v5n}svu>kQ!!9!0Xo7PQa-Ho*uu+q*A94P&R{w9NC_k$0)Vmg@# z9eH}^`teVLeix=%$fLb5U<&}Cd4|>!P$W|4;UXMhurAaU_!-JwsUDL+=G57bI*ll3ge%2X6p@s)jxR(bXA zsi{ImdEKv|yw?>NLD;R1lcAkqaDhWd*PU>9f|oO$x9i&5_SK)_HjWv^2Ol9WUr9iv z8l4cBP3S2uf}@lyo&x|lV{@|p`F(}m)%BTETC(quyHk>)T4VHuM!YOCV&uiX?X;fQ zxki46JfAOas^K8N4-X2Vu}6C*)nn;3dn6Ff(K=SEn8q>JjfyPrS_tV+w(d*2sX@4> zu*6d~GRfhD#>;hi)HwQC3`G3NDqIUFm#l;`{Ad42+gY5vK0e6oV5(4o0C0uXVv@?U z?*&e9qEY(r9Y10ghLZ)IYt}^;HxOXQ+V(>pN(D2kU5G9~^tjV!3P9nI1r2YUX}ta! zn+|#xalt?|EXEmf`3E3i~Px$yh%hsR7l5T_)lZNFv2XDwrJOj*B@wQ!M#VX^xVn{8yC^af~1le;aL-PTuP6f zy+ytS&XFxU;$8(rc*Ii1dITng3n*R z+Xgq_QZsw`J~AzEi*Eb*^EX7z#$9KqZ^3~R*N~OPpH7KR85zJ34c7~YI4 zZsQ83A*c64C$Hm*?K!BSgs`A@))riGyLrz!v>fXZ+y3j|KRiZ!;j*w;j_q z0-c72b{)E8;a7`Uu9deh!&H3m#5ISoCgge>YC(R(LP(vb3YF>I?$Obm&_!+W5r)0HMinzs633%>V!Z07*qoM6N<$ Eg8Y#4WB>pF diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_alliance_bank.imageset/stp_bank_fpx_alliance_bank@2x.png b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_alliance_bank.imageset/stp_bank_fpx_alliance_bank@2x.png deleted file mode 100644 index b3f642076bb5d0e0de8472a4673d0ebd551143d3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 806 zcmV+>1KIqEP)00001b5ch_0Itp) z=>Px%;7LS5RA}Dq+22c3VHm*i^M`cVO*1kJ96?F6m0GkEi;#+lkRZ~aZ8>!c&3bg1)g=bYy`=RMmS@56)W#a_-= z_L<--yWEC4BBlCA^DwiBl?7#FrIiW|L8n$0eY0@W8eEg8_f;2M>7#@3^ zw{D{Gq^$ua?Hbq2D!{y5gPNHHSY_9UX6pl>c7Lv>&1kkh0Ax3{w6gPX@7(uAv}TI~ zpmw{i+$XPUyEuy0Y;gd{?wb!^$p3WZ7f!zXgwt$6K+T~Zgxy>&*L3Qd@*MTY`+u!v z5Sq8{>oglsS=)}Vdv{_|^?7o0{3$|nh1;k5KW(jmiAPg7yG~C~6|iM*2Tt=?Jc$e- zcSJi5cBAdmi_@%oLsc~3(w{pbv|V~}ngjhYaDZ}0WX3MNIL+iYLSkS6${mqOyY%8T zHx|F4l9<}1*K*AgYrCv9OU3LSJsY_kNf_L7J)^)YoDt)PpYRTAXqF1vEzd2e`JVt^ zII6nntgJmxlC-zN?RU7m;C1_SPu{f0uX>)-!4be;Vlqq4nuT@iOSOxRDqSQZKm>?@ k|2v@kM+Arf5y1KU2C}}y$+3sfR{#J207*qoM6N<$f^`3W5C8xG diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_alliance_bank.imageset/stp_bank_fpx_alliance_bank@3x.png b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_alliance_bank.imageset/stp_bank_fpx_alliance_bank@3x.png deleted file mode 100644 index b1f28c253c1f7454d365e9b766627dc224a91291..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1067 zcmV+`1l0S9P)Px&Ejloag<`e!&m8 z?oa72jqXU4fC5n<3Pgb@5Cx(@6o~iC&i`y|8>B#Sr?R0hIkW6t=raYA5$m)R8wW&p-F$7X^yioVKSbHjupj#(oME zwOLh1UU9VM97wTQ-qc;bVDnw2(f$)HZV#lgx$V~Q!a_K^phhUIjRiVY-I06bBGm54 z4=OD@g>?&yVflz>FQ%eDXjx^u4>tgw_~6NF+(7aftQR0VIuTM%De|`?ozgQf=Ey*& zgB`J_e3_m}$vI1bN)(&Few$Stbmis{1&Z3t9;DLRy@7HHYa=$Z6RWj*1I60R4!G71 z3#77{9dNCk6iCx%c3`!3QXoy6v9)$gARU`gwRTJ(eVf@i>A&HkK=LniMxPQ&YX<~M z&}Jm99S|r%n~}5@J&+-rF|-yvkWrh#wH7*%37f&S7B|plPlY*~*}2^HXblFsYSw00 ztpyEa(Pluc1r0PZ@gDq-4d%2KF%XE&P+AKY2+(E_t%VB&Xfue`Vg&-XnVqNOlMW7q zVY5Z81qy^@vqh~%350616|F@Hgle-Dt%V3=gUzP379x;6Hk;F$e<0gzHm5b`KsMWK zLTk=}Y_{2i);t4ovDv8BJOlBvSwrip>%s*Bv03)ZSKo`OHJ?CGHWvl{e;a7*)dxJS z`2+&7d1N9Kc{T5$`tZ^pB&|6F0}ziEo}2zY zhoQCIfr*_t+AN6Hl8(*$jy1#DJo++ZS(PI==_Dgc>mgAtJk+FyWHq*+*zKKQ3ANh z8Kov3L*DfKV7#|B66czPu@B7Vv%E9w);o89cVd1XM1d#}1)@L{hyqa{3gqHIE*uI( lfhZ6KqCgag0#P8h&Oh3v`dAhczx@CJ002ovPDHLkV1o1Z@_YaQ diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_ambank.imageset/Contents.json b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_ambank.imageset/Contents.json deleted file mode 100644 index 5025fc70623..00000000000 --- a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_ambank.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "filename" : "stp_bank_fpx_ambank.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "stp_bank_fpx_ambank@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "stp_bank_fpx_ambank@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_ambank.imageset/stp_bank_fpx_ambank.png b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_ambank.imageset/stp_bank_fpx_ambank.png deleted file mode 100644 index 2de2c6608ade2beadc4116eb25a2b9c0343a2eee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 585 zcmV-P0=E5$P)Px%14%?dR7l5Tcq^kqQ^YW8!Kej8)q+onX+Jk_`}^$Kzn?$KLXJbL`WC-}X++wV(P zuqya3`e+=-yB9sec|k#H9eJ9nB6D3vjs|832RjQ%vH&zkhKl z02+eb0${kKJLlemAFJ2>K6e34{M)oyz|a6GxO?yC*6qMJKvRGm9|#M8v5Ktd`>eUZ z$b?9J&dmGw?;pYwFJ68rtNv161Jx_9{(Zq>WWB&R$6^66%^=+V@DWfOvQK|(*oo;%} zzpvdux1h8V#e%?aGzGt}UPFZ8>o-^|0OlrSBY>d{mjVU|ehWSql%gc0!$+}L0L-gs ziQ(tYJztyKzb{=0Of6U~_>`3XrM?9irDz&K*&a(iP|^bCRqWa4=`*Yr0249R438*O z&@vjZB>4CJ2MHFeT8o+0frj8Ki#~=#0rM(m0YHoeK#f4{giF(RI>x}f`uF(@gaxT%ux$QEkH*A X_4SPVFc&W200000NkvXXu0mjfm5~uB diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_ambank.imageset/stp_bank_fpx_ambank@2x.png b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_ambank.imageset/stp_bank_fpx_ambank@2x.png deleted file mode 100644 index 6c152301352df0d1f2bef4e14a035aad2fce504a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1097 zcmV-P1h)H$P)00001b5ch_0Itp) z=>Px(14%?dRA}Dqnfpr=Q547hLwZ=`BTKFD5haR6Wkgn>{*aOuYVb3cV=fhOQw~3@7$Snjp$zH$Gzv?&%O7Y z^F3#Mm^q97>CcA(Pyh-*0Vn_kpa2wr0#E=7FlzvYwHwXnN^DKdQg6S5*y% zDODti+=BGJ+qflhW&niTql(?`)IRJjt!!unSP&o9>zJqF@C{+ z%z{UP--P(!k?Uv%2H|J$M- zWkXy%$^t%PfP^6e0G)#};rRNE4O)%~YUYws%npDMJOQVaLLwY2i;QMX%|rm8(vZi0 zpn--7Fsv3MttW0K=wjnD~M6KzCBYFBo6= zfoiZ;RKj}9Jbzc{3=W5rlRppJTiZ1NELc1he3yn<%E}d4#w`jSJT3hrwGjRlP2Gl( zhkZ|~AWZC$gAm*TqQmww-IGHNI+1~)jEyHHqHVSYBjgDf{ zdjPH$f##CZHxR0FF9IYclbU_o_N&8asEI*ZVUpVH0LUYwunqlP2`(}k{OoT5NIiYr z${3FuTmB)ohNq-=J#zrAR)AWgQbTKz-;s`y*?IsHwj&R|Z-7L2Yj5t(^@Cgpl_4Z! z_h(k$;0XX^6|wFypSk}>e)ML0-8ay%As+4ow7a?Jv?)8+)intY|EWaw2zkfdelTk) zLM)2};b}fqEF3=OY7Ri1IoV64{|`_A3P1rU00p1`6o3Ly017|>{tJNb%k?w;VR*%O P00000NkvXXu0mjf&eZBZ diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_ambank.imageset/stp_bank_fpx_ambank@3x.png b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_ambank.imageset/stp_bank_fpx_ambank@3x.png deleted file mode 100644 index 3bb86b8d8173d701cd76df942f18f2e8db778d60..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1638 zcmV-s2ATPZP)Px*AW1|)RCwC$oB3}QRTRhjhbTnt61q|#2-pY+E`SCwEC#SNq%8_o(1H{qn5c29 z1*(ERdvX{W+|$DB5s*NDlD=j$;Bzu&-cS)M*|Qy{(k+!cOeg&Qnn|29QX$x24t>} z5BrhJnCvYe->f-C_qC8`O+WWl|GoAdB&}IzS(fYL8&|vdnU8q|2=yw+x)A?6JvCxoy3QX3YHy;qOFWuFF52oCP+~fBBw_Nt;LpDpt!fBx1Z40T4u?)U)>V`rj<(r%WFhXH25+iA73zrKRh1n@H2RlT?WsHD8Ii(E_$b0bD%cN##?Ro~8 zg8c2mG8qAp>s25X(=H%TQc7yt-r3FoNLa9hTn1qT1gblcnJ`Vb$f*U%m3gFZc;5jw zIT#*{$ffS+WCR2`2_gg3cb#DYzPSrXZ{oUoHnr5eaf9du2NXs?kW?X>K$ckm&7MmN zsJ?*>kR^&lFW4ur9 zTTkt&vqke%Y90uW{Ir=7O@mrlMF;52msCLpWVET?t0TEX*;_#;1_`3P_0=JB2Jq-m zvj96koY?UK5Qs$PHM+!>4k> z_DM*C00(MHppXITp5Yy;M~*4G%fYV0LxV>?z;x0B5b=|AdE0A)C-T4h9()}G#V2s9 z!byjM8|j6Ygr~Bhpb0;R!tccp5CTF#2nag@LO=)z0U;m+gn$qb0>X}f5D)@FKnMr{ kAs_^V9RVRA1Qgx=H;60jwuTvY761SM07*qoM6N<$g8Ay{y8r+H diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bank_islam.imageset/Contents.json b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bank_islam.imageset/Contents.json deleted file mode 100644 index 4749fb7c0bb..00000000000 --- a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bank_islam.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "filename" : "stp_bank_fpx_bank_islam.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "stp_bank_fpx_bank_islam@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "stp_bank_fpx_bank_islam@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bank_islam.imageset/stp_bank_fpx_bank_islam.png b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bank_islam.imageset/stp_bank_fpx_bank_islam.png deleted file mode 100644 index ccff189ddf3f950bb8060828d6e8e95b09a49da1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 463 zcmV;=0WkiFP)Px$iAh93R7l5TIL=;7Q^YW8!Kei^wcxBu^WCh~_wv?W51f0=ch&{N?sMv`XA~Px z@RU(z0axj*xFzp)Tzgo(<&0bdm3?s8cH*}iFQ0VnJ;7g2{UEwuwEoYh?^iu%&?FA- zX0H18=kImj*))mdvr0{Wzx{f-;3Tb5(er6X{{R1fUb~%E7JR+>{MVZ=G|UHozWn%p z`!x+M_OP2jW3qBsXM=ejBmZ?Y22hS!R z0NU}mWhYfkKd0G-Zovue(s$dh0quCyu$>aqPl?yu2%d+dEaEJAG4m+UjyLNs0<#_& zre8Ge1(pZ|O4DmzGrrw?2~4<;+jpN;Cf1sB8m*7&x8Dp~KvaDI46d6|i#{B<4J@7B z@4WG#Y||x+{u8|D)c{cBqDjyFl8rBB9Rrf5M5;)x(ay*>+=^fFa_$LW0{ijs-OuMA zzg&F!<=o>>$M3)2asBPa%fLDVXg8j;H(KeBS}+7G002(UQ|rM{NnZc}002ovPDHLk FV1g`9-}V3i diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bank_islam.imageset/stp_bank_fpx_bank_islam@2x.png b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bank_islam.imageset/stp_bank_fpx_bank_islam@2x.png deleted file mode 100644 index d17971a24b71f436fd3fe17a4410c51a368b6595..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 992 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%0DrJI zmw4U>020=_1fbF?0?n-iSm06W8tg=XrtTrI-Rl6#EhLcW8ZPmy?+|#^-T+Z;2GHHN z0d_cvx`tUFV7?0oyyQlJQkw%LL{hm_xvdC1}KEg#`ekJVIR^j7^(1ZCV5WLSU-tu~;m2#J>V08(DZ6 z8HNDtF{X)HT@iS`+xY=WQd9;bpZU(98cA2Qb<5np0P! zPx%4M{{nR7l5T5GdS9Q^YW8!H}_FYrgA)e04aQRuGd_P=zdVI^RsPa5I?}#1}Rq zn{_>3*SKK8#e5@V!K8wEGJPOZxbbYh39?zG1x1YoS;!*$^6iBRx07i>b3q2OS;z7% z4GS0D%GX8~3@qp&GY)`e-O1NNHY>QGYes$~vIxXaWLmJSAOP8*)dfB_g|pC12cm2F zdMX90NVXuLpaV+$TZiE|mJ6{`^ z8MhT6io(Q#2Exe{Sh@kT7%p@pUl-ZQ%M1J+3#UWad-5I73MK3oC>E~0oNtIHpwJMo z{Fqq)DnGmmCJ>v^(hF*cx8Qibg;Bwx`2`^)Ka1*U8kS^Tl hU(h?+@EX(>004_TDX#hfkgEUy002ovPDHLkV1jry`V9a8 diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bank_rakyat.imageset/stp_bank_fpx_bank_rakyat@2x.png b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bank_rakyat.imageset/stp_bank_fpx_bank_rakyat@2x.png deleted file mode 100644 index 8fe59be10c8068d95923500e17c9dea79ee3d603..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1098 zcmV-Q1hxB#P)00001b5ch_0Itp) z=>Px(1W80eRA}DqT4_%cVG!mgcxzNXi1C1;A_x?N0SzQ7A|{9+7`z4Xm>E<&5dje~ z9`!&8;Sdv%GvHCd7){iO8a2kC##?`iLorP)bauP#c5SlBd}z9pedl@KnR#aB-HjnUrNcLxtC|Lg< zqC=@?A>H@^;ey&l*l5fN6ytt*`*&a|tF>UJpz{SHXH$m(0A^9gCzvl-_7IkiqrMcp zB7;1JdyI*JTF8?vOQp-K)(5GA&O3;iPPYvJkVMyH>l-1P)$*uHRx7|`24tbJ)ZdRO zqFY-cuyr!oUxHOodkTpY=)M5}wqTjOuSan&tL;+?@qDZ>fCoacmmOCy>lMULp}RAv z`vWYH0W?9D0RXD7KsGCvs)m>gw#sV5!Z|9S0HUcyrlek6&T5Lx<&+1wj3X*=0NQc2 zV9hU>n?MbU%;hGV@kD?CWa1gw6q}$q*SW)3BUm?=Hxw6Y`95Ym^+e4y2)=y#=4bg^CWBVtX#dSOsO6L+Nxpede zWPk1MRkvM&k9IECe&f{k1KaVh(r;&axr{zA_ z7vX4TZwYf5z@(AQ|NQ`u7`{V#tu8V`W`m_e65rUzC8-=_wJbksSE zw_-!^0dQUrdX+l=ua7+vseTZn*qws-Yn51aWsmu}jS0X6U;;1!m;gq|ABs_?zf>Wu QMF0Q*07*qoM6N<$f|TRz1^@s6 diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bank_rakyat.imageset/stp_bank_fpx_bank_rakyat@3x.png b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bank_rakyat.imageset/stp_bank_fpx_bank_rakyat@3x.png deleted file mode 100644 index 00d9c0f404531fe92db403d7f279428efd66bc13..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1583 zcmV+~2GIG5P)Px)=}AOERCwC$T>EcTMG)?vprY2O^^u?;uS$!yMg+lBMOzBiDkNCYmNtMgGbjqa zkc#D@t)&_?L`vlmpr}w45PV0Y_=A8N1;y8&;^#f~SlWAUclMsW_nflHgtX;McK17b zX1;ms7F{4my=0Lh4}k~B1LOhn0C|8sKpr3ukQWb-2gn2D0rCKOfDGh9`RFiL{Y_)c zWi?ZvyO(Nzr*Y=ez^%yxXpyW{p>v!nFOv_TSi>DE#ZUS6i{wbc04kBb6I8BR=R8>t zMJ)9*nyyl;kyn%ViM_-vszn~4S%KnWeom#hpR1E+gUWcvA9REHBLAYXm9hB7p z1`xiHGc-{J(7nGF{%VV}^qS<4%#D zxC8W#lD~w}la?8#6$E{;2B@AlsMd3uCSEVSfo?C=dtX7z84A z%+R&VcLEUd$6ESZoT9%L%+N60jS)b|GiV)99dEK`hOS+H^Z;$62kjE0m&^Nh%rLub zq{bKlRK>4r{V~`;j?8e_A@YAY!BQbha zzkyiCEvKl=Tu>2IjWt`^9Rh@G4jj#}f(2{e?OcAvZr)3kFT>j98v!&`wmRDUU(r;% z{1!gv&uN-!tYua%-}Dp9F*wR1%jGF8G{FzZ$!cBx)q0n23eafo{e>pE00^}mbE<+T zck!I?SN!bSa-RvUjfji`odPU*$LF3gDC$b zm4}6$Hf~mpwTEjRx_QI|1*9tIVi@|dSR^e~E?>=qv{kC8<~^U=(l#|fTKHLaF25)b zc|vU|b*P|w>N~0!^n4%R9r`tG4#3>y+c0U^R7aaA)4Vf$c7H@Xs@@)Wuuf+gv zT>j*t^G@YY(sT3^1FZE9s&nD;En_jfYDb%B11%mjRyWm~JYOn1RRP*Dn&A*23#M-< z;5Fz%3kSMWUK^GoAjuy_yo&Zk?r zn}_Tnrp*SGZcv19(iyQKnFhl%-fXIbl87kwoo|}Uy-Njv5 z9y>Fj0GAJd@Wwu-8IC-fHlVAJ|2~`^zCY7rpj7!zx!$4dk8&pm`?)pxug<2UPN45rjdONRb$Bd;k;(jMuwpQ$ts0AY`mr24P$@5ysdgxDQyiOh>3 za~hLP)YfmUv0n!My_!1j|>^It?>)9%`&`R{YQk zPVU9A!wi*DBzDEZjMJ4iT3X=k_b?4Ctxw~UG&50!CJYoR?{mazQ7U4mS zWZ(X>iaC2@==ly1n)6|aO=`2}@BKm5Ll`MKZT$sH=Qj5910gy{NR7(vGMo_z&{)|U z<`2;0;jidQBg{_%owvEp-(i+9+l!Ou!BKk;P{v!W{4IF?nm`Yb2gn2D0rKJj@&I{& hJU|{G573B_e*o2fcQdqz1L*(&002ovPDHLkV1jRf{D=Sm diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bsn.imageset/Contents.json b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bsn.imageset/Contents.json deleted file mode 100644 index 9f546f444f2..00000000000 --- a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bsn.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "filename" : "stp_bank_fpx_bsn.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "stp_bank_fpx_bsn@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "stp_bank_fpx_bsn@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bsn.imageset/stp_bank_fpx_bsn.png b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bsn.imageset/stp_bank_fpx_bsn.png deleted file mode 100644 index 686dc52b64aaad79e51df5df50b158846ab0cf6a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 885 zcmV-*1B(2KP)Px&FG)l}R7l6|R!L}6Q53CKaUp_eoe-Q5v0_((f^Ni(A_}62A_xlNu(7&uA*kR& zMZ_vN(N=4lCQX~PP17Oilr~M;v^HroHAyqiX~v(qP3Xqse_JX3n5+~oA^+ub&wb~f zb8pI4)v`+(W&aXDMH7EA6fwjTmAsyk09+ZCce%V@=WWlF+F}B%u4R9in^y$GmxpBL zL@J!io$iy|kSew}w-*QCs6dRoPn4Ptr{|`0vcYTvQDTo@8Hp7EU~?mHM{|cQl@2ZC zz8EdnM<(h`R$Stf!E8yU{ubbT|7awan@=S7bA=~_1FA^u(bO!;m-rW6spn3155Aby zS1VM71AI1EYIG*qLI{Q9@$s}eu(*_7UM4C6X>E45HWokCGgKfz6~7ntN&~^!D7B@D zk4qrCil%=3H!jYR-J8uGT2ZyX2Pm)OywMuiRwwe}@qt1G747B-0D!6wwsniWf#bpf z)P8kXes6qwQzMTVz&Y`#G8|=D9bCI>O&td(t#%j7;s5|zg2I7;!wn6szU(5*!Ld1+ z0UT%*I#OxqGV9DoY}|if{*}!fDiD_o)!U6seB%vc!x1X$a0w9i|^~|Ti$Ao zP<@}rkL<>H0w>RBbV!ZDuSv$ADm9QYGXQwXmC1CwedRPiL_(x|O^iZ6K;SV!Kh9Bv zGo8V8_qKE~06_M;@*hYC$)6EP$RVg87&v_Imud2U>MoHpKwo(x7a}7XbBV zMI%U8qcg6p=iFDQ2mpS)H8us(#sVSm0})RI!&_PH3;;0TL|%U^pXWK;{oY^HtD}^N z{(`{$-sw%igB9??YmEW$%zCi#ds{S@$E|0gv7PLWi-Thr2^c{H0OiAjun0y4-{D3} zE(}N+I~hYCrUe^NJxG9N5Ci~WO{V6k1UU3$vM_TMt+zs^={8n73V*LR!C&@Nnq)U6 zk{DBv6XxBKPEjRoy2AGX78yi>0SE0PJL&~#@WdbPH3lp54lP^^*HSJ0YFei9(gA!l zn2AP91)!(mq{%Bxp27ik(aV4YS#U)LfUV$LcpDVK9RL5D7BPMTA$JrrEco7U00000 LNkvXXu0mjfwgrk5 diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bsn.imageset/stp_bank_fpx_bsn@2x.png b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bsn.imageset/stp_bank_fpx_bsn@2x.png deleted file mode 100644 index aea604cb4990c7865538a8315fd58d8ea2146fa4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1874 zcmV-Y2d(&tP)00001b5ch_0Itp) z=>Px+3`s;mRA}Dqns;d3RTRf-#VsmY_ZAha78OMWsZy;29MC$d;shsZYu(hXhzpC< zQQLIbq}hA#(d@jJm%aDiyGfI#|M7>idwJ)3&-$M8%d!)8 z?00Kf<^kXV-~r$Pa1{B%TGBXnuxD~Ipt0rreZg)9;H|8JgGY`iiEZn2GXUvbJ?Qai_0q0T4&8 zA02xy$4cg5{d{UR`vpv=LbSJqfI7SCR7_bG+qB&1`glVj1B8KmFrmHkv|av74dB_7EWW#Kd;)FW&n;xVr?x?z zUh5yp4oVl=LxL=%PS4yO06}82d}w&su*|0g#Y+tUw-%p%H6t&grJZ$JXOI4XrEfqF ziR-j7e0M~GyQQl^}4Fnmk|N~b#)fLw}iwl9f0%x4f>>@ zhzou&CPm+WEIu7=$TpA0r}3-eaL6+$S*l?7Pfd}s?hKFr%uQI+ z!4yO`<`(LwUmJXZ^n%B)42)8bK_$pDLXCbYsnqi(6qSTaDD!7uO3yJJz>eyANuBX+ zoh-Oc45CiaEULAGeJGG_f$wZ(dATbdaG3jch^4^BR*qn=SNewkQ#JFK{Tf=#1pozT(qaILF9}C(ov**xClszP4x`Ij zE#hf+ek-j~l~@-lwCPz0C;1@H_G59y>c~X3dFlSpXv6zqov&o%-V>Rqt3`mSC#e-2KT4p3ehaCy>rmc^N?+Z_hX!Jqh?DQ*qmph zYm?Bw$}b!buel^HVxvbE`Dcqy&m^mN_J159FfEXl_>zI zJA4Oyt<~T;^e*$Zwm6sr09-{{d&=DUIbM#rRPT>$Evq&QfP@_>kNZ@>=S zgHWxogTs@T_=KtsZjC_@@h-Cf2#3MS0Y=xW1cN-4oT)!aTAT~u!+e|m4AmN2(cCCE z+iaN5L;z1GXDUOpcq20(QXOd|AB4=PdsOA@5=$MBE}kUDSjB25+td)fSwlEAF$+Pw zC}E+^ZClH#ZV!u7y=Cv@jCTP>4RLeqaVbKrfJXtc-=6+!Mn-82mK)6-)DSY;IzF+8 z&St@N0A?orlvFP0F}|yM15yp1fKKJJIWsMb+%$!P=ocD78^BCJoaaLCkfmUwXYC1) zY)Jhd)l5HcS#=Pq^^0jaicoAcdNIA&nO+B^6!2wrqhpw!pcLnpFUG}J1;@asWrpP- zTshUsp`yzXML>pm+pFqK2e2|ITGILJnfVDu{)XNGhQWzfb^R7gF}Z~lq{drHm|37P zjEKxbGC0Z0SN;^HBlOoLX2`f@DLOJDSg8e)TSH^FSJmmdl5H{3vE3=FyZ0LZ2wBtO z2ulxH)U<2C0O+lLC@NxVzC&JloZ$-7X(c!SeF99A^ddWYKM-n< zPHHwWKm|Bn+MD>2ug2)Jj@Hh*!CT5)jSDT5;=2R@oeTY3Qt5sGgrAB~q}>d_3Omo4 zcRK9`03L};bzpLC27r0GLm@j?8$-AO0QpZ3UDhvrZhA1Hc2o17IQYA3t4VPAoEO3jhEB M07*qoM6N<$f{#RaRsaA1 diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bsn.imageset/stp_bank_fpx_bsn@3x.png b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_bsn.imageset/stp_bank_fpx_bsn@3x.png deleted file mode 100644 index e9365facc6c0acbfdfbe1b5b423018c423f107a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2235 zcmV;s2t@aZP)kOT!v*F~g*Mvs|TB=kJH!h`ufrB?`FcuC#kZn-{R}|`04lf zH?O$Z@bSy)>~6-)wBqG7uD9*^`QP*O@%s8TueZYz`fWiH((dn$(%0kfAEmE8vbqzXs(j1Pui)b_t+he3yUgqDO}M{o#mlbW;vA%|yX59ty~N@4 z^_11wddkqc~YQ)Mwvbrg$vZUMJ z8>Fq0)Y!M<=D+6X51*-7y~OJH_%5uqeaq00)7RSZ@^Qz_Q@X;p;^kq$$D-Tb)$j0E zyu+;D;%LLk5TB`n&C*1)yd|iyA*Qf)${xi&uhfW9;L6E*V~EE z)xqZJ9i^_G+1%dp^V9C{m)6=bt+sN<%_FCqubxm?e2)r)ET3#rrh9;($;s$&yCU6PPo5P?h=Lo00pB- zL_t(|UhUS?llC>mrfIG969qkt*x15}YWr^H!1>0P?qZL>^p%#|P9S^{I=?u)5JL(~S zU``6mP`FKh=b8JX<&OlP2RNZHt8N20;(gtNB`ro1Pc+9VY;qzozR=`3z$*W#6kz2< zh08%GS+^GwQ&kO#-l9@0r2`Zu3*jaucwn1aAxn+GexOQWvK;Q$W)D=G0B;SP)*Ilv zs_^&>Jj>gl^r{swM-eber+@_tk3Ys@tdbS*f>NOK>`=H%y_fUDCvJ;ZOD&d1CfQGL zJGNWZYr~fTvHP_7;R8#vVUP((D8Z=mN`Cc9bOy#0Ny;3-v?wcJEgd&^rEgfBnLFsO zzGds86uL$rrLMc&HbGY_l$Ovei?;!Iq|8nAg5HZ}_~Gu-h-G9~Qf&@0g7(qE(?u9o27`Y&S~a zf>%0+B~?=YACSLg^4Qt1p-7=wlm%RQPR2gqfOG>OUs6#85!)pt{CJ~oR6g;5SB^be zhh=@dj9I{9Z3KvwMo;6Gk7XQd1UQrv$`?vLuuF!21aw42nSk6`5c!a7jTl?y(1XB8 z?2wKaqRv-tQIP`a3!H-jb^Cd>W%}ZvnpY-~b&r6Ch=gjOk_3$#Q5c zmXEyZ_AWsKbJzNSl2<0lk~}K|5(mkV3D~}^pwo2Ql?JfzRoVW5an|W+wEV*cxGPRU zyZB%2e%XEnERkl0=A`@hZ8MZbBV0OQKHLzF?OsvD=89A>CV7z_9 z#RPm`k_HUUA_yXL<;0>U;Ci#9Ut|N>pG#61woXa!w*z?6P8T*}iHMdn@uP3b8+>q_ zr0GY1f(Ip4W1Ff+FJqW0nY*wi@h1c2RLm@ZuFs|OF9OSc_H&)Xb}5B`+7Duqt2g!c zDg?j8C~fb=R=4$ef*5o6WA%e(f;r#slye(B5IGa0$wvSf@<=Dk+fTqK7 zS^Qs%-o$oUAxQnxkUzf`r54DzduI|ojJa(Dq-hnF+J_XnC!tFE3q1@_Jv2!ZQt-@p zO1-ccBHrH?3B~CIybTnp5(>;j&Qz~#j=)w_M!@kQKoanh!l4l3Z_=|EiE(T4v2^@h zVX>kOnjV+*8O9K4ZWB-ut#B!N)l8GK7+WMIzgIZSuW&n#@uu7|45L|Yc^RWcZfU`o zC%0U~SRuE3h4C-Bwli{9CR_@DNZSSF9kY zRc?5iphCG}H$iX74Tlry_8+-o!Q;ghNwXu5zBEqXEPeX)`7h127HGG)A=m%_002ov JPDHLkV1l$K!f^lq diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_cimb.imageset/Contents.json b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_cimb.imageset/Contents.json deleted file mode 100644 index aff081a9e3b..00000000000 --- a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_cimb.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "filename" : "stp_bank_fpx_cimb.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "stp_bank_fpx_cimb@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "stp_bank_fpx_cimb@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_cimb.imageset/stp_bank_fpx_cimb.png b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_cimb.imageset/stp_bank_fpx_cimb.png deleted file mode 100644 index 5c3471ca77a3d95981845e40914b432105cc5158..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 305 zcmV-10nYx3P)Px#>q$gGR7l5TsAS-vDPkD4U_@F_!_G%Ms$?YHf|Il6{wEroU%H%R3u-y|pIy8} zydCS(vPh1DUUl6cpFb06!LRS%C+eAy9LX!9;)(af>zlXgd4x$$MO29ld=`)#8L62h z=L51mTNR@g3?&NyZkx2`U>YI_00000NkvXXu0mjf D+t+`% diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_cimb.imageset/stp_bank_fpx_cimb@2x.png b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_cimb.imageset/stp_bank_fpx_cimb@2x.png deleted file mode 100644 index 85b966c3eca07a0bf0b603ab83c42b1cedde20bb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 462 zcmV;<0WtoGP)00001b5ch_0Itp) z=>Px$h)G02RA}Dq*}X~wK@s)t$Yz1UqL}zAw^oT5j2=i8=I(w zy&zh|MlFI^nL;oYqD86%EOeegnV&QF3MbqLm@heJXC|9$C!_y*5&{SyfB*srAbGl2rWN4k9$LPRrd8ya!f(#cMTQN#}vbqKW zeD(YL%PTRSLJG@Z2T)iB>wN%QhV{)D8=0yyIPS!H%HRmlQwI05kdiWZ9p*HY!S^&O zUIt$PwhWE48216$GK9I%2$mt(jqJ8o7b!z9fGNYv^-ZtSLCjsP4hK{R$J+VAXK4{J zmxUr6(9C8*tA8raR|dcxXiR3H)xXV^cZMdgCEgoO-!ZE zebKiATutTXS4Pa^Ovx?!e9cM#0R#|0009ILK!Aez0U`X;ip#c$rT_o{07*qoM6N<$ Ef`)3oG5`Po diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_cimb.imageset/stp_bank_fpx_cimb@3x.png b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_cimb.imageset/stp_bank_fpx_cimb@3x.png deleted file mode 100644 index 79eb5e52e6207848af9be103678932e76e0a6138..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 622 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1SE5RJ;(=AjKx9jP7LeL$-HD>VAAk(aSW-r z_4c;CzH_3;@sHjdUaH}@M07J<_ppe?F*ED8w7BdN5Zd@7*wAQ0m{L-r;f4^OAkJWE zq3$nb6C|WOr-~qXD++#fA2lF^MAdz>h6sCW6X>V3@i!^j2sROOag2m z0?KDrU})vpBIuoWEO_DhUG^FxFUr#Q>pl3j?keB%G!>>)>)&zQ--UXbie`Q-zEab? z?XqyZqr$-#FaJ1YEb&i!{@Q5W>7}9z{S7}GW{IAt>EXEMxGmXbbAXAA@}{X<7D)K| zd9!SiQa)9_@xDap>SIYRe>Q1pxOJa)y8o>AXouX1h@OaV%{oUrvJby0$vf!QBT+8$ zzO0xn=?I64hTGC-$wzjp=PJ0pnf>in@{>m)&ZRvu3@iI4E-p6QYgklXu)@U6&p*uc z*a^)E$0T;z&CWlfQK3_3x4*@XznWdBu_*Shyz*mF#^Sf?M;O;`b@w`)$!T@;NX9nb zxMr@8OIYT9zj7nYefhfa|kL0R5jB{O+fou+s z{Hhp+zf08@o7n0#ge-5D^{B3@XyjSaE_lMNN}@4mNjvumpQ?xkou%zSUsb(m>{;3_ z;o(=+r)-xSY8!p~%%{4{d{f&Lhp@}e%u}|{mSa-5{W236WK~hDyCfy5ywjZKAM;J} u;{RvP4~r*Y6fr@g3=~^D;3)H)Eq`Al#&6Dp^X0$<#Ng@b=d#Wzp$PyC=JnG6 diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_hong_leong_bank.imageset/Contents.json b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_hong_leong_bank.imageset/Contents.json deleted file mode 100644 index 9b2f9334427..00000000000 --- a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_hong_leong_bank.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "filename" : "stp_bank_fpx_hong_leong_bank.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "stp_bank_fpx_hong_leong_bank@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "stp_bank_fpx_hong_leong_bank@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_hong_leong_bank.imageset/stp_bank_fpx_hong_leong_bank.png b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_hong_leong_bank.imageset/stp_bank_fpx_hong_leong_bank.png deleted file mode 100644 index 46e2202e41f464d82965682e3014cbf5e157dd7d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 923 zcmV;M17!S(P)Px&RY^oaR7l5T_)lZNFp@0Tb@7R3%Z^`v{?WvOL)Ts~h0I|Hnq9f{G?gv*^!?Yv z*I)kp{byFb5oiI>n!T5wQO$z0_ui=Htg@=w^!MNY>rX!LMlS@~!5KM!-N^^kv0&Pc zYd{l$Xu_5&K<>uV4a1GJJH3modU0`(WpKLKPvdHYo$b`g-PmA~fM`)@#z4W}OR#Vmx_q2bn* zWLGuOqw2@EpCnk&zU~50Gi%t~(|2A2xl0b+ff%QpwerEM&p?ser*2O7t=%N)cTT_& zfe1Ixpe^H<}y^fZ*`;7mUH6u=Z}< z`5PRYlQ&*SHZD9Y;s!VLg1Gy==$cp4R$rR8?a%K&B&VXf6=xx?j+=Dg$Ni@_?9$*y zFO~~QaINoKb`qFH$WNv~XNUFf1zKR_)OuXP6Jqokt?)444v57-B>ND@SonMo(MPeypZ#q;Id~O z3+}Gk{})HL#%;l$zqfq~A*OuTau_HuY3cE$@}Ur;fq~X>jD?rkJ|2}V< z4{-sRk^H=C(RpDPNZ`DlyAfi&-OAnn|NWz=!g=04A5`W@dH#Cz0u*#fO%T&> zdFB6p`HmWO@}IxYI~Kf}x*EuQHDevbbf9nkefvS>R>jZzPl5gbntt6n`QMLU)Ni%` x^TAEGoC^}}->==LS00001b5ch_0Itp) z=>Px*tRgB!LySX_%Uk1{Koha`cL`gU!nsA1+;X1m_z^81Gv zf$LAJM_YvedeJ-?Q#8Z~*ac(|=wW_hc~!1~H24I%`?z1*-$FTjWgGU2!BlDj`P4R_ z1PbwQa!~_H0OrEIv7Jn=G7^9c1?UhbBR2Xxy&OWF27#TPYMA5t!{Hu zbYh(Y@#vDV*F!8w?&j5_8?s)uXh`J)F~79AY2%lEJ*hM^r<%_f$cq5f5cI6!88yTb z)W<0f5$NitmRGR|ft&`~5+c1JKxdWbp1F=!rdXz_8N3*?8fGJvE-wP{`Sn;mVf3(x z)qL=hmV3p3{g8yta2~-ZU%31n-HO zO{j_1=bwm{^p+n^(lB~2=%NYhN|yhUX|g{~e@{nCr`(ko0%?S#gMiKpHEKLTzw@y; zziC_E0lIM9nkob5=Cffe3RT$OPm+)k<9uQ%7VAsgo$v-qHIg zfiFxh#?IL)6MBM%vEdSrkKaI-E>l13j{_z4i7rTv&Ec|nq)9Y*q}CdkN^3Gx{+_pL>WQ3_faggDBbqo0;F zF~S~{Og2^uB}NCx5MJXoji(xTqiG7s?K6Grdz4tipmMznW#`E!d;MA6ERqOx-pj)3 zec1x*`tnz(>7QnB=E2*o1ZBDzIJ}p)-GU&WIQF*NL&23Ue_-8twPpoc($ zaFPiuU+Mf=AAgK=iZh zDq8uXZSQC=DF!YDuD)sBQGG0q9CM&OGDW0cO2=EyXmwcC&KJ9`xWf&)ASMO&hcZ1xF5SEb_~B9IZDq%3b}`YLKm=l&=T z9vxe;KNAS38~5S%Q`;Q!L5bdx4dCqR74bjciU`Qq&oaX;A@&1_{S01}1;Pe)9uP;O)J3AA2} zh7Lh&R~@{B@*Hycy%1zG1pRcpdz3mpd#== Z<8OBhi5jDJYEb|H002ovPDHLkV1kq+qNC+n6Yi`#aQu>gh+bwWwdZtGoWy z`9R8OoN<6SKpY?r5C@0@!~x;}ae)4}_BbTVY9WcpufzUSJ-8#9dKzqU^a1pez&O1@{hG2(CEN`hk;4O9H8HA z(GeFQf)1Egc@+&(4p2^6{kMizSVj|fzGxDNIvpT10pE5{!UBR}eATxT0g_0i=U&G5 zSYcn&D4;!GaM+o|Xs=yFrvOx1(8JV+_5q4_)s$@)<9K8ew$hanvkkVq^!;1KnZ7Cmys6K<&UeuqdBAQ;PU2DAvp z9SsnK)NhR=Hei>SJTyrupK@nlG-db8-17R4w#1;e!bUq_trIOkO#)T|f@R{vFQh%pF0K1Y-vS%$U5{ib zVhMRw%#2`kUvBRdl*uwc<#o*pC)_^QeOO%GNPFqjvsi4LU+P=%ax1Zn&>|Kc^AElC z;uW$3P;g2KC>4MH?tS)=v{wZp$?#41RG z-y2)O$&lvepIA)W@2LSvN+`yJmy};UX#Jx$0a0HHNzKkby{M{Dwg73K^F)8{s@s96 z=ds5z3}qK~0#r8$luo*}2hb17*C)?AW;AKr)=_H?j$VCr(whAALYV+$e%&9d>BQ$$ zqH~QZIMA{FelTf<9&(Dpp0mGIxw&}e{$sOpnl7^NGJFLzRF%AE50Y!lwfT|i=eloQ|qlKBp&#glJue&5NWD~RNezdYn z(%4*j^D%FjHbQ|VfWR)k=3%3S-Mzk9i284S7{b74&Ve_u7{N{4&{T5OkvB*KgMeLt z;BQXal8vtTVpA^^=nRZTt+eAGeh@!E4T+qcfWSghOR-%F7@(`7{*b}-E_!4A6{qj> z{7oK-ndN}MU>m{)3|Sd!G;B|mCUNv%a{hil-G7Bk)K3e7x-0s1kEuy-B7~T-g_MmyyO+|jjz7LVl0UZuXW&3~(5Exki z2-VL>iam^D@(0?ptlYXNXieGmiTYjI+tDLCwE4GMhCc90fzt-8Vs>cKP|$y8glWBR zAGM}UG!fn9S4`Xfh1%_Q>Or5X-xU1_A0S#)O2xD9vv>IMJ2hy@2l=1uKmjl0K(nlqz`>#bC7 z!)0y%PNMBcs&ogb?5=pMbTfgC0H0%eIx9b{1BtE~&O`3lk7S50jkHgc; zFj84yT=FbZ=3+mf(pyg%!g$yq>?Q zG^bRi0f{PV_#=tRj<3?r@AdK0J?vB7zskKAl%(lP^Y>h@aS0ZdRk5Vh5R21Pwvpn= zG&uwg&|Dt6@iC2#>BKEjKg@3@7s%XYcb*ALE7@19796-uiYh~Uw?rVMF1_kp@cOHs zQoDm3BZ&%G?$%3nw0{D$8}^R{(wtv1ns-neJv%2}&yt~w_a zRyDE`5Qv_n#GEwMTwH^>LkFr*>_pQx=^Polth>TxYB54H8ljf6FTB$AZH z>#^ZM1E(dY2z>|C7Ksy#nbADyp+0uODGCi%@P><_aDal_9niUjTeO*pd4i@EnF9n( zK77{bvZOwgkNN{L{%C#X5@f}=O;E?RDR)4bHge(V<>NPB9BBOKU52#CRM`U5l$;G9 zuyMkX53{n$tC{D{+pbDu$Pv^z z?SK7F#!low`E4EEkblOT#SjK`{46=2G!G8GBjWH?hTwKtb z7ZhM(1C^&uG?47!Kmh1jR?Szx2|#-iqynuWG6_@AU2|%aPWI|k2w9c@LNiqI?3LIc zA#-80q^I7@XyW^+R=@J6{8q z3+oP*%^=M)>{IwdHtT1Qt#e#Yy1#T3p2!?ZBZ^1A@gx`WLWFql4hk*#SY% z2U>|JorJN5;<`o-&|m*bn6u_I4N$FbloX5uL>XLbr7Db^wP)Z72Z(M>{0wLi!M|RD zX2Jo&8{{2C#^wMa#uh-Faez2L93T!52Z#g20pb90_J0NsbN@4btS0~f002ovPDHLk FV1iEx{Br;R diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_hsbc.imageset/Contents.json b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_hsbc.imageset/Contents.json deleted file mode 100644 index ba1d3ca058b..00000000000 --- a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_hsbc.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "filename" : "stp_bank_fpx_hsbc.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "stp_bank_fpx_hsbc@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "stp_bank_fpx_hsbc@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_hsbc.imageset/stp_bank_fpx_hsbc.png b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_hsbc.imageset/stp_bank_fpx_hsbc.png deleted file mode 100644 index 36da803e01e85bb4627bbd6ec64d9d7cd068fd7d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 411 zcmV;M0c8G(P)Px$RY^oaR7l5Tc%Yz1Q^YW8!KekJ7T~quvAN5enwIxHlkuQ8Rn0(U8 z%g;mN|NZ#!9|!pR>GLz6aG)}vV$v*lsA>M=;*~$|KLFXUGK>EG{flWj(BkLei9iKF zWkAJ1Eks+OZ20ZKVW1HZ3xMctV<)=lzka<;%!bGUl>tS*?LQ3ENR$PiSFMMb0=EE& zKF(c?F#Ye}SGi?yDToC?0Mtm>g7=eV!VN;U;DMt4m#w=X;%};&khQ=q00N+Pd=|Ve zu0{?A6bpbz&E)&(bMHF((TqU000@AF;I!b0lkeY;AMsgm>g>CY33x03Y6lvEFNj`5 zr~do>o4gC8;dhqiONQ_G*%&bxo+_rBtD znH?tE=DxV;z`%lm)cF)@?PDr_$LV_NrPr0&)#|@7cX)O&Ia66G*Eagk$It7#H-3NV zz2qs6lj4GUhLzFVLql7&?6@1{EY&vc)Yq#$uInJs;^ffsm07{ChWEVeCo6_!6^RS} z{61fJclxyOmTe2<7#DuvJ*2c_JHzaSj;h;NTd!b9IL7XNCF$bMYE31M#(SrpS~0LS zIUmw)h}huor^4?W!kAH6TI&-kqWPl*;X<8XRIGiGct4ZO zm!+D~-=CJa?WtJ$>`)ei?x$B)Pj)bEVfiLLE$i|EJ_h68HMb7g8l}Ac6!16HltE%b zvxa)Zva&DL%{FFC2j+h+e$R7vvBx9l#ce`g86*T;P52mgPS5Y*z9`^OA9G(U`>uCT z(U-QFEs6|mOYSnIESop8OvspFZ^AV*zPs99ub#EEc1bd@@oZqu>GzG=>Qvm&Jnd?{ z-`f}e@9g}1;8qJO16$4phK}d@4|f_fCoGDa>ZB-Kmo%I08p8%gV;z5m?^SK=2ZE?w=;;1~6sJU@=`Hm?Ybfu?V&G>dyyI!nV;8U7?!K&o< zhuzmtzdWH~Lb&v-7cbXcIyI|YT8gE;WqY*OM(Y-n4@urDQ^U(o^!wKSdByQ<{T%bJ zs+@^`t;250?LYlJf|c>F-3_PZk4rZ^-IICgq7tJ313D_0{hvX2mBrrN&gTe~DWM4fDJNAW diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_hsbc.imageset/stp_bank_fpx_hsbc@3x.png b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_hsbc.imageset/stp_bank_fpx_hsbc@3x.png deleted file mode 100644 index abae989ded38bea076820da5cb4e44af6b8dfcd7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1205 zcmV;m1WNmfP)Px(Z%IT!RCwC$+U-kIQ5*;G{*<&7l29|lOkbpBDP$2v)|*s_NFxaC0eaRVmL%D8 z66TAHAPVY*FAOxS1PLnAeCP@1Hr<>~H+AdovA);I9B#Y2ciww<2EW63(VOo1o{zid zoO{k$rCps)RiLgS0s7 zIz9Kb5C5LIc~@B-pKtQiMKpxw&?uT_9cVNyhwC3ibUzU4?DJR30a@xB{H>rlzR~_c z1Yj6wZI+|E#~(caq+PSY(e+*lotdVGfu{XHC!rG;#E#&+Cl}glgPh?&G+X=r}(1YEw6cJ~#w2-&E+mUfEP0E;W ze=AbQZ8YigiiPtC0P(-Rfnfwz5hx`KgJqQQLKp}&HT&P zR{Ro1JP@j>qT1(n2e0wWC(cOfhIk_?Q~_#I8VDUh zcjO;~OyyPB09NG{yQ&-zx`2)-Hj7=+B>EtYE-1SWnr(Zb#x(DCD>2O@yz(n)>@oNB zCgMU7u@PR4PYrB4xc-c&@u@L4KVEuJ79a!`*e#L&YaXX`9;+=;K2{Mm=3~X!_k&D_ zjs%aa%x-reB%;P=M-fY2_BYI8SeMJWCv9tKlf30x-=Nx-E8@lbR3kal@$Q3qoAzlE zHti8C^nfT1$3Fb_>yKZo9s3|s%-gK;9~>I;OEBHAb8yJdefcG99X<2E4yTKSqi4iG z7#1%t1mBoa{PIHUvq(UQ!S4Ma>w^~cuD{%V6bgg@Y~L_T%CL8I#p?nUnnnQDui)W@ zat;hFUcqa;r}!1T)0g}}Xf)EvJ#&{h^|?j(W2$$Fv#JKoq0xl82Ao@@>NVia+vy@X z-Lxkl0wN#+qDnvnL_h>YKm diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_kfh.imageset/Contents.json b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_kfh.imageset/Contents.json deleted file mode 100644 index aa870e59ef1..00000000000 --- a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_kfh.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "filename" : "stp_bank_fpx_kfh.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "stp_bank_fpx_kfh@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "stp_bank_fpx_kfh@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_kfh.imageset/stp_bank_fpx_kfh.png b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_kfh.imageset/stp_bank_fpx_kfh.png deleted file mode 100644 index bebc29a9bc093e9f0d9fe93cccc0dec769bc3d76..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1088 zcmV-G1i$-Px&`bk7VR7l6|miJE-X&8Y015T4OF&cAGR!)^~t8A<>wY`}eyswXd@jjaZ3gQcD%ZuvtCG}NhCPR6{tBM9AdXcBEO7~FM0Hn$6BiZXeS!P+EequBPUW6_xExkD`cAgc7ZWZ;k@$yV>!lB zUOAVkunG|SB3t{qa-i#q-ANuHDNx|G;QyYsLv4E`D7VRhDTLAV!zHD*VLp zi~x+fTa-fFKNsK0at9c-Ee$_=ZN%e*@@G~7#(LZTm*FpJAMLf_SKq%`kZRUEFv@fN zFgM%5*KNjlZzSi{O|`ZWr;;ji5-Y3&xTMQP?f6cH&#HolyRQi?PG|oQ- zVo#E6qTf~o4`6&5@Ne2J%gAu0io%LBR!5wSD0$3ZE5eR7ceLi$ytt@Vc6E0hO_vKV zq8$cy^aePR<|k;M9kg5Avn>o!!ICE#GH&t>(!^O*`XV)zuf1LcdE++N8J#cAO&GMrkOM@T6uqACHvF5mXdh{zUAhkd+%Hv$weP79(IX5&)+EEF2Y~jL zj<&oS-6+|*FE^S1SR8T?ONCptLF<=Y(K7Q9}OtaaI8$ zOI0<^CJvKdd^ZctAuxuz*$(?ynAmhUk@@ZRE*>L{RspufT{HLm=w1dgUBk=NJ_~cN zKgp9r`b?%@C~$`Mj6lZ;K7WTg@=WT=;NW!DJ|rKE};V$H8ff;2T@-> zTgG{B;!qSqK?m4Ho$vn-FJ`?{qWh`GcV^vo`u=U&kMb76iHAuxmKi4i0000zdX}pstpJea&^wsR(x8KX~`1G04wKSw` zSG0yyvxIQJnBej05|vbw&#@q!Uk;Q~k-OF)RQn9;OYw1$Gmr97x}n$os+!kyOb;&H&4DWGLswuv^T zZat}UnbNlV{robcYZsVUGo)fWr{!!Dv|!sFBD^zC@Vo@Tp|HKlIY?&Dpzixiet ziOQ;y&aiaBo9y=Sgvh2Oo?#G`Q?}m9rPsb)zh*=V7^xale?` z@8v9^XIr+2#pTr_onfxq#W|;NJE(GX!kn<&#_IL&xZlin!kjOnX_nBlLaTQbmsa2L z=!3_l%IDd?;?c?H*k!tqvfaqj>))>1#ACUSMyz>_%&mpUr!b>xU$~4&u6w%R%|5Ag zF{5hc^X;hEz;nTxZ8JP|FqFazMtH^;OGVRYc%tAc z$+)bgBxkRK2iC{V%-ZXPj1NVj5f5QL$@&K^EXvFp_j&9aBc9$oYu4tY-wz5i&5r*? z6vE^}&$yxwHqKuJH*zH2PhS@=3SOuxrmXlQsMV+DcIwnD`c#~ue~&fQXV7?C8)d_w7TwKYipshvMxEp=R=g^44Ka29F1e+K;_r0PialXK2Y zT=rJj;PdhY!9j5l{763>B{w!Z?W3lW8#I?`58NU7oY7PmJCw<E1}VoO-_Ldat<)u5r8p$)M!mh`}lM( zZ2uNFHWm4SnQMo+XC(emcXZw>~IQ< ze4Bg+TggZWMyv7@ER=a8PY%RhjE114bUflcGHyAXB$5?qa|G^?46F{?GfYo%H&%vL zb9hr6gm8WwF_&DEgaJNb2>k9|Ad#G|vu>g6)1=Sht65%I3SmLMZC{Ron!lJQ0%Ks) zpf#Hf25q=jYcQMru1uN41q=1CS)L;A&*6T}f5J=#z@=}PSg8b}#C`=_yBDa}>58ou z{m|&RQoTN8s+BxK)~YFKcwa7XQs`FFDa?1>GAgdv8D>cPLjHvP^T4vag0fa zOH<~Mx>nR_+y~OgrIXz3PZbV!7Z{6GI@g5*{p7?`$kVaQ-M29q2%@V(r->}g21>{U zP!miRi9=i!M*dnhHUdBlIRt82Nrv7AZYYI}@xJ#=5uz^tM)G&4xe!QMSQL^aQ5Yi8 zmB|{Y+D~Ena`;aag&ex_2izEIx@IZ1Gyz9+qELHgvR$BE?#y01m?O3u@DR3%|KV={ z84QU3n^5tURDl~fRwQ*FMMo6@%wmR6b4wxHF!yWq~B)Ve&VbEMY2@A&jIq-@6K z*8Kha9GY7lnp{Myc>DeQZoZZ}r*RpWSwX6HMyz?E)w?~ZbGYBkx8KVZmsW4Tmmr&7 z#O2j2p=TDCSNZ(-Oh)u$jhI+)GRI`M|<<)h+G`Su!_T1>Bgy5P-mznJ*^`m)`~rPsc} zX zSG0x?lv0?{v_h+Qd&Hof)48qM!>HK6$>-R;;m=#Ph*GkGN3D8!!=9?y!F0i!oYT0X z)x0mFX@JI~CZ1zZv4Ps|))^2#)`|UlFqQ)@8*%t zu;laWgvh4x`Sq*W!miuI>h|!S)Vagt)Ue#fNUeL&>fK7NeW%#JPOyNJ&#|f4!CJM5 zkj<}Fw1r~1j)lpmn$ot0$*3@+YK+XRvE0XMypz@J;MVQp<@4-=$E8oPfOx~69-CcJ zv4UZ_jmYNLg~+F1xQ*8A;b*&%kIk-q#i2;9d%oh(F{5f+wuwWlcZkZVm(a9kyODOn zoUGcz==AQ6&92nz;Ap&(-|^_-@#*IC?ZV^JW4Vu6wTC61Vr9CJ%IDeL@a9#sgh{S^ zMXY(z>fYP$o>_=ZTTvEn3`)d!b0N7TQ9gw3NEL zyHIy`clWMux9jfiZr#1Md+%QN&-Z6662xhwv^IpcuYwL6wdwnwUuxD@ZgS`q2|YY3O7D8voPAn zC*bgJ@11dI>)6&aya!>`rz>~g|K*7Dr@w`EgHGw`L`!$I@GyX=g;YfwpiyEIohuro z7Cx1QNmLzzMm}^U4c#_SdIdo0qg367CTk~A3i`)_d0p>FdR$s$b+m931}lZvwMt+Y zv>9)IeFF6d3;IOG1BN*i?#IM13jNe~i9$(r3zR@lXi{LmZ{!Bv8okT}Or#WmDD{zP zrW6if(-^k`6YTe4;CZH8YT61kQu4vm>eI%LQUN42kP8i_Iqbv8e&m+!)vWr~Jh#YAj*oDdw z@o>h=abMcAqh`m0HG6;%hNZ~BMS7c(tbxsz3{JBTlwcFPPDcBBx9%@)^JCm6`y~FTn36>53>cnqc9lD$R(v{&s*xg&O6J5R%6ec^*iIe?^oslY}z@3KKN)9fHl?= z6pZ6K`@j{HkbEivZTmvq$Ma-=s4V4la27kuN-;M_1oSWIzGeax`zb`?9EDj%wB_n_ zb>E9*FjV!FV*fdYjIQ-AVgUZdNsE*}vObHpKqQ4w>UGH-sx?2Oic9A`xxI*Ds0EH9|<8B{N&|d{Ye;&}mUjI0j!e|W~+7s&- zhyg-wlD4da_@5|j1iCo}%=t1Ll$BDxePQ~Xz;xvcTwf8;N8+0862(xchvjh!(;M49 zx)4-~E)IbRTFqG~UXy6G9Kbyy!2AJ042Qy>2)W=~=xD&{@pzfbS+k%Tou0viM0Ur45^YpO|fs~S3Pw+5~a2*tbS==+* zm(mOq+A(-LIRX0}0)`;|Tu^lQi#Z7*um-bifn?vF#;H#CrQ=x)N2Egl!kV)>V9--_YTGw-^a{H2wA=g0a|qN^bptbL^Y(o!eu+zb>zxNylupr*KWLLrVY)dKK;kG{!C3M7GDlska&vPRPnr7@g$JNbCKXFkf#8iS#+N`cE)ATK^@yV?ZN1UdSl6TCobA(0>*c vO9sI+bm8xi{I8c0o?}S1pi`$#zcl{?))B24h5I(&00000NkvXXu0mjf@Evfv diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_maybank2e.imageset/Contents.json b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_maybank2e.imageset/Contents.json deleted file mode 100644 index 1c49aa5d065..00000000000 --- a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_maybank2e.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "filename" : "stp_bank_fpx_maybank2e.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "stp_bank_fpx_maybank2e@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "stp_bank_fpx_maybank2e@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_maybank2e.imageset/stp_bank_fpx_maybank2e.png b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_maybank2e.imageset/stp_bank_fpx_maybank2e.png deleted file mode 100644 index 11be27be9276d745f0bca95cfaed12571f8d299b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1376 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 Ef?KJaJpcdz diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_maybank2u.imageset/Contents.json b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_maybank2u.imageset/Contents.json deleted file mode 100644 index 17d19707957..00000000000 --- a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_maybank2u.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "filename" : "stp_bank_fpx_maybank2u.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "stp_bank_fpx_maybank2u@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "stp_bank_fpx_maybank2u@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_maybank2u.imageset/stp_bank_fpx_maybank2u.png b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_maybank2u.imageset/stp_bank_fpx_maybank2u.png deleted file mode 100644 index 11be27be9276d745f0bca95cfaed12571f8d299b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1376 zcmV-m1)utfP)Px)8c9S!R7l6|mU~cCWf;cY8@tP8mt}WZSlDHznhcW^O(n4;NQ1l~$k3>O7Z7y} zM7(4OYA9(GiKe20f|8h+3Yd691w=(q>0VRW{X%6{niXB_cR0EMv!D*sUp4d1neTk( zobP$x_j#W8J3X#7_4rpukN*I`g;y0DGqjV!O`(Ba{d!sZ-)jvU;x%QgDSwIfqe?}$ z0A4Ru#*Fe9>~C2#O@BDg@x3yKOEt2K)v`BVQ65JG$ zwl2=nFmL+^q@e@6H)Uv^Zu+ zA~jk)Yxu$6($I|u|!4q1b(c* z@yaP_OKZHSfZZQ^$ct-n*7dJ8WN69EKEMYR4gq~EEjKj7?r~#G)P!>Py2}Uc2M_Wl z(s9E*Npay3x#4kRLd>Qb3N2LM_smr+5r%6br&%C5UDlC3>P(fL+8*>U(vD)dIV?xN=SGZhmr6*~;yB&bxfnMyz1g@@}6kLdyOrg+ z&eVXUg9dur0icnwJFz^QqDxQI!y(B=J?cqi@HPY@Q;Kjr-!UY>Yu1e-|d`jBXJn7tBV^zzl$xjkE=qFb;LO@>`q!32IieX0x8Vgyv?^Fwkx409xb z`*?HEeS%4MX1k=s+9MfJr^Xp=w?v9p!C(%bJc0l^^Ho8+61>fN&1N;-iEGYW9kh!U zn;Gp6h8=)U4=C>MZ56d|8z1gd>|5hRazsisARKyVrTB}ds4Fo_2sU=K2LPa=B|$7l z<@Q@e!Z;IKv|SOL+1pBG5DZeuPSvr9au>M52UpPt9fo-1(NO6b)Lm5bZU44F z7g-}a656rSg?KSG13A*BrbU^sH~yfxcI(IMVvVdU*Cj2%5FgPVor!Or6(FH i);No9`2XLuo8xcUTo{V*e1{YO0000Yi- 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 Ef?KJaJpcdz diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_ocbc.imageset/Contents.json b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_ocbc.imageset/Contents.json deleted file mode 100644 index 46838072a6a..00000000000 --- a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_ocbc.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "filename" : "stp_bank_fpx_ocbc.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "stp_bank_fpx_ocbc@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "stp_bank_fpx_ocbc@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_ocbc.imageset/stp_bank_fpx_ocbc.png b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_ocbc.imageset/stp_bank_fpx_ocbc.png deleted file mode 100644 index 39c40013ec5046825d7fe8090de7eddc057e0ae5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 880 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 diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_public_bank.imageset/stp_bank_fpx_public_bank@2x.png b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_public_bank.imageset/stp_bank_fpx_public_bank@2x.png deleted file mode 100644 index 844f65bee24ad5fcae740be75d092012de855890..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 927 zcmV;Q17Q4#P)00001b5ch_0Itp) z=>Px&SxH1eRA}Dqn)y!?K@`XP_b5<6qA8;OYzT;GAjoNmN6>ggO3UG2povH1G-6bY zCQ39!LzGkv;tv|6TOd7w)&%JRy|*p2+v01Qph7#{*>-o^WH$3tr*HTBY2SPE=FLjf z`wH@UNC*G{AOHk_01yBIVD6O17-pN@#n1s`Q*#ahV5$Fyp(Q5(%% zK&WQ|0o%w!^cRfHt)c;-)klLtQ)?R=$P5`Iyr>U_OlRBK|53)4HbDU_UCLNAno|Ad zrm6iLuCsAwzy`1=km|R#md;<`7BC5y;};;E`tb6_j?BY`F93_O8=*cH4lj3HVii1y zp8%f$0|2dl!5%(y~+x!U4duVL^b;=gTXCMk7`s~K)8=TOYi8qNG6nYy6J_x*=xE@T@X321c)m0^biF&ofoJt~#>St!-DF+NU}9Pmz0 zV_D@2fb-2;_5MPzqNF9B&tLKkz&SCIP@fo-w0N(phyW0AI@u_2y?YO#x!b&`*!|%n zEAz=oz5ukxD>qkH(?5Q%`ot)d!YtZ6u($|I3SR*8vU13MXa$g$5O=T+4WrH7Q&SK# zd;x?^OKg0=`k+6lIqZ*F<*rw+#Sh}Od-r$Q+D9MfSsML)=k8ziPoC!AIuK{LbsMap z$jjY@j8?0mKZPoI=G2H;D5AVyXG8;_DT*pCH8eCbJ|Bl-4hmQ(W8n_|pL5~>?DS~$ zr|TkaHp%5Ho(ip}v8` zmNKb&ak3D^fWEFiE9yl{qYPx(iAh93RCwC$+*wZ(Q4|2+{vJg@#24eUVw4b(_^MB!AaOxaLE{n;QQTM*6i`7E z;t~x}afwQBsUp~7!WOBOr7g9EZUNFxTfBtQR71<0nLE>a>zUlgY18>S%Q@$sI~v`J zBpfk@1_=-dfe;9R5D0+~2!U`Q5CS0(0wE9rMH$1nc>%9?PTn?gvmr5ohI4nx*9jRl zG$tAlMIH5x6bBm4+f7#|WYpM{2tZJsU?3oVXKT|fzJZ`R)?2p?yYd5GA5%t30YMM- zcXNxh4=Qb>VM6EbJvkp&)QCQiVK?mXY^|;GiOJ>32M}22{sUU4q4oA1)`1N91)xK+ zKYB#>QdPo86EB^~$4_)CS5d#6S?@Hn2xKVO1Jh}16Qjd|kw$%;si)6$Ny+L24euXL+YR12^4tJlOI2%z)&wHzG@MmzyI-@Mf&r>Y#L za|7h;=+LL6s-Md60p#j@uTNPWmvoNT+1E>V7cUp$>|aMqXc;9A&_7wouj0c&zaN2OWg*6*gF!(+pgHHes9DI*efwn^ zF#!||1|=VWtFtq97V@)jFQ}ZtBG5=lskHxjJ_`|%qe07+e^qr^DY=qZc6Ju@>)oF| zg>y7X1B6(z%&vfuiZs|m+ArbIb0+<7%pdOTV_$TU!7+aY;Q(bb9Uyz1MS z5p70*^-FBx#?A0<fYxg$=8o2Qs%xqL!m zhP<2(Pmg(XRkiv$oW((=%U7uBY!IcxU!WK{r>=qymyz^%#d+0qSOFr>a#%ibwp_Xn zq;lrz`6j;8SlN;**yv1|(&vt+yQepOEklju6ZJPhMx&=rbD=|XDFVodWKSY%#&Df( ziaL}Rvp|hVp2@fl{pC<3w*VLg0;HFNn$Fj+y=&G|583H2r~?}nA7NHUsU?|Y&I>e$ zWjuIDmQGifLOKdA>a|?E4l_DX#GsC{%fewsf@=&1B^6Y558?Pqm#)O$USnVylFI;y^4$y{ASLq|)ch=H%@LLdY} tAOu1n1j2zp2!ucggg^*{KnV2Tjz8xT+`BC^GH(C?002ovPDHLkV1n(TI)MNH diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_rhb.imageset/Contents.json b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_rhb.imageset/Contents.json deleted file mode 100644 index 1e7327983f4..00000000000 --- a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_rhb.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "filename" : "stp_bank_fpx_rhb.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "stp_bank_fpx_rhb@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "stp_bank_fpx_rhb@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_rhb.imageset/stp_bank_fpx_rhb.png b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_rhb.imageset/stp_bank_fpx_rhb.png deleted file mode 100644 index 7a560ebfb2159f0438c7b86e6d089b07ead0bdce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 681 zcmV;a0#^NrP)Px%V@X6oR7l5TU`XFcTQq9Hs0E`I3^xl@YxlHmyE)_FeYXk6fL!j}EiGGb8nqk% zvYq>m)^5BGQKnF}t99GWxkny`&OD8*T_AN8Q~Cy+7I;oN{`2?WGY{VX{rm6#|Nmy~ z2TRsm0W#(teaM-!`R$jVK(=)GPMfa7-+unN_UzM#Z@+*dK2uIWw2LJ#Kj|7W)h`F# z4hY4VzVZI+ukXM9V#(Ze@AVg;&g4bs*Pnj|WK7(97wC!qV8EZh_1wb`Ko^J>ZwGo5 zC{nieD%|w!e*TYGG2fF!JD@Q z$awSlCs51b+i!qulhy;srem=KLb>!G1*+b2{grVm$g#Vwz69Fz_2+LOJ95sM=B+n@ zjN^CT!o70#;d>yt_{1aL)YWLFLr|Z80g45gOD{rn{{Hh97znJHo21HiKtvwD`vwej zAY;ji$KhbFY`OG8t^(xan=d{C^)?2UqM81}!PPNlGKvMgyYE1P2uK2h*sx{4ZTDdy z`_JEhK+6u^0)bGiRVA`RbqwbkpG$IQAX^raTB+ zr*R)JhP4~^0kZ-`M5u6^aM3m(0~l`Z6OREi9WaJQ3%gMZMlBe%fO-f35Q;h$laL(m P00000NkvXXu0mjfddo8XP)00001b5ch_0Itp) z=>Px(%}GQ-RA}DqmuYNNRTRfd1jSv9Chi|xJ}97m!1Y5vSmP2EMT{|MfM855lxopJ z6;Y5x+Ni{0S&ATFfEuEOu8b{hnJI0j3oTt~r|Wc`(ssH`+i5!s{$KC(aJ_Hly@`p5 zntO9Uy!U_i-FJTPo^$TGAtB+Z|LraTB!C2v01`j~NB{{S0VIF~kN^@u0!V=WCBU5U z)Ca#f6SlMP-q=6XPjB0B`o)BzTRzU@#oIqo#G60L^gG)_Th6@lWAVbRd2=Ju{#k$< zqcY+Q7KhVydA7A&8VmilfCfCZ!#FrL1-+@yacyKe6Q7MY4UJDjY_vJ9S(i?OasAoJ z`r(Obnhn>h4pnGa7WUq*`5&bGO@N2L%IzI?URE`a$NSj!d^V=8dzAE76U|Jt*c>Ec z9hi7WjG>X!`S$L?a=!+wcqh&t8kX|%YJCQ^bZ3mgIylZgkb0r_{a-4_Cavb4}d#p0ezAe3hB@i+K4Iu&1P}@gJS^E%sH^1S^LKQYE ztGAf@*%ekFKvs>7Qo@rvjKNs1#UR}CZoq8i*91$!90RG7#9zz0)C+Z_s6+T2Xy4~F z?=!a1ZOm`A!CN1YK>*<0Al_hsvftEB0ryOt2?|`<<@V69BvTtUJES0fp|+%6R7XX} z;Kby#n_Xjudp0SXT1&14y9=>5x9 z#hlw{86X9lBa{WvSwcn*o}p50y#R1sWCpnb(g=c#K8C%FtvGtbu`1qH6h9C*_)Dxk zv)lQ^lzWaU%ayj-`LAm;__tmF;FCsjX%~6F5Uk&2H>r1`-KxZT{rU`2YP(0&S#HnS zR>7J;3<0ed0G917q1m@*HsaUv}!c;=WG_ruImeA6VISy zy#T=b49hvFEcoa|DF#=DLz5DI^a6Vq#Wsm+jwp39>gPZ?3cK=6{tgTRgTD0w0Bxn2 z)ix4eN+@QLjZztIeb+_q=`3u+g#b#p+dSr4nvKEa230_=#yowGtSR8D<)W1x- zhyojD19>Kv01`j~NB{{S0VIF~kN^@u0!RP}AOR$R1o#*9KLP$??h#&3x48fS002ov JPDHLkV1ny~X)OQ% diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_rhb.imageset/stp_bank_fpx_rhb@3x.png b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_rhb.imageset/stp_bank_fpx_rhb@3x.png deleted file mode 100644 index 988620427f447f30de2a6577c9eaa2c7596679a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1876 zcmY+Fc{Ce{7RH02QClpvM?*T6+KQl)QbcUEuSFwhQlwG_(N0yWwrpwU%v-V4pu_PWsd^@03jP|qzh;J z{b(RJXI|T%3FR!V2p1~^fYv9!1OOZpwn3V?{WiW@a1(#RLY~=nAM!>Iy=jLme*;yf zIO_z#K;j@IFHBUVVv?JC0SL^BgWOY6lK_F9i-Oo@A{T5gr7CO$**c~U#=AsqmC-9z zZbzb3wilaTgicp0=N&3F#0e$xLd77 zRwDOkvS>^W2+ENH72Kk~Tw*v^*WlPKD^&*AMHYUy#KJkyZI`S@x^j_bbHb62xX%(T z92%Y&9+@0`sP+d6d$D!O_8_e_aP0HZPaw(owCJfieS@avEn>6$RAjvCX|UevGj^WR$E?lGRWSuq}yvK-lp|4s_*3I6a4y|GcYPhYLo zJGG$IB#rg!kacd#=pen%0o8H_22F?;)vaH7X(O8En5I>;pXneq+W89e=?RQ~u^cmjIjFU!U{uz-v(|mYh?eCWZ?&mS z$-;Xr))O4+?Jn{#?gV_a=- z5ybESyZUp9`Q3}~bRU`!tRC64w@M+PlB0yS;z)_thlx->Uu&FM0#}(rl9*x})mhDG zE<;{UKBk1Vfwpo6#L+1kTEhw?&mPm=v~rajlL(1i?O71{pmDrIA3CBC3R|GDQ&i8k^h%PZM?c1$g( zUM%CP%zC?{>rWA{QE$ShW)V*=FCd5kBW6!%CN8SOU*ZYJq;fAQK2895M;!jHrua;R zfafHw%D(9rUXjiaS9f)t-eEVWl9i77-Q*McFo?u)!>(7%9!Su~^~db7unE1AeXRh8 zAev+x@7+)I($ql9fIC4u$!rhnX?#!rDHMrE+ietgdQg?>Fc$WZTeeyGLwlQyfqYBq zkr-Gc`5j>3UGU6uYcAKtN<}9qNehF(RTX>8M@O19vnNs}Ps*1j#+!%O5fM>OUDvt? zcs?~`rn0$s4p+I`aTIY2m|$s~5gOe#?HfwyAy;N?I~H24Z=Jps-I@x zUNfW>6AZq{uy9`$UfhWSoph9I%#&^Rst_HqUwm5pc1=BUqqd|Z;!QbC;2*!>fLW*vAL;=kcyabq^P?9&K?mv zYZf0CJKo#X0ohJ>v|KG_LF#)ii}`;>6{%J{4(x<5ae<` zd9=AK5p2a;Ed|4(g5lY}o>}nJ7{iBB`~vhs;>e#Ar}y_USOd7RbzZfM(W%t@A9@JrySS;X%JdYj^`$lF~Fcp-HA0B z)okF^^Pc(mvw{!Q#ca!>!$OJ}W*w&UIiATHX;t6_;jiWCJ1&PvGTQ37Sf|H0>6_wr z%W>XqW^3=ZiT0TvOnIjFH(CBhM_Azh!G4(42gP6@XJV77j=n H!Y}SG*Ee-N diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_standard_chartered.imageset/Contents.json b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_standard_chartered.imageset/Contents.json deleted file mode 100644 index 4ecaa2a848c..00000000000 --- a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_standard_chartered.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "filename" : "stp_bank_fpx_standard_chartered.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "stp_bank_fpx_standard_chartered@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "stp_bank_fpx_standard_chartered@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_standard_chartered.imageset/stp_bank_fpx_standard_chartered.png b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_standard_chartered.imageset/stp_bank_fpx_standard_chartered.png deleted file mode 100644 index db55641e80a6d3fbb6762a646c8726087a7571d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 890 zcmV-=1BLvFP)Px&G)Y83R7l6wmg`HCQ5?tZP4o{``O$39;UPKqDgaUgZXc4lO zmu`wtB%1ibrJK6V={9%uGMmQcrCoiVZR+OSo@cJPi*rtQw?l{Km}~T`1$Fqo80_%< zJm+^gzmv21msife1&D2K%1y3Lxj7VxWgmcf)|(`APkPlrjA?5&0fBIoqr#uEG|(N0 z%$bR03!t)k>Ue0}8me{x$-)VoYr(cLQ<60lS8e-K0AlxEYnP>T@0wVQCIrannzOCq zgaLUC;#@N48C#oZ{gRKOHg9~7YuzcF<#j6CyVM=vHvxbW^Xw?61D$y{{6?gM?!5{O zWE*Y>MuL-8IaNgg?oiX%1OY(57KZ?+^G%XhVx2D#iN}Pg?T%YReKAW3046Q2L;%zt z5}PbS@D;BDpQ3AMNdS|3o>&e}HV$rQ0PU*mz1K6PS#lYcb!?Oc-DQ?>!b!Gx{0Hm! zDH%`&tx~bUj(II+&q9WMun~?_i;>+Vb{foydQqPi%MhSgM!(`y%WLjdnepgrVH(VB z+GHdeBL?7GrDbE)9U#Oiio`T*_bu^tOBY){|B6vB(GvhTHe5%TMW@-ZRI9)VrK<236M+X5&+PQyaV)npaQ}DZiLaPq)=6#W}RE#sI+*hxZ3?SyhKJQ z68&93i=GYvP?rRE+h(XMK_C2g(dBo=v;4T4x3a**}AR3G23rn{%fDSP(myVO=4h^{VTBSw+sNo_PnnzQ{ zCtVeRJQs-{rer`}87kviMlp|n+U$U#L0)UjWzC&jAZiL|mchK87L&@vE8V3}L9}u}JRs+wu$kr$p=#Yd_ z9ACb$zggFPid_N#phbu!*%t^8qIU3t18tT5q38|y9#1vSuUh_x$8QGfI}$Y~`Q7a) Q2LJ#707*qoM6N<$f>BzMPXGV_ diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_standard_chartered.imageset/stp_bank_fpx_standard_chartered@2x.png b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_standard_chartered.imageset/stp_bank_fpx_standard_chartered@2x.png deleted file mode 100644 index 134a74391b8c7f4233f0291370e5316deb8b831a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1807 zcmV+q2k`ibP)00001b5ch_0Itp) z=>Px*$w@>(RA}DqntM!BcNE9nE7_7|{d{hOhk}mD$|(h6bX-lErn8`ypcEZD1DdG+R_KmLLbm~>21r-`ZIUca_jA_ zw?IPk{ezI+%lUB6>vzswF}K7&E0zJ40Tw^Nl+(u=G-%AOr3ZioLk%+1iAu>)w&-}J zSTZ)VlmHY)M{fNvn2zfdS32$XF9CoVkH6@SHqvxlT;cel1_*}cI+W)0D#^UogU<5g zix)s^abIj6Au=7;Y#_Mk0Nk^Ia=sz0Li|wcK>>J7iwdBB)OxyFM#gkdZoOg=xsY+j zd!_9zNz;)at1cD*p3HcRoX$7U*lMWx@Ju#2l?@kiH zcZ~kWer0CV%E((^*sFE=FoMh*l$bUD~bgLNTs48yKja@fKX`e#Zz1a@LXC&PMtiq^~^!N%NLkG^ZH%wqqlL>aW$&y zXawlen345JFQixH+~4isy3jN-YH<6)WeVyV%7U*yb%WRsFIaS0jgLAq%zT>w8-48;aOdh#%9M?p`o)`G4Yvl}>a zHc9Il!ot~rk1l{_;~&1?V&M(3?hI%BYTu0rc9L+6(PU zN4St#J(g}=C;Xe|wI1Rd3;O9TWK5yq@k6Y589*zKRUYCBb+-Td1uy0i8i!btvPkRe zm9@TjoQHZVk=-&(0RRt=orS%9IxE~K5DKU)%IaYbQ^HVMD7M)YyV1->`O`<(lrcab zUTS5F$541cnp%K%S~=zX^zZgW7(lDCYX9m~C3472^hDOFF>kxs{lsBbA{eh`))WnD zlMR4{0?-#gV*@{{EiNb#&!$x*g0ba#C!92r1R%63as^k51O<>uL`H!Z^TIEuJ^pj8 zikJVWrp)j`UW?T|OFKZNw)xHSEyc1j06=1hih6Wi(_R}ICzkMa>&`b(W7v4LgI<8< z@!nO;ji53)3kSf}bhiN-2lUN$_0;G2T@;E2WGA`+9DdijsxJ{hF8@k201_OsMl6az z5JSmoAB+FY?{VZ@NN#iiTvM=+^`N)eTg&BaA_h>6g6j|5>kG^-Uq*xM`SdC>06-fI zg=hiT-f{p3Kn$0K`K6-b2TX^MfKCAl?E{y4vB0G^RSJpfp|!amJpk0px7b@F0gyi7 zrRGbDZ;2VW|JZ$Y!b7Rb9G=e&rJobfI5Qcq;(MEyMA z#N64Uf1oW*1mm5`ZIBqo-BSy8A~Sg`x#An|a&{zw@kaS)=fpQW@sA`D1(?Nx$Z_Fs z7pk})^HLMR*wnCZ!edSn0C;WpU2_Ik3grnFtR}k`HA{`-Jv(n7rp&ORZZ~))?Eq@C zD>{+i=+casoahS@o9dT4Ij@&*roaFdgGK;&34+n5i?Nb{y~e<(6$_^oqsN>hy1th4 zMZEDa>9x`V06r7rC5T9!sgXg~fR;;c%v+%1e8k&Do}o-rM+-n^jV!LcDwHR98u(g? ztG~UeVJ{hg^r6eN0NfhTleZq?yH{KP5J=>apjt#KCH;Wbkc!7!hR@m;vVl4|z zLtnKWAp%Gnyhv9NL&l74dUoBgY{E|RZhVV;Pv^;KfP7^oT>$W=4AH>~-kYcqPf!@s z%BR&o_GCr^7+fZL>%gGamd*Qr#SOI#UP?r@jPj@7EJ+E6`1f5INopm`PT#Q6VX%3q xwZZc=CP9C$IA85BB(<4a@Xs>9GC+c#e*r)8ji|msX)XW&002ovPDHLkV1jptSgrs7 diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_standard_chartered.imageset/stp_bank_fpx_standard_chartered@3x.png b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_standard_chartered.imageset/stp_bank_fpx_standard_chartered@3x.png deleted file mode 100644 index c8d75605ad116a298f03adb01ff1f432a82ecaf4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2596 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 VN~XOd=8gaW002ovPDHLkV1o09kyZcz diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_uob.imageset/stp_bank_fpx_uob@2x.png b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_uob.imageset/stp_bank_fpx_uob@2x.png deleted file mode 100644 index ed32e64498ffdcb39582acdd94736419bf17aa6c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 560 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1SD0tpLGH$#^NA%Cx&(BWL^T-@$DNus#!8YBj_<#VHEd>|VI@T>P%k7;cwzY%j)V8a#ENh$AIsIBXWkHX|qD@y? z1zOX*W~61BKDID^enb4?pAOf}8+7hHT=Pu!`5ETViahzgYqq`gUoQo;5D4n{3hZA^ z(qFe@)u!j-FF#mZytmf%qucBkHxv2$=M<~f&7K=?^3TB7QaRquB3Wm)@b=o0jbf^| zc758%Jgs`sZLNvfyEZj3y!^2z!@_7?q^=ilpXgclHS1ixr)HdySlWK9*DN{2f;&_o z-~+pF!%ItDFY7r=8-9h!7ECr^l<|`_uw{q115O^;&!kfQwyD}V;^w96tJ-bTd}p^F zD*06Fsop5mu;Ja+Ahl<`g0X8{ON5hMqW8=-fA{*H$2Z;xwhPzWldj6NY~fkZFLRao zL2FYfLvkofK*%R14nOx^&VmUeT}}iwqn^_U``p%rE$E+W(F$iz}BG&R*`m iET94u@eB+PZod|lI-;MhF1jZU#P@Xdb6Mw<&;$T%lIh_9 diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_uob.imageset/stp_bank_fpx_uob@3x.png b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_bank_fpx_uob.imageset/stp_bank_fpx_uob@3x.png deleted file mode 100644 index 1adae8c70c11633aceb676ec9766a174d109a278..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 757 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1SE5RJ;(=AjKx9jP7LeL$-HD>U|R3#;uunK z>+PN0*};ht$3L#q;<_iU9}&Hk&rej}b$8WTg*?4SD*qVY>G4@b6khCWTH748=fbh1 zqpk<_WVPbhvWsn(cot_1O`bE`f7J@x_tjP>G?%o$KW+WbqVlt)z@i+}?IBZ%0@$h0D~(MWv#6*aZDKR3PJ)t5QzV@l=&$DG%7rZcT-7Fk*4r52w% zw5j;#s~gdeZ%CTXym2>Ht|m#1_xL82%(G8dPc%PvF*wU;TW0>pa}AcZk4>bC7lyfgbyD2SqYr-_*Z=jT&Cfq5&V&C-^||+F7@3#$&AGB|?V3BOZjWz; zE&k6kX_~ruiTACIOw5zoHhf_8JROzb(3jiJ?{VuF6LZnw9Z%M=fA3gotXOko)6N48 zTIZD&|4fpT<>&Fx();Pfef9jGFFjZEPDg62yZbd=`uO=@VqO1_r09ogXr; zJ$q#?m)NF0yOJ%I_a$5UgwWjfs8pYXUw@X~`pvmJB5U56O;YpsiT!?m-0c13GLdli zIP>EydS7g#Hs3te9sbL(QI`Gb;*Z%r3C1(eh0JsPlFVfOZlYmhZ~p!IeomdU|0}*H remj)P=4;d`3<-4+NccxB{H=aFY&~o6_6OR)bj;xC>gTe~DWM4f>M%(( diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_fpx_big_logo.imageset/Contents.json b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_fpx_big_logo.imageset/Contents.json deleted file mode 100644 index 8d8210fc3df..00000000000 --- a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_fpx_big_logo.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "filename" : "stp_fpx_big_logo.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "stp_fpx_big_logo@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "stp_fpx_big_logo@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_fpx_big_logo.imageset/stp_fpx_big_logo.png b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_fpx_big_logo.imageset/stp_fpx_big_logo.png deleted file mode 100644 index 78e2899583b39bd7d4ec33ddbae0948a2178f2f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3536 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 J38`Qm@?S&Z>5%{c diff --git a/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_fpx_big_logo.imageset/stp_fpx_big_logo@3x.png b/Stripe/StripeiOS/Resources/StripeiOS.xcassets/FPX/stp_fpx_big_logo.imageset/stp_fpx_big_logo@3x.png deleted file mode 100644 index e157d8274f4d1b29351d60909092909492c48aa2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12473 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 KMNUMnLSTXAz|EF*i2kuTN8~d?+HnSydthg zX@?_4(F}z+mA$YU(Vt#j+%e&_tY-*dj-@86%BX9zYhIg}g#0D$37Svh`lukQ~5 zeN)QU(ZFv8q&eE)01x>)rT_pi5N~Bc3KP!Wo^~ZUt29eYt1}A4diSx1-Z&mGd=%z$ ztFVamfWgGITkdX#oEei~uq{>2;Cz-LF{zI@N!7=v*!m1B_z!}U3}MM*60Ek!$o;gybk53%{ZfCEpP>u z23N5KoR{Zae`mrW(nu+Y`3h&w-={$>82ARpb%mW=(%^qedf(5lt$ZU9fX*1P& zZfxgi05j8lZLv$rGezX8i@@yZW~_ds)y#oot&y82IF~$!L)e*S*G`tdH8B52gH~ zf|~4bA0I1tZfl63g}YA@^Vqn%i9Bg&rilP2T?$p>^0_7UW+xUxr6N9WOn~$%{Kq`A za@U)U)P>TG*FA_i84h;7>GqWYeCt=s3Ai&wR4wAvF5jX+Dtx+`Gfo4? zi%AxwXs?-0-=&Mxz7IfF*7CTi_RYgzZNU_@nkzOrzg}Bh9yp_^u7&^zR_{|i9nFoe zf#lW8{57&o`U2~`fM?5mJ)HVmq$VA!+;TG7ln3M&fvifHX?-oPtl_Ws3AEk3zTtdS zAFg(}A_?|b{KaBc>%!N($rKFcjzl*_{I$*}7-JkKiX0c^J3~b*TdWyK(jQlvAdkQE z5xG5C&#j=r^}gmcy-n1IaA`TkmDy}{b9WL}QRT5XU2jB|3hNLLPQcgz27JAzRVEFS z%%4!OFBS1C-3+8<8j4-(PBFZwy_Sga!2<%H-r58+N0OrfRHMCBU((^mIMkwl7h1{> z>J!}?nj4)_YO8rZy22iNm9jfH(H0xj4oS3)x9_yW^HPJ?JS>RzO_$#V?L_U2yjm%B z2ljFT9WjHSkT{fOUX9W=jjES{)O;_7Gqq@vBb@TH zx9PGL8tZftwQ5RksaXk$Z-;Wz+jV0N>3r{aVEYTBoTyaqPn^=pC^V&d!^Ey?EiaHd z=+1CCe&Y3DW3@tA5?U5)v!RMLj@B<4kxs1LCu_>p5dy~%V8H-;;aTf3O1D1nAcOzp z^|3hKLthW)#p0}fbPMPY;c)TeXPnhblesgWXUSp)c&XKf*67^tRAPwm+aI|=f0Hiw zlt;b7127MCo=_ku9&KxZ@q-8R65Gtz`9YXiEg7xgd>KDD=P8(?1UYx3c|Xdk_ZkuG zGJhdQ95Ib(r1H8ABT6195ufYu)>F2i<+GbVZg|4l1}mT%! Void typealias STPPaymentCompletionBlock = (STPPaymentStatus, Error?) -> Void -typealias STPPaymentSummaryItemCompletionBlock = ([PKPaymentSummaryItem]) -> Void -typealias STPShippingMethodSelectionBlock = ( - PKShippingMethod, @escaping STPPaymentSummaryItemCompletionBlock -) -> Void -typealias STPShippingAddressValidationBlock = ( - STPShippingStatus, [PKShippingMethod], [PKPaymentSummaryItem] -) -> Void -typealias STPShippingAddressSelectionBlock = ( - STPAddress, @escaping STPShippingAddressValidationBlock -) -> Void typealias STPPaymentAuthorizationBlock = (PKPayment) -> Void -extension PKPaymentAuthorizationViewController { - class func stp_controller( - with paymentRequest: PKPaymentRequest, - apiClient: STPAPIClient, - onShippingAddressSelection: @escaping STPShippingAddressSelectionBlock, - onShippingMethodSelection: @escaping STPShippingMethodSelectionBlock, - onPaymentAuthorization: @escaping STPPaymentAuthorizationBlock, - onPaymentMethodCreation: @escaping STPApplePayPaymentMethodHandlerBlock, - onFinish: @escaping STPPaymentCompletionBlock - ) -> Self? { - let delegate = STPBlockBasedApplePayDelegate() - delegate.apiClient = apiClient - delegate.onShippingAddressSelection = onShippingAddressSelection - delegate.onShippingMethodSelection = onShippingMethodSelection - delegate.onPaymentAuthorization = onPaymentAuthorization - delegate.onPaymentMethodCreation = onPaymentMethodCreation - delegate.onFinish = onFinish - let viewController = self.init(paymentRequest: paymentRequest) - viewController?.delegate = delegate - if let viewController = viewController { - objc_setAssociatedObject( - viewController, - UnsafeRawPointer(&kSTPBlockBasedApplePayDelegateAssociatedObjectKey), - delegate, - .OBJC_ASSOCIATION_RETAIN_NONATOMIC - ) - } - return viewController - } -} -private var kSTPBlockBasedApplePayDelegateAssociatedObjectKey = 0 typealias STPApplePayShippingMethodCompletionBlock = ( PKPaymentAuthorizationStatus, [PKPaymentSummaryItem]? ) -> Void typealias STPApplePayShippingAddressCompletionBlock = ( PKPaymentAuthorizationStatus, [PKShippingMethod]?, [PKPaymentSummaryItem]? ) -> Void -class STPBlockBasedApplePayDelegate: NSObject, PKPaymentAuthorizationViewControllerDelegate { - var apiClient: STPAPIClient? - var onShippingAddressSelection: STPShippingAddressSelectionBlock? - var onShippingMethodSelection: STPShippingMethodSelectionBlock? - var onPaymentAuthorization: STPPaymentAuthorizationBlock? - var onPaymentMethodCreation: STPApplePayPaymentMethodHandlerBlock? - var onFinish: STPPaymentCompletionBlock? - var lastError: Error? - var didSucceed = false - - // Remove all this once we drop iOS 11 support - func paymentAuthorizationViewController( - _ controller: PKPaymentAuthorizationViewController, - didAuthorizePayment payment: PKPayment, - completion: @escaping (PKPaymentAuthorizationStatus) -> Void - ) { - onPaymentAuthorization?(payment) - - let paymentMethodCreateCompletion: ((STPPaymentMethod?, Error?) -> Void)? = { - result, - paymentMethodCreateError in - if let paymentMethodCreateError = paymentMethodCreateError { - self.lastError = paymentMethodCreateError - completion(.failure) - return - } - guard let result = result else { - self.lastError = NSError.stp_genericFailedToParseResponseError() - completion(.failure) - return - } - self.onPaymentMethodCreation?( - result, - { status, error in - if status != .success || error != nil { - self.lastError = error - completion(.failure) - if controller.presentingViewController == nil { - // If we call completion() after dismissing, didFinishWithStatus is NOT called. - self._finish() - } - return - } - self.didSucceed = true - completion(.success) - if controller.presentingViewController == nil { - // If we call completion() after dismissing, didFinishWithStatus is NOT called. - self._finish() - } - } - ) - } - if let paymentMethodCreateCompletion = paymentMethodCreateCompletion { - apiClient?.createPaymentMethod(with: payment, completion: paymentMethodCreateCompletion) - } - } - - func paymentAuthorizationViewController( - _ controller: PKPaymentAuthorizationViewController, - didSelect shippingMethod: PKShippingMethod, - completion: @escaping (PKPaymentAuthorizationStatus, [PKPaymentSummaryItem]) -> Void - ) { - onShippingMethodSelection?( - shippingMethod, - { summaryItems in - completion(PKPaymentAuthorizationStatus.success, summaryItems) - } - ) - } - - func paymentAuthorizationViewController( - _ controller: PKPaymentAuthorizationViewController, - didSelectShippingContact contact: PKContact, - handler completion: @escaping (PKPaymentRequestShippingContactUpdate) -> Void - ) { - let stpAddress = STPAddress(pkContact: contact) - onShippingAddressSelection?( - stpAddress, - { status, shippingMethods, summaryItems in - if status == .invalid { - let genericShippingError = NSError( - domain: PKPaymentErrorDomain, - code: PKPaymentError.shippingContactInvalidError.rawValue, - userInfo: nil - ) - completion( - PKPaymentRequestShippingContactUpdate( - errors: [genericShippingError], - paymentSummaryItems: summaryItems, - shippingMethods: shippingMethods - ) - ) - } else { - completion( - PKPaymentRequestShippingContactUpdate( - errors: nil, - paymentSummaryItems: summaryItems, - shippingMethods: shippingMethods - ) - ) - } - } - ) - } - - func paymentAuthorizationViewControllerDidFinish( - _ controller: PKPaymentAuthorizationViewController - ) { - _finish() - } - - func _finish() { - if didSucceed { - onFinish?(.success, nil) - } else if let lastError = lastError { - onFinish?(.error, lastError) - } else { - onFinish?(.userCancellation, nil) - } - } -} typealias STPPaymentAuthorizationStatusCallback = (PKPaymentAuthorizationStatus) -> Void diff --git a/Stripe/StripeiOS/Source/STPAPIClient+BasicUI.swift b/Stripe/StripeiOS/Source/STPAPIClient+BasicUI.swift deleted file mode 100644 index 00e78896600..00000000000 --- a/Stripe/StripeiOS/Source/STPAPIClient+BasicUI.swift +++ /dev/null @@ -1,178 +0,0 @@ -// -// STPAPIClient+BasicUI.swift -// StripeiOS -// -// Created by David Estes on 6/30/22. -// Copyright © 2022 Stripe, Inc. All rights reserved. -// - -import Foundation -@_spi(STP) import StripeCore -@_spi(STP) import StripePayments - -/// A client for making connections to the Stripe API. -extension STPAPIClient { - /// Initializes an API client with the given configuration. - /// - Parameter configuration: The configuration to use. - /// - Returns: An instance of STPAPIClient. - @available( - *, - deprecated, - message: - "This initializer previously configured publishableKey and stripeAccount via the STPPaymentConfiguration instance. This behavior is deprecated; set the STPAPIClient configuration, publishableKey, and stripeAccount properties directly on the STPAPIClient instead." - ) - public convenience init( - configuration: STPPaymentConfiguration - ) { - // For legacy reasons, we'll support this initializer and use the deprecated configuration.{publishableKey, stripeAccount} properties - self.init() - publishableKey = configuration.publishableKey - stripeAccount = configuration.stripeAccount - } -} - -extension STPAPIClient { - /// The client's configuration. - /// Defaults to `STPPaymentConfiguration.shared`. - @objc public var configuration: STPPaymentConfiguration { - get { - if let config = _stored_configuration as? STPPaymentConfiguration { - return config - } else { - return .shared - } - } - set { - _stored_configuration = newValue - } - } - - /// Update a customer with parameters - /// - seealso: https://stripe.com/docs/api#update_customer - func updateCustomer( - withParameters parameters: [String: Any], - using ephemeralKey: STPEphemeralKey, - completion: @escaping STPCustomerCompletionBlock - ) { - let endpoint = "\(APIEndpointCustomers)/\(ephemeralKey.customerID ?? "")" - APIRequest.post( - with: self, - endpoint: endpoint, - additionalHeaders: authorizationHeader(using: ephemeralKey), - parameters: parameters - ) { object, _, error in - completion(object, error) - } - } - - /// Attach a Payment Method to a customer - /// - seealso: https://stripe.com/docs/api/payment_methods/attach - func attachPaymentMethod( - _ paymentMethodID: String, - toCustomerUsing ephemeralKey: STPEphemeralKey, - completion: @escaping STPErrorBlock - ) { - guard let customerID = ephemeralKey.customerID else { - assertionFailure() - completion(nil) - return - } - let endpoint = "\(APIEndpointPaymentMethods)/\(paymentMethodID)/attach" - APIRequest.post( - with: self, - endpoint: endpoint, - additionalHeaders: authorizationHeader(using: ephemeralKey), - parameters: [ - "customer": customerID - ] - ) { _, _, error in - completion(error) - } - } - - /// Detach a Payment Method from a customer - /// - seealso: https://stripe.com/docs/api/payment_methods/detach - func detachPaymentMethod( - _ paymentMethodID: String, - fromCustomerUsing ephemeralKey: STPEphemeralKey, - completion: @escaping STPErrorBlock - ) { - let endpoint = "\(APIEndpointPaymentMethods)/\(paymentMethodID)/detach" - APIRequest.post( - with: self, - endpoint: endpoint, - additionalHeaders: authorizationHeader(using: ephemeralKey), - parameters: [:] - ) { _, _, error in - completion(error) - } - } - - /// Retrieves a list of Payment Methods attached to a customer. - /// @note This only fetches card type Payment Methods - func listPaymentMethodsForCustomer( - using ephemeralKey: STPEphemeralKey, - completion: @escaping STPPaymentMethodsCompletionBlock - ) { - let header = authorizationHeader(using: ephemeralKey) - let params: [String: Any] = [ - "customer": ephemeralKey.customerID ?? "", - "type": "card", - ] - APIRequest.getWith( - self, - endpoint: APIEndpointPaymentMethods, - additionalHeaders: header, - parameters: params as [String: Any] - ) { deserializer, _, error in - if let error = error { - completion(nil, error) - } else if let paymentMethods = deserializer?.paymentMethods { - completion(paymentMethods, nil) - } - } - } - - /// Retrieve a customer - /// - seealso: https://stripe.com/docs/api#retrieve_customer - func retrieveCustomer( - using ephemeralKey: STPEphemeralKey, - completion: @escaping STPCustomerCompletionBlock - ) { - let endpoint = "\(APIEndpointCustomers)/\(ephemeralKey.customerID ?? "")" - APIRequest.getWith( - self, - endpoint: endpoint, - additionalHeaders: authorizationHeader(using: ephemeralKey), - parameters: [:] - ) { object, _, error in - completion(object, error) - } - } - - // MARK: FPX - /// Retrieves the online status of the FPX banks from the Stripe API. - /// - Parameter completion: The callback to run with the returned FPX bank list, or an error. - func retrieveFPXBankStatus( - withCompletion completion: @escaping STPFPXBankStatusCompletionBlock - ) { - APIRequest.getWith( - self, - endpoint: APIEndpointFPXStatus, - parameters: [ - "account_holder_type": "individual" - ] - ) { statusResponse, _, error in - completion(statusResponse, error) - } - } - - // MARK: Helpers - - /// A helper method that returns the Authorization header to use for API requests. If ephemeralKey is nil, uses self.publishableKey instead. - func authorizationHeader(using ephemeralKey: STPEphemeralKey? = nil) -> [String: String] { - return authorizationHeader(using: ephemeralKey?.secret) - } -} - -private let APIEndpointFPXStatus = "fpx/bank_statuses" diff --git a/Stripe/StripeiOS/Source/STPAPIClient+PushProvisioning.swift b/Stripe/StripeiOS/Source/STPAPIClient+PushProvisioning.swift index 1acda1480be..8d681367cbf 100644 --- a/Stripe/StripeiOS/Source/STPAPIClient+PushProvisioning.swift +++ b/Stripe/StripeiOS/Source/STPAPIClient+PushProvisioning.swift @@ -37,4 +37,10 @@ extension STPAPIClient { completion(details, error) } } + // MARK: Helpers + + /// A helper method that returns the Authorization header to use for API requests. If ephemeralKey is nil, uses self.publishableKey instead. + func authorizationHeader(using ephemeralKey: STPEphemeralKey? = nil) -> [String: String] { + return authorizationHeader(using: ephemeralKey?.secret) + } } diff --git a/Stripe/StripeiOS/Source/STPAddCardViewController.swift b/Stripe/StripeiOS/Source/STPAddCardViewController.swift deleted file mode 100644 index 853908fd4ba..00000000000 --- a/Stripe/StripeiOS/Source/STPAddCardViewController.swift +++ /dev/null @@ -1,1001 +0,0 @@ -// -// STPAddCardViewController.swift -// StripeiOS -// -// Created by Jack Flintermann on 3/23/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -@_spi(STP) import StripeCore -@_spi(STP) import StripePayments -@_spi(STP) import StripePaymentsUI -@_spi(STP) import StripeUICore -import UIKit - -/// This view controller contains a credit card entry form that the user can fill out. On submission, it will use the Stripe API to convert the user's card details to a Stripe token. It renders a right bar button item that submits the form, so it must be shown inside a `UINavigationController`. -public class STPAddCardViewController: STPCoreTableViewController, STPAddressViewModelDelegate, - STPCardScannerDelegate, STPPaymentCardTextFieldDelegate, UITableViewDelegate, - UITableViewDataSource -{ - - /// A convenience initializer; equivalent to calling `init(configuration: STPPaymentConfiguration.shared, theme: STPTheme.defaultTheme)`. - @objc - public convenience init() { - self.init(configuration: STPPaymentConfiguration.shared, theme: STPTheme.defaultTheme) - } - - /// Initializes a new `STPAddCardViewController` with the provided configuration and theme. Don't forget to set the `delegate` property after initialization. - /// - Parameters: - /// - configuration: The configuration to use (this determines the Stripe publishable key to use, the required billing address fields, whether or not to use SMS autofill, etc). - seealso: STPPaymentConfiguration - /// - theme: The theme to use to inform the view controller's visual appearance. - seealso: STPTheme - @objc(initWithConfiguration:theme:) - public init( - configuration: STPPaymentConfiguration, - theme: STPTheme - ) { - addressViewModel = STPAddressViewModel( - requiredBillingFields: configuration.requiredBillingAddressFields, - availableCountries: configuration.availableCountries - ) - super.init(theme: theme) - commonInit(with: configuration) - } - - /// The view controller's delegate. This must be set before showing the view controller in order for it to work properly. - seealso: STPAddCardViewControllerDelegate - @objc public weak var delegate: STPAddCardViewControllerDelegate? - /// You can set this property to pre-fill any information you've already collected from your user. - seealso: STPUserInformation.h - @objc public var prefilledInformation: STPUserInformation? { - didSet { - if let address = prefilledInformation?.billingAddress { - addressViewModel.address = address - } - } - } - // Should be overwritten if this class is used by STPPaymentContext or STPPaymentOptionsViewController - internal var analyticsLogger: STPPaymentContext.AnalyticsLogger = .init(product: STPAddCardViewController.self) - private var _customFooterView: UIView? - /// Provide this view controller with a footer view. - /// When the footer view needs to be resized, it will be sent a - /// `sizeThatFits:` call. The view should respond correctly to this method in order - /// to be sized and positioned properly. - @objc public var customFooterView: UIView? { - get { - _customFooterView - } - set(footerView) { - _customFooterView = footerView - _configureFooterView() - } - } - - func _configureFooterView() { - if isViewLoaded, let footerView = _customFooterView { - let size = footerView.sizeThatFits( - CGSize(width: view.bounds.size.width, height: CGFloat.greatestFiniteMagnitude) - ) - footerView.frame = CGRect(x: 0, y: 0, width: size.width, height: size.height) - - tableView?.tableFooterView = footerView - } - } - - /// The API Client to use to make requests. - /// Defaults to `STPAPIClient.shared` - public var apiClient: STPAPIClient = STPAPIClient.shared - - /// Use init: or initWithConfiguration:theme: - required init( - theme: STPTheme? - ) { - let configuration = STPPaymentConfiguration.shared - addressViewModel = STPAddressViewModel( - requiredBillingFields: configuration.requiredBillingAddressFields, - availableCountries: configuration.availableCountries - ) - super.init(theme: theme) - } - - /// Use init: or initWithConfiguration:theme: - required init( - nibName nibNameOrNil: String?, - bundle nibBundleOrNil: Bundle? - ) { - let configuration = STPPaymentConfiguration.shared - addressViewModel = STPAddressViewModel( - requiredBillingFields: configuration.requiredBillingAddressFields, - availableCountries: configuration.availableCountries - ) - super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) - } - - /// Use init: or initWithConfiguration:theme: - required init?( - coder aDecoder: NSCoder - ) { - let configuration = STPPaymentConfiguration.shared - addressViewModel = STPAddressViewModel( - requiredBillingFields: configuration.requiredBillingAddressFields, - availableCountries: configuration.availableCountries - ) - super.init(coder: aDecoder) - } - - private var _alwaysEnableDoneButton = false - @objc var alwaysEnableDoneButton: Bool { - get { - _alwaysEnableDoneButton - } - set(alwaysEnableDoneButton) { - if alwaysEnableDoneButton != _alwaysEnableDoneButton { - _alwaysEnableDoneButton = alwaysEnableDoneButton - updateDoneButton() - } - } - } - private var configuration: STPPaymentConfiguration? - @objc var shippingAddress: STPAddress? - private var hasUsedShippingAddress = false - private weak var cardImageView: UIImageView? - private var doneItem: UIBarButtonItem? - private var cardHeaderView: STPSectionHeaderView? - - @available(macCatalyst 14.0, *) - private var cardScanner: STPCardScanner? { - get { - _cardScanner as? STPCardScanner - } - set { - _cardScanner = newValue - } - } - - /// Storage for `cardScanner`. - private var _cardScanner: NSObject? - - @available(macCatalyst 14.0, *) - private var scannerCell: STPCardScannerTableViewCell? { - get { - _scannerCell as? STPCardScannerTableViewCell - } - set { - _scannerCell = newValue - } - } - - /// Storage for `scannerCell`. - private var _scannerCell: NSObject? - - private var _isScanning = false - private var isScanning: Bool { - get { - _isScanning - } - set(isScanning) { - if _isScanning == isScanning { - return - } - _isScanning = isScanning - - cardHeaderView?.button?.isEnabled = !isScanning - let indexPath = IndexPath( - row: 0, - section: STPPaymentCardSection.stpPaymentCardScannerSection.rawValue - ) - tableView?.beginUpdates() - if isScanning { - tableView?.insertRows(at: [indexPath], with: .automatic) - } else { - tableView?.deleteRows(at: [indexPath], with: .automatic) - } - tableView?.endUpdates() - if isScanning { - tableView?.scrollToRow(at: indexPath, at: .middle, animated: true) - } - updateInputAccessoryVisiblity() - } - } - private var addressHeaderView: STPSectionHeaderView? - var paymentCell: STPPaymentCardTextFieldCell? - var viewDidAppearStartTime: Date? - - private var _loading = false - @objc var loading: Bool { - get { - _loading - } - set(loading) { - if loading == _loading { - return - } - _loading = loading - stp_navigationItemProxy?.setHidesBackButton(loading, animated: true) - stp_navigationItemProxy?.leftBarButtonItem?.isEnabled = !loading - activityIndicator?.animating = loading - if loading { - tableView?.endEditing(true) - var loadingItem: UIBarButtonItem? - if let activityIndicator = activityIndicator { - loadingItem = UIBarButtonItem(customView: activityIndicator) - } - stp_navigationItemProxy?.setRightBarButton(loadingItem, animated: true) - cardHeaderView?.buttonHidden = true - } else { - stp_navigationItemProxy?.setRightBarButton(doneItem, animated: true) - cardHeaderView?.buttonHidden = false - } - var cells = addressViewModel.addressCells as [UITableViewCell] - - if let paymentCell = paymentCell { - cells.append(paymentCell) - } - for cell in cells { - cell.isUserInteractionEnabled = !loading - UIView.animate( - withDuration: 0.1, - animations: { - cell.alpha = loading ? 0.7 : 1.0 - } - ) - } - } - } - private var activityIndicator: STPPaymentActivityIndicatorView? - private weak var lookupActivityIndicator: STPPaymentActivityIndicatorView? - var addressViewModel: STPAddressViewModel - private var inputAccessoryToolbar: UIToolbar? - private var lookupSucceeded = false - private var scannerCompleteAnimationTimer: Timer? - var didSendFormInteractedAnalytic = false - - @objc(commonInitWithConfiguration:) func commonInit(with configuration: STPPaymentConfiguration) - { - STPAnalyticsClient.sharedClient.addClass( - toProductUsageIfNecessary: STPAddCardViewController.self - ) - - self.configuration = configuration - shippingAddress = nil - hasUsedShippingAddress = false - addressViewModel.delegate = self - title = STPLocalizedString("Add a Card", "Title for Add a Card view") - - if #available(macCatalyst 14.0, *) { - cardScanner = STPCardScanner() - } - } - - /// :nodoc: - @objc - public func tableView( - _ tableView: UITableView, - estimatedHeightForRowAt indexPath: IndexPath - ) -> CGFloat { - return 44.0 - } - - @objc override func createAndSetupViews() { - super.createAndSetupViews() - - let doneItem = UIBarButtonItem( - barButtonSystemItem: .done, - target: self, - action: #selector(nextPressed(_:)) - ) - self.doneItem = doneItem - stp_navigationItemProxy?.rightBarButtonItem = doneItem - updateDoneButton() - - stp_navigationItemProxy?.leftBarButtonItem?.accessibilityIdentifier = - "AddCardViewControllerNavBarCancelButtonIdentifier" - stp_navigationItemProxy?.rightBarButtonItem?.accessibilityIdentifier = - "AddCardViewControllerNavBarDoneButtonIdentifier" - - let cardImageView = UIImageView(image: STPLegacyImageLibrary.largeCardFrontImage()) - cardImageView.contentMode = .center - cardImageView.frame = CGRect( - x: 0, - y: 0, - width: view.bounds.size.width, - height: cardImageView.bounds.size.height + (57 * 2) - ) - self.cardImageView = cardImageView - tableView?.tableHeaderView = cardImageView - - let paymentCell = STPPaymentCardTextFieldCell( - style: .default, - reuseIdentifier: "STPAddCardViewControllerPaymentCardTextFieldCell" - ) - paymentCell.paymentField?.delegate = self - if configuration?.requiredBillingAddressFields == .postalCode { - // If postal code collection is enabled, move the postal code field into the card entry field. - // Otherwise, this will be picked up by the billing address fields below. - paymentCell.paymentField?.postalCodeEntryEnabled = true - } - self.paymentCell = paymentCell - - activityIndicator = STPPaymentActivityIndicatorView( - frame: CGRect(x: 0, y: 0, width: 20.0, height: 20.0) - ) - - inputAccessoryToolbar = UIToolbar.stp_inputAccessoryToolbar( - withTarget: self, - action: #selector(paymentFieldNextTapped) - ) - inputAccessoryToolbar?.stp_setEnabled(false) - updateInputAccessoryVisiblity() - tableView?.dataSource = self - tableView?.delegate = self - tableView?.reloadData() - if let address = prefilledInformation?.billingAddress { - addressViewModel.address = address - } - - let addressHeaderView = STPSectionHeaderView() - addressHeaderView.theme = theme - addressHeaderView.title = String.Localized.billing_address - switch configuration?.shippingType { - case .shipping: - addressHeaderView.button?.setTitle( - STPLocalizedString( - "Use Shipping", - "Button to fill billing address from shipping address." - ), - for: .normal - ) - case .delivery: - addressHeaderView.button?.setTitle( - STPLocalizedString( - "Use Delivery", - "Button to fill billing address from delivery address." - ), - for: .normal - ) - default: - break - } - addressHeaderView.button?.addTarget( - self, - action: #selector(useShippingAddress(_:)), - for: .touchUpInside - ) - let requiredFields = configuration?.requiredBillingAddressFields ?? .none - let needsAddress = requiredFields != .none && !addressViewModel.isValid - let buttonVisible = - needsAddress && shippingAddress?.containsContent(for: requiredFields) != nil - && !hasUsedShippingAddress - addressHeaderView.buttonHidden = !buttonVisible - addressHeaderView.setNeedsLayout() - self.addressHeaderView = addressHeaderView - let cardHeaderView = STPSectionHeaderView() - cardHeaderView.theme = theme - cardHeaderView.title = STPPaymentMethodType.card.displayName - cardHeaderView.buttonHidden = true - self.cardHeaderView = cardHeaderView - - // re-set the custom footer view if it was added before we loaded - _configureFooterView() - - view.addGestureRecognizer( - UITapGestureRecognizer(target: self, action: #selector(endEditing)) - ) - - setUpCardScanningIfAvailable() - - STPAnalyticsClient.sharedClient.clearAdditionalInfo() - } - - /// :nodoc: - @objc - public override func viewDidLayoutSubviews() { - super.viewDidLayoutSubviews() - - // Resetting it re-calculates the size based on new view width - // UITableView requires us to call setter again to actually pick up frame - // change on footers - if tableView?.tableFooterView != nil { - customFooterView = tableView?.tableFooterView - } - } - - func setUpCardScanningIfAvailable() { - if #available(macCatalyst 14.0, *) { - if !STPCardScanner.cardScanningAvailable || configuration?.cardScanningEnabled != true { - return - } - let scannerCell = STPCardScannerTableViewCell() - self.scannerCell = scannerCell - - let cardScanner = STPCardScanner(delegate: self) - cardScanner.cameraView = scannerCell.cameraView - self.cardScanner = cardScanner - - cardHeaderView?.buttonHidden = false - cardHeaderView?.button?.setTitle( - String.Localized.scan_card_title_capitalization, - for: .normal - ) - cardHeaderView?.button?.addTarget( - self, - action: #selector(scanCard), - for: .touchUpInside - ) - cardHeaderView?.setNeedsLayout() - } - } - - @available(macCatalyst 14.0, *) - @objc func scanCard() { - view.endEditing(true) - isScanning = true - cardScanner?.start() - sendFormInteractedAnalyticIfNecessary() - } - - @objc func endEditing() { - view.endEditing(false) - } - - /// :nodoc: - @objc - public override func updateAppearance() { - super.updateAppearance() - - view.backgroundColor = theme.primaryBackgroundColor - - let navBarTheme = navigationController?.navigationBar.stp_theme ?? theme - doneItem?.stp_setTheme(navBarTheme) - tableView?.allowsSelection = false - - cardImageView?.tintColor = theme.accentColor - activityIndicator?.tintColor = theme.accentColor - - paymentCell?.theme = theme - cardHeaderView?.theme = theme - addressHeaderView?.theme = theme - for cell in addressViewModel.addressCells { - cell.theme = theme - } - setNeedsStatusBarAppearanceUpdate() - } - - /// :nodoc: - @objc - public override func viewDidAppear(_ animated: Bool) { - super.viewDidAppear(animated) - viewDidAppearStartTime = Date() - analyticsLogger.logFormShown(paymentMethodType: .card) - - stp_beginObservingKeyboardAndInsettingScrollView( - tableView, - onChange: nil - ) - firstEmptyField()?.becomeFirstResponder() - } - - func firstEmptyField() -> UIResponder? { - - if paymentCell?.isEmpty != nil { - return paymentCell! - } - - for cell in addressViewModel.addressCells { - if cell.contents?.count ?? 0 == 0 { - return cell - } - } - return nil - } - - /// :nodoc: - @objc - public override func handleCancelTapped(_ sender: Any?) { - delegate?.addCardViewControllerDidCancel(self) - } - - @objc func nextPressed(_ sender: Any?) { - analyticsLogger.logDoneButtonTapped(paymentMethodType: .card, shownStartDate: viewDidAppearStartTime) - loading = true - guard let cardParams = paymentCell?.paymentField?.paymentMethodParams.card else { - return - } - // Create and return a Payment Method - let billingDetails = STPPaymentMethodBillingDetails() - if configuration?.requiredBillingAddressFields == .postalCode { - let address = STPAddress() - address.postalCode = paymentCell?.paymentField?.postalCode - billingDetails.address = STPPaymentMethodAddress(address: address) - } else { - billingDetails.address = STPPaymentMethodAddress(address: addressViewModel.address) - billingDetails.email = addressViewModel.address.email - billingDetails.name = addressViewModel.address.name - billingDetails.phone = addressViewModel.address.phone - } - let paymentMethodParams = STPPaymentMethodParams( - card: cardParams, - billingDetails: billingDetails, - metadata: nil - ) - apiClient.createPaymentMethod(with: paymentMethodParams) { - paymentMethod, - createPaymentMethodError in - if let createPaymentMethodError = createPaymentMethodError { - self.handleError(createPaymentMethodError) - } else { - if let paymentMethod = paymentMethod { - self.delegate?.addCardViewController( - self, - didCreatePaymentMethod: paymentMethod - ) { - attachToCustomerError in - stpDispatchToMainThreadIfNecessary({ - if let attachToCustomerError = attachToCustomerError { - self.handleError(attachToCustomerError) - } else { - self.loading = false - } - }) - } - } - } - } - } - - func handleError(_ error: Error) { - loading = false - firstEmptyField()?.becomeFirstResponder() - - let alertController = UIAlertController( - title: error.localizedDescription, - message: (error as NSError).localizedFailureReason, - preferredStyle: .alert - ) - - alertController.addAction( - UIAlertAction( - title: String.Localized.ok, - style: .cancel, - handler: nil - ) - ) - - present(alertController, animated: true) - } - - func updateDoneButton() { - stp_navigationItemProxy?.rightBarButtonItem?.isEnabled = - (paymentCell?.paymentField?.isValid ?? false && addressViewModel.isValid) - || alwaysEnableDoneButton - } - - func updateInputAccessoryVisiblity() { - // The inputAccessoryToolbar switches from the paymentCell to the first address field. - // It should only be shown when there *is* an address field. This compensates for the lack - // of a 'Return' key on the number pad used for paymentCell entry - let hasAddressCells = (addressViewModel.addressCells.count) > 0 - paymentCell?.inputAccessoryView = hasAddressCells ? inputAccessoryToolbar : nil - } - - /// Only send form interacted analytic once per time this screen is shown - func sendFormInteractedAnalyticIfNecessary() { - if !didSendFormInteractedAnalytic { - didSendFormInteractedAnalytic = true - analyticsLogger.logFormInteracted(paymentMethodType: .card) - } - } - - /// Only send card number completed analytic once per time the card number changes from invalid to valid - var shouldSendCardNumberCompletedAnalytic = true - func sendCardNumberCompletedAnalyticIfNecessary(cardNumber: String?) { - let isCardNumberValid = STPCardValidator.validationState(forNumber: cardNumber, validatingCardBrand: true) == .valid - if isCardNumberValid, shouldSendCardNumberCompletedAnalytic { - analyticsLogger.logCardNumberCompleted() - shouldSendCardNumberCompletedAnalytic = false - } else if !isCardNumberValid { - // Reset shouldSendCardNumberCompletedAnalytic when the card number is invalid, so that it gets sent when the card number becomes valid. - shouldSendCardNumberCompletedAnalytic = true - } - } - - // MARK: - STPPaymentCardTextField - @objc - public func paymentCardTextFieldDidChange(_ textField: STPPaymentCardTextField) { - sendFormInteractedAnalyticIfNecessary() - sendCardNumberCompletedAnalyticIfNecessary(cardNumber: textField.cardNumber) - inputAccessoryToolbar?.stp_setEnabled(textField.isValid) - updateDoneButton() - } - - @objc func paymentFieldNextTapped() { - _ = addressViewModel.addressCells.stp_boundSafeObject(at: 0)?.becomeFirstResponder() - } - - @objc - public func paymentCardTextFieldWillEndEditing(forReturn textField: STPPaymentCardTextField) { - paymentFieldNextTapped() - } - - @objc - public func paymentCardTextFieldDidBeginEditingCVC(_ textField: STPPaymentCardTextField) { - let isAmex = STPCardValidator.brand(forNumber: textField.cardNumber ?? "") == .amex - var newImage: UIImage? - var animationTransition: UIView.AnimationOptions - - if isAmex { - newImage = STPLegacyImageLibrary.largeCardAmexCVCImage() - animationTransition = .transitionCrossDissolve - } else { - newImage = STPLegacyImageLibrary.largeCardBackImage() - animationTransition = .transitionFlipFromRight - } - - if let cardImageView = cardImageView { - UIView.transition( - with: cardImageView, - duration: 0.2, - options: animationTransition, - animations: { - self.cardImageView?.image = newImage - } - ) - } - } - - @objc - public func paymentCardTextFieldDidEndEditingCVC(_ textField: STPPaymentCardTextField) { - let isAmex = STPCardValidator.brand(forNumber: textField.cardNumber ?? "") == .amex - let animationTransition: UIView.AnimationOptions = - isAmex ? .transitionCrossDissolve : .transitionFlipFromLeft - - if let cardImageView = cardImageView { - UIView.transition( - with: cardImageView, - duration: 0.2, - options: animationTransition, - animations: { - self.cardImageView?.image = STPLegacyImageLibrary.largeCardFrontImage() - } - ) - } - } - - @objc - public func paymentCardTextFieldDidBeginEditing(_ textField: STPPaymentCardTextField) { - if #available(macCatalyst 14.0, *) { - cardScanner?.stop() - } - } - - // MARK: - STPAddressViewModelDelegate - func addressViewModel(_ addressViewModel: STPAddressViewModel, addedCellAt index: Int) { - let indexPath = IndexPath( - row: index, - section: STPPaymentCardSection.stpPaymentCardBillingAddressSection.rawValue - ) - tableView?.insertRows(at: [indexPath], with: .automatic) - updateInputAccessoryVisiblity() - } - - func addressViewModel(_ addressViewModel: STPAddressViewModel, removedCellAt index: Int) { - let indexPath = IndexPath( - row: Int(index), - section: STPPaymentCardSection.stpPaymentCardBillingAddressSection.rawValue - ) - tableView?.deleteRows(at: [indexPath], with: .automatic) - updateInputAccessoryVisiblity() - } - - func addressViewModelDidChange(_ addressViewModel: STPAddressViewModel) { - updateDoneButton() - } - - func addressViewModelWillUpdate(_ addressViewModel: STPAddressViewModel) { - tableView?.beginUpdates() - } - - func addressViewModelDidUpdate(_ addressViewModel: STPAddressViewModel) { - tableView?.endUpdates() - } - - // MARK: - UITableView - /// :nodoc: - @objc - public func numberOfSections(in tableView: UITableView) -> Int { - return 3 - } - - /// :nodoc: - @objc - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - if section == STPPaymentCardSection.stpPaymentCardNumberSection.rawValue { - return 1 - } else if section == STPPaymentCardSection.stpPaymentCardScannerSection.rawValue { - return isScanning ? 1 : 0 - } else if section == STPPaymentCardSection.stpPaymentCardBillingAddressSection.rawValue { - return addressViewModel.addressCells.count - } - return 0 - } - - /// :nodoc: - @objc - public func tableView( - _ tableView: UITableView, - cellForRowAt indexPath: IndexPath - ) -> UITableViewCell { - var cell: UITableViewCell? - switch indexPath.section { - case STPPaymentCardSection.stpPaymentCardNumberSection.rawValue: - cell = paymentCell - case STPPaymentCardSection.stpPaymentCardScannerSection.rawValue: - if #available(macCatalyst 14.0, *) { - cell = scannerCell - } else { - return UITableViewCell() - } - case STPPaymentCardSection.stpPaymentCardBillingAddressSection.rawValue: - cell = addressViewModel.addressCells.stp_boundSafeObject(at: indexPath.row) - default: - return UITableViewCell() // won't be called; exists to make the static analyzer happy - } - cell?.backgroundColor = theme.secondaryBackgroundColor - cell?.contentView.backgroundColor = UIColor.clear - return cell! - } - - /// :nodoc: - @objc - public func tableView( - _ tableView: UITableView, - willDisplay cell: UITableViewCell, - forRowAt indexPath: IndexPath - ) { - let topRow = indexPath.row == 0 - let bottomRow = - self.tableView(tableView, numberOfRowsInSection: indexPath.section) - 1 == indexPath.row - cell.stp_setBorderColor(theme.tertiaryBackgroundColor) - cell.stp_setTopBorderHidden(!topRow) - cell.stp_setBottomBorderHidden(!bottomRow) - cell.stp_setFakeSeparatorColor(theme.quaternaryBackgroundColor) - cell.stp_setFakeSeparatorLeftInset(15.0) - } - - /// :nodoc: - @objc - public func tableView( - _ tableView: UITableView, - heightForFooterInSection section: Int - ) - -> CGFloat - { - if self.tableView(tableView, numberOfRowsInSection: section) == 0 { - return 0.01 - } - return 27.0 - } - - /// :nodoc: - @objc - public override func tableView( - _ tableView: UITableView, - heightForHeaderInSection section: Int - ) -> CGFloat { - let fittingSize = CGSize( - width: view.bounds.size.width, - height: CGFloat.greatestFiniteMagnitude - ) - let numberOfRows = self.tableView(tableView, numberOfRowsInSection: section) - if section == STPPaymentCardSection.stpPaymentCardNumberSection.rawValue { - return cardHeaderView?.sizeThatFits(fittingSize).height ?? 0.0 - } else if section == STPPaymentCardSection.stpPaymentCardBillingAddressSection.rawValue - && numberOfRows != 0 - { - return addressHeaderView?.sizeThatFits(fittingSize).height ?? 0.0 - } else if section == STPPaymentCardSection.stpPaymentCardScannerSection.rawValue { - return 0.01 - } else if numberOfRows != 0 { - return tableView.sectionHeaderHeight - } - return 0.01 - } - - /// :nodoc: - @objc - public func tableView( - _ tableView: UITableView, - viewForHeaderInSection section: Int - ) - -> UIView? - { - if self.tableView(tableView, numberOfRowsInSection: section) == 0 { - return UIView() - } else { - if section == STPPaymentCardSection.stpPaymentCardNumberSection.rawValue { - return cardHeaderView - } else if section == STPPaymentCardSection.stpPaymentCardBillingAddressSection.rawValue - { - return addressHeaderView - } - } - return nil - } - - /// :nodoc: - @objc - public func tableView( - _ tableView: UITableView, - viewForFooterInSection section: Int - ) - -> UIView? - { - return UIView() - } - - @objc func useShippingAddress(_ sender: UIButton) { - tableView?.beginUpdates() - addressViewModel.address = shippingAddress ?? STPAddress() - hasUsedShippingAddress = true - firstEmptyField()?.becomeFirstResponder() - UIView.animate( - withDuration: 0.2, - animations: { - self.addressHeaderView?.buttonHidden = true - } - ) - tableView?.endUpdates() - } - - // MARK: - STPCardScanner - /// :nodoc: - @objc - public override func viewWillTransition( - to size: CGSize, - with coordinator: UIViewControllerTransitionCoordinator - ) { - super.viewWillTransition(to: size, with: coordinator) - let orientation = UIDevice.current.orientation - if orientation.isPortrait || orientation.isLandscape { - if #available(macCatalyst 14.0, *) { - cardScanner?.deviceOrientation = orientation - } - } - if isScanning { - let indexPath = IndexPath( - row: 0, - section: STPPaymentCardSection.stpPaymentCardScannerSection.rawValue - ) - DispatchQueue.main.async(execute: { - self.tableView?.scrollToRow(at: indexPath, at: .middle, animated: true) - }) - } - } - - static let cardScannerKSTPCardScanAnimationTime: TimeInterval = 0.04 - - @available(macCatalyst 14.0, *) - func cardScanner( - _ scanner: STPCardScanner, - didFinishWith cardParams: STPPaymentMethodCardParams?, - error: Error? - ) { - if let error = error { - handleError(error) - } - if let cardParams = cardParams { - view.isUserInteractionEnabled = false - paymentCell?.paymentField?.inputView = UIView() as? UIInputView - var i = 0 - scannerCompleteAnimationTimer = Timer.scheduledTimer( - withTimeInterval: STPAddCardViewController.cardScannerKSTPCardScanAnimationTime, - repeats: true, - block: { timer in - i += 1 - let newParams = STPPaymentMethodCardParams() - guard let number = cardParams.number else { - timer.invalidate() - self.view.isUserInteractionEnabled = false - return - } - if i < number.count { - newParams.number = String( - number[...number.index(number.startIndex, offsetBy: i)] - ) - } else { - newParams.number = number - } - self.paymentCell?.paymentField?.paymentMethodParams = STPPaymentMethodParams( - card: newParams, - billingDetails: nil, - metadata: nil - ) - if i > number.count { - self.paymentCell?.paymentField?.paymentMethodParams = - STPPaymentMethodParams( - card: cardParams, - billingDetails: nil, - metadata: nil - ) - self.isScanning = false - self.paymentCell?.paymentField?.inputView = nil - // Force the inputView to reload by asking the text field to resign/become first responder: - _ = self.paymentCell?.paymentField?.resignFirstResponder() - _ = self.paymentCell?.paymentField?.becomeFirstResponder() - timer.invalidate() - self.view.isUserInteractionEnabled = true - } - } - ) - } else { - isScanning = false - } - } - -} - -/// An `STPAddCardViewControllerDelegate` is notified when an `STPAddCardViewController` -/// successfully creates a card token or is cancelled. It has internal error-handling -/// logic, so there's no error case to deal with. -@objc public protocol STPAddCardViewControllerDelegate: NSObjectProtocol { - /// Called when the user cancels adding a card. You should dismiss (or pop) the - /// view controller at this point. - /// - Parameter addCardViewController: the view controller that has been cancelled - func addCardViewControllerDidCancel(_ addCardViewController: STPAddCardViewController) - - /// This is called when the user successfully adds a card and Stripe returns a - /// Payment Method. - /// You should send the PaymentMethod to your backend to store it on a customer, and then - /// call the provided `completion` block when that call is finished. If an error - /// occurs while talking to your backend, call `completion(error)`, otherwise, - /// dismiss (or pop) the view controller. - /// - Parameters: - /// - addCardViewController: the view controller that successfully created a token - /// - paymentMethod: the Payment Method that was created. - seealso: STPPaymentMethod - /// - completion: call this callback when you're done sending the token to your backend - @objc func addCardViewController( - _ addCardViewController: STPAddCardViewController, - didCreatePaymentMethod paymentMethod: STPPaymentMethod, - completion: @escaping STPErrorBlock - ) - - // MARK: - Deprecated - - /// This method is deprecated as of v16.0.0 (https://github.com/stripe/stripe-ios/blob/master/MIGRATING.md#migrating-from-versions--1600). - /// To use this class, migrate your integration from Charges to PaymentIntents. See https://stripe.com/docs/payments/payment-intents/migration/charges#read - @available( - *, - deprecated, - message: - "Use addCardViewController(_:didCreatePaymentMethod:completion:) instead and migrate your integration to PaymentIntents. See https://stripe.com/docs/payments/payment-intents/migration/charges#read", - renamed: "addCardViewController(_:didCreatePaymentMethod:completion:)" - ) - @objc optional func addCardViewController( - _ addCardViewController: STPAddCardViewController, - didCreateToken token: STPToken, - completion: STPErrorBlock - ) - /// This method is deprecated as of v16.0.0 (https://github.com/stripe/stripe-ios/blob/master/MIGRATING.md#migrating-from-versions--1600). - /// To use this class, migrate your integration from Charges to PaymentIntents. See https://stripe.com/docs/payments/payment-intents/migration/charges#read - @available( - *, - deprecated, - message: - "Use addCardViewController(_:didCreatePaymentMethod:completion:) instead and migrate your integration to PaymentIntents. See https://stripe.com/docs/payments/payment-intents/migration/charges#read", - renamed: "addCardViewController(_:didCreatePaymentMethod:completion:)" - ) - @objc optional func addCardViewController( - _ addCardViewController: STPAddCardViewController, - didCreateSource source: STPSource, - completion: STPErrorBlock - ) -} - -private let STPPaymentCardCellReuseIdentifier = "STPPaymentCardCellReuseIdentifier" -enum STPPaymentCardSection: Int { - case stpPaymentCardNumberSection = 0 - case stpPaymentCardScannerSection = 1 - case stpPaymentCardBillingAddressSection = 2 -} - -/// :nodoc: -@_spi(STP) extension STPAddCardViewController: STPAnalyticsProtocol { - @_spi(STP) public static let stp_analyticsIdentifier = "STPAddCardViewController" -} diff --git a/Stripe/StripeiOS/Source/STPAddress+BasicUI.swift b/Stripe/StripeiOS/Source/STPAddress+BasicUI.swift deleted file mode 100644 index d99df351702..00000000000 --- a/Stripe/StripeiOS/Source/STPAddress+BasicUI.swift +++ /dev/null @@ -1,212 +0,0 @@ -// -// STPAddress+BasicUI.swift -// StripeiOS -// -// Created by David Estes on 6/30/22. -// Copyright © 2022 Stripe, Inc. All rights reserved. -// - -import Foundation -import PassKit -@_spi(STP) import StripePayments -@_spi(STP) import StripePaymentsUI -@_spi(STP) import StripeUICore - -/// What set of billing address information you need to collect from your user. -/// -/// @note If the user is from a country that does not use zip/postal codes, -/// the user may not be asked for one regardless of this setting. -@objc -public enum STPBillingAddressFields: UInt { - /// No billing address information - case none - /// Just request the user's billing postal code - case postalCode - /// Request the user's full billing address - case full - /// Just request the user's billing name - case name - /// Just request the user's billing ZIP (synonym for STPBillingAddressFieldsZip) - @available(*, deprecated, message: "Use STPBillingAddressFields.postalCode instead") - case zip -} - -extension STPAddress { - - /// Checks if this STPAddress has the level of valid address information - /// required by the passed in setting. - /// - Parameter requiredFields: The required level of billing address information to - /// check against. - /// - Returns: YES if this address contains at least the necessary information, - /// NO otherwise. - @objc - public func containsRequiredFields(_ requiredFields: STPBillingAddressFields) -> Bool { - switch requiredFields { - case .none: - return true - case .postalCode: - return STPPostalCodeValidator.validationState( - forPostalCode: postalCode, - countryCode: country - ) == .valid - case .full: - return hasValidPostalAddress() - case .name: - return (name?.count ?? 0) > 0 - default: - fatalError() - } - } - - /// 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. - /// - Returns: YES if there is any data in this STPAddress that's relevant for those fields. - @objc(containsContentForBillingAddressFields:) - public func containsContent(for desiredFields: STPBillingAddressFields) -> Bool { - switch desiredFields { - case .none: - return false - case .postalCode: - return (postalCode?.count ?? 0) > 0 - case .full: - return hasPartialPostalAddress() - case .name: - return (name?.count ?? 0) > 0 - default: - fatalError() - } - } - - /// Checks if this STPAddress has the level of valid address information - /// required by the passed in setting. - /// Note: When `requiredFields == nil`, this method always returns - /// YES. - /// - Parameter requiredFields: The required shipping address information to check against. - /// - Returns: YES if this address contains at least the necessary information, - /// NO otherwise. - @objc - public func containsRequiredShippingAddressFields( - _ requiredFields: Set? - ) - -> Bool - { - guard let requiredFields = requiredFields else { - return true - } - var containsFields = true - - if requiredFields.contains(.name) { - containsFields = containsFields && (name?.count ?? 0) > 0 - } - if requiredFields.contains(.emailAddress) { - containsFields = - containsFields && STPEmailAddressValidator.stringIsValidEmailAddress(email) - } - if requiredFields.contains(.phoneNumber) { - containsFields = - containsFields - && STPPhoneNumberValidator.stringIsValidPhoneNumber( - phone ?? "", - forCountryCode: country - ) - } - if requiredFields.contains(.postalAddress) { - containsFields = containsFields && hasValidPostalAddress() - } - return containsFields - } - - /// 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 == nil`, this method always returns - /// NO. - /// @parameter desiredFields The shipping address information the caller is interested in. - /// - Returns: YES if there is any data in this STPAddress that's relevant for those fields. - @objc - public func containsContent( - forShippingAddressFields desiredFields: Set? - ) - -> Bool - { - guard let desiredFields = desiredFields else { - return false - } - return (desiredFields.contains(.name) && (name?.count ?? 0) > 0) - || (desiredFields.contains(.emailAddress) && (email?.count ?? 0) > 0) - || (desiredFields.contains(.phoneNumber) && (phone?.count ?? 0) > 0) - || (desiredFields.contains(.postalAddress) && hasPartialPostalAddress()) - } - - /// Converts an STPBillingAddressFields enum value into the closest equivalent - /// representation of PKContactField options - /// - Parameter billingAddressFields: Stripe billing address fields enum value to convert. - /// - Returns: The closest representation of the billing address requirement as - /// a PKContactField value. - @objc(applePayContactFieldsFromBillingAddressFields:) - public class func applePayContactFields( - from billingAddressFields: STPBillingAddressFields - ) - -> Set - { - switch billingAddressFields { - case .none: - return Set([]) - case .postalCode, .full: - return Set([.name, .postalAddress]) - case .name: - return Set([.name]) - case .zip: - return Set() - @unknown default: - fatalError() - } - } - - /// Converts a set of STPContactField values into the closest equivalent - /// representation of PKContactField options - /// - Parameter contactFields: Stripe contact fields values to convert. - /// - Returns: The closest representation of the contact fields as - /// a PKContactField value. - @objc - public class func pkContactFields( - fromStripeContactFields contactFields: Set? - ) -> Set? { - guard let contactFields = contactFields else { - return nil - } - - var pkFields: Set = Set() - let stripeToPayKitContactMap: [STPContactField: PKContactField] = [ - STPContactField.postalAddress: PKContactField.postalAddress, - STPContactField.emailAddress: PKContactField.emailAddress, - STPContactField.phoneNumber: PKContactField.phoneNumber, - STPContactField.name: PKContactField.name, - ] - - for contactField in contactFields { - if let convertedField = stripeToPayKitContactMap[contactField] { - pkFields.insert(convertedField) - } - } - return pkFields - } - - private func hasValidPostalAddress() -> Bool { - return (line1?.count ?? 0) > 0 && (city?.count ?? 0) > 0 && (country?.count ?? 0) > 0 - && ((state?.count ?? 0) > 0 || !(country == "US")) - && (STPPostalCodeValidator.validationState( - forPostalCode: postalCode, - countryCode: country - ) == .valid) - } -} diff --git a/Stripe/StripeiOS/Source/STPAddressFieldTableViewCell.swift b/Stripe/StripeiOS/Source/STPAddressFieldTableViewCell.swift deleted file mode 100644 index 7ae4b4e76a8..00000000000 --- a/Stripe/StripeiOS/Source/STPAddressFieldTableViewCell.swift +++ /dev/null @@ -1,509 +0,0 @@ -// -// STPAddressFieldTableViewCell.swift -// StripeiOS -// -// Created by Ben Guo on 4/13/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -@_spi(STP) import StripeCore -@_spi(STP) import StripePaymentsUI -@_spi(STP) import StripeUICore -import UIKit - -enum STPAddressFieldType: Int { - case name - case line1 - case line2 - case city - case state - case zip - case country - case email - case phone -} - -protocol STPAddressFieldTableViewCellDelegate: AnyObject { - func addressFieldTableViewCellDidUpdateText(_ cell: STPAddressFieldTableViewCell) - - func addressFieldTableViewCellDidReturn(_ cell: STPAddressFieldTableViewCell) - func addressFieldTableViewCellDidEndEditing(_ cell: STPAddressFieldTableViewCell) - var addressFieldTableViewCountryCode: String? { get set } - var availableCountries: Set? { get set } -} - -class STPAddressFieldTableViewCell: UITableViewCell, UITextFieldDelegate, UIPickerViewDelegate, - UIPickerViewDataSource -{ - - init( - type: STPAddressFieldType, - contents: String?, - lastInList: Bool, - delegate: STPAddressFieldTableViewCellDelegate? - ) { - textField = { - if type == .phone { - // We have very specific US-based phone formatting that's built into STPFormTextField - let formTextField = STPFormTextField() - formTextField.preservesContentsOnPaste = false - formTextField.selectionEnabled = false - return formTextField - } else { - return STPValidatedTextField() - } - }() - - super.init(style: .default, reuseIdentifier: nil) - self.delegate = delegate - theme = STPTheme() - _contents = contents - - textField.delegate = self - textField.addTarget( - self, - action: #selector(STPAddressFieldTableViewCell.textFieldTextDidChange(textField:)), - for: .editingChanged - ) - contentView.addSubview(textField) - - let toolbar = UIToolbar() - let flexibleItem = UIBarButtonItem( - barButtonSystemItem: .flexibleSpace, - target: nil, - action: nil - ) - let nextItem = UIBarButtonItem( - title: STPLocalizedString("Next", nil), - style: .done, - target: self, - action: #selector(nextTapped(sender:)) - ) - toolbar.items = [flexibleItem, nextItem] - inputAccessoryToolbar = toolbar - - var countryCode = NSLocale.autoupdatingCurrent.regionCode - var otherCountryCodes = Array( - self.delegate?.availableCountries ?? Set(NSLocale.isoCountryCodes) - ) - if otherCountryCodes.contains(countryCode ?? "") { - // Remove the current country code to re-add it once we sort the list. - otherCountryCodes.removeAll { $0 == 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 - } - let locale = NSLocale.current as NSLocale - otherCountryCodes = - (otherCountryCodes as NSArray).sortedArray(comparator: { code1, code2 in - guard let code1 = code1 as? String, let code2 = code2 as? String else { - return .orderedDescending - } - let localeID1 = NSLocale.localeIdentifier(fromComponents: [ - NSLocale.Key.countryCode.rawValue: code1 - ]) - let localeID2 = NSLocale.localeIdentifier(fromComponents: [ - NSLocale.Key.countryCode.rawValue: code2 - ]) - if let name1 = locale.displayName(forKey: .identifier, value: localeID1), - let name2 = locale.displayName(forKey: .identifier, value: localeID2) - { - return name1.compare(name2) - } else { - return .orderedDescending - } - }) as? [String] ?? [] - if let countryCode = countryCode { - countryCodes = ["", countryCode] + otherCountryCodes - } else { - countryCodes = [""] + otherCountryCodes - } - let pickerView = UIPickerView() - pickerView.dataSource = self - pickerView.delegate = self - countryPickerView = pickerView - - self.lastInList = lastInList - self.type = type - self.textField.text = contents - - var ourCountryCode = self.delegate?.addressFieldTableViewCountryCode - - if ourCountryCode == nil { - ourCountryCode = countryCode - } - delegateCountryCodeDidChange(countryCode: ourCountryCode ?? "") - updateAppearance() - - self.textField.translatesAutoresizingMaskIntoConstraints = false - - NSLayoutConstraint.activate( - [ - textField.leadingAnchor.constraint( - equalTo: contentView.safeAreaLayoutGuide.leadingAnchor, - constant: 15 - ), - textField.trailingAnchor.constraint( - equalTo: contentView.safeAreaLayoutGuide.trailingAnchor, - constant: -15 - ), - textField.topAnchor.constraint( - equalTo: contentView.safeAreaLayoutGuide.topAnchor, - constant: 1 - ), - contentView.safeAreaLayoutGuide.bottomAnchor.constraint( - greaterThanOrEqualTo: textField.bottomAnchor - ), - textField.heightAnchor.constraint(greaterThanOrEqualToConstant: 43), - inputAccessoryToolbar?.heightAnchor.constraint(equalToConstant: 44), - ].compactMap { $0 } - ) - } - - var type: STPAddressFieldType = .name - var caption: String? { - get { - self.textField.placeholder - } - set { - self.textField.placeholder = newValue - } - } - - private(set) var textField: STPValidatedTextField - private var _contents: String? - var contents: String? { - get { - // iOS 11 QuickType completions from textContentType have a space at the end. - // This *keeps* that space in the `textField`, but removes leading/trailing spaces from - // the logical contents of this field, so they're ignored for validation and persisting - return _contents?.trimmingCharacters(in: CharacterSet.whitespaces) - } - set { - _contents = newValue - if self.type == .country { - self.updateTextFieldsAndCaptions() - } else { - self.textField.text = contents - } - if self.textField.isFirstResponder { - self.textField.validText = self.potentiallyValidContents - } else { - self.textField.validText = self.validContents - } - self.delegate?.addressFieldTableViewCellDidUpdateText(self) - } - } - - var theme: STPTheme = .defaultTheme { - didSet { - updateAppearance() - } - } - - var lastInList: Bool = false { - didSet { - updateTextFieldsAndCaptions() - } - } - - private var inputAccessoryToolbar: UIToolbar? - private var countryPickerView: UIPickerView? - private var countryCodes: [AnyHashable]? - private weak var delegate: STPAddressFieldTableViewCellDelegate? - private var ourCountryCode: String? - - func updateTextFieldsAndCaptions() { - textField.placeholder = placeholder(for: type) - - if !lastInList { - textField.returnKeyType = .next - } else { - textField.returnKeyType = .default - } - switch type { - case .name: - textField.keyboardType = .default - textField.textContentType = .name - case .line1: - textField.keyboardType = .numbersAndPunctuation - textField.textContentType = .streetAddressLine1 - case .line2: - textField.keyboardType = .numbersAndPunctuation - textField.textContentType = .streetAddressLine2 - case .city: - textField.keyboardType = .default - textField.textContentType = .addressCity - case .state: - textField.keyboardType = .default - textField.textContentType = .addressState - case .zip: - textField.keyboardType = .numbersAndPunctuation - textField.textContentType = .postalCode - case .country: - textField.keyboardType = .default - // Don't set textContentType for Country, because we don't want iOS to skip the UIPickerView for input - textField.inputView = countryPickerView - // If we're being set directly to a country we don't allow, add it to the allowed list - let countryCodes = self.countryCodes ?? [] - if let contents = contents, - !countryCodes.contains(contents) && NSLocale.isoCountryCodes.contains(contents) - { - self.countryCodes = countryCodes + [contents] - } - let index = countryCodes.firstIndex(of: contents ?? "") ?? NSNotFound - if index == NSNotFound { - textField.text = "" - } else { - countryPickerView?.selectRow(index, inComponent: 0, animated: false) - if let countryPickerView = countryPickerView { - textField.text = pickerView( - countryPickerView, - titleForRow: index, - forComponent: 0 - ) - } - } - textField.validText = validContents - case .phone: - self.textField.keyboardType = .numbersAndPunctuation - self.textField.textContentType = .telephoneNumber - let behavior: STPFormTextFieldAutoFormattingBehavior = - (self.countryCodeIsUnitedStates ? .phoneNumbers : .none) - (self.textField as? STPFormTextField)?.autoFormattingBehavior = behavior - case .email: - self.textField.keyboardType = .emailAddress - self.textField.textContentType = .emailAddress - } - - if !self.lastInList { - self.textField.inputAccessoryView = self.inputAccessoryToolbar - } else { - self.textField.inputAccessoryView = nil - } - self.textField.accessibilityLabel = self.textField.placeholder - self.textField.accessibilityIdentifier = self.accessibilityIdentifierForAddressField( - type: self.type - ) - } - - func accessibilityIdentifierForAddressField(type: STPAddressFieldType) -> String { - switch type { - case .name: - return "ShippingAddressFieldTypeNameIdentifier" - case .line1: - return "ShippingAddressFieldTypeLine1Identifier" - case .line2: - return "ShippingAddressFieldTypeLine2Identifier" - case .city: - return "ShippingAddressFieldTypeCityIdentifier" - case .state: - return "ShippingAddressFieldTypeStateIdentifier" - case .zip: - return "ShippingAddressFieldTypeZipIdentifier" - case .country: - return "ShippingAddressFieldTypeCountryIdentifier" - case .email: - return "ShippingAddressFieldTypeEmailIdentifier" - case .phone: - return "ShippingAddressFieldTypePhoneIdentifier" - } - } - - func stateFieldCaption(forCountryCode countryCode: String?) -> String { - return StripeSharedStrings.localizedStateString(for: countryCode) - } - - func placeholder(for addressFieldType: STPAddressFieldType) -> String { - switch addressFieldType { - case .name: - return String.Localized.name - case .line1: - return String.Localized.address - case .line2: - return STPLocalizedString( - "Apt.", - "Caption for Apartment/Address line 2 field on address form" - ) - case .city: - return String.Localized.city - case .state: - return stateFieldCaption(forCountryCode: self.ourCountryCode) - case .zip: - return StripeSharedStrings.localizedPostalCodeString(for: self.ourCountryCode) - case .country: - return String.Localized.country - case .email: - return String.Localized.email - case .phone: - return String.Localized.phone - } - } - - func delegateCountryCodeDidChange(countryCode: String) { - if self.type == .country { - self.contents = countryCode - } - - self.ourCountryCode = countryCode - self.updateTextFieldsAndCaptions() - self.setNeedsLayout() - } - - func updateAppearance() { - self.backgroundColor = self.theme.secondaryBackgroundColor - self.contentView.backgroundColor = .clear - self.textField.placeholderColor = theme.tertiaryForegroundColor - self.textField.defaultColor = theme.primaryForegroundColor - self.textField.errorColor = self.theme.errorColor - self.textField.font = self.theme.font - self.setNeedsLayout() - } - - var countryCodeIsUnitedStates: Bool { - self.ourCountryCode == "US" - } - - public override func becomeFirstResponder() -> Bool { - return self.textField.becomeFirstResponder() - } - - @objc func nextTapped(sender: NSObject) { - delegate?.addressFieldTableViewCellDidReturn(self) - } - - @objc - public func textFieldShouldReturn(_ textField: UITextField) -> Bool { - self.delegate?.addressFieldTableViewCellDidReturn(self) - return false - } - - @objc - public func textFieldDidEndEditing(_ textField: UITextField) { - (textField as? STPFormTextField)?.validText = validContents - self.delegate?.addressFieldTableViewCellDidEndEditing(self) - } - - public override func accessibilityElementCount() -> Int { - return 1 - } - - public override func accessibilityElement(at index: Int) -> Any? { - return textField - } - - public override func index(ofAccessibilityElement element: Any) -> Int { - return 0 - } - - @objc func textFieldTextDidChange(textField: STPValidatedTextField) { - if self.type != .country { - _contents = textField.text - if textField.isFirstResponder { - textField.validText = self.potentiallyValidContents - } else { - textField.validText = self.validContents - } - } - self.delegate?.addressFieldTableViewCellDidUpdateText(self) - } - - // pragma mark - UITextFieldDelegate - - var validContents: Bool { - switch self.type { - case .name, .line1, .city, .state, .country: - return self.contents?.count ?? 0 > 0 - case .line2: - return true - case .zip: - return STPPostalCodeValidator.validationState( - forPostalCode: self.contents, - countryCode: self.ourCountryCode - ) == .valid - case .email: - return STPEmailAddressValidator.stringIsValidEmailAddress(self.contents) - case .phone: - return STPPhoneNumberValidator.stringIsValidPhoneNumber( - self.contents ?? "", - forCountryCode: self.ourCountryCode - ) - } - } - - var potentiallyValidContents: Bool { - switch self.type { - case .name, .line1, .city, .state, .country, .line2, .phone: - return true - case .zip: - let validationState = STPPostalCodeValidator.validationState( - forPostalCode: self.contents, - countryCode: self.ourCountryCode - ) - return validationState == .valid || validationState == .incomplete - case .email: - return STPEmailAddressValidator.stringIsValidPartialEmailAddress(self.contents) - } - } - - public func pickerView( - _ pickerView: UIPickerView, - didSelectRow row: Int, - inComponent component: Int - ) { - guard let countryCode = self.countryCodes?[row] as? String - else { - return - } - self.ourCountryCode = countryCode - self.contents = self.ourCountryCode - textField.text = self.pickerView(pickerView, titleForRow: row, forComponent: component) - // UIControlEvent not fired for programmatic changes - self.textFieldTextDidChange(textField: textField) - self.delegate?.addressFieldTableViewCountryCode = self.ourCountryCode ?? "" - - } - - public func pickerView( - _ pickerView: UIPickerView, - titleForRow row: Int, - forComponent component: Int - ) -> String? { - guard let countryCode = self.countryCodes?[row] as? String else { - return nil - } - let identifier = Locale.identifier(fromComponents: [ - NSLocale.Key.countryCode.rawValue: countryCode - ]) - return (NSLocale.autoupdatingCurrent as NSLocale).displayName( - forKey: NSLocale.Key(rawValue: NSLocale.Key.identifier.rawValue), - value: identifier - ) - } - - public func numberOfComponents(in pickerView: UIPickerView) -> Int { - return 1 - } - - public func pickerView( - _ pickerView: UIPickerView, - numberOfRowsInComponent component: Int - ) - -> Int - { - self.countryCodes?.count ?? 0 - } - - required convenience init?( - coder aDecoder: NSCoder - ) { - assertionFailure("Use initWithType: instead.") - self.init( - type: .name, - contents: nil, - lastInList: false, - delegate: nil - ) - } - -} diff --git a/Stripe/StripeiOS/Source/STPAddressViewModel.swift b/Stripe/StripeiOS/Source/STPAddressViewModel.swift deleted file mode 100644 index aa3fa68b6dd..00000000000 --- a/Stripe/StripeiOS/Source/STPAddressViewModel.swift +++ /dev/null @@ -1,434 +0,0 @@ -// -// STPAddressViewModel.swift -// StripeiOS -// -// Created by Jack Flintermann on 4/21/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -import Contacts -import CoreLocation -@_spi(STP) import StripeCore -@_spi(STP) import StripePaymentsUI -import UIKit - -protocol STPAddressViewModelDelegate: AnyObject { - func addressViewModelDidChange(_ addressViewModel: STPAddressViewModel) - func addressViewModel(_ addressViewModel: STPAddressViewModel, addedCellAt index: Int) - func addressViewModel(_ addressViewModel: STPAddressViewModel, removedCellAt index: Int) - func addressViewModelWillUpdate(_ addressViewModel: STPAddressViewModel) - func addressViewModelDidUpdate(_ addressViewModel: STPAddressViewModel) -} - -class STPAddressViewModel: STPAddressFieldTableViewCellDelegate { - private(set) var addressCells: [STPAddressFieldTableViewCell] = [] - weak var delegate: STPAddressViewModelDelegate? - - var addressFieldTableViewCountryCode: String? = Locale.autoupdatingCurrent.regionCode { - didSet { - updatePostalCodeCellIfNecessary() - if let addressFieldTableViewCountryCode = addressFieldTableViewCountryCode { - for cell in addressCells { - cell.delegateCountryCodeDidChange(countryCode: addressFieldTableViewCountryCode) - } - } - } - } - - var address: STPAddress { - get { - let address = STPAddress() - for cell in addressCells { - - switch cell.type { - case .name: - address.name = cell.contents - case .line1: - address.line1 = cell.contents - case .line2: - address.line2 = cell.contents - case .city: - address.city = cell.contents - case .state: - address.state = cell.contents - case .zip: - address.postalCode = cell.contents - case .country: - address.country = cell.contents - case .email: - address.email = cell.contents - case .phone: - address.phone = cell.contents - } - } - // Prefer to use the contents of STPAddressFieldTypeCountry, but fallback to - // `addressFieldTableViewCountryCode` if nil (important for STPBillingAddressFieldsPostalCode) - address.country = address.country ?? addressFieldTableViewCountryCode - return address - } - set(address) { - if let country = address.country { - addressFieldTableViewCountryCode = country - } - - for cell in addressCells { - switch cell.type { - case .name: - cell.contents = address.name - case .line1: - cell.contents = address.line1 - case .line2: - cell.contents = address.line2 - case .city: - cell.contents = address.city - case .state: - cell.contents = address.state - case .zip: - cell.contents = address.postalCode - case .country: - cell.contents = address.country - case .email: - cell.contents = address.email - case .phone: - cell.contents = address.phone - } - } - } - } - - // The default value of availableCountries is nil, which will allow all known countries. - var availableCountries: Set? - - var isValid: Bool { - if isBillingAddress { - // The AddressViewModel is only for address fields. - // Determining whether the postal code is present is up to the - // STPCardTextFieldViewModel. - if requiredBillingAddressFields == .postalCode { - return true - } else { - return address.containsRequiredFields(requiredBillingAddressFields) - } - - } else { - if let requiredShippingAddressFields = requiredShippingAddressFields { - return address.containsRequiredShippingAddressFields(requiredShippingAddressFields) - } - return false - } - } - - // The default value of availableCountries is nil, which will allow all known countries. - init( - requiredBillingFields requiredBillingAddressFields: STPBillingAddressFields, - availableCountries: Set? = nil - ) { - isBillingAddress = true - self.availableCountries = availableCountries - self.requiredBillingAddressFields = requiredBillingAddressFields - switch requiredBillingAddressFields { - case .none: - addressCells = [] - case .zip, .postalCode: - addressCells = [] // Postal code cell will be added later if necessary - case .full: - addressCells = [ - STPAddressFieldTableViewCell( - type: .name, - contents: "", - lastInList: false, - delegate: self - ), - STPAddressFieldTableViewCell( - type: .line1, - contents: "", - lastInList: false, - delegate: self - ), - STPAddressFieldTableViewCell( - type: .line2, - contents: "", - lastInList: false, - delegate: self - ), - STPAddressFieldTableViewCell( - type: .country, - contents: addressFieldTableViewCountryCode, - lastInList: false, - delegate: self - ), - // Postal code cell will be added here later if necessary - STPAddressFieldTableViewCell( - type: .city, - contents: "", - lastInList: false, - delegate: self - ), - STPAddressFieldTableViewCell( - type: .state, - contents: "", - lastInList: true, - delegate: self - ), - ] - case .name: - addressCells = [ - STPAddressFieldTableViewCell( - type: .name, - contents: "", - lastInList: true, - delegate: self - ), - ] - default: - fatalError() - } - commonInit() - } - - init( - requiredShippingFields requiredShippingAddressFields: Set, - availableCountries: Set? = nil - ) { - isBillingAddress = false - self.availableCountries = availableCountries - self.requiredShippingAddressFields = requiredShippingAddressFields - var cells: [STPAddressFieldTableViewCell] = [] - - if requiredShippingAddressFields.contains(STPContactField.name) { - cells.append( - STPAddressFieldTableViewCell( - type: .name, - contents: "", - lastInList: false, - delegate: self - ) - ) - } - if requiredShippingAddressFields.contains(.emailAddress) { - cells.append( - STPAddressFieldTableViewCell( - type: .email, - contents: "", - lastInList: false, - delegate: self - ) - ) - } - if requiredShippingAddressFields.contains(STPContactField.postalAddress) { - var postalCells = [ - STPAddressFieldTableViewCell( - type: .name, - contents: "", - lastInList: false, - delegate: self - ), - STPAddressFieldTableViewCell( - type: .line1, - contents: "", - lastInList: false, - delegate: self - ), - STPAddressFieldTableViewCell( - type: .line2, - contents: "", - lastInList: false, - delegate: self - ), - STPAddressFieldTableViewCell( - type: .country, - contents: addressFieldTableViewCountryCode, - lastInList: false, - delegate: self - ), - // Postal code cell will be added here later if necessary - STPAddressFieldTableViewCell( - type: .city, - contents: "", - lastInList: false, - delegate: self - ), - STPAddressFieldTableViewCell( - type: .state, - contents: "", - lastInList: false, - delegate: self - ), - ] - if requiredShippingAddressFields.contains(.name) { - postalCells.remove(at: 0) - } - cells.append(contentsOf: postalCells.compactMap { $0 }) - } - if requiredShippingAddressFields.contains(.phoneNumber) { - cells.append( - STPAddressFieldTableViewCell( - type: .phone, - contents: "", - lastInList: false, - delegate: self - ) - ) - } - if let lastCell = cells.last { - lastCell.lastInList = true - } - addressCells = cells - commonInit() - } - - private func cell(at index: Int) -> STPAddressFieldTableViewCell? { - guard index > 0, - index < addressCells.count - else { - return nil - } - return addressCells[index] - } - - private var isBillingAddress = false - private var requiredBillingAddressFields: STPBillingAddressFields = .none - private var requiredShippingAddressFields: Set? - private var showingPostalCodeCell = false - private var geocodeInProgress = false - - private func commonInit() { - if let countryCode = Locale.autoupdatingCurrent.regionCode { - addressFieldTableViewCountryCode = countryCode - } - updatePostalCodeCellIfNecessary() - } - - private func updatePostalCodeCellIfNecessary() { - delegate?.addressViewModelWillUpdate(self) - let shouldBeShowingPostalCode = STPPostalCodeValidator.postalCodeIsRequired( - forCountryCode: addressFieldTableViewCountryCode - ) - - if shouldBeShowingPostalCode && !showingPostalCodeCell { - if containsStateAndPostalFields() { - // Add before city - let zipFieldIndex = addressCells.firstIndex(where: { $0.type == .city }) ?? 0 - - var mutableAddressCells = addressCells - mutableAddressCells.insert( - STPAddressFieldTableViewCell( - type: .zip, - contents: "", - lastInList: false, - delegate: self - ), - at: zipFieldIndex - ) - addressCells = mutableAddressCells - delegate?.addressViewModel(self, addedCellAt: zipFieldIndex) - delegate?.addressViewModelDidChange(self) - } - } else if !shouldBeShowingPostalCode && showingPostalCodeCell { - if containsStateAndPostalFields() { - if let zipFieldIndex = addressCells.firstIndex(where: { $0.type == .zip }) { - - var mutableAddressCells = addressCells - mutableAddressCells.remove(at: zipFieldIndex) - addressCells = mutableAddressCells - delegate?.addressViewModel(self, removedCellAt: zipFieldIndex) - delegate?.addressViewModelDidChange(self) - } - } - } - showingPostalCodeCell = shouldBeShowingPostalCode - delegate?.addressViewModelDidUpdate(self) - } - - private func containsStateAndPostalFields() -> Bool { - if isBillingAddress { - return requiredBillingAddressFields == .full - } else { - return requiredShippingAddressFields?.contains(.postalAddress) ?? false - } - } - - func updateCityAndState(fromZipCodeCell zipCell: STPAddressFieldTableViewCell?) { - - let zipCode = zipCell?.contents - - if geocodeInProgress || zipCode == nil || !(zipCell?.textField.validText ?? false) - || !(addressFieldTableViewCountryCode == "US") - { - return - } - - var cityCell: STPAddressFieldTableViewCell? - var stateCell: STPAddressFieldTableViewCell? - for cell in addressCells { - if cell.type == .city { - cityCell = cell - } else if cell.type == .state { - stateCell = cell - } - } - - if (cityCell == nil && stateCell == nil) - || ((cityCell?.contents?.count ?? 0) > 0 || (stateCell?.contents?.count ?? 0) > 0) - { - // Don't auto fill if either have text already - // Or if neither are non-nil - return - } else { - geocodeInProgress = true - let geocoder = CLGeocoder() - - let onCompletion: CLGeocodeCompletionHandler = { placemarks, error in - stpDispatchToMainThreadIfNecessary({ - if (placemarks?.count ?? 0) > 0 && error == nil { - let placemark = placemarks?.first - if (cityCell?.contents?.count ?? 0) == 0 - && (stateCell?.contents?.count ?? 0) == 0 - && (zipCell?.contents == zipCode) - { - // Check contents again to make sure they're still empty - // And that zipcode hasn't changed to something else - cityCell?.contents = placemark?.locality - stateCell?.contents = placemark?.administrativeArea - } - } - self.geocodeInProgress = false - }) - } - - let address = CNMutablePostalAddress() - address.postalCode = zipCode ?? "" - address.isoCountryCode = addressFieldTableViewCountryCode ?? "" - - geocoder.geocodePostalAddress( - address, - completionHandler: onCompletion - ) - } - } - - private func cell(after cell: STPAddressFieldTableViewCell?) -> STPAddressFieldTableViewCell? { - guard let cell = cell, - let cellIndex = addressCells.firstIndex(of: cell), - cellIndex + 1 < addressCells.count - else { - return nil - } - return addressCells[cellIndex + 1] - } - - func addressFieldTableViewCellDidUpdateText(_ cell: STPAddressFieldTableViewCell) { - delegate?.addressViewModelDidChange(self) - } - - func addressFieldTableViewCellDidReturn(_ cell: STPAddressFieldTableViewCell) { - _ = self.cell(after: cell)?.becomeFirstResponder() - } - - func addressFieldTableViewCellDidEndEditing(_ cell: STPAddressFieldTableViewCell) { - if cell.type == .zip { - updateCityAndState(fromZipCodeCell: cell) - } - } - -} diff --git a/Stripe/StripeiOS/Source/STPAnalyticsClient+BasicUI.swift b/Stripe/StripeiOS/Source/STPAnalyticsClient+BasicUI.swift deleted file mode 100644 index 809037ab7a5..00000000000 --- a/Stripe/StripeiOS/Source/STPAnalyticsClient+BasicUI.swift +++ /dev/null @@ -1,160 +0,0 @@ -// -// STPAnalyticsClient+BasicUI.swift -// StripeiOS -// -// Created by Yuki Tokuhiro on 1/24/24. -// - -import Foundation -@_spi(STP) import StripeCore -@_spi(STP) import StripePayments - -extension STPPaymentContext { - final class AnalyticsLogger { - let analyticsClient = STPAnalyticsClient.sharedClient - var apiClient: STPAPIClient = .shared - var product: String - lazy var commonParameters: [String: Any] = { - [ - "product": product, - ] - }() - - init(product: T.Type) { - self.product = product.stp_analyticsIdentifier - } - - // MARK: - Loading - - func logLoadStarted() { - log(event: .biLoadStarted, params: [:]) - } - - func logLoadSucceeded(loadStartDate: Date, defaultPaymentOption: STPPaymentOption?) { - let event: STPAnalyticEvent = .biLoadSucceeded - let duration = Date().timeIntervalSince(loadStartDate) - let defaultPaymentMethod: String = { - guard let defaultPaymentOption else { - return "none" - } - switch defaultPaymentOption { - case is STPApplePayPaymentOption: - return "apple_pay" - case let defaultPaymentMethod as STPPaymentMethod: - return defaultPaymentMethod.type.identifier - default: - assertionFailure() - return "unknown" - } - }() - let params: [String: Any] = [ - "duration": duration, - "selected_lpm": defaultPaymentMethod, - ] - log(event: event, params: params) - } - - func logLoadFailed(loadStartDate: Date, error: Error) { - let event: STPAnalyticEvent = .biLoadFailed - let duration = Date().timeIntervalSince(loadStartDate) - var params: [String: Any] = [ - "duration": duration, - ] - params.mergeAssertingOnOverwrites(error.serializeForV1Analytics()) - log(event: event, params: params) - } - - // MARK: - Payment - - func logPayment(status: STPPaymentStatus, loadStartDate: Date?, paymentOption: STPPaymentOption, error: Error?) { - let didSucceed: Bool - switch status { - case .userCancellation: - // Don't send analytic for cancels - return - case .success: - didSucceed = true - case .error: - didSucceed = false - @unknown default: - return - } - - let event: STPAnalyticEvent - let paymentMethodType: String - switch paymentOption { - case let paymentMethod as STPPaymentMethod: - paymentMethodType = paymentMethod.type.identifier - event = didSucceed ? .biPaymentCompleteSavedPMSuccess : .biPaymentCompleteSavedPMFailure - case let params as STPPaymentMethodParams: - paymentMethodType = params.type.identifier - event = didSucceed ? .biPaymentCompleteNewPMSuccess : .biPaymentCompleteNewPMFailure - case is STPApplePayPaymentOption: - paymentMethodType = "apple_pay" - event = didSucceed ? .biPaymentCompleteApplePaySuccess : .biPaymentCompleteApplePayFailure - default: - assertionFailure("Unknown payment option!") - return - } - - var params: [String: Any] = ["selected_lpm": paymentMethodType] - if let error { - params.mergeAssertingOnOverwrites(error.serializeForV1Analytics()) - } - if let loadStartDate { - params["duration"] = Date().timeIntervalSince(loadStartDate) - } - - log(event: event, params: params) - } - - // MARK: - UI - - func logPaymentOptionsScreenAppeared() { - log(event: .biOptionsShown, params: [:]) - } - - func logFormShown(paymentMethodType: STPPaymentMethodType) { - let event = STPAnalyticEvent.biFormShown - let params = ["selected_lpm": paymentMethodType] - log(event: event, params: params) - } - - /// - Parameter shownStartDate: The date when the form was first shown. This should never be nil. - func logDoneButtonTapped(paymentMethodType: STPPaymentMethodType, shownStartDate: Date?) { - let event = STPAnalyticEvent.biDoneButtonTapped - - var params: [String: Any] = [ - "selected_lpm": paymentMethodType, - ] - if let shownStartDate { - let duration = Date().timeIntervalSince(shownStartDate) - params["duration"] = duration - } else if NSClassFromString("XCTest") == nil { - assertionFailure("Shown start date should never be nil!") - } - - log(event: event, params: params) - } - - func logFormInteracted(paymentMethodType: STPPaymentMethodType) { - log(event: .biFormInteracted, params: [ - "selected_lpm": paymentMethodType, - ]) - } - - func logCardNumberCompleted() { - log(event: .biCardNumberCompleted, params: [:]) - } - - // MARK: - Helpers - - private func log(event: STPAnalyticEvent, params: [String: Any]) { - let analytic = GenericAnalytic(event: event, params: params.merging(commonParameters, uniquingKeysWith: { new, _ in - assertionFailure("Constructing analytics parameters with duplicate keys") - return new - })) - analyticsClient.log(analytic: analytic, apiClient: apiClient) - } - } -} diff --git a/Stripe/StripeiOS/Source/STPApplePayPaymentOption.swift b/Stripe/StripeiOS/Source/STPApplePayPaymentOption.swift deleted file mode 100644 index 14edba1fba9..00000000000 --- a/Stripe/StripeiOS/Source/STPApplePayPaymentOption.swift +++ /dev/null @@ -1,51 +0,0 @@ -// -// STPApplePayPaymentOption.swift -// StripeiOS -// -// Created by Ben Guo on 4/19/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -import Foundation -@_spi(STP) import StripeCore -@_spi(STP) import StripePaymentsUI -import UIKit - -/// An empty class representing that the user wishes to pay via Apple Pay. This can -/// be checked on an `STPPaymentContext`, e.g: -/// ``` -/// if paymentContext.selectedPaymentOption is STPApplePayPaymentOption { -/// // Don't ask the user for their card number; they want to pay with apple pay. -/// } -/// ``` -@objc public class STPApplePayPaymentOption: NSObject, STPPaymentOption { - // MARK: - STPPaymentOption - @objc public var image: UIImage { - return STPImageLibrary.applePayCardImage() - } - - @objc public var templateImage: UIImage { - // No template for Apple Pay - return STPImageLibrary.applePayCardImage() - } - - @objc public var label: String { - return String.Localized.apple_pay - } - - @objc public var isReusable: Bool { - return true - } - - // MARK: - Equality - /// :nodoc: - @objc - public override func isEqual(_ object: Any?) -> Bool { - return object is STPApplePayPaymentOption - } - - /// :nodoc: - @objc public override var hash: Int { - return NSStringFromClass(STPApplePayPaymentOption.self).hash - } -} diff --git a/Stripe/StripeiOS/Source/STPBackendAPIAdapter.swift b/Stripe/StripeiOS/Source/STPBackendAPIAdapter.swift deleted file mode 100644 index 2cd6ed58c1d..00000000000 --- a/Stripe/StripeiOS/Source/STPBackendAPIAdapter.swift +++ /dev/null @@ -1,86 +0,0 @@ -// -// STPBackendAPIAdapter.swift -// StripeiOS -// -// Created by Jack Flintermann on 1/12/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -import Foundation -import UIKit - -/// A "bridge" from our pre-built UI (`STPPaymentContext`, `STPPaymentOptionsViewController`) -/// to your backend to fetch Customer-related information needed to power those views. -/// Typically, you will not need to implement this protocol yourself. You -/// should instead use `STPCustomerContext`, which implements -/// and manages retrieving and updating a Stripe customer for you. -/// - seealso: STPCustomerContext.h -/// If you would prefer retrieving and updating your Stripe customer object via -/// your own backend instead of using `STPCustomerContext`, you should make your -/// application's API client conform to this interface. -@objc public protocol STPBackendAPIAdapter: NSObjectProtocol { - /// Retrieve the customer to be displayed inside a payment context. - /// If you are not using STPCustomerContext: - /// On your backend, retrieve the Stripe customer associated with your currently - /// logged-in user ( https://stripe.com/docs/api#retrieve_customer ), and return - /// the raw JSON response from the Stripe API. Back in your iOS app, after you've - /// called this API, deserialize your API response into an `STPCustomer` object - /// (you can use the `STPCustomerDeserializer` class to do this). - /// - seealso: STPCard - /// - Parameter completion: call this callback when you're done fetching and parsing the above information from your backend. For example, `completion(customer, nil)` (if your call succeeds) or `completion(nil, error)` if an error is returned. - func retrieveCustomer(_ completion: STPCustomerCompletionBlock?) - /// Retrieves a list of Payment Methods attached to a customer. - /// If you are implementing your own : - /// Call the list method ( https://stripe.com/docs/api/payment_methods/list ) - /// with the Stripe customer. If this API call succeeds, call `completion(paymentMethods)` - /// with the list of PaymentMethods. Otherwise, call `completion(error)` with the error - /// that occurred. - /// - Parameter completion: Call this callback with the list of Payment Methods attached to the - /// customer. For example, `completion(paymentMethods)` (if your call succeeds) or - /// `completion(error)` if an error is returned. - func listPaymentMethodsForCustomer(completion: STPPaymentMethodsCompletionBlock?) - /// Adds a Payment Method to a customer. - /// If you are implementing your own : - /// On your backend, retrieve the Stripe customer associated with your logged-in user. - /// Then, call the Attach method on the Payment Method with that customer's ID - /// ( https://stripe.com/docs/api/payment_methods/attach ). If this API call succeeds, - /// call `completion(nil)`. Otherwise, call `completion(error)` with the error that - /// occurred. - /// - Parameters: - /// - paymentMethod: A valid Payment Method - /// - completion: Call this callback when you're done adding the payment method - /// to the customer on your backend. For example, `completion(nil)` (if your call succeeds) - /// or `completion(error)` if an error is returned. - func attachPaymentMethod(toCustomer paymentMethod: STPPaymentMethod, completion: STPErrorBlock?) - - /// Deletes the given Payment Method from the customer. - /// If you are implementing your own : - /// Call the Detach method ( https://stripe.com/docs/api/payment_methods/detach ) - /// on the Payment Method. If this API call succeeds, call `completion(nil)`. - /// Otherwise, call `completion(error)` with the error that occurred. - /// - Parameters: - /// - paymentMethod: The Payment Method to delete from the customer - /// - completion: Call this callback when you're done deleting the Payment Method - /// from the customer on your backend. For example, `completion(nil)` (if your call - /// succeeds) or `completion(error)` if an error is returned. - @objc optional func detachPaymentMethod( - fromCustomer paymentMethod: STPPaymentMethod, - completion: STPErrorBlock? - ) - /// Sets the given shipping address on the customer. - /// If you are implementing your own : - /// On your backend, retrieve the Stripe customer associated with your logged-in user. - /// Then, call the Customer Update method ( https://stripe.com/docs/api#update_customer ) - /// specifying shipping to be the given shipping address. If this API call succeeds, - /// call `completion(nil)`. Otherwise, call `completion(error)` with the error that occurred. - /// - Parameters: - /// - shipping: The shipping address to set on the customer - /// - completion: call this callback when you're done updating the customer on - /// your backend. For example, `completion(nil)` (if your call succeeds) or - /// `completion(error)` if an error is returned. - /// - seealso: https://stripe.com/docs/api#update_customer - @objc optional func updateCustomer( - withShippingAddress shipping: STPAddress, - completion: STPErrorBlock? - ) -} diff --git a/Stripe/StripeiOS/Source/STPBankSelectionTableViewCell.swift b/Stripe/StripeiOS/Source/STPBankSelectionTableViewCell.swift deleted file mode 100644 index 6d7a730d288..00000000000 --- a/Stripe/StripeiOS/Source/STPBankSelectionTableViewCell.swift +++ /dev/null @@ -1,124 +0,0 @@ -// -// STPBankSelectionTableViewCell.swift -// StripeiOS -// -// Created by David Estes on 8/9/19. -// Copyright © 2019 Stripe, Inc. All rights reserved. -// - -import UIKit - -class STPBankSelectionTableViewCell: UITableViewCell { - func configure( - withBank bankBrand: STPFPXBankBrand, - theme: STPTheme, - selected: Bool, - offline: Bool, - enabled: Bool - ) { - bank = bankBrand - self.theme = theme - - backgroundColor = theme.secondaryBackgroundColor - - // Left icon - leftIcon?.image = STPLegacyImageLibrary.fpxBrandImage(for: bank) - leftIcon?.tintColor = primaryColorForPaymentOption(withSelected: selected, enabled: enabled) - - // Title label - titleLabel?.font = theme.font - titleLabel?.text = STPFPXBank.stringFrom(bank) - if offline { - let format = STPLocalizedString( - "%@ - Offline", - "Bank name when bank is offline for maintenance." - ) - titleLabel?.text = String(format: format, STPFPXBank.stringFrom(bank) ?? "") - } - titleLabel?.textColor = primaryColorForPaymentOption( - withSelected: isSelected, - enabled: enabled - ) - - // Loading indicator - activityIndicator?.tintColor = theme.accentColor - if selected { - activityIndicator?.startAnimating() - } else { - activityIndicator?.stopAnimating() - } - - setNeedsLayout() - } - - private var bank: STPFPXBankBrand! - private var theme: STPTheme = .defaultTheme - private var leftIcon: UIImageView? - private var titleLabel: UILabel? - private var activityIndicator: UIActivityIndicatorView? - - override init( - style: UITableViewCell.CellStyle, - reuseIdentifier: String? - ) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - // Left icon - let leftIcon = UIImageView() - self.leftIcon = leftIcon - contentView.addSubview(leftIcon) - - // Title label - let titleLabel = UILabel() - self.titleLabel = titleLabel - contentView.addSubview(titleLabel) - - // Loading indicator - let activityIndicator = UIActivityIndicatorView(style: .medium) - self.activityIndicator = activityIndicator - self.activityIndicator?.hidesWhenStopped = true - contentView.addSubview(activityIndicator) - } - - override func layoutSubviews() { - super.layoutSubviews() - - let midY = bounds.midY - let padding: CGFloat = 15.0 - let iconWidth: CGFloat = 26.0 - - // Left icon - leftIcon?.sizeToFit() - leftIcon?.center = CGPoint(x: padding + (iconWidth / 2.0), y: midY) - - // Activity indicator - activityIndicator?.center = CGPoint( - x: bounds.width - padding - (activityIndicator?.bounds.midX ?? 0.0), - y: midY - ) - - // Title label - var labelFrame = bounds - // not every icon is `iconWidth` wide, but give them all the same amount of space: - labelFrame.origin.x = padding + iconWidth + padding - labelFrame.size.width = - (activityIndicator?.frame.minX ?? 0.0) - padding - labelFrame.origin.x - titleLabel?.frame = labelFrame - } - - func primaryColorForPaymentOption(withSelected selected: Bool, enabled: Bool) -> UIColor { - if selected { - return theme.accentColor - } else { - return - (enabled - ? theme.primaryForegroundColor - : theme.primaryForegroundColor.withAlphaComponent(0.6)) - } - } - - required init?( - coder aDecoder: NSCoder - ) { - super.init(coder: aDecoder) - } -} diff --git a/Stripe/StripeiOS/Source/STPBankSelectionViewController.swift b/Stripe/StripeiOS/Source/STPBankSelectionViewController.swift deleted file mode 100644 index b6fb8cdd235..00000000000 --- a/Stripe/StripeiOS/Source/STPBankSelectionViewController.swift +++ /dev/null @@ -1,300 +0,0 @@ -// -// STPBankSelectionViewController.swift -// StripeiOS -// -// Created by David Estes on 8/9/19. -// Copyright © 2019 Stripe, Inc. All rights reserved. -// - -import PassKit -@_spi(STP) import StripeCore -@_spi(STP) import StripePayments -@_spi(STP) import StripePaymentsUI -import UIKit - -/// The payment methods supported by STPBankSelectionViewController. -@objc public enum STPBankSelectionMethod: Int { - /// FPX (Malaysia) - case FPX - /// An unknown payment method - case unknown -} - -/// This view controller displays a list of banks of the specified type, allowing the user to select one to pay from. -/// Once a bank is selected, it will return a PaymentMethodParams object, which you can use to confirm a PaymentIntent -/// or inspect to obtain details about the selected bank. -public class STPBankSelectionViewController: STPCoreTableViewController, UITableViewDataSource, - UITableViewDelegate -{ - /// A convenience initializer; equivalent to calling `init( bankMethod:bankMethod configuration:STPPaymentConfiguration.shared theme:STPTheme.defaultTheme`. - @objc - public convenience init( - bankMethod: STPBankSelectionMethod - ) { - self.init( - bankMethod: bankMethod, - configuration: STPPaymentConfiguration.shared, - theme: STPTheme.defaultTheme - ) - } - - @objc public convenience required init( - theme: STPTheme? - ) { - self.init( - bankMethod: .FPX, - configuration: STPPaymentConfiguration.shared, - theme: theme ?? .defaultTheme - ) - } - - /// Initializes a new `STPBankSelectionViewController` with the provided configuration and theme. Don't forget to set the `delegate` property after initialization. - /// - Parameters: - /// - bankMethod: The user will be presented with a list of banks for this payment method. STPBankSelectionMethodFPX is currently the only supported payment method. - /// - configuration: The configuration to use. This determines the Stripe publishable key to use when querying metadata about the banks. - seealso: STPPaymentConfiguration - /// - theme: The theme to use to inform the view controller's visual appearance. - seealso: STPTheme - @objc - public init( - bankMethod: STPBankSelectionMethod, - configuration: STPPaymentConfiguration, - theme: STPTheme - ) { - super.init(theme: theme) - STPAnalyticsClient.sharedClient.addClass( - toProductUsageIfNecessary: STPBankSelectionViewController.self - ) - assert(bankMethod == .FPX, "STPBankSelectionViewController currently only supports FPX.") - self.bankMethod = bankMethod - self.configuration = configuration - selectedBank = .unknown - apiClient = STPAPIClient.shared - if bankMethod == .FPX { - _refreshFPXStatus() - NotificationCenter.default.addObserver( - self, - selector: #selector(_refreshFPXStatus), - name: UIApplication.didBecomeActiveNotification, - object: nil - ) - } - title = String.Localized.bank_account - } - - /// The view controller's delegate. This must be set before showing the view controller in order for it to work properly. - seealso: STPBankSelectionViewControllerDelegate - @objc public weak var delegate: STPBankSelectionViewControllerDelegate? - - /// The API Client to use to make requests. - /// Defaults to `STPAPIClient.shared` - public var apiClient: STPAPIClient = .shared - - private var bankMethod: STPBankSelectionMethod = .unknown - private var selectedBank: STPFPXBankBrand = .unknown - private var configuration: STPPaymentConfiguration? - private weak var imageView: UIImageView? - private var headerView: STPSectionHeaderView? - private var loading = false - private var bankStatus: STPFPXBankStatusResponse? - - deinit { - NotificationCenter.default.removeObserver(self) - } - - @objc func _refreshFPXStatus() { - apiClient.retrieveFPXBankStatus(withCompletion: { bankStatusResponse, error in - if error == nil && bankStatusResponse != nil { - if let bankStatusResponse = bankStatusResponse { - self._update(withBankStatus: bankStatusResponse) - } - } - }) - } - - @objc override func createAndSetupViews() { - super.createAndSetupViews() - - tableView?.register( - STPBankSelectionTableViewCell.self, - forCellReuseIdentifier: STPBankSelectionCellReuseIdentifier - ) - - tableView?.dataSource = self - tableView?.delegate = self - tableView?.reloadData() - } - - @objc override func updateAppearance() { - super.updateAppearance() - - tableView?.reloadData() - } - - @objc override func useSystemBackButton() -> Bool { - return true - } - - func _update(withBankStatus bankStatusResponse: STPFPXBankStatusResponse) { - bankStatus = bankStatusResponse - - tableView?.beginUpdates() - if let indexPathsForVisibleRows = tableView?.indexPathsForVisibleRows { - tableView?.reloadRows(at: indexPathsForVisibleRows, with: .none) - } - tableView?.endUpdates() - } - - // MARK: - UITableView - - /// :nodoc: - @objc - public func numberOfSections(in tableView: UITableView) -> Int { - return 1 - } - - /// :nodoc: - @objc - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return STPFPXBankBrand.unknown.rawValue - } - - /// :nodoc: - @objc - public func tableView( - _ tableView: UITableView, - cellForRowAt indexPath: IndexPath - ) -> UITableViewCell { - let cell = - tableView.dequeueReusableCell( - withIdentifier: STPBankSelectionCellReuseIdentifier, - for: indexPath - ) - as? STPBankSelectionTableViewCell - let bankBrand = STPFPXBankBrand(rawValue: indexPath.row) - let selected = selectedBank == bankBrand - var offline: Bool? - if let bankBrand = bankBrand { - offline = bankStatus != nil && !(bankStatus?.bankBrandIsOnline(bankBrand) ?? false) - } - if let bankBrand = bankBrand { - cell?.configure( - withBank: bankBrand, - theme: theme, - selected: selected, - offline: offline ?? false, - enabled: !loading - ) - } - return cell! - } - - /// :nodoc: - @objc - public func tableView( - _ tableView: UITableView, - willDisplay cell: UITableViewCell, - forRowAt indexPath: IndexPath - ) { - let topRow = indexPath.row == 0 - let bottomRow = - self.tableView(tableView, numberOfRowsInSection: indexPath.section) - 1 == indexPath.row - cell.stp_setBorderColor(theme.tertiaryBackgroundColor) - cell.stp_setTopBorderHidden(!topRow) - cell.stp_setBottomBorderHidden(!bottomRow) - cell.stp_setFakeSeparatorColor(theme.quaternaryBackgroundColor) - cell.stp_setFakeSeparatorLeftInset(15.0) - } - - /// :nodoc: - @objc - public func tableView( - _ tableView: UITableView, - heightForFooterInSection section: Int - ) - -> CGFloat - { - return 27.0 - } - - /// :nodoc: - @objc - public func tableView( - _ tableView: UITableView, - shouldHighlightRowAt indexPath: IndexPath - ) - -> Bool - { - return !loading - } - - /// :nodoc: - @objc - public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - if loading { - return // Don't allow user interaction if we're currently setting up a payment method - } - loading = true - tableView.deselectRow(at: indexPath, animated: true) - let bankIndex = indexPath.row - selectedBank = STPFPXBankBrand(rawValue: bankIndex) ?? .unknown - tableView.reloadSections( - NSIndexSet(index: indexPath.section) as IndexSet, - with: .none - ) - - let fpx = STPPaymentMethodFPXParams() - fpx.bank = STPFPXBankBrand(rawValue: bankIndex) ?? .unknown - // Create and return a Payment Method Params object - let paymentMethodParams = STPPaymentMethodParams( - fpx: fpx, - billingDetails: nil, - metadata: nil - ) - if delegate?.responds( - to: #selector( - STPBankSelectionViewControllerDelegate.bankSelectionViewController( - _: - didCreatePaymentMethodParams: - )) - ) ?? false { - delegate?.bankSelectionViewController( - self, - didCreatePaymentMethodParams: paymentMethodParams - ) - } - } - - required init?( - coder aDecoder: NSCoder - ) { - super.init(coder: aDecoder) - } - - required init( - nibName nibNameOrNil: String?, - bundle nibBundleOrNil: Bundle? - ) { - fatalError("init(nibName:bundle:) has not been implemented") - } -} - -/// An `STPBankSelectionViewControllerDelegate` is notified when a user selects a bank. -@objc public protocol STPBankSelectionViewControllerDelegate: NSObjectProtocol { - /// This is called when the user selects a bank. - /// You can use the returned PaymentMethodParams to confirm a PaymentIntent, or inspect - /// it to obtain details about the selected bank. - /// Once you're done, you'll want to dismiss (or pop) the view controller. - /// - Parameters: - /// - bankViewController: the view controller that created the PaymentMethodParams - /// - paymentMethodParams: the PaymentMethodParams that was created. - seealso: STPPaymentMethodParams - @objc(bankSelectionViewController:didCreatePaymentMethodParams:) - func bankSelectionViewController( - _ bankViewController: STPBankSelectionViewController, - didCreatePaymentMethodParams paymentMethodParams: STPPaymentMethodParams - ) -} - -private let STPBankSelectionCellReuseIdentifier = "STPBankSelectionCellReuseIdentifier" - -/// :nodoc: -@_spi(STP) extension STPBankSelectionViewController: STPAnalyticsProtocol { - @_spi(STP) public static var stp_analyticsIdentifier = "STPBankSelectionViewController" -} diff --git a/Stripe/StripeiOS/Source/STPBasicUIAnalyticsSerializer.swift b/Stripe/StripeiOS/Source/STPBasicUIAnalyticsSerializer.swift deleted file mode 100644 index a0f9aaa19cf..00000000000 --- a/Stripe/StripeiOS/Source/STPBasicUIAnalyticsSerializer.swift +++ /dev/null @@ -1,84 +0,0 @@ -// -// STPAnalyticsClient+BasicUI.swift -// StripeiOS -// -// Created by David Estes on 6/30/22. -// Copyright © 2022 Stripe, Inc. All rights reserved. -// - -import Foundation -@_spi(STP) import StripeCore -@_spi(STP) import StripePayments - -@objc(STPBasicUIAnalyticsSerializer) -class STPBasicUIAnalyticsSerializer: NSObject, STPAnalyticsSerializer { - static func serializeConfiguration( - _ configuration: NSObject - ) -> [String: - String] - { - var dictionary: [String: String] = [:] - dictionary["publishable_key"] = STPAPIClient.shared.publishableKey ?? "unknown" - - guard let configuration = configuration as? STPPaymentConfiguration else { - return dictionary - } - - if configuration.applePayEnabled && !configuration.fpxEnabled { - dictionary["additional_payment_methods"] = "default" - } else if !configuration.applePayEnabled && !configuration.fpxEnabled { - dictionary["additional_payment_methods"] = "none" - } else if !configuration.applePayEnabled && configuration.fpxEnabled { - dictionary["additional_payment_methods"] = "fpx" - } else if configuration.applePayEnabled && configuration.fpxEnabled { - dictionary["additional_payment_methods"] = "applepay,fpx" - } - - switch configuration.requiredBillingAddressFields { - case .none: - dictionary["required_billing_address_fields"] = "none" - case .postalCode: - dictionary["required_billing_address_fields"] = "zip" - case .full: - dictionary["required_billing_address_fields"] = "full" - case .name: - dictionary["required_billing_address_fields"] = "name" - default: - fatalError() - } - - var shippingFields: [String] = [] - if let shippingAddressFields = configuration.requiredShippingAddressFields { - if shippingAddressFields.contains(.name) { - shippingFields.append("name") - } - if shippingAddressFields.contains(.emailAddress) { - shippingFields.append("email") - } - if shippingAddressFields.contains(.postalAddress) { - shippingFields.append("address") - } - if shippingAddressFields.contains(.phoneNumber) { - shippingFields.append("phone") - } - } - - if shippingFields.isEmpty { - shippingFields.append("none") - } - dictionary["required_shipping_address_fields"] = shippingFields.joined(separator: "_") - - switch configuration.shippingType { - case .shipping: - dictionary["shipping_type"] = "shipping" - case .delivery: - dictionary["shipping_type"] = "delivery" - @unknown default: - break - } - - dictionary["company_name"] = configuration.companyName - dictionary["apple_merchant_identifier"] = configuration.appleMerchantIdentifier ?? "unknown" - return dictionary - } -} diff --git a/Stripe/StripeiOS/Source/STPBlocks.swift b/Stripe/StripeiOS/Source/STPBlocks.swift deleted file mode 100644 index e750cc71983..00000000000 --- a/Stripe/StripeiOS/Source/STPBlocks.swift +++ /dev/null @@ -1,44 +0,0 @@ -// -// STPBlocks.swift -// StripeiOS -// -// Created by David Estes on 6/30/22. -// Copyright © 2022 Stripe, Inc. All rights reserved. -// - -import Foundation -import PassKit - -/// A callback to be run with a response from the Stripe API containing information about the online status of FPX banks. -/// - Parameters: -/// - bankStatusResponse: The response from Stripe containing the status of the various banks. Will be nil if an error occurs. - seealso: STPFPXBankStatusResponse -/// - error: The error returned from the response, or nil if none occurs. -typealias STPFPXBankStatusCompletionBlock = (STPFPXBankStatusResponse?, Error?) -> Void - -/// These values control the labels used in the shipping info collection form. -@objc public enum STPShippingType: Int { - /// Shipping the purchase to the provided address using a third-party - /// shipping company. - case shipping - /// Delivering the purchase by the seller. - case delivery -} - -/// An enum representing the status of a shipping address validation. -@objc public enum STPShippingStatus: Int { - /// The shipping address is valid. - case valid - /// The shipping address is invalid. - case invalid -} - -/// A callback to be run with a validation result and shipping methods for a -/// shipping address. -/// - Parameters: -/// - status: An enum representing whether the shipping address is valid. -/// - shippingValidationError: If the shipping address is invalid, an error describing the issue with the address. If no error is given and the address is invalid, the default error message will be used. -/// - shippingMethods: The shipping methods available for the address. -/// - selectedShippingMethod: The default selected shipping method for the address. -public typealias STPShippingMethodsCompletionBlock = ( - STPShippingStatus, Error?, [PKShippingMethod]?, PKShippingMethod? -) -> Void diff --git a/Stripe/StripeiOS/Source/STPCameraView.swift b/Stripe/StripeiOS/Source/STPCameraView.swift deleted file mode 100644 index 17fa42470b5..00000000000 --- a/Stripe/StripeiOS/Source/STPCameraView.swift +++ /dev/null @@ -1,77 +0,0 @@ -// -// STPCameraView.swift -// StripeiOS -// -// Created by David Estes on 8/17/20. -// Copyright © 2020 Stripe, Inc. All rights reserved. -// - -import AVFoundation -import UIKit - -@available(macCatalyst 14.0, *) -class STPCameraView: UIView { - private var flashLayer: CALayer? - - var captureSession: AVCaptureSession? { - get { - return (videoPreviewLayer.session)! - } - set(captureSession) { - videoPreviewLayer.session = captureSession - } - } - - var videoPreviewLayer: AVCaptureVideoPreviewLayer { - return layer as! AVCaptureVideoPreviewLayer - } - - func playSnapshotAnimation() { - CATransaction.begin() - CATransaction.setValue( - kCFBooleanTrue, - forKey: kCATransactionDisableActions - ) - flashLayer?.frame = CGRect( - x: 0, - y: 0, - width: layer.bounds.size.width, - height: layer.bounds.size.height - ) - flashLayer?.opacity = 1.0 - CATransaction.commit() - DispatchQueue.main.async(execute: { - let fadeAnim = CABasicAnimation(keyPath: "opacity") - fadeAnim.fromValue = NSNumber(value: 1.0) - fadeAnim.toValue = NSNumber(value: 0.0) - fadeAnim.duration = 1.0 - self.flashLayer?.add(fadeAnim, forKey: "opacity") - self.flashLayer?.opacity = 0.0 - }) - } - - override init( - frame: CGRect - ) { - super.init(frame: frame) - flashLayer = CALayer() - if let flashLayer = flashLayer { - layer.addSublayer(flashLayer) - } - flashLayer?.masksToBounds = true - flashLayer?.backgroundColor = UIColor.black.cgColor - flashLayer?.opacity = 0.0 - layer.masksToBounds = true - videoPreviewLayer.videoGravity = .resizeAspectFill - } - - override class var layerClass: AnyClass { - return AVCaptureVideoPreviewLayer.self - } - - required init?( - coder aDecoder: NSCoder - ) { - super.init(coder: aDecoder) - } -} diff --git a/Stripe/StripeiOS/Source/STPCard+BasicUI.swift b/Stripe/StripeiOS/Source/STPCard+BasicUI.swift deleted file mode 100644 index 2b90f89209b..00000000000 --- a/Stripe/StripeiOS/Source/STPCard+BasicUI.swift +++ /dev/null @@ -1,30 +0,0 @@ -// -// STPCard+BasicUI.swift -// StripeiOS -// -// Created by David Estes on 6/30/22. -// Copyright © 2022 Stripe, Inc. All rights reserved. -// - -import Foundation -import UIKit - -extension STPCard: STPPaymentOption { - // MARK: - STPPaymentOption - @objc public var image: UIImage { - return STPImageLibrary.cardBrandImage(for: brand) - } - - @objc public var templateImage: UIImage { - return STPImageLibrary.templatedBrandImage(for: brand) - } - - @objc public var label: String { - let brand = STPCard.string(from: self.brand) - return "\(brand) \(last4 )" - } - - @objc public var isReusable: Bool { - return true - } -} diff --git a/Stripe/StripeiOS/Source/STPCardScanner.swift b/Stripe/StripeiOS/Source/STPCardScanner.swift deleted file mode 100644 index c55e104b467..00000000000 --- a/Stripe/StripeiOS/Source/STPCardScanner.swift +++ /dev/null @@ -1,488 +0,0 @@ -// -// STPCardScanner.swift -// StripeiOS -// -// Created by David Estes on 8/17/20. -// Copyright © 2020 Stripe, Inc. All rights reserved. -// - -import AVFoundation -import Foundation -@_spi(STP) import StripeCore -@_spi(STP) import StripePayments -@_spi(STP) import StripePaymentsUI -import UIKit -import Vision - -enum STPCardScannerError: Int { - /// Camera not available. - case cameraNotAvailable -} - -@available(macCatalyst 14.0, *) -@objc protocol STPCardScannerDelegate: NSObjectProtocol { - @objc(cardScanner:didFinishWithCardParams:error:) func cardScanner( - _ scanner: STPCardScanner, - didFinishWith cardParams: - STPPaymentMethodCardParams?, - error: Error?) -} - -@available(macCatalyst 14.0, *) -@objc(STPCardScanner_legacy) -class STPCardScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelegate { - // iOS will kill the app if it tries to request the camera without an NSCameraUsageDescription - static let cardScanningAvailableCameraHasUsageDescription = { - return - (Bundle.main.infoDictionary?["NSCameraUsageDescription"] != nil - || Bundle.main.localizedInfoDictionary?["NSCameraUsageDescription"] != nil) - }() - - static var cardScanningAvailable: Bool { - // Always allow in tests: - if NSClassFromString("XCTest") != nil { - return true - } - return cardScanningAvailableCameraHasUsageDescription - } - - weak var cameraView: STPCameraView? - - var feedbackGenerator: UINotificationFeedbackGenerator? - - @objc public var deviceOrientation: UIDeviceOrientation { - get { - return stp_deviceOrientation - } - set(newDeviceOrientation) { - stp_deviceOrientation = newDeviceOrientation - - // This is an optimization for portrait mode: The card will be centered in the screen, - // so we can ignore the top and bottom. We'll use the whole frame in landscape. - let kSTPCardScanningScreenCenter = CGRect( - x: 0, y: CGFloat(0.3), width: 1, height: CGFloat(0.4)) - - // iOS camera image data is returned in LandcapeLeft orientation by default. We'll flip it as needed: - switch newDeviceOrientation { - case .portraitUpsideDown: - videoOrientation = .portraitUpsideDown - textOrientation = .left - regionOfInterest = kSTPCardScanningScreenCenter - case .landscapeLeft: - videoOrientation = .landscapeRight - textOrientation = .up - regionOfInterest = CGRect(x: 0, y: 0, width: 1, height: 1) - case .landscapeRight: - videoOrientation = .landscapeLeft - textOrientation = .down - regionOfInterest = CGRect(x: 0, y: 0, width: 1, height: 1) - case .portrait, .faceUp, .faceDown, .unknown: - fallthrough - default: - videoOrientation = .portrait - textOrientation = .right - regionOfInterest = kSTPCardScanningScreenCenter - } - cameraView?.videoPreviewLayer.connection?.videoOrientation = videoOrientation - } - } - - override init() { - } - - init(delegate: STPCardScannerDelegate?) { - super.init() - self.delegate = delegate - captureSessionQueue = DispatchQueue(label: "com.stripe.CardScanning.CaptureSessionQueue") - deviceOrientation = UIDevice.current.orientation - } - - func start() { - if isScanning { - return - } - STPAnalyticsClient.sharedClient.addClass(toProductUsageIfNecessary: STPCardScanner.self) - startTime = Date() - - isScanning = true - timeoutTime = nil - feedbackGenerator = UINotificationFeedbackGenerator() - feedbackGenerator?.prepare() - - captureSessionQueue?.async(execute: { - #if targetEnvironment(simulator) - // Camera not supported on Simulator - self.stopWithError(STPCardScanner.stp_cardScanningError()) - return - #else - self.detectedNumbers = NSCountedSet() - self.detectedExpirations = NSCountedSet() - self.setupCamera() - DispatchQueue.main.async(execute: { - self.cameraView?.captureSession = self.captureSession - self.cameraView?.videoPreviewLayer.connection?.videoOrientation = - self.videoOrientation - }) - #endif - }) - } - - func stop() { - stopWithError(nil) - } - - private weak var delegate: STPCardScannerDelegate? - private var captureDevice: AVCaptureDevice? - private var captureSession: AVCaptureSession? - private var captureSessionQueue: DispatchQueue? - private var videoDataOutput: AVCaptureVideoDataOutput? - private var videoDataOutputQueue: DispatchQueue? - private var textRequest: VNRecognizeTextRequest? - private var isScanning = false - - private var timeoutTime: Date? - private var didTimeout: Bool { - if let timeoutTime = timeoutTime { - return timeoutTime <= Date() - } - return false - } - - private var stp_deviceOrientation: UIDeviceOrientation! - private var videoOrientation: AVCaptureVideoOrientation! - private var textOrientation: CGImagePropertyOrientation! - private var regionOfInterest = CGRect.zero - private var detectedNumbers = NSCountedSet() - private var detectedExpirations = NSCountedSet() - private var startTime: Date? - - // MARK: Public - - class func stp_cardScanningError() -> Error { - let userInfo = [ - NSLocalizedDescriptionKey: String.Localized.allow_camera_access, - STPError.errorMessageKey: "The camera couldn't be used.", - ] - return NSError( - domain: STPCardScannerErrorDomain, - code: STPCardScannerError.cameraNotAvailable.rawValue, - userInfo: userInfo) - } - - deinit { - if isScanning { - captureDevice?.unlockForConfiguration() - captureSession?.stopRunning() - } - } - - func stopWithError(_ error: Error?) { - if isScanning { - finish(with: nil, error: error) - } - } - - // MARK: Setup - func setupCamera() { - weak var weakSelf = self - textRequest = VNRecognizeTextRequest(completionHandler: { request, error in - let strongSelf = weakSelf - if !(strongSelf?.isScanning ?? false) { - return - } - if error != nil { - strongSelf?.stopWithError(STPCardScanner.stp_cardScanningError()) - return - } - strongSelf?.processVNRequest(request) - }) - - let captureDevice = AVCaptureDevice.default( - .builtInWideAngleCamera, for: .video, position: .back) - self.captureDevice = captureDevice - - captureSession = AVCaptureSession() - captureSession?.sessionPreset = .hd1920x1080 - - var deviceInput: AVCaptureDeviceInput? - do { - if let captureDevice = captureDevice { - deviceInput = try AVCaptureDeviceInput(device: captureDevice) - } - } catch { - stopWithError(STPCardScanner.stp_cardScanningError()) - return - } - - if let deviceInput = deviceInput { - if captureSession?.canAddInput(deviceInput) ?? false { - captureSession?.addInput(deviceInput) - } else { - stopWithError(STPCardScanner.stp_cardScanningError()) - return - } - } - - videoDataOutputQueue = DispatchQueue(label: "com.stripe.CardScanning.VideoDataOutputQueue") - videoDataOutput = AVCaptureVideoDataOutput() - videoDataOutput?.alwaysDiscardsLateVideoFrames = true - videoDataOutput?.setSampleBufferDelegate(self, queue: videoDataOutputQueue) - - // This is the recommended pixel buffer format for Vision: - videoDataOutput?.videoSettings = [ - kCVPixelBufferPixelFormatTypeKey as String: - kCVPixelFormatType_420YpCbCr8BiPlanarFullRange, - ] - - if let videoDataOutput = videoDataOutput { - if captureSession?.canAddOutput(videoDataOutput) ?? false { - captureSession?.addOutput(videoDataOutput) - } else { - stopWithError(STPCardScanner.stp_cardScanningError()) - return - } - } - - // This improves recognition quality, but means the VideoDataOutput buffers won't match what we're seeing on screen. - videoDataOutput?.connection(with: .video)?.preferredVideoStabilizationMode = .auto - - captureSession?.startRunning() - - do { - try self.captureDevice?.lockForConfiguration() - self.captureDevice?.autoFocusRangeRestriction = .near - } catch { - } - } - - // MARK: Processing - func captureOutput( - _ output: AVCaptureOutput, - didOutput sampleBuffer: CMSampleBuffer, - from connection: AVCaptureConnection - ) { - if !isScanning { - return - } - let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) - if pixelBuffer == nil { - return - } - textRequest?.recognitionLevel = .accurate - textRequest?.usesLanguageCorrection = false - textRequest?.regionOfInterest = regionOfInterest - var handler: VNImageRequestHandler? - if let pixelBuffer = pixelBuffer { - handler = VNImageRequestHandler( - cvPixelBuffer: pixelBuffer, orientation: textOrientation, options: [:]) - } - do { - try handler?.perform([textRequest].compactMap { $0 }) - } catch { - } - } - - func processVNRequest(_ request: VNRequest) { - var allNumbers: [String] = [] - for observation in request.results ?? [] { - guard let observation = observation as? VNRecognizedTextObservation else { - continue - } - let candidates = observation.topCandidates(5) - let topCandidate = candidates.first?.string - if STPCardValidator.sanitizedNumericString(for: topCandidate ?? "").count >= 4 { - allNumbers.append(topCandidate ?? "") - } - for recognizedText in candidates { - let possibleNumber = STPCardValidator.sanitizedNumericString( - for: recognizedText.string) - if possibleNumber.count < 4 { - continue // This probably isn't something we're interested in, so don't bother processing it. - } - - // First strategy: We check if Vision sent us a number in a group on its own. If that fails, we'll try - // to catch it later when we iterate over all the numbers. - if STPCardValidator.validationState( - forNumber: possibleNumber, validatingCardBrand: true) - == .valid - { - addDetectedNumber(possibleNumber) - } else if possibleNumber.count >= 4 && possibleNumber.count <= 6 - && STPStringUtils.stringMayContainExpirationDate(recognizedText.string) - { - // Try to parse anything that looks like an expiration date. - let expirationString = STPStringUtils.expirationDateString( - from: recognizedText.string) - let sanitizedExpiration = STPCardValidator.sanitizedNumericString( - for: expirationString ?? "") - let month = (sanitizedExpiration as NSString).substring(to: 2) - let year = (sanitizedExpiration as NSString).substring(from: 2) - - // Ignore expiration dates 10+ years in the future, as they're likely to be incorrect recognitions - let calendar = Calendar(identifier: .gregorian) - let presentYear = calendar.component(.year, from: Date()) - let maxYear = (presentYear % 100) + 10 - - if STPCardValidator.validationState(forExpirationYear: year, inMonth: month) - == .valid - && Int(year) ?? 0 < maxYear - { - addDetectedExpiration(sanitizedExpiration) - } - } - } - } - // Second strategy: We look for consecutive groups of 4/4/4/4 or 4/6/5 - // Vision is sending us groups like ["1234 565", "1234 1"], so we'll normalize these into groups with spaces: - let allGroups = allNumbers.joined(separator: " ").components(separatedBy: " ") - if allGroups.count < 3 { - return - } - for i in 0..<(allGroups.count - 3) { - let string1 = allGroups[i] - let string2 = allGroups[i + 1] - let string3 = allGroups[i + 2] - var string4 = "" - if i + 3 < allGroups.count { - string4 = allGroups[i + 3] - } - // Then we'll go through each group and build a potential match: - let potentialCardString = "\(string1)\(string2)\(string3)\(string4)" - let potentialAmexString = "\(string1)\(string2)\(string3)" - - // Then we'll add valid matches. It's okay if we add a number a second time after doing so above, as the success of that first pass means it's more likely to be a good match. - if STPCardValidator.validationState( - forNumber: potentialCardString, validatingCardBrand: true) - == .valid - { - addDetectedNumber(potentialCardString) - } else if STPCardValidator.validationState( - forNumber: potentialAmexString, validatingCardBrand: true) == .valid - { - addDetectedNumber(potentialAmexString) - } - } - } - - func addDetectedNumber(_ number: String) { - detectedNumbers.add(number) - - // Set a timeout: If we don't get enough scans in the next 0.6 seconds, we'll use the best option we have. - if timeoutTime == nil { - self.timeoutTime = Date().addingTimeInterval(kSTPCardScanningTimeout) - weak var weakSelf = self - DispatchQueue.main.async(execute: { - let strongSelf = weakSelf - strongSelf?.cameraView?.playSnapshotAnimation() - strongSelf?.feedbackGenerator?.notificationOccurred(.success) - }) - // Just in case we don't get any frames, add another call to `finishIfReady` after timeoutTime to check - videoDataOutputQueue?.asyncAfter( - deadline: DispatchTime.now() + kSTPCardScanningTimeout, - execute: { - let strongSelf = weakSelf - if strongSelf?.isScanning ?? false { - strongSelf?.finishIfReady() - } - }) - } - - if (detectedNumbers.count(for: number)) >= kSTPCardScanningMinimumValidScans { - finishIfReady() - } - } - - func addDetectedExpiration(_ expiration: String) { - detectedExpirations.add(expiration) - if (detectedExpirations.count(for: expiration)) >= kSTPCardScanningMinimumValidScans { - finishIfReady() - } - } - - // MARK: Completion - func finishIfReady() { - if !isScanning { - return - } - let detectedNumbers = self.detectedNumbers - let detectedExpirations = self.detectedExpirations - - let topNumber = (detectedNumbers.allObjects as NSArray).sortedArray(comparator: { - obj1, obj2 in - let c1 = detectedNumbers.count(for: obj1) - let c2 = detectedNumbers.count(for: obj2) - if c1 < c2 { - return .orderedAscending - } else if c1 > c2 { - return .orderedDescending - } else { - return .orderedSame - } - }).last - let topExpiration = (detectedExpirations.allObjects as NSArray).sortedArray(comparator: { - obj1, obj2 in - let c1 = detectedExpirations.count(for: obj1) - let c2 = detectedExpirations.count(for: obj2) - if c1 < c2 { - return .orderedAscending - } else if c1 > c2 { - return .orderedDescending - } else { - return .orderedSame - } - }).last - - var didSeeEnoughScans = false - if let topNumber = topNumber, let topExpiration = topExpiration { - didSeeEnoughScans = detectedNumbers.count(for: topNumber) >= kSTPCardScanningMinimumValidScans && - detectedExpirations.count(for: topExpiration) >= kSTPCardScanningMinimumValidScans - } - if didTimeout || didSeeEnoughScans { - let params = STPPaymentMethodCardParams() - params.number = topNumber as? String - if let topExpiration = topExpiration { - params.expMonth = NSNumber( - value: Int((topExpiration as! NSString).substring(to: 2)) ?? 0) - params.expYear = NSNumber( - value: Int((topExpiration as! NSString).substring(from: 2)) ?? 0) - } - finish(with: params, error: nil) - } - } - - func finish(with params: STPPaymentMethodCardParams?, error: Error?) { - var duration: TimeInterval? - if let startTime = startTime { - duration = Date().timeIntervalSince(startTime) - } - isScanning = false - captureDevice?.unlockForConfiguration() - captureSession?.stopRunning() - - DispatchQueue.main.async(execute: { - if params == nil { - STPAnalyticsClient.sharedClient.logCardScanCancelled(withDuration: duration ?? 0.0) - } else { - STPAnalyticsClient.sharedClient.logCardScanSucceeded(withDuration: duration ?? 0.0) - } - self.feedbackGenerator = nil - - self.cameraView?.captureSession = nil - self.delegate?.cardScanner(self, didFinishWith: params, error: error) - }) - } - - // MARK: Orientation -} - -// The number of successful scans required for both card number and expiration date before returning a result. -private let kSTPCardScanningMinimumValidScans = 2 -// Once one successful scan is found, we'll stop scanning after this many seconds. -private let kSTPCardScanningTimeout: TimeInterval = 0.6 -let STPCardScannerErrorDomain = "STPCardScannerErrorDomain" - -/// :nodoc: -@available(macCatalyst 14.0, *) -extension STPCardScanner: STPAnalyticsProtocol { - static var stp_analyticsIdentifier = "STPCardScanner" -} diff --git a/Stripe/StripeiOS/Source/STPCardScannerTableViewCell.swift b/Stripe/StripeiOS/Source/STPCardScannerTableViewCell.swift deleted file mode 100644 index 7692e148785..00000000000 --- a/Stripe/StripeiOS/Source/STPCardScannerTableViewCell.swift +++ /dev/null @@ -1,67 +0,0 @@ -// -// STPCardScannerTableViewCell.swift -// StripeiOS -// -// Created by David Estes on 8/17/20. -// Copyright © 2020 Stripe, Inc. All rights reserved. -// - -import UIKit - -@available(macCatalyst 14.0, *) -class STPCardScannerTableViewCell: UITableViewCell { - private(set) weak var cameraView: STPCameraView? - - private var _theme: STPTheme? - var theme: STPTheme? { - get { - _theme - } - set(theme) { - _theme = theme - updateAppearance() - } - } - - let cardSizeRatio: CGFloat = 2.125 / 3.370 // ID-1 card size (in inches) - - override init( - style: UITableViewCell.CellStyle, - reuseIdentifier: String? - ) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - let cameraView = STPCameraView(frame: bounds) - contentView.addSubview(cameraView) - self.cameraView = cameraView - theme = STPTheme.defaultTheme - self.cameraView?.translatesAutoresizingMaskIntoConstraints = false - contentView.addConstraints( - [ - cameraView.heightAnchor.constraint( - equalTo: cameraView.widthAnchor, - multiplier: cardSizeRatio - ), - cameraView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: 0), - cameraView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 0), - cameraView.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: 0), - cameraView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 0), - ]) - updateAppearance() - } - - override func layoutSubviews() { - - super.layoutSubviews() - } - - @objc func updateAppearance() { - // The first few frames of the camera view will be black, so our background should be black too. - cameraView?.backgroundColor = UIColor.black - } - - required init?( - coder aDecoder: NSCoder - ) { - super.init(coder: aDecoder) - } -} diff --git a/Stripe/StripeiOS/Source/STPCardValidationState.swift b/Stripe/StripeiOS/Source/STPCardValidationState.swift deleted file mode 100644 index 48e1f46b0e9..00000000000 --- a/Stripe/StripeiOS/Source/STPCardValidationState.swift +++ /dev/null @@ -1,9 +0,0 @@ -// -// STPCardValidationState.swift -// StripeiOS -// -// Created by Jack Flintermann on 8/7/15. -// Copyright (c) 2015 Stripe, Inc. All rights reserved. -// - -import Foundation diff --git a/Stripe/StripeiOS/Source/STPCoreScrollViewController.swift b/Stripe/StripeiOS/Source/STPCoreScrollViewController.swift deleted file mode 100644 index de3b7bbf15d..00000000000 --- a/Stripe/StripeiOS/Source/STPCoreScrollViewController.swift +++ /dev/null @@ -1,62 +0,0 @@ -// -// STPCoreScrollViewController.swift -// StripeiOS -// -// Created by Brian Dorfman on 1/6/17. -// Copyright © 2017 Stripe, Inc. All rights reserved. -// - -import Foundation -@_spi(STP) import StripeUICore -import UIKit - -/// This is the base class for all Stripe scroll view controllers. It is intended -/// for use only by Stripe classes, you should not subclass it yourself in your app. -public class STPCoreScrollViewController: STPCoreViewController { - /// This returns the scroll view being managed by the view controller - @objc public lazy var scrollView: UIScrollView = { - createScrollView() - }() - - /// This method is used by the base implementation to create the object - /// backing the `scrollView` property. Subclasses can override to change the - /// type of the scroll view (eg UITableView or UICollectionView instead of - /// UIScrollView). - - func createScrollView() -> UIScrollView { - return UIScrollView() - } - - override func createAndSetupViews() { - super.createAndSetupViews() - view.addSubview(scrollView) - } - - /// :nodoc: - @objc - public override func viewDidLoad() { - super.viewDidLoad() - - scrollView.contentInsetAdjustmentBehavior = .automatic - } - - /// :nodoc: - @objc - public override func viewDidLayoutSubviews() { - super.viewDidLayoutSubviews() - scrollView.frame = view.bounds - } - - @objc override func updateAppearance() { - super.updateAppearance() - - scrollView.backgroundColor = theme.primaryBackgroundColor - scrollView.tintColor = theme.accentColor - - if theme.primaryBackgroundColor.isBright { - scrollView.indicatorStyle = .black - } else { - scrollView.indicatorStyle = .white - } - } -} diff --git a/Stripe/StripeiOS/Source/STPCoreTableViewController.swift b/Stripe/StripeiOS/Source/STPCoreTableViewController.swift deleted file mode 100644 index 5d7105e38b2..00000000000 --- a/Stripe/StripeiOS/Source/STPCoreTableViewController.swift +++ /dev/null @@ -1,54 +0,0 @@ -// -// STPCoreTableViewController.swift -// StripeiOS -// -// Created by Brian Dorfman on 1/6/17. -// Copyright © 2017 Stripe, Inc. All rights reserved. -// - -import Foundation -import UIKit - -/// This is the base class for all Stripe scroll view controllers. It is intended -/// for use only by Stripe classes, you should not subclass it yourself in your app. -/// It inherits from STPCoreScrollViewController and changes the type of the -/// created scroll view to UITableView, as well as other shared table view logic. -public class STPCoreTableViewController: STPCoreScrollViewController { - /// This points to the same object as `STPCoreScrollViewController`'s `scrollView` - /// property but with the type cast to `UITableView` - - @objc public var tableView: UITableView? { - return (scrollView as? UITableView) - } - - override func createScrollView() -> UIScrollView { - let tableView = UITableView(frame: CGRect.zero, style: .grouped) - tableView.sectionHeaderHeight = 30 - - return tableView - } - - /// :nodoc: - @objc - public override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - - tableView?.reloadData() - } - - @objc override func updateAppearance() { - super.updateAppearance() - tableView?.separatorStyle = .none // handle this with fake separator views for flexibility - } - - /// :nodoc: - @objc - public func tableView( - _ tableView: UITableView, - heightForHeaderInSection section: Int - ) - -> CGFloat - { - return 0.01 - } -} diff --git a/Stripe/StripeiOS/Source/STPCoreViewController.swift b/Stripe/StripeiOS/Source/STPCoreViewController.swift deleted file mode 100644 index 105b544d8e6..00000000000 --- a/Stripe/StripeiOS/Source/STPCoreViewController.swift +++ /dev/null @@ -1,162 +0,0 @@ -// -// STPCoreViewController.swift -// StripeiOS -// -// Created by Brian Dorfman on 1/6/17. -// Copyright © 2017 Stripe, Inc. All rights reserved. -// - -@_spi(STP) import StripeUICore -import UIKit - -/// This is the base class for all Stripe view controllers. It is intended for use -/// only by Stripe classes, you should not subclass it yourself in your app. -/// It theming, back/cancel button management, and other shared logic for -/// Stripe view controllers. -public class STPCoreViewController: UIViewController { - /// A convenience initializer; equivalent to calling `init(theme: STPTheme.defaultTheme)`. - @objc - public convenience init() { - self.init(theme: STPTheme.defaultTheme) - } - - /// Initializes a new view controller with the specified theme - /// - Parameter theme: The theme to use to inform the view controller's visual appearance. - seealso: STPTheme - @objc public required init( - theme: STPTheme? - ) { - super.init(nibName: nil, bundle: nil) - commonInit(with: theme) - } - - /// Passes through to the default UIViewController behavior for this initializer, - /// and then also sets the default theme as in `init` - @objc public required override init( - nibName nibNameOrNil: String?, - bundle nibBundleOrNil: Bundle? - ) { - super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) - commonInit(with: STPTheme.defaultTheme) - } - - /// Passes through to the default UIViewController behavior for this initializer, - /// and then also sets the default theme as in `init` - @objc public required init?( - coder aDecoder: NSCoder - ) { - super.init(coder: aDecoder) - commonInit(with: STPTheme.defaultTheme) - } - - private var _theme: STPTheme = STPTheme.defaultTheme - @objc var theme: STPTheme { - get { - _theme - } - set(theme) { - _theme = theme - updateAppearance() - } - } - @objc var cancelItem: UIBarButtonItem? - - /// All designated initializers funnel through this method to do their setup - /// - Parameter theme: Initial theme for this view controller - func commonInit(with theme: STPTheme?) { - if let theme = theme { - _theme = theme - } else { - _theme = .defaultTheme - } - - if !useSystemBackButton() { - cancelItem = UIBarButtonItem( - barButtonSystemItem: .cancel, - target: self, - action: #selector(STPAddCardViewController.handleCancelTapped(_:)) - ) - cancelItem?.accessibilityIdentifier = "CoreViewControllerCancelIdentifier" - - stp_navigationItemProxy?.leftBarButtonItem = cancelItem - } - - NotificationCenter.default.addObserver( - self, - selector: #selector(STPAddCardViewController.updateAppearance), - name: UIContentSizeCategory.didChangeNotification, - object: nil - ) - } - - /// Called in viewDidLoad after doing base implementation, before - /// calling updateAppearance - func createAndSetupViews() { - // do nothing - } - - // These viewDidX() methods have significant code done - // in the base class and super must be called if they are overidden - /// :nodoc: - @objc - public override func viewDidLoad() { - super.viewDidLoad() - - createAndSetupViews() - updateAppearance() - } - /// :nodoc: - @objc - public override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - updateAppearance() - } - /// :nodoc: - @objc - public override func viewWillDisappear(_ animated: Bool) { - super.viewWillDisappear(animated) - view.endEditing(true) - } - - /// Update views based on current STPTheme - @objc func updateAppearance() { - let navBarTheme = navigationController?.navigationBar.stp_theme ?? theme - navigationItem.leftBarButtonItem?.stp_setTheme(navBarTheme) - navigationItem.rightBarButtonItem?.stp_setTheme(navBarTheme) - cancelItem?.stp_setTheme(navBarTheme) - - view.backgroundColor = theme.primaryBackgroundColor - - setNeedsStatusBarAppearanceUpdate() - } - - /// :nodoc: - @objc public override var preferredStatusBarStyle: UIStatusBarStyle { - let navBarTheme = navigationController?.navigationBar.stp_theme ?? theme - return navBarTheme.secondaryBackgroundColor.isBright - ? .default - : .lightContent - } - - /// Called by the automatically-managed back/cancel button - /// By default pops the top item off the navigation stack, or if we are the - /// root of the navigation controller, dimisses presentation - /// - Parameter sender: Sender of the target action, if applicable. - @objc func handleCancelTapped(_ sender: Any?) { - if stp_isAtRootOfNavigationController() { - // if we're the root of the navigation controller, we've been presented modally. - presentingViewController?.dismiss(animated: true) - } else { - // otherwise, we've been pushed onto the stack. - navigationController?.popViewController(animated: true) - } - } - - /// If you override this and return YES, then your CoreVC implementation will not - /// create and set up a cancel and instead just use the default - /// UIViewController back button behavior. - /// You won't receive calls to `handleCancelTapped` if this is YES. - /// Defaults to NO. - func useSystemBackButton() -> Bool { - return false - } -} diff --git a/Stripe/StripeiOS/Source/STPCustomerContext.swift b/Stripe/StripeiOS/Source/STPCustomerContext.swift deleted file mode 100644 index 13820fa2094..00000000000 --- a/Stripe/StripeiOS/Source/STPCustomerContext.swift +++ /dev/null @@ -1,419 +0,0 @@ -// -// STPCustomerContext.swift -// StripeiOS -// -// Created by Ben Guo on 5/2/17. -// Copyright © 2017 Stripe, Inc. All rights reserved. -// - -import Foundation -@_spi(STP) import StripeCore -@_spi(STP) import StripePaymentsUI - -/// An `STPCustomerContext` retrieves and updates a Stripe customer and their attached -/// payment methods using an ephemeral key, a short-lived API key scoped to a specific -/// customer object. If your current user logs out of your app and a new user logs in, -/// be sure to either create a new instance of `STPCustomerContext` or clear the current -/// instance's cache. On your backend, be sure to create and return a -/// new ephemeral key for the Customer object associated with the new user. -open class STPCustomerContext: NSObject, STPBackendAPIAdapter { - /// Initializes a new `STPCustomerContext` with the specified key provider. - /// Upon initialization, a CustomerContext will fetch a new ephemeral key from - /// your backend and use it to prefetch the customer object specified in the key. - /// Subsequent customer and payment method retrievals (e.g. by `STPPaymentContext`) - /// will return the prefetched customer / attached payment methods immediately if - /// its age does not exceed 60 seconds. - /// - Parameter keyProvider: The key provider the customer context will use. - /// - Returns: the newly-instantiated customer context. - @objc(initWithKeyProvider:) - public convenience init( - keyProvider: STPCustomerEphemeralKeyProvider - ) { - self.init(keyProvider: keyProvider, apiClient: STPAPIClient.shared) - } - - /// Initializes a new `STPCustomerContext` with the specified key provider. - /// Upon initialization, a CustomerContext will fetch a new ephemeral key from - /// your backend and use it to prefetch the customer object specified in the key. - /// Subsequent customer and payment method retrievals (e.g. by `STPPaymentContext`) - /// will return the prefetched customer / attached payment methods immediately if - /// its age does not exceed 60 seconds. - /// - Parameters: - /// - keyProvider: The key provider the customer context will use. - /// - apiClient: The API Client to use to make requests. - /// - Returns: the newly-instantiated customer context. - @objc(initWithKeyProvider:apiClient:) - public convenience init( - keyProvider: STPCustomerEphemeralKeyProvider?, - apiClient: STPAPIClient - ) { - let keyManager = STPEphemeralKeyManager( - keyProvider: keyProvider, - apiVersion: STPAPIClient.apiVersion, - performsEagerFetching: true - ) - self.init(keyManager: keyManager, apiClient: apiClient) - } - - /// `STPCustomerContext` will cache its customer object and associated payment methods - /// for up to 60 seconds. If your current user logs out of your app and a new user logs - /// in, be sure to either call this method or create a new instance of `STPCustomerContext`. - /// On your backend, be sure to create and return a new ephemeral key for the - /// customer object associated with the new user. - @objc - public func clearCache() { - clearCachedCustomer() - clearCachedPaymentMethods() - } - - private var _includeApplePayPaymentMethods = false - /// By default, `STPCustomerContext` will filter Apple Pay when it retrieves - /// Payment Methods. Apple Pay payment methods should generally not be re-used and - /// shouldn't be offered to customers as a new payment method (Apple Pay payment - /// methods may only be re-used for subscriptions). - /// If you are using `STPCustomerContext` to back your own UI and would like to - /// disable Apple Pay filtering, set this property to YES. - /// Note: If you are using `STPPaymentContext`, you should not change this property. - @objc public var includeApplePayPaymentMethods: Bool { - get { - _includeApplePayPaymentMethods - } - set(includeApplePayMethods) { - _includeApplePayPaymentMethods = includeApplePayMethods - customer?.updateSources(filteringApplePay: !includeApplePayMethods) - } - } - - private var _customer: STPCustomer? - private var customer: STPCustomer? { - get { - _customer - } - set(customer) { - _customer = customer - customerRetrievedDate = (customer) != nil ? Date() : nil - } - } - @objc internal var customerRetrievedDate: Date? - - private var _paymentMethods: [STPPaymentMethod]? - private var paymentMethods: [STPPaymentMethod]? { - get { - if !includeApplePayPaymentMethods { - var paymentMethodsExcludingApplePay: [STPPaymentMethod]? = [] - for paymentMethod in _paymentMethods ?? [] { - let isApplePay = - paymentMethod.type == .card && paymentMethod.card?.wallet?.type == .applePay - if !isApplePay { - paymentMethodsExcludingApplePay?.append(paymentMethod) - } - } - return paymentMethodsExcludingApplePay ?? [] - } else { - return _paymentMethods ?? [] - } - } - set(paymentMethods) { - _paymentMethods = paymentMethods - paymentMethodsRetrievedDate = paymentMethods != nil ? Date() : nil - } - } - @objc internal var paymentMethodsRetrievedDate: Date? - private var keyManager: STPEphemeralKeyManagerProtocol - private var apiClient: STPAPIClient - - init( - keyManager: STPEphemeralKeyManagerProtocol, - apiClient: STPAPIClient - ) { - STPAnalyticsClient.sharedClient.addClass(toProductUsageIfNecessary: STPCustomerContext.self) - self.keyManager = keyManager - self.apiClient = apiClient - _includeApplePayPaymentMethods = false - super.init() - retrieveCustomer(nil) - listPaymentMethodsForCustomer(completion: nil) - } - - func clearCachedCustomer() { - customer = nil - } - - func clearCachedPaymentMethods() { - paymentMethods = nil - } - - func shouldUseCachedCustomer() -> Bool { - if customer == nil || customerRetrievedDate == nil { - return false - } - let now = Date() - if let customerRetrievedDate = customerRetrievedDate { - return now.timeIntervalSince(customerRetrievedDate) < CachedCustomerMaxAge - } - return false - } - - func shouldUseCachedPaymentMethods() -> Bool { - if paymentMethods == nil || paymentMethodsRetrievedDate == nil { - return false - } - let now = Date() - if let paymentMethodsRetrievedDate = paymentMethodsRetrievedDate { - return now.timeIntervalSince(paymentMethodsRetrievedDate) < CachedCustomerMaxAge - } - return false - } - - // MARK: - STPBackendAPIAdapter - @objc - public func retrieveCustomer(_ completion: STPCustomerCompletionBlock? = nil) { - if shouldUseCachedCustomer() { - if let completion = completion { - stpDispatchToMainThreadIfNecessary({ - completion(self.customer, nil) - }) - } - return - } - keyManager.getOrCreateKey({ ephemeralKey, retrieveKeyError in - guard let ephemeralKey = ephemeralKey, retrieveKeyError == nil else { - if let completion = completion { - stpDispatchToMainThreadIfNecessary({ - completion(nil, retrieveKeyError) - }) - } - return - } - self.apiClient.retrieveCustomer(using: ephemeralKey) { customer, error in - if let customer = customer { - customer.updateSources(filteringApplePay: !self.includeApplePayPaymentMethods) - self.customer = customer - } - if let completion = completion { - stpDispatchToMainThreadIfNecessary({ - completion(self.customer, error) - }) - } - } - }) - } - - @objc - public func updateCustomer( - withShippingAddress shipping: STPAddress, - completion: STPErrorBlock? - ) { - keyManager.getOrCreateKey({ ephemeralKey, retrieveKeyError in - guard let ephemeralKey = ephemeralKey, retrieveKeyError == nil else { - if let completion = completion { - stpDispatchToMainThreadIfNecessary({ - completion(retrieveKeyError) - }) - } - return - } - var params: [String: Any] = [:] - params["shipping"] = STPAddress.shippingInfoForCharge( - with: shipping, - shippingMethod: nil - ) - self.apiClient.updateCustomer( - withParameters: params, - using: ephemeralKey - ) { customer, error in - if let customer = customer { - customer.updateSources(filteringApplePay: !self.includeApplePayPaymentMethods) - self.customer = customer - } - if let completion = completion { - stpDispatchToMainThreadIfNecessary({ - completion(error) - }) - } - } - }) - } - - /// A convenience method for attaching the PaymentMethod to the current Customer - @objc - public func attachPaymentMethodToCustomer( - paymentMethodId: String, - completion: STPErrorBlock? - ) { - keyManager.getOrCreateKey({ ephemeralKey, retrieveKeyError in - guard let ephemeralKey = ephemeralKey, retrieveKeyError == nil else { - if let completion = completion { - stpDispatchToMainThreadIfNecessary({ - completion(retrieveKeyError) - }) - } - return - } - - self.apiClient.attachPaymentMethod( - paymentMethodId, - toCustomerUsing: ephemeralKey - ) { error in - self.clearCachedPaymentMethods() - if let completion = completion { - stpDispatchToMainThreadIfNecessary({ - completion(error) - }) - } - } - }) - } - - @objc - public func attachPaymentMethod( - toCustomer paymentMethod: STPPaymentMethod, - completion: STPErrorBlock? - ) { - attachPaymentMethodToCustomer( - paymentMethodId: paymentMethod.stripeId, - completion: completion - ) - } - - /// A convenience method for detaching the PaymentMethod to the current Customer - @objc - public func detachPaymentMethodFromCustomer( - paymentMethodId: String, - completion: STPErrorBlock? - ) { - keyManager.getOrCreateKey({ ephemeralKey, retrieveKeyError in - guard let ephemeralKey = ephemeralKey, retrieveKeyError == nil else { - if let completion = completion { - stpDispatchToMainThreadIfNecessary({ - completion(retrieveKeyError) - }) - } - return - } - - self.apiClient.detachPaymentMethod( - paymentMethodId, - fromCustomerUsing: ephemeralKey - ) { error in - self.clearCachedPaymentMethods() - if let completion = completion { - stpDispatchToMainThreadIfNecessary({ - completion(error) - }) - } - } - }) - - } - - @objc - public func detachPaymentMethod( - fromCustomer paymentMethod: STPPaymentMethod, - completion: STPErrorBlock? - ) { - detachPaymentMethodFromCustomer( - paymentMethodId: paymentMethod.stripeId, - completion: completion - ) - } - - @objc - public func listPaymentMethodsForCustomer(completion: STPPaymentMethodsCompletionBlock? = nil) { - if shouldUseCachedPaymentMethods() { - if let completion = completion { - stpDispatchToMainThreadIfNecessary({ - completion(self.paymentMethods, nil) - }) - } - return - } - - keyManager.getOrCreateKey({ ephemeralKey, retrieveKeyError in - guard let ephemeralKey = ephemeralKey, retrieveKeyError == nil else { - if let completion = completion { - stpDispatchToMainThreadIfNecessary({ - completion(nil, retrieveKeyError) - }) - } - return - } - - self.apiClient.listPaymentMethodsForCustomer(using: ephemeralKey) { - paymentMethods, - error in - if paymentMethods != nil { - self.paymentMethods = paymentMethods - } - if let completion = completion { - stpDispatchToMainThreadIfNecessary({ - completion(self.paymentMethods, error) - }) - } - } - }) - } - - func saveLastSelectedPaymentMethodID( - forCustomer paymentMethodID: String?, - completion: STPErrorBlock? - ) { - keyManager.getOrCreateKey({ ephemeralKey, retrieveKeyError in - guard let ephemeralKey = ephemeralKey, retrieveKeyError == nil else { - if let completion = completion { - stpDispatchToMainThreadIfNecessary({ - completion(retrieveKeyError) - }) - } - return - } - - var customerToDefaultPaymentMethodID = - (UserDefaults.standard.dictionary(forKey: kLastSelectedPaymentMethodDefaultsKey)) - as? [String: String] ?? [:] - if let customerID = ephemeralKey.customerID { - customerToDefaultPaymentMethodID[customerID] = paymentMethodID - UserDefaults.standard.set( - customerToDefaultPaymentMethodID, - forKey: kLastSelectedPaymentMethodDefaultsKey - ) - } - - if let completion = completion { - stpDispatchToMainThreadIfNecessary({ - completion(nil) - }) - } - }) - } - - func retrieveLastSelectedPaymentMethodIDForCustomer( - completion: @escaping (String?, Error?) -> Void - ) { - keyManager.getOrCreateKey({ ephemeralKey, retrieveKeyError in - guard let ephemeralKey = ephemeralKey, retrieveKeyError == nil else { - stpDispatchToMainThreadIfNecessary({ - completion(nil, retrieveKeyError) - }) - return - } - - let customerToDefaultPaymentMethodID = - (UserDefaults.standard.dictionary(forKey: kLastSelectedPaymentMethodDefaultsKey)) - as? [String: String] ?? [:] - stpDispatchToMainThreadIfNecessary({ - completion(customerToDefaultPaymentMethodID[ephemeralKey.customerID ?? ""], nil) - }) - }) - } -} - -/// Stores the key we use in NSUserDefaults to save a dictionary of Customer id to their last selected payment method ID -private let kLastSelectedPaymentMethodDefaultsKey = - UserDefaults.StripeKeys.customerToLastSelectedPaymentMethod.rawValue -private let CachedCustomerMaxAge: TimeInterval = 60 - -/// :nodoc: -@_spi(STP) extension STPCustomerContext: STPAnalyticsProtocol { - @_spi(STP) public static var stp_analyticsIdentifier = "STPCustomerContext" -} diff --git a/Stripe/StripeiOS/Source/STPEphemeralKey.swift b/Stripe/StripeiOS/Source/STPEphemeralKey.swift index 6ddf10b62a1..de27b5cf3db 100644 --- a/Stripe/StripeiOS/Source/STPEphemeralKey.swift +++ b/Stripe/StripeiOS/Source/STPEphemeralKey.swift @@ -15,7 +15,6 @@ class STPEphemeralKey: NSObject, STPAPIResponseDecodable { private(set) var livemode = false private(set) var secret: String private(set) var expires: Date - private(set) var customerID: String? private(set) var issuingCardID: String? /// You cannot directly instantiate an `STPEphemeralKey`. You should instead use @@ -70,7 +69,6 @@ class STPEphemeralKey: NSObject, STPAPIResponseDecodable { return nil } let key = self.init(stripeID: stripeId, created: created, secret: secret, expires: expires) - key.customerID = customerID key.issuingCardID = issuingCardID key.stripeID = stripeId key.livemode = dict.stp_bool(forKey: "livemode", or: true) diff --git a/Stripe/StripeiOS/Source/STPFPXBankStatusResponse.swift b/Stripe/StripeiOS/Source/STPFPXBankStatusResponse.swift deleted file mode 100644 index 73a2ff66b97..00000000000 --- a/Stripe/StripeiOS/Source/STPFPXBankStatusResponse.swift +++ /dev/null @@ -1,44 +0,0 @@ -// -// STPFPXBankStatusResponse.swift -// StripeiOS -// -// Created by David Estes on 10/21/19. -// Copyright © 2019 Stripe, Inc. All rights reserved. -// - -import Foundation -@_spi(STP) import StripePayments - -class STPFPXBankStatusResponse: NSObject, STPAPIResponseDecodable { - func bankBrandIsOnline(_ bankBrand: STPFPXBankBrand) -> Bool { - let bankCode = STPFPXBank.bankCodeFrom(bankBrand, false) - let bankStatus = bankList?[bankCode ?? ""] - if bankCode != nil && bankStatus != nil { - return bankStatus?.boolValue ?? false - } - // This status endpoint isn't reliable. If we don't know this bank's status, default to online. - // The worst that will happen here is that the user ends up at their bank's "Down For Maintenance" page when checking out. - return true - } - - private var bankList: [String: NSNumber]? - private(set) var allResponseFields: [AnyHashable: Any] = [:] - - required internal override init() { - super.init() - } - - class func decodedObject(fromAPIResponse response: [AnyHashable: Any]?) -> Self? { - guard let response = response else { - return nil - } - let dict = response.stp_dictionaryByRemovingNulls() - - let statusResponse = self.init() - statusResponse.bankList = - dict.stp_dictionary(forKey: "parsed_bank_status") as? [String: NSNumber] - statusResponse.allResponseFields = dict - - return statusResponse - } -} diff --git a/Stripe/StripeiOS/Source/STPImageLibrary.swift b/Stripe/StripeiOS/Source/STPImageLibrary.swift deleted file mode 100644 index dac95afba29..00000000000 --- a/Stripe/StripeiOS/Source/STPImageLibrary.swift +++ /dev/null @@ -1,94 +0,0 @@ -// -// STPImageLibrary.swift -// StripeiOS -// -// Created by Jack Flintermann on 6/30/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -import Foundation -@_spi(STP) import StripePaymentsUI -@_spi(STP) import StripeUICore -import UIKit - -/// This class lets you access card icons used by the Stripe SDK. All icons are 32 x 20 points. -@objc class STPLegacyImageLibrary: NSObject { - - /// This returns the appropriate icon for the specified bank brand. - @objc(brandImageForFPXBankBrand:) public class func fpxBrandImage( - for brand: STPFPXBankBrand - ) - -> UIImage - { - let imageName = "stp_bank_fpx_\(STPFPXBank.identifierFrom(brand) ?? "")" - let image = self.safeImageNamed( - imageName, - templateIfAvailable: false - ) - return image - } - - /// An icon representing FPX. - @objc - public class func fpxLogo() -> UIImage { - return self.safeImageNamed("stp_fpx_logo", templateIfAvailable: false) - } - - /// A large branding image for FPX. - @objc - public class func largeFpxLogo() -> UIImage { - return self.safeImageNamed("stp_fpx_big_logo", templateIfAvailable: false) - } - - @objc class func addIcon() -> UIImage { - return self.safeImageNamed("stp_icon_add", templateIfAvailable: true) - } - - @objc class func checkmarkIcon() -> UIImage { - return self.safeImageNamed("stp_icon_checkmark", templateIfAvailable: true) - } - - @objc class func largeCardFrontImage() -> UIImage { - return self.safeImageNamed("stp_card_form_front", templateIfAvailable: true) - } - - @objc class func largeCardBackImage() -> UIImage { - return self.safeImageNamed("stp_card_form_back", templateIfAvailable: true) - } - - @objc class func largeCardAmexCVCImage() -> UIImage { - return self.safeImageNamed("stp_card_form_amex_cvc", templateIfAvailable: true) - } - - @objc class func largeShippingImage() -> UIImage { - return self.safeImageNamed("stp_shipping_form", templateIfAvailable: true) - } - - class func image( - withTintColor color: UIColor, - for image: UIImage - ) -> UIImage { - var newImage: UIImage? - UIGraphicsBeginImageContextWithOptions(image.size, false, image.scale) - color.set() - let templateImage = image.withRenderingMode(.alwaysTemplate) - templateImage.draw( - in: CGRect( - x: 0, - y: 0, - width: templateImage.size.width, - height: templateImage.size.height - ) - ) - newImage = UIGraphicsGetImageFromCurrentImageContext() - UIGraphicsEndImageContext() - return newImage ?? image - } -} - -// MARK: - ImageMaker - -// :nodoc: -@_spi(STP) extension STPLegacyImageLibrary: ImageMaker { - @_spi(STP) public typealias BundleLocator = StripeBundleLocator -} diff --git a/Stripe/StripeiOS/Source/STPIntentActionLinkAuthenticateAccount.swift b/Stripe/StripeiOS/Source/STPIntentActionLinkAuthenticateAccount.swift deleted file mode 100644 index be029dbe0ff..00000000000 --- a/Stripe/StripeiOS/Source/STPIntentActionLinkAuthenticateAccount.swift +++ /dev/null @@ -1,33 +0,0 @@ -// -// STPIntentActionLinkAuthenticateAccount.swift -// StripeiOS -// -// Created by Cameron Sabol on 7/6/21. -// Copyright © 2021 Stripe, Inc. All rights reserved. -// - -import UIKit - -class STPIntentActionLinkAuthenticateAccount: NSObject { - - let allResponseFields: [AnyHashable: Any] - - required init( - _ allResponseFields: [AnyHashable: Any] - ) { - self.allResponseFields = allResponseFields - super.init() - } - -} - -/// :nodoc: -extension STPIntentActionLinkAuthenticateAccount: STPAPIResponseDecodable { - class func decodedObject(fromAPIResponse response: [AnyHashable: Any]?) -> Self? { - guard let response = response else { - return nil - } - - return STPIntentActionLinkAuthenticateAccount(response) as? Self - } -} diff --git a/Stripe/StripeiOS/Source/STPLocalizedString.swift b/Stripe/StripeiOS/Source/STPLocalizedString.swift deleted file mode 100644 index 76afd0076ca..00000000000 --- a/Stripe/StripeiOS/Source/STPLocalizedString.swift +++ /dev/null @@ -1,16 +0,0 @@ -// -// STPLocalizedString.swift -// StripeiOS -// -// Created by David Estes on 10/19/20. -// Copyright © 2020 Stripe, Inc. All rights reserved. -// - -@_spi(STP) import StripeCore - -@inline(__always) func STPLocalizedString(_ key: String, _ comment: String?) -> String { - return STPLocalizationUtils.localizedStripeString( - forKey: key, - bundleLocator: StripeBundleLocator.self - ) -} diff --git a/Stripe/StripeiOS/Source/STPPaymentActivityIndicatorView.swift b/Stripe/StripeiOS/Source/STPPaymentActivityIndicatorView.swift deleted file mode 100644 index 68c03b6ea39..00000000000 --- a/Stripe/StripeiOS/Source/STPPaymentActivityIndicatorView.swift +++ /dev/null @@ -1,135 +0,0 @@ -// -// STPPaymentActivityIndicatorView.swift -// StripeiOS -// -// Created by Jack Flintermann on 5/12/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -import UIKit - -/// This class can be used wherever you'd use a `UIActivityIndicatorView` and is intended to have a similar API. It renders as a spinning circle with a gap in it, similar to what you see in the App Store app or in the Apple Pay dialog when making a purchase. To change its color, set the `tintColor` property. -public class STPPaymentActivityIndicatorView: UIView { - /// Tell the view to start or stop spinning. If `hidesWhenStopped` is true, it will fade in/out if animated is true. - @objc - public func setAnimating( - _ animating: Bool, - animated: Bool - ) { - if animating == _animating { - return - } - _animating = animating - if animating { - if hidesWhenStopped { - UIView.animate( - withDuration: animated ? 0.2 : 0, - animations: { - self.alpha = 1.0 - } - ) - } - var currentRotation = Double(0) - if let currentLayer = layer.presentation() { - currentRotation = Double( - truncating: (currentLayer.value(forKeyPath: "transform.rotation.z") as! NSNumber) - ) - } - let animation = CABasicAnimation(keyPath: "transform.rotation.z") - animation.fromValue = NSNumber(value: Float(currentRotation)) - let toValue = NSNumber(value: currentRotation + 2 * Double.pi) - animation.toValue = toValue - animation.duration = 1.0 - animation.repeatCount = Float.infinity - layer.add(animation, forKey: "rotation") - } else { - if hidesWhenStopped { - UIView.animate( - withDuration: animated ? 0.2 : 0, - animations: { - self.alpha = 0.0 - } - ) - } - } - } - - private var _animating = false - /// Whether or not the view is animating. - @objc public var animating: Bool { - get { - _animating - } - set(animating) { - setAnimating(animating, animated: false) - } - } - - private var _hidesWhenStopped = true - /// If true, the view will hide when it is not spinning. Default is true. - @objc public var hidesWhenStopped: Bool { - get { - _hidesWhenStopped - } - set(hidesWhenStopped) { - _hidesWhenStopped = hidesWhenStopped - if !animating && hidesWhenStopped { - alpha = 0 - } else { - alpha = 1 - } - } - } - private weak var indicatorLayer: CAShapeLayer? - - /// :nodoc: - @objc override init( - frame: CGRect - ) { - var initialFrame = frame - if initialFrame.isEmpty { - initialFrame = CGRect(x: frame.origin.x, y: frame.origin.y, width: 40, height: 40) - } - super.init(frame: initialFrame) - backgroundColor = UIColor.clear - let layer = CAShapeLayer() - layer.backgroundColor = UIColor.clear.cgColor - layer.fillColor = UIColor.clear.cgColor - layer.strokeColor = tintColor.cgColor - layer.strokeStart = 0 - layer.lineCap = .round - layer.strokeEnd = 0.75 - layer.lineWidth = 2.0 - indicatorLayer = layer - self.layer.addSublayer(layer) - alpha = 0 - } - - /// :nodoc: - @objc public override var tintColor: UIColor! { - get { - return super.tintColor - } - set(tintColor) { - super.tintColor = tintColor - indicatorLayer?.strokeColor = tintColor.cgColor - } - } - - /// :nodoc: - @objc - public override func layoutSubviews() { - super.layoutSubviews() - var bounds = self.bounds - bounds.size.width = CGFloat(min(bounds.size.width, bounds.size.height)) - bounds.size.height = bounds.size.width - let path = UIBezierPath(ovalIn: bounds) - indicatorLayer?.path = path.cgPath - } - - required init?( - coder aDecoder: NSCoder - ) { - super.init(coder: aDecoder) - } -} diff --git a/Stripe/StripeiOS/Source/STPPaymentCardTextFieldCell.swift b/Stripe/StripeiOS/Source/STPPaymentCardTextFieldCell.swift deleted file mode 100644 index 40112d5dea9..00000000000 --- a/Stripe/StripeiOS/Source/STPPaymentCardTextFieldCell.swift +++ /dev/null @@ -1,91 +0,0 @@ -// -// STPPaymentCardTextFieldCell.swift -// StripeiOS -// -// Created by Jack Flintermann on 6/16/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -@_spi(STP) import StripePaymentsUI -import UIKit - -class STPPaymentCardTextFieldCell: UITableViewCell { - private(set) weak var paymentField: STPPaymentCardTextField? - - var theme: STPTheme = STPTheme.defaultTheme { - didSet { - updateAppearance() - } - } - - private var _inputAccessoryView: UIView? - override var inputAccessoryView: UIView? { - get { - _inputAccessoryView - } - set(inputAccessoryView) { - _inputAccessoryView = inputAccessoryView - paymentField?.inputAccessoryView = inputAccessoryView - } - } - - func isEmpty() -> Bool { - return (paymentField?.cardNumber?.count ?? 0) == 0 - } - - override init( - style: UITableViewCell.CellStyle, - reuseIdentifier: String? - ) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - let paymentField = STPPaymentCardTextField(frame: bounds) - paymentField.postalCodeEntryEnabled = false - contentView.addSubview(paymentField) - self.paymentField = paymentField - theme = STPTheme.defaultTheme - updateAppearance() - } - - override func layoutSubviews() { - super.layoutSubviews() - paymentField?.frame = contentView.bounds - } - - @objc func updateAppearance() { - paymentField?.backgroundColor = UIColor.clear - paymentField?.placeholderColor = theme.tertiaryForegroundColor - paymentField?.borderColor = UIColor.clear - paymentField?.textColor = theme.primaryForegroundColor - paymentField?.textErrorColor = theme.errorColor - paymentField?.font = theme.font - backgroundColor = theme.secondaryBackgroundColor - } - - @objc override func becomeFirstResponder() -> Bool { - return paymentField?.becomeFirstResponder() ?? false - } - - override func accessibilityElementCount() -> Int { - return paymentField?.allFields.count ?? 0 - } - - override func accessibilityElement(at index: Int) -> Any? { - return paymentField?.allFields[index] - } - - override func index(ofAccessibilityElement element: Any) -> Int { - let fields = paymentField?.allFields - for i in 0..<(fields?.count ?? 0) { - if (element as? AnyHashable) == fields?[i] { - return i - } - } - return 0 - } - - required init?( - coder aDecoder: NSCoder - ) { - super.init(coder: aDecoder) - } -} diff --git a/Stripe/StripeiOS/Source/STPPaymentConfiguration.swift b/Stripe/StripeiOS/Source/STPPaymentConfiguration.swift deleted file mode 100644 index 12719a4903a..00000000000 --- a/Stripe/StripeiOS/Source/STPPaymentConfiguration.swift +++ /dev/null @@ -1,244 +0,0 @@ -// -// STPPaymentConfiguration.swift -// StripeiOS -// -// Created by Jack Flintermann on 5/18/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -import Foundation -@_spi(STP) import StripeCore - -/// An `STPPaymentConfiguration` represents all the options you can set or change -/// around a payment. -/// You provide an `STPPaymentConfiguration` object to your `STPPaymentContext` -/// when making a charge. The configuration generally has settings that -/// will not change from payment to payment and thus is reusable, while the context -/// is specific to a single particular payment instance. -public class STPPaymentConfiguration: NSObject, NSCopying { - /// This is a convenience singleton configuration that uses the default values for - /// every property - @objc(sharedConfiguration) public static var shared = STPPaymentConfiguration() - - private var _applePayEnabled = true - /// The user is allowed to pay with Apple Pay if it's configured and available on their device. - @objc public var applePayEnabled: Bool { - get { - return appleMerchantIdentifier != nil && _applePayEnabled - && StripeAPI.deviceSupportsApplePay() - } - set { - _applePayEnabled = newValue - } - } - - /// The user is allowed to pay with FPX. - @objc public var fpxEnabled = false - - /// The billing address fields the user must fill out when prompted for their - /// payment details. These fields will all be present on the returned PaymentMethod from - /// Stripe. - /// The default value is `STPBillingAddressFieldsPostalCode`. - /// - seealso: https://stripe.com/docs/api/payment_methods/create#create_payment_method-billing_details - @objc public var requiredBillingAddressFields = STPBillingAddressFields.postalCode - /// The shipping address fields the user must fill out when prompted for their - /// shipping info. Set to nil if shipping address is not required. - /// The default value is nil. - @objc public var requiredShippingAddressFields: Set? - /// Whether the user should be prompted to verify prefilled shipping information. - /// The default value is YES. - @objc public var verifyPrefilledShippingAddress = true - /// The type of shipping for this purchase. This property sets the labels displayed - /// when the user is prompted for shipping info, and whether they should also be - /// asked to select a shipping method. - /// The default value is STPShippingTypeShipping. - @objc public var shippingType = STPShippingType.shipping - /// The set of countries supported when entering an address. This property accepts - /// a set of ISO 2-character country codes. - /// The default value is all known countries. Setting this property will limit - /// the available countries to your selected set. - @objc public var availableCountries: Set = Set(NSLocale.isoCountryCodes) - - /// 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 - /// "PAY {companyName}". - /// The default value is the name of your iOS application which is derived from the - /// `kCFBundleNameKey` of `Bundle.main`. - @objc public var companyName = Bundle.stp_applicationName() ?? "" - /// The Apple Merchant Identifier to use during Apple Pay transactions. To create - /// one of these, see our guide at https://stripe.com/docs/apple-pay . You - /// must set this to a valid identifier in order to automatically enable Apple Pay. - @objc public var appleMerchantIdentifier: String? - /// Determines whether or not the user is able to delete payment options - /// This is only relevant to the `STPPaymentOptionsViewController` which, if - /// enabled, will allow the user to delete payment options by tapping the "Edit" - /// button in the navigation bar or by swiping left on a payment option and tapping - /// "Delete". Currently, the user is not allowed to delete the selected payment - /// option but this may change in the future. - /// Default value is YES but will only work if `STPPaymentOptionsViewController` is - /// initialized with a `STPCustomerContext` either through the `STPPaymentContext` - /// or directly as an init parameter. - @objc public var canDeletePaymentOptions = true - /// Determines whether STPAddCardViewController allows the user to - /// scan cards using the camera on devices running iOS 13 or later. - /// To use this feature, you must also set the `NSCameraUsageDescription` - /// value in your app's Info.plist. - /// @note This feature is currently in beta. Please file bugs at - /// https://github.com/stripe/stripe-ios/issues - /// The default value is currently NO. This will be changed in a future update. - @objc public var cardScanningEnabled = false - // MARK: - Deprecated - - /// An enum value representing which payment options you will accept from your user - /// in addition to credit cards. - @available( - *, - deprecated, - message: - "additionalPaymentOptions has been removed. Set applePayEnabled and fpxEnabled on STPPaymentConfiguration instead." - ) - @objc public var additionalPaymentOptions: Int = 0 - - private var _publishableKey: String? - /// If you used STPPaymentConfiguration.shared.publishableKey, use STPAPIClient.shared.publishableKey instead. The SDK uses STPAPIClient.shared to make API requests by default. - /// Your Stripe publishable key - /// - seealso: https://dashboard.stripe.com/account/apikeys - @available( - *, - deprecated, - message: - "If you used STPPaymentConfiguration.shared.publishableKey, use STPAPIClient.shared.publishableKey instead. If you passed a STPPaymentConfiguration instance to an SDK component, create an STPAPIClient, set publishableKey on it, and set the SDK component's APIClient property." - ) - @objc public var publishableKey: String? { - get { - if self == STPPaymentConfiguration.shared { - return STPAPIClient.shared.publishableKey - } - return _publishableKey ?? "" - } - set(publishableKey) { - if self == STPPaymentConfiguration.shared { - STPAPIClient.shared.publishableKey = publishableKey - } else { - _publishableKey = publishableKey - } - } - } - - private var _stripeAccount: String? - /// If you used STPPaymentConfiguration.shared.stripeAccount, use STPAPIClient.shared.stripeAccount instead. The SDK uses STPAPIClient.shared to make API requests by default. - /// In order to perform API requests on behalf of a connected account, e.g. to - /// create charges for a connected account, set this property to the ID of the - /// account for which this request is being made. - /// - seealso: https://stripe.com/docs/payments#connected-accounts - @available( - *, - deprecated, - message: - "If you used STPPaymentConfiguration.shared.stripeAccount, use STPAPIClient.shared.stripeAccount instead. If you passed a STPPaymentConfiguration instance to an SDK component, create an STPAPIClient, set stripeAccount on it, and set the SDK component's APIClient property." - ) - @objc public var stripeAccount: String? { - get { - if self == STPPaymentConfiguration.shared { - return STPAPIClient.shared.stripeAccount - } - return _stripeAccount ?? "" - } - set(stripeAccount) { - if self == STPPaymentConfiguration.shared { - STPAPIClient.shared.stripeAccount = stripeAccount - } else { - _stripeAccount = stripeAccount - } - } - } - - // MARK: - Description - /// :nodoc: - @objc public override var description: String { - var additionalPaymentOptionsDescription: String? - - var paymentOptions: [String] = [] - - if _applePayEnabled { - paymentOptions.append("STPPaymentOptionTypeApplePay") - } - - if fpxEnabled { - paymentOptions.append("STPPaymentOptionTypeFPX") - } - - additionalPaymentOptionsDescription = paymentOptions.joined(separator: "|") - - var requiredBillingAddressFieldsDescription: String? - - switch requiredBillingAddressFields { - case .none: - requiredBillingAddressFieldsDescription = "STPBillingAddressFieldsNone" - case .postalCode: - requiredBillingAddressFieldsDescription = "STPBillingAddressFieldsPostalCode" - case .full: - requiredBillingAddressFieldsDescription = "STPBillingAddressFieldsFull" - case .name: - requiredBillingAddressFieldsDescription = "STPBillingAddressFieldsName" - default: - break - } - - let requiredShippingAddressFieldsDescription = requiredShippingAddressFields?.map({ - $0.rawValue - }).joined(separator: "|") - - var shippingTypeDescription: String? - - switch shippingType { - case .shipping: - shippingTypeDescription = "STPShippingTypeShipping" - case .delivery: - shippingTypeDescription = "STPShippingTypeDelivery" - default: - break - } - - let props = [ - // Object - String(format: "%@: %p", NSStringFromClass(STPPaymentConfiguration.self), self), - // Basic configuration - "additionalPaymentOptions = \(additionalPaymentOptionsDescription ?? "")", - // Billing and shipping - "requiredBillingAddressFields = \(requiredBillingAddressFieldsDescription ?? "")", - "requiredShippingAddressFields = \(requiredShippingAddressFieldsDescription ?? "")", - "verifyPrefilledShippingAddress = \((verifyPrefilledShippingAddress) ? "YES" : "NO")", - "shippingType = \(shippingTypeDescription ?? "")", - "availableCountries = \(availableCountries )", - // Additional configuration - "companyName = \(companyName )", - "appleMerchantIdentifier = \(appleMerchantIdentifier ?? "")", - "canDeletePaymentOptions = \((canDeletePaymentOptions) ? "YES" : "NO")", - "cardScanningEnabled = \((cardScanningEnabled) ? "YES" : "NO")", - ] - - return "<\(props.joined(separator: "; "))>" - } - - // MARK: - NSCopying - /// :nodoc: - @objc - public func copy(with zone: NSZone? = nil) -> Any { - let copy = STPPaymentConfiguration() - copy.applePayEnabled = _applePayEnabled - copy.fpxEnabled = fpxEnabled - copy.requiredBillingAddressFields = requiredBillingAddressFields - copy.requiredShippingAddressFields = requiredShippingAddressFields - copy.verifyPrefilledShippingAddress = verifyPrefilledShippingAddress - copy.shippingType = shippingType - copy.companyName = companyName - copy.appleMerchantIdentifier = appleMerchantIdentifier - copy.canDeletePaymentOptions = canDeletePaymentOptions - copy.cardScanningEnabled = cardScanningEnabled - copy.availableCountries = availableCountries - copy._publishableKey = _publishableKey - copy._stripeAccount = _stripeAccount - return copy - } -} diff --git a/Stripe/StripeiOS/Source/STPPaymentContext.swift b/Stripe/StripeiOS/Source/STPPaymentContext.swift deleted file mode 100644 index 45af07a5155..00000000000 --- a/Stripe/StripeiOS/Source/STPPaymentContext.swift +++ /dev/null @@ -1,1266 +0,0 @@ -// -// STPPaymentContext.swift -// StripeiOS -// -// Created by Jack Flintermann on 4/20/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -import Foundation -import ObjectiveC -import PassKit -@_spi(STP) import StripeCore -@_spi(STP) import StripePaymentsUI - -/// An `STPPaymentContext` keeps track of all of the state around a payment. It will manage fetching a user's saved payment methods, tracking any information they select, and prompting them for required additional information before completing their purchase. It can be used to power your application's "payment confirmation" page with just a few lines of code. -/// `STPPaymentContext` also provides a unified interface to multiple payment methods - for example, you can write a single integration to accept both credit card payments and Apple Pay. -/// `STPPaymentContext` saves information about a user's payment methods to a Stripe customer object, and requires an `STPCustomerContext` to manage retrieving and modifying the customer. -@objc(STPPaymentContext) -public class STPPaymentContext: NSObject, STPAuthenticationContext, - STPPaymentOptionsViewControllerDelegate, STPShippingAddressViewControllerDelegate -{ - /// This is a convenience initializer; it is equivalent to calling - /// `init(customerContext:customerContext - /// configuration:STPPaymentConfiguration.shared - /// theme:STPTheme.defaultTheme`. - /// - Parameter customerContext: The customer context the payment context will use to fetch - /// and modify its Stripe customer. - seealso: STPCustomerContext.h - /// - Returns: the newly-instantiated payment context - @objc - public convenience init( - customerContext: STPCustomerContext - ) { - self.init(apiAdapter: customerContext) - } - - /// Initializes a new Payment Context with the provided customer context, configuration, - /// and theme. After this class is initialized, you should also make sure to set its - /// `delegate` and `hostViewController` properties. - /// - Parameters: - /// - customerContext: The customer context the payment context will use to fetch - /// and modify its Stripe customer. - seealso: STPCustomerContext.h - /// - configuration: The configuration for the payment context to use. This - /// lets you set your Stripe publishable API key, required billing address fields, etc. - /// - seealso: STPPaymentConfiguration.h - /// - theme: The theme describing the visual appearance of all UI - /// that the payment context automatically creates for you. - seealso: STPTheme.h - /// - Returns: the newly-instantiated payment context - @objc - public convenience init( - customerContext: STPCustomerContext, - configuration: STPPaymentConfiguration, - theme: STPTheme - ) { - self.init( - apiAdapter: customerContext, - configuration: configuration, - theme: theme - ) - } - - /// Note: Instead of providing your own backend API adapter, we recommend using - /// `STPCustomerContext`, which will manage retrieving and updating a - /// Stripe customer for you. - seealso: STPCustomerContext.h - /// This is a convenience initializer; it is equivalent to calling - /// `init(apiAdapter:apiAdapter configuration:STPPaymentConfiguration.shared theme:STPTheme.defaultTheme)`. - @objc - public convenience init( - apiAdapter: STPBackendAPIAdapter - ) { - self.init( - apiAdapter: apiAdapter, - configuration: STPPaymentConfiguration.shared, - theme: STPTheme.defaultTheme - ) - } - - /// Note: Instead of providing your own backend API adapter, we recommend using - /// `STPCustomerContext`, which will manage retrieving and updating a - /// Stripe customer for you. - seealso: STPCustomerContext.h - /// Initializes a new Payment Context with the provided API adapter and configuration. - /// After this class is initialized, you should also make sure to set its `delegate` - /// and `hostViewController` properties. - /// - Parameters: - /// - apiAdapter: The API adapter the payment context will use to fetch and - /// modify its contents. You need to make a class conforming to this protocol that - /// talks to your server. - seealso: STPBackendAPIAdapter.h - /// - configuration: The configuration for the payment context to use. This lets - /// you set your Stripe publishable API key, required billing address fields, etc. - /// - seealso: STPPaymentConfiguration.h - /// - theme: The theme describing the visual appearance of all UI that - /// the payment context automatically creates for you. - seealso: STPTheme.h - /// - Returns: the newly-instantiated payment context - @objc - public init( - apiAdapter: STPBackendAPIAdapter, - configuration: STPPaymentConfiguration, - theme: STPTheme - ) { - STPAnalyticsClient.sharedClient.addClass(toProductUsageIfNecessary: STPPaymentContext.self) - AnalyticsHelper.shared.generateSessionID() - self.configuration = configuration - self.apiAdapter = apiAdapter - self.theme = theme - paymentCurrency = "USD" - paymentCountry = "US" - apiClient = STPAPIClient.shared - modalPresentationStyle = .fullScreen - state = STPPaymentContextState.none - super.init() - retryLoading() - } - - /// Note: Instead of providing your own backend API adapter, we recommend using - /// `STPCustomerContext`, which will manage retrieving and updating a - /// Stripe customer for you. - seealso: STPCustomerContext.h - /// The API adapter the payment context will use to fetch and modify its contents. - /// You need to make a class conforming to this protocol that talks to your server. - /// - seealso: STPBackendAPIAdapter.h - @objc public private(set) var apiAdapter: STPBackendAPIAdapter - /// The configuration for the payment context to use internally. - seealso: STPPaymentConfiguration.h - @objc public private(set) var configuration: STPPaymentConfiguration - /// The visual appearance that will be used by any views that the context generates. - seealso: STPTheme.h - @objc public private(set) var theme: STPTheme - - private var _prefilledInformation: STPUserInformation? - /// If you've already collected some information from your user, you can set it here and it'll be automatically filled out when possible/appropriate in any UI that the payment context creates. - @objc public var prefilledInformation: STPUserInformation? { - get { - _prefilledInformation - } - set(prefilledInformation) { - _prefilledInformation = prefilledInformation - if prefilledInformation?.shippingAddress != nil && shippingAddress == nil { - shippingAddress = prefilledInformation?.shippingAddress - shippingAddressNeedsVerification = true - } - } - } - - private weak var _hostViewController: UIViewController? - /// The view controller that any additional UI will be presented on. If you have a "checkout view controller" in your app, that should be used as the host view controller. - @objc public weak var hostViewController: UIViewController? { - get { - _hostViewController - } - set(hostViewController) { - assert( - _hostViewController == nil, - "You cannot change the hostViewController on an STPPaymentContext after it's already been set." - ) - _hostViewController = hostViewController - if hostViewController is UINavigationController { - originalTopViewController = - (hostViewController as? UINavigationController)?.topViewController - } - if let hostViewController = hostViewController { - artificiallyRetain(hostViewController) - } - } - } - - private weak var _delegate: STPPaymentContextDelegate? - /// This delegate will be notified when the payment context's contents change. - seealso: STPPaymentContextDelegate - @objc public weak var delegate: STPPaymentContextDelegate? { - get { - _delegate - } - set(delegate) { - _delegate = delegate - DispatchQueue.main.async(execute: { - self.delegate?.paymentContextDidChange(self) - }) - } - } - /// Whether or not the payment context is currently loading information from the network. - - @objc public var loading: Bool { - return !(loadingPromise?.completed)! - } - /// @note This is no longer recommended as of v18.3.0 - the SDK automatically saves the Stripe ID of the last selected - /// payment method using NSUserDefaults and displays it as the default pre-selected option. You can override this behavior - /// by setting this property. - /// The Stripe ID of a payment method to display as the default pre-selected option. - /// @note Set this property immediately after initializing STPPaymentContext, or call `retryLoading` afterwards. - @objc public var defaultPaymentMethod: String? - - private var _selectedPaymentOption: STPPaymentOption? - /// The user's currently selected payment option. May be nil. - @objc public private(set) var selectedPaymentOption: STPPaymentOption? { - get { - _selectedPaymentOption - } - set { - if let newValue = newValue, let paymentOptions = self.paymentOptions { - if !paymentOptions.contains(where: { (option) -> Bool in - newValue.isEqual(option) - }) { - if newValue.isReusable { - self.paymentOptions = paymentOptions + [newValue] - } - } - } - if !(_selectedPaymentOption?.isEqual(newValue) ?? false) { - _selectedPaymentOption = newValue - stpDispatchToMainThreadIfNecessary({ - self.delegate?.paymentContextDidChange(self) - }) - } - - } - } - - private var _paymentOptions: [STPPaymentOption]? - /// The available payment options the user can choose between. May be nil. - @objc public private(set) var paymentOptions: [STPPaymentOption]? { - get { - _paymentOptions - } - set { - _paymentOptions = newValue?.sorted(by: { (obj1, obj2) -> Bool in - let applePayKlass = STPApplePayPaymentOption.self - let paymentMethodKlass = STPPaymentMethod.self - if obj1.isKind(of: applePayKlass) { - return true - } else if obj2.isKind(of: applePayKlass) { - return false - } - if obj1.isKind(of: paymentMethodKlass) && obj2.isKind(of: paymentMethodKlass) { - return (obj1.label.compare(obj2.label) == .orderedAscending) - } - return false - }) - } - } - - /// The user's currently selected shipping method. May be nil. - @objc public internal(set) var selectedShippingMethod: PKShippingMethod? - - private var _shippingMethods: [PKShippingMethod]? - /// An array of STPShippingMethod objects that describe the supported shipping methods. May be nil. - @objc public private(set) var shippingMethods: [PKShippingMethod]? { - get { - _shippingMethods - } - set { - _shippingMethods = newValue - if let shippingMethods = newValue, - let selectedShippingMethod = self.selectedShippingMethod - { - if shippingMethods.count == 0 { - self.selectedShippingMethod = nil - } else if shippingMethods.contains(selectedShippingMethod) { - self.selectedShippingMethod = shippingMethods.first - } - } - } - } - - /// The user's shipping address. May be nil. - /// If you've already collected a shipping address from your user, you may - /// prefill it by setting a shippingAddress in PaymentContext's prefilledInformation. - /// When your user enters a new shipping address, PaymentContext will save it to - /// the current customer object. When PaymentContext loads, if you haven't - /// manually set a prefilled value, any shipping information saved on the customer - /// will be used to prefill the shipping address form. Note that because your - /// customer's email may not be the same as the email provided with their shipping - /// info, PaymentContext will not prefill the shipping form's email using your - /// customer's email. - /// You should not rely on the shipping information stored on the Stripe customer - /// for order fulfillment, as your user may change this information if they make - /// multiple purchases. We recommend adding shipping information when you create - /// a charge (which can also help prevent fraud), or saving it to your own - /// database. https://stripe.com/docs/api/payment_intents/create#create_payment_intent-shipping - /// Note: by default, your user will still be prompted to verify a prefilled - /// shipping address. To change this behavior, you can set - /// `verifyPrefilledShippingAddress` to NO in your `STPPaymentConfiguration`. - @objc public private(set) var shippingAddress: STPAddress? - /// The amount of money you're requesting from the user, in the smallest currency - /// unit for the selected currency. For example, to indicate $10 USD, use 1000 - /// (i.e. 1000 cents). For more information, see https://stripe.com/docs/api/payment_intents/create#create_payment_intent-amount - /// @note This value must be present and greater than zero in order for Apple Pay - /// to be automatically enabled. - /// @note You should only set either this or `paymentSummaryItems`, not both. - /// The other will be automatically calculated on demand using your `paymentCurrency`. - - @objc public var paymentAmount: Int { - get { - return paymentAmountModel.paymentAmount( - withCurrency: paymentCurrency, - shippingMethod: selectedShippingMethod - ) - } - set(paymentAmount) { - paymentAmountModel = STPPaymentContextAmountModel(amount: paymentAmount) - } - } - /// The three-letter currency code for the currency of the payment (i.e. USD, GBP, - /// JPY, etc). Defaults to "USD". - /// @note Changing this property may change the return value of `paymentAmount` - /// or `paymentSummaryItems` (whichever one you didn't directly set yourself). - @objc public var paymentCurrency: String - /// The two-letter country code for the country where the payment will be processed. - /// You should set this to the country your Stripe account is in. Defaults to "US". - /// @note Changing this property will change the `countryCode` of your Apple Pay - /// payment requests. - /// - seealso: PKPaymentRequest for more information. - @objc public var paymentCountry: String - /// If you support Apple Pay, you can optionally set the PKPaymentSummaryItems - /// you want to display here instead of using `paymentAmount`. Note that the - /// grand total (the amount of the last summary item) must be greater than zero. - /// If not set, a single summary item will be automatically generated using - /// `paymentAmount` and your configuration's `companyName`. - /// - seealso: PKPaymentRequest for more information - /// @note You should only set either this or `paymentAmount`, not both. - /// The other will be automatically calculated on demand using your `paymentCurrency.` - - @objc public var paymentSummaryItems: [PKPaymentSummaryItem] { - get { - return paymentAmountModel.paymentSummaryItems( - withCurrency: paymentCurrency, - companyName: configuration.companyName, - shippingMethod: selectedShippingMethod - ) ?? [] - } - set(paymentSummaryItems) { - paymentAmountModel = STPPaymentContextAmountModel( - paymentSummaryItems: paymentSummaryItems - ) - } - } - - /// A value that indicates whether Apple Pay Later is available for a transaction. - /// Defaults to enabled. - /// - Seealso: This property is mirrors `PKPaymentRequest.applePayLaterAvailability` -#if compiler(>=5.9) - @available(macOS 14.0, iOS 17.0, *) - @objc public var applePayLaterAvailability: PKApplePayLaterAvailability { - // Stored properties cannot be marked potentially unavailable with '@available', so do this workaround instead - get { - return _applePayLaterAvailability as! PKApplePayLaterAvailability - } - set { - _applePayLaterAvailability = newValue - - } - } - private lazy var _applePayLaterAvailability: Any? = { - if #available(macOS 14.0, iOS 17.0, *) { - return PKApplePayLaterAvailability.available - } - return nil - }() -#endif - /// The presentation style used for all view controllers presented modally by the context. - /// Since custom transition styles are not supported, you should set this to either - /// `UIModalPresentationFullScreen`, `UIModalPresentationPageSheet`, or `UIModalPresentationFormSheet`. - /// The default value is `UIModalPresentationFullScreen`. - @objc public var modalPresentationStyle: UIModalPresentationStyle = .fullScreen - /// The mode to use when displaying the title of the navigation bar in all view - /// controllers presented by the context. The default value is `automatic`, - /// which causes the title to use the same styling as the previously displayed - /// navigation item (if the view controller is pushed onto the `hostViewController`). - /// If the `prefersLargeTitles` property of the `hostViewController`'s navigation bar - /// is false, this property has no effect and the navigation item's title is always - /// displayed as a small title. - /// If the view controller is presented modally, `automatic` and - /// `never` always result in a navigation bar with a small title. - @objc public var largeTitleDisplayMode = UINavigationItem.LargeTitleDisplayMode.automatic - /// A view that will be placed as the footer of the payment options selection - /// view controller. - /// When the footer view needs to be resized, it will be sent a - /// `sizeThatFits:` call. The view should respond correctly to this method in order - /// to be sized and positioned properly. - @objc public var paymentOptionsViewControllerFooterView: UIView? - /// A view that will be placed as the footer of the add card view controller. - /// When the footer view needs to be resized, it will be sent a - /// `sizeThatFits:` call. The view should respond correctly to this method in order - /// to be sized and positioned properly. - @objc public var addCardViewControllerFooterView: UIView? - /// The API Client to use to make requests. - /// Defaults to STPAPIClient.shared - public var apiClient: STPAPIClient = .shared { - didSet { - analyticsLogger.apiClient = apiClient - } - } - internal let analyticsLogger: AnalyticsLogger = .init(product: STPPaymentContext.self) - internal var loadingStartDate: Date? - - /// If `paymentContext:didFailToLoadWithError:` is called on your delegate, you - /// can in turn call this method to try loading again (if that hasn't been called, - /// calling this will do nothing). If retrying in turn fails, `paymentContext:didFailToLoadWithError:` - /// will be called again (and you can again call this to keep retrying, etc). - @objc - public func retryLoading() { - let loadingStartDate = Date() - self.loadingStartDate = loadingStartDate - analyticsLogger.logLoadStarted() - // Clear any cached customer object and attached payment methods before refetching - if apiAdapter is STPCustomerContext { - let customerContext = apiAdapter as? STPCustomerContext - customerContext?.clearCache() - } - weak var weakSelf = self - loadingPromise = STPPromise.init().onSuccess({ tuple in - guard let strongSelf = weakSelf else { - return - } - strongSelf.analyticsLogger.logLoadSucceeded(loadStartDate: loadingStartDate, defaultPaymentOption: tuple.selectedPaymentOption) - strongSelf.paymentOptions = tuple.paymentOptions - strongSelf.selectedPaymentOption = tuple.selectedPaymentOption - }).onFailure({ error in - guard let strongSelf = weakSelf else { - return - } - strongSelf.analyticsLogger.logLoadFailed(loadStartDate: loadingStartDate, error: error) - if strongSelf.hostViewController != nil { - if strongSelf.paymentOptionsViewController != nil - && strongSelf.paymentOptionsViewController?.viewIfLoaded?.window != nil - { - if let paymentOptionsViewController1 = strongSelf.paymentOptionsViewController { - strongSelf.appropriatelyDismiss(paymentOptionsViewController1) { - strongSelf.delegate?.paymentContext( - strongSelf, - didFailToLoadWithError: error - ) - } - } - } else { - strongSelf.delegate?.paymentContext(strongSelf, didFailToLoadWithError: error) - } - } - }) - apiAdapter.retrieveCustomer({ customer, retrieveCustomerError in - stpDispatchToMainThreadIfNecessary({ - guard let strongSelf = weakSelf else { - return - } - if let retrieveCustomerError = retrieveCustomerError { - strongSelf.loadingPromise?.fail(retrieveCustomerError) - return - } - if strongSelf.shippingAddress == nil && customer?.shippingAddress != nil { - strongSelf.shippingAddress = customer?.shippingAddress - strongSelf.shippingAddressNeedsVerification = true - } - - strongSelf.apiAdapter.listPaymentMethodsForCustomer(completion: { - paymentMethods, - error in - guard let strongSelf2 = weakSelf else { - return - } - stpDispatchToMainThreadIfNecessary({ - if let error = error { - strongSelf2.loadingPromise?.fail(error) - return - } - - if self.defaultPaymentMethod == nil - && (strongSelf2.apiAdapter is STPCustomerContext) - { - // Retrieve the last selected payment method saved by STPCustomerContext - (strongSelf2.apiAdapter as? STPCustomerContext)? - .retrieveLastSelectedPaymentMethodIDForCustomer(completion: { - paymentMethodID, - _ in - guard let strongSelf3 = weakSelf else { - return - } - if let paymentMethods = paymentMethods { - let paymentTuple = STPPaymentOptionTuple( - filteredForUIWith: paymentMethods, - selectedPaymentMethod: paymentMethodID, - configuration: strongSelf3.configuration - ) - strongSelf3.loadingPromise?.succeed(paymentTuple) - } else { - strongSelf3.loadingPromise?.fail( - STPErrorCode.invalidRequestError as! Error - ) - } - }) - } else { - if let paymentMethods = paymentMethods { - let paymentTuple = STPPaymentOptionTuple( - filteredForUIWith: paymentMethods, - selectedPaymentMethod: self.defaultPaymentMethod, - configuration: strongSelf2.configuration - ) - strongSelf2.loadingPromise?.succeed(paymentTuple) - } - } - }) - }) - }) - }) - } - - /// This creates, configures, and appropriately presents an `STPPaymentOptionsViewController` - /// on top of the payment context's `hostViewController`. It'll be dismissed automatically - /// when the user is done selecting their payment method. - /// @note This method will do nothing if it is called while STPPaymentContext is - /// already showing a view controller or in the middle of requesting a payment. - @objc - public func presentPaymentOptionsViewController() { - presentPaymentOptionsViewController(withNewState: .showingRequestedViewController) - } - - /// This creates, configures, and appropriately pushes an `STPPaymentOptionsViewController` - /// onto the navigation stack of the context's `hostViewController`. It'll be popped - /// automatically when the user is done selecting their payment method. - /// @note This method will do nothing if it is called while STPPaymentContext is - /// already showing a view controller or in the middle of requesting a payment. - @objc - public func pushPaymentOptionsViewController() { - assert( - hostViewController != nil && hostViewController?.viewIfLoaded?.window != nil, - "hostViewController must not be nil on STPPaymentContext when calling pushPaymentOptionsViewController on it. Next time, set the hostViewController property first!" - ) - var navigationController: UINavigationController? - if hostViewController is UINavigationController { - navigationController = hostViewController as? UINavigationController - } else { - navigationController = hostViewController?.navigationController - } - assert( - navigationController != nil, - "The payment context's hostViewController is not a navigation controller, or is not contained in one. Either make sure it is inside a navigation controller before calling pushPaymentOptionsViewController, or call presentPaymentOptionsViewController instead." - ) - if state == STPPaymentContextState.none { - state = .showingRequestedViewController - - let paymentOptionsViewController = STPPaymentOptionsViewController(paymentContext: self) - self.paymentOptionsViewController = paymentOptionsViewController - paymentOptionsViewController.prefilledInformation = prefilledInformation - paymentOptionsViewController.defaultPaymentMethod = defaultPaymentMethod - paymentOptionsViewController.paymentOptionsViewControllerFooterView = - paymentOptionsViewControllerFooterView - paymentOptionsViewController.addCardViewControllerFooterView = - addCardViewControllerFooterView - paymentOptionsViewController.navigationItem.largeTitleDisplayMode = - largeTitleDisplayMode - - navigationController?.pushViewController( - paymentOptionsViewController, - animated: transitionAnimationsEnabled() - ) - } - } - - /// This creates, configures, and appropriately presents a view controller for - /// collecting shipping address and shipping method on top of the payment context's - /// `hostViewController`. It'll be dismissed automatically when the user is done - /// entering their shipping info. - /// @note This method will do nothing if it is called while STPPaymentContext is - /// already showing a view controller or in the middle of requesting a payment. - @objc - public func presentShippingViewController() { - presentShippingViewController(withNewState: .showingRequestedViewController) - } - - /// This creates, configures, and appropriately pushes a view controller for - /// collecting shipping address and shipping method onto the navigation stack of - /// the context's `hostViewController`. It'll be popped automatically when the - /// user is done entering their shipping info. - /// @note This method will do nothing if it is called while STPPaymentContext is - /// already showing a view controller, or in the middle of requesting a payment. - @objc - public func pushShippingViewController() { - assert( - hostViewController != nil && hostViewController?.viewIfLoaded?.window != nil, - "hostViewController must not be nil on STPPaymentContext when calling pushShippingViewController on it. Next time, set the hostViewController property first!" - ) - var navigationController: UINavigationController? - if hostViewController is UINavigationController { - navigationController = hostViewController as? UINavigationController - } else { - navigationController = hostViewController?.navigationController - } - assert( - navigationController != nil, - "The payment context's hostViewController is not a navigation controller, or is not contained in one. Either make sure it is inside a navigation controller before calling pushShippingInfoViewController, or call presentShippingInfoViewController instead." - ) - if state == STPPaymentContextState.none { - state = .showingRequestedViewController - - let addressViewController = STPShippingAddressViewController(paymentContext: self) - addressViewController.navigationItem.largeTitleDisplayMode = largeTitleDisplayMode - navigationController?.pushViewController( - addressViewController, - animated: transitionAnimationsEnabled() - ) - } - } - - /// Requests payment from the user. This may need to present some supplemental UI - /// to the user, in which case it will be presented on the payment context's - /// `hostViewController`. For instance, if they've selected Apple Pay as their - /// payment method, calling this method will show the payment sheet. If the user - /// has a card on file, this will use that without presenting any additional UI. - /// After this is called, the `paymentContext:didCreatePaymentResult:completion:` - /// and `paymentContext:didFinishWithStatus:error:` methods will be called on the - /// context's `delegate`. - /// @note This method will do nothing if it is called while STPPaymentContext is - /// already showing a view controller, or in the middle of requesting a payment. - @objc - public func requestPayment() { - weak var weakSelf = self - loadingPromise?.onSuccess({ _ in - guard let strongSelf = weakSelf else { - return - } - - if strongSelf.state != STPPaymentContextState.none { - return - } - - if strongSelf.selectedPaymentOption == nil { - strongSelf.presentPaymentOptionsViewController(withNewState: .requestingPayment) - } else if strongSelf.requestPaymentShouldPresentShippingViewController() { - strongSelf.presentShippingViewController(withNewState: .requestingPayment) - } else if let selectedPaymentOption = strongSelf.selectedPaymentOption, - (selectedPaymentOption is STPPaymentMethod || selectedPaymentOption is STPPaymentMethodParams) - { - strongSelf.state = .requestingPayment - let result = STPPaymentResult(paymentOption: strongSelf.selectedPaymentOption!) - strongSelf.delegate?.paymentContext(self, didCreatePaymentResult: result) { status, error in - // Note `selectedPaymentOption` is always an `STPPaymentMethod` for cards - strongSelf.analyticsLogger.logPayment(status: status, loadStartDate: strongSelf.loadingStartDate, paymentOption: selectedPaymentOption, error: error) - stpDispatchToMainThreadIfNecessary({ - strongSelf.didFinish(with: status, error: error) - }) - } - } else if let selectedPaymentOption = strongSelf.selectedPaymentOption, selectedPaymentOption is STPApplePayPaymentOption { - assert( - strongSelf.hostViewController != nil, - "hostViewController must not be nil on STPPaymentContext. Next time, set the hostViewController property first!" - ) - strongSelf.state = .requestingPayment - let paymentRequest = strongSelf.buildPaymentRequest() - let shippingAddressHandler: STPShippingAddressSelectionBlock = { - shippingAddress, - completion in - // Apple Pay always returns a partial address here, so we won't - // update self.shippingAddress or self.shippingMethods - if strongSelf.delegate?.responds( - to: #selector( - STPPaymentContextDelegate.paymentContext( - _: - didUpdateShippingAddress: - completion: - )) - ) - ?? false - { - strongSelf.delegate?.paymentContext?( - strongSelf, - didUpdateShippingAddress: shippingAddress - ) { status, _, shippingMethods, _ in - completion( - status, - shippingMethods ?? [], - strongSelf.paymentSummaryItems - ) - } - } else { - completion( - .valid, - strongSelf.shippingMethods ?? [], - strongSelf.paymentSummaryItems - ) - } - } - let shippingMethodHandler: STPShippingMethodSelectionBlock = { - shippingMethod, - completion in - strongSelf.selectedShippingMethod = shippingMethod - strongSelf.delegate?.paymentContextDidChange(strongSelf) - completion(self.paymentSummaryItems) - } - let paymentHandler: STPPaymentAuthorizationBlock = { payment in - strongSelf.selectedShippingMethod = payment.shippingMethod - if let shippingContact = payment.shippingContact { - strongSelf.shippingAddress = STPAddress(pkContact: shippingContact) - } - strongSelf.shippingAddressNeedsVerification = false - strongSelf.delegate?.paymentContextDidChange(strongSelf) - if strongSelf.apiAdapter is STPCustomerContext { - let customerContext = strongSelf.apiAdapter as? STPCustomerContext - if let shippingAddress1 = strongSelf.shippingAddress { - customerContext?.updateCustomer( - withShippingAddress: shippingAddress1, - completion: nil - ) - } - } - } - let applePayPaymentMethodHandler: STPApplePayPaymentMethodHandlerBlock = { - paymentMethod, - completion in - strongSelf.apiAdapter.attachPaymentMethod(toCustomer: paymentMethod) { - attachPaymentMethodError in - stpDispatchToMainThreadIfNecessary({ - if attachPaymentMethodError != nil { - completion(.error, attachPaymentMethodError) - } else { - let result = STPPaymentResult(paymentOption: paymentMethod) - strongSelf.delegate?.paymentContext( - strongSelf, - didCreatePaymentResult: result - ) { - status, - error in - // for Apple Pay, the didFinishWithStatus callback is fired later when Apple Pay VC finishes - completion(status, error) - } - } - }) - } - } - if let paymentRequest = paymentRequest { - strongSelf.applePayVC = PKPaymentAuthorizationViewController.stp_controller( - with: paymentRequest, - apiClient: strongSelf.apiClient, - onShippingAddressSelection: shippingAddressHandler, - onShippingMethodSelection: shippingMethodHandler, - onPaymentAuthorization: paymentHandler, - onPaymentMethodCreation: applePayPaymentMethodHandler, - onFinish: { status, error in - strongSelf.analyticsLogger.logPayment(status: status, loadStartDate: strongSelf.loadingStartDate, paymentOption: selectedPaymentOption, error: error) - if strongSelf.applePayVC?.presentingViewController != nil { - strongSelf.hostViewController?.dismiss( - animated: strongSelf.transitionAnimationsEnabled() - ) { - strongSelf.didFinish(with: status, error: error) - } - } else { - strongSelf.didFinish(with: status, error: error) - } - strongSelf.applePayVC = nil - } - ) - } - if let applePayVC1 = strongSelf.applePayVC { - strongSelf.hostViewController?.present( - applePayVC1, - animated: strongSelf.transitionAnimationsEnabled() - ) - } - } - }).onFailure({ error in - guard let strongSelf = weakSelf else { - return - } - strongSelf.didFinish(with: .error, error: error) - }) - } - private var loadingPromise: STPPromise? - private weak var paymentOptionsViewController: STPPaymentOptionsViewController? - private var state: STPPaymentContextState = .none - private var paymentAmountModel = STPPaymentContextAmountModel(amount: 0) - private var shippingAddressNeedsVerification = false - // If hostViewController was set to a nav controller, the original VC on top of the stack - private weak var originalTopViewController: UIViewController? - private var applePayVC: PKPaymentAuthorizationViewController? - - // Disable transition animations in tests - func transitionAnimationsEnabled() -> Bool { - return NSClassFromString("XCTest") == nil - } - - var currentValuePromise: STPPromise { - weak var weakSelf = self - return - (loadingPromise?.map({ _ in - guard let strongSelf = weakSelf, let paymentOptions = strongSelf.paymentOptions - else { - return STPPaymentOptionTuple() - } - return STPPaymentOptionTuple( - paymentOptions: paymentOptions, - selectedPaymentOption: strongSelf.selectedPaymentOption - ) - }))! - } - - func remove(_ paymentOptionToRemove: STPPaymentOption?) { - // Remove payment method from cached representation - var paymentOptions = self.paymentOptions - paymentOptions?.removeAll { $0 as AnyObject === paymentOptionToRemove as AnyObject } - self.paymentOptions = paymentOptions - - // Elect new selected payment method if needed - if let selectedPaymentOption = selectedPaymentOption, - selectedPaymentOption.isEqual(paymentOptionToRemove) - { - self.selectedPaymentOption = self.paymentOptions?.first - } - } - - // MARK: - Payment Methods - - func presentPaymentOptionsViewController(withNewState state: STPPaymentContextState) { - assert( - hostViewController != nil && hostViewController?.viewIfLoaded?.window != nil, - "hostViewController must not be nil on STPPaymentContext when calling pushPaymentOptionsViewController on it. Next time, set the hostViewController property first!" - ) - if self.state == STPPaymentContextState.none { - self.state = state - let paymentOptionsViewController = STPPaymentOptionsViewController(paymentContext: self) - self.paymentOptionsViewController = paymentOptionsViewController - paymentOptionsViewController.prefilledInformation = prefilledInformation - paymentOptionsViewController.defaultPaymentMethod = defaultPaymentMethod - paymentOptionsViewController.paymentOptionsViewControllerFooterView = - paymentOptionsViewControllerFooterView - paymentOptionsViewController.addCardViewControllerFooterView = - addCardViewControllerFooterView - paymentOptionsViewController.navigationItem.largeTitleDisplayMode = - largeTitleDisplayMode - - let navigationController = UINavigationController( - rootViewController: paymentOptionsViewController - ) - navigationController.navigationBar.stp_theme = theme - navigationController.navigationBar.prefersLargeTitles = true - navigationController.modalPresentationStyle = modalPresentationStyle - hostViewController?.present( - navigationController, - animated: transitionAnimationsEnabled() - ) - } - } - - @objc - public func paymentOptionsViewController( - _ paymentOptionsViewController: STPPaymentOptionsViewController, - didSelect paymentOption: STPPaymentOption - ) { - selectedPaymentOption = paymentOption - } - - @objc - public func paymentOptionsViewControllerDidFinish( - _ paymentOptionsViewController: STPPaymentOptionsViewController - ) { - appropriatelyDismiss(paymentOptionsViewController) { - if self.state == .requestingPayment { - self.state = STPPaymentContextState.none - self.requestPayment() - } else { - self.state = STPPaymentContextState.none - } - } - } - - @objc - public func paymentOptionsViewControllerDidCancel( - _ paymentOptionsViewController: STPPaymentOptionsViewController - ) { - appropriatelyDismiss(paymentOptionsViewController) { - if self.state == .requestingPayment { - self.didFinish( - with: .userCancellation, - error: nil - ) - } else { - self.state = STPPaymentContextState.none - } - } - } - - @objc - public func paymentOptionsViewController( - _ paymentOptionsViewController: STPPaymentOptionsViewController, - didFailToLoadWithError error: Error - ) { - // we'll handle this ourselves when the loading promise fails. - } - - @objc(appropriatelyDismissPaymentOptionsViewController:completion:) func appropriatelyDismiss( - _ viewController: STPPaymentOptionsViewController, - completion: @escaping STPVoidBlock - ) { - if viewController.stp_isAtRootOfNavigationController() { - // if we're the root of the navigation controller, we've been presented modally. - viewController.presentingViewController?.dismiss( - animated: transitionAnimationsEnabled() - ) { - self.paymentOptionsViewController = nil - completion() - } - } else { - // otherwise, we've been pushed onto the stack. - var destinationViewController = hostViewController - // If hostViewController is a nav controller, pop to the original VC on top of the stack. - if hostViewController is UINavigationController { - destinationViewController = originalTopViewController - } - viewController.navigationController?.stp_pop( - to: destinationViewController, - animated: transitionAnimationsEnabled() - ) { - self.paymentOptionsViewController = nil - completion() - } - } - } - - // MARK: - Shipping Info - - func presentShippingViewController(withNewState state: STPPaymentContextState) { - assert( - hostViewController != nil && hostViewController?.viewIfLoaded?.window != nil, - "hostViewController must not be nil on STPPaymentContext when calling presentShippingViewController on it. Next time, set the hostViewController property first!" - ) - - if self.state == STPPaymentContextState.none { - self.state = state - - let addressViewController = STPShippingAddressViewController(paymentContext: self) - addressViewController.navigationItem.largeTitleDisplayMode = largeTitleDisplayMode - let navigationController = UINavigationController( - rootViewController: addressViewController - ) - navigationController.navigationBar.stp_theme = theme - navigationController.navigationBar.prefersLargeTitles = true - navigationController.modalPresentationStyle = modalPresentationStyle - hostViewController?.present( - navigationController, - animated: transitionAnimationsEnabled() - ) - } - } - - @objc - public func shippingAddressViewControllerDidCancel( - _ addressViewController: STPShippingAddressViewController - ) { - appropriatelyDismiss(addressViewController) { - if self.state == .requestingPayment { - self.didFinish( - with: .userCancellation, - error: nil - ) - } else { - self.state = STPPaymentContextState.none - } - } - } - - @objc - public func shippingAddressViewController( - _ addressViewController: STPShippingAddressViewController, - didEnter address: STPAddress, - completion: @escaping STPShippingMethodsCompletionBlock - ) { - if delegate?.responds( - to: #selector( - STPPaymentContextDelegate.paymentContext(_:didUpdateShippingAddress:completion:)) - ) - ?? false - { - delegate?.paymentContext?(self, didUpdateShippingAddress: address) { - status, - shippingValidationError, - shippingMethods, - selectedMethod in - self.shippingMethods = shippingMethods - completion(status, shippingValidationError, shippingMethods, selectedMethod) - } - } else { - completion(.valid, nil, nil, nil) - } - } - - @objc - public func shippingAddressViewController( - _ addressViewController: STPShippingAddressViewController, - didFinishWith address: STPAddress, - shippingMethod method: PKShippingMethod? - ) { - shippingAddress = address - shippingAddressNeedsVerification = false - selectedShippingMethod = method - delegate?.paymentContextDidChange(self) - if apiAdapter.responds( - to: #selector(STPCustomerContext.updateCustomer(withShippingAddress:completion:)) - ) { - if let shippingAddress = shippingAddress { - apiAdapter.updateCustomer?(withShippingAddress: shippingAddress, completion: nil) - } - } - appropriatelyDismiss(addressViewController) { - if self.state == .requestingPayment { - self.state = STPPaymentContextState.none - self.requestPayment() - } else { - self.state = STPPaymentContextState.none - } - } - } - - @objc(appropriatelyDismissViewController:completion:) func appropriatelyDismiss( - _ viewController: UIViewController, - completion: @escaping STPVoidBlock - ) { - if viewController.stp_isAtRootOfNavigationController() { - // if we're the root of the navigation controller, we've been presented modally. - viewController.presentingViewController?.dismiss( - animated: transitionAnimationsEnabled() - ) { - completion() - } - } else { - // otherwise, we've been pushed onto the stack. - var destinationViewController = hostViewController - // If hostViewController is a nav controller, pop to the original VC on top of the stack. - if hostViewController is UINavigationController { - destinationViewController = originalTopViewController - } - viewController.navigationController?.stp_pop( - to: destinationViewController, - animated: transitionAnimationsEnabled() - ) { - completion() - } - } - } - - // MARK: - Request Payment - func requestPaymentShouldPresentShippingViewController() -> Bool { - let shippingAddressRequired = (configuration.requiredShippingAddressFields?.count ?? 0) > 0 - var shippingAddressIncomplete: Bool? - if let requiredShippingAddressFields1 = configuration.requiredShippingAddressFields { - shippingAddressIncomplete = - !(shippingAddress?.containsRequiredShippingAddressFields( - requiredShippingAddressFields1 - ) - ?? false) - } - let shippingMethodRequired = - configuration.shippingType == .shipping - && delegate?.responds( - to: #selector( - STPPaymentContextDelegate.paymentContext(_:didUpdateShippingAddress:completion:) - ) - ) - ?? false - && selectedShippingMethod == nil - let verificationRequired = - configuration.verifyPrefilledShippingAddress && shippingAddressNeedsVerification - // true if STPShippingVC should be presented to collect or verify a shipping address - let shouldPresentShippingAddress = - shippingAddressRequired && (shippingAddressIncomplete ?? false || verificationRequired) - // this handles a corner case where STPShippingVC should be presented because: - // - shipping address has been pre-filled - // - no verification is required, but the user still needs to enter a shipping method - let shouldPresentShippingMethods = - shippingAddressRequired && !(shippingAddressIncomplete ?? false) - && !verificationRequired - && shippingMethodRequired - return shouldPresentShippingAddress || shouldPresentShippingMethods - } - - func didFinish( - with status: STPPaymentStatus, - error: Error? - ) { - state = STPPaymentContextState.none - delegate?.paymentContext( - self, - didFinishWith: status, - error: error - ) - } - - func buildPaymentRequest() -> PKPaymentRequest? { - guard let appleMerchantIdentifier = configuration.appleMerchantIdentifier, paymentAmount > 0 - else { - return nil - } - let paymentRequest = StripeAPI.paymentRequest( - withMerchantIdentifier: appleMerchantIdentifier, - country: paymentCountry, - currency: paymentCurrency - ) - -#if compiler(>=5.9) - if #available(macOS 14.0, iOS 17.0, *) { - paymentRequest.applePayLaterAvailability = applePayLaterAvailability._convertedToSwiftValue() - } -#endif - - let summaryItems = paymentSummaryItems - paymentRequest.paymentSummaryItems = summaryItems - - let requiredFields = STPAddress.applePayContactFields( - from: configuration.requiredBillingAddressFields - ) - paymentRequest.requiredBillingContactFields = requiredFields - - var shippingRequiredFields: Set? - if let requiredShippingAddressFields1 = configuration.requiredShippingAddressFields { - shippingRequiredFields = STPAddress.pkContactFields( - fromStripeContactFields: requiredShippingAddressFields1 - ) - } - if let shippingRequiredFields = shippingRequiredFields { - paymentRequest.requiredShippingContactFields = shippingRequiredFields - } - - paymentRequest.currencyCode = paymentCurrency.uppercased() - if let selectedShippingMethod = selectedShippingMethod { - var orderedShippingMethods = shippingMethods - orderedShippingMethods?.removeAll { - $0 as AnyObject === selectedShippingMethod as AnyObject - } - orderedShippingMethods?.insert(selectedShippingMethod, at: 0) - paymentRequest.shippingMethods = orderedShippingMethods - } else { - paymentRequest.shippingMethods = shippingMethods - } - - paymentRequest.shippingType = STPPaymentContext.pkShippingType(configuration.shippingType) - - if let shippingAddress = shippingAddress { - paymentRequest.shippingContact = shippingAddress.pkContactValue() - } - return paymentRequest - } - - class func pkShippingType(_ shippingType: STPShippingType) -> PKShippingType { - switch shippingType { - case .shipping: - return .shipping - case .delivery: - return .delivery - @unknown default: - fatalError() - } - } - - func artificiallyRetain(_ host: NSObject) { - objc_setAssociatedObject( - host, - UnsafeRawPointer(&kSTPPaymentCoordinatorAssociatedObjectKey), - self, - .OBJC_ASSOCIATION_RETAIN_NONATOMIC - ) - } - - // MARK: - STPAuthenticationContext - @objc - public func authenticationPresentingViewController() -> UIViewController { - return hostViewController! - } - - @objc - public func prepare(forPresentation completion: @escaping STPVoidBlock) { - if applePayVC != nil && applePayVC?.presentingViewController != nil { - hostViewController?.dismiss( - animated: transitionAnimationsEnabled() - ) { - completion() - } - } else { - completion() - } - } -} - -/// Implement `STPPaymentContextDelegate` to get notified when a payment context changes, finishes, encounters errors, etc. In practice, if your app has a "checkout screen view controller", that is a good candidate to implement this protocol. -@objc public protocol STPPaymentContextDelegate: NSObjectProtocol { - /// Called when the payment context encounters an error when fetching its initial set of data. A few ways to handle this are: - /// - If you're showing the user a checkout page, dismiss the checkout page when this is called and present the error to the user. - /// - Present the error to the user using a `UIAlertController` with two buttons: Retry and Cancel. If they cancel, dismiss your UI. If they Retry, call `retryLoading` on the payment context. - /// To make it harder to get your UI into a bad state, this won't be called until the context's `hostViewController` has finished appearing. - /// - Parameters: - /// - paymentContext: the payment context that encountered the error - /// - error: the error that was encountered - func paymentContext(_ paymentContext: STPPaymentContext, didFailToLoadWithError error: Error) - /// This is called every time the contents of the payment context change. When this is called, you should update your app's UI to reflect the current state of the payment context. For example, if you have a checkout page with a "selected payment method" row, you should update its payment method with `paymentContext.selectedPaymentOption.label`. If that checkout page has a "buy" button, you should enable/disable it depending on the result of `paymentContext.isReadyForPayment`. - /// - Parameter paymentContext: the payment context that changed - func paymentContextDidChange(_ paymentContext: STPPaymentContext) - /// Inside this method, you should make a call to your backend API to make a PaymentIntent with that Customer + payment method, and invoke the `completion` block when that is done. - /// - Parameters: - /// - paymentContext: The context that succeeded - /// - paymentResult: Information associated with the payment that you can pass to your server. You should go to your backend API with this payment result and use the PaymentIntent API to complete the payment. See https://stripe.com/docs/mobile/ios/basic#submit-payment-intents Once that's done call the `completion` block with any error that occurred (or none, if the payment succeeded). - seealso: STPPaymentResult.h - /// - completion: Call this block when you're done creating a payment intent (or subscription, etc) on your backend. If it succeeded, call `completion(STPPaymentStatusSuccess, nil)`. If it failed with an error, call `completion(STPPaymentStatusError, error)`. If the user canceled, call `completion(STPPaymentStatusUserCancellation, nil)`. - func paymentContext( - _ paymentContext: STPPaymentContext, - didCreatePaymentResult paymentResult: STPPaymentResult, - completion: @escaping STPPaymentStatusBlock - ) - /// This is invoked by an `STPPaymentContext` when it is finished. This will be called after the payment is done and all necessary UI has been dismissed. You should inspect the returned `status` and behave appropriately. For example: if it's `STPPaymentStatusSuccess`, show the user a receipt. If it's `STPPaymentStatusError`, inform the user of the error. If it's `STPPaymentStatusUserCancellation`, do nothing. - /// - Parameters: - /// - paymentContext: The payment context that finished - /// - status: The status of the payment - `STPPaymentStatusSuccess` if it succeeded, `STPPaymentStatusError` if it failed with an error (in which case the `error` parameter will be non-nil), `STPPaymentStatusUserCancellation` if the user canceled the payment. - /// - error: An error that occurred, if any. - func paymentContext( - _ paymentContext: STPPaymentContext, - didFinishWith status: STPPaymentStatus, - error: Error? - ) - - /// Inside this method, you should verify that you can ship to the given address. - /// You should call the completion block with the results of your validation - /// and the available shipping methods for the given address. If you don't implement - /// this method, the user won't be prompted to select a shipping method and all - /// addresses will be valid. If you call the completion block with nil or an - /// empty array of shipping methods, the user won't be prompted to select a - /// shipping method. - /// @note If a user updates their shipping address within the Apple Pay dialog, - /// this address will be anonymized. For example, in the US, it will only include the - /// city, state, and zip code. The payment context will have the user's complete - /// shipping address by the time `paymentContext:didFinishWithStatus:error` is - /// called. - /// - Parameters: - /// - paymentContext: The context that updated its shipping address - /// - address: The current shipping address - /// - completion: Call this block when you're done validating the shipping - /// address and calculating available shipping methods. If you call the completion - /// block with nil or an empty array of shipping methods, the user won't be prompted - /// to select a shipping method. - @objc optional func paymentContext( - _ paymentContext: STPPaymentContext, - didUpdateShippingAddress address: STPAddress, - completion: @escaping STPShippingMethodsCompletionBlock - ) -} - -/// The current state of the payment context -/// - STPPaymentContextStateNone: No view controllers are currently being shown. The payment may or may not have already been completed -/// - STPPaymentContextStateShowingRequestedViewController: The view controller that you requested the context show is being shown (via the push or present payment methods or shipping view controller methods) -/// - STPPaymentContextStateRequestingPayment: The payment context is in the middle of requesting payment. It may be showing some other UI or view controller if more information is necessary to complete the payment. -enum STPPaymentContextState: Int { - case none - case showingRequestedViewController - case requestingPayment -} - -private var kSTPPaymentCoordinatorAssociatedObjectKey = 0 - -/// :nodoc: -@_spi(STP) extension STPPaymentContext: STPAnalyticsProtocol { - @_spi(STP) public static var stp_analyticsIdentifier = "STPPaymentContext" -} - -#if compiler(>=5.9) -@available(macOS 14.0, iOS 17.0, *) -extension PKApplePayLaterAvailability { - func _convertedToSwiftValue() -> PKPaymentRequest.ApplePayLaterAvailability { - switch self { - case .available: - return .available - case .unavailableItemIneligible: - return .unavailable(.itemIneligible) - case .unavailableRecurringTransaction: - return .unavailable(.recurringTransaction) - @unknown default: - fatalError() - } - } -} -#endif diff --git a/Stripe/StripeiOS/Source/STPPaymentContextAmountModel.swift b/Stripe/StripeiOS/Source/STPPaymentContextAmountModel.swift deleted file mode 100644 index c79c13e2041..00000000000 --- a/Stripe/StripeiOS/Source/STPPaymentContextAmountModel.swift +++ /dev/null @@ -1,96 +0,0 @@ -// -// STPPaymentContextAmountModel.swift -// StripeiOS -// -// Created by Brian Dorfman on 8/16/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -import Foundation -import PassKit -@_spi(STP) import StripePayments - -/// Internal model for STPPaymentContext's `paymentAmount` and -/// `paymentSummaryItems` properties. -class STPPaymentContextAmountModel: NSObject { - private var paymentAmount = 0 - private var paymentSummaryItems: [PKPaymentSummaryItem]? - - init( - amount paymentAmount: Int - ) { - super.init() - self.paymentAmount = paymentAmount - paymentSummaryItems = nil - } - - init( - paymentSummaryItems: [PKPaymentSummaryItem]? - ) { - super.init() - paymentAmount = 0 - self.paymentSummaryItems = paymentSummaryItems - } - - func paymentAmount(withCurrency currency: String?, shippingMethod: PKShippingMethod?) -> Int { - let shippingAmount = - ((shippingMethod != nil) - ? shippingMethod?.amount.stp_amount(withCurrency: currency) : 0) ?? 0 - if paymentSummaryItems == nil { - return paymentAmount + shippingAmount - } else { - let lastItem = paymentSummaryItems?.last - return (lastItem?.amount.stp_amount(withCurrency: currency) ?? 0) + shippingAmount - } - } - - func paymentSummaryItems( - withCurrency currency: String?, - companyName: String?, - shippingMethod: PKShippingMethod? - ) -> [PKPaymentSummaryItem]? { - var shippingItem: PKPaymentSummaryItem? - if let shippingMethod = shippingMethod { - shippingItem = PKPaymentSummaryItem( - label: shippingMethod.label, - amount: shippingMethod.amount - ) - } - if paymentSummaryItems == nil { - let shippingAmount = shippingMethod?.amount.stp_amount(withCurrency: currency) ?? 0 - let total = NSDecimalNumber.stp_decimalNumber( - withAmount: paymentAmount + shippingAmount, - currency: currency - ) - let totalItem = PKPaymentSummaryItem(label: companyName ?? "", amount: total) - var items = [totalItem] - if let shippingItem = shippingItem { - items.insert(shippingItem, at: 0) - } - return items.compactMap { $0 } - } else { - if (paymentSummaryItems?.count ?? 0) > 0 && shippingItem != nil { - var items = paymentSummaryItems - let origTotalItem = items?.last - var newTotal: NSDecimalNumber? - if let amount1 = shippingItem?.amount { - newTotal = origTotalItem?.amount.adding(amount1) - } - var totalItem: PKPaymentSummaryItem? - if let newTotal = newTotal { - totalItem = PKPaymentSummaryItem( - label: origTotalItem?.label ?? "", - amount: newTotal - ) - } - items?.removeLast() - if let items = items { - return items + [shippingItem, totalItem].compactMap { $0 } - } - return nil - } else { - return paymentSummaryItems - } - } - } -} diff --git a/Stripe/StripeiOS/Source/STPPaymentIntentParams+BasicUI.swift b/Stripe/StripeiOS/Source/STPPaymentIntentParams+BasicUI.swift deleted file mode 100644 index 007367db13f..00000000000 --- a/Stripe/StripeiOS/Source/STPPaymentIntentParams+BasicUI.swift +++ /dev/null @@ -1,22 +0,0 @@ -// -// STPPaymentIntentParams+BasicUI.swift -// StripeiOS -// -// Created by David Estes on 6/30/22. -// Copyright © 2022 Stripe, Inc. All rights reserved. -// - -import Foundation - -extension STPPaymentIntentParams { - /// Provide an STPPaymentResult from STPPaymentContext, and this will populate - /// the proper field (either paymentMethodId or paymentMethodParams) for your PaymentMethod. - @objc - public func configure(with paymentResult: STPPaymentResult) { - if let paymentMethod = paymentResult.paymentMethod { - paymentMethodId = paymentMethod.stripeId - } else if let params = paymentResult.paymentMethodParams { - paymentMethodParams = params - } - } -} diff --git a/Stripe/StripeiOS/Source/STPPaymentMethod+BasicUI.swift b/Stripe/StripeiOS/Source/STPPaymentMethod+BasicUI.swift deleted file mode 100644 index b99758bc683..00000000000 --- a/Stripe/StripeiOS/Source/STPPaymentMethod+BasicUI.swift +++ /dev/null @@ -1,94 +0,0 @@ -// -// STPPaymentMethod+BasicUI.swift -// StripeiOS -// -// Created by David Estes on 6/30/22. -// Copyright © 2022 Stripe, Inc. All rights reserved. -// - -import Foundation -@_spi(STP) import StripeCore -@_spi(STP) import StripePayments -@_spi(STP) import StripePaymentsUI -import UIKit - -extension STPPaymentMethod: STPPaymentOption { - // MARK: - STPPaymentOption - @objc public var image: UIImage { - if type == .card, let card = card { - return STPImageLibrary.cardBrandImage(for: card.preferredDisplayBrand) - } else { - return STPImageLibrary.cardBrandImage(for: .unknown) - } - } - - @objc public var templateImage: UIImage { - if type == .card, let card = card { - return STPImageLibrary.templatedBrandImage(for: card.preferredDisplayBrand) - } else { - return STPImageLibrary.templatedBrandImage(for: .unknown) - } - } - - @objc public var label: String { - switch type { - case .card: - if let card = card { - let brand = STPCardBrandUtilities.stringFrom(card.preferredDisplayBrand) - return "\(brand ?? "") \(card.last4 ?? "")" - } else { - return STPCardBrandUtilities.stringFrom(.unknown) ?? "" - } - case .FPX: - if let fpx = fpx { - return STPFPXBank.stringFrom(STPFPXBank.brandFrom(fpx.bankIdentifierCode)) ?? "" - } else { - fallthrough - } - case .USBankAccount: - if let usBankAccount = usBankAccount { - return String( - format: String.Localized.bank_name_account_ending_in_last_4, - usBankAccount.bankName, - usBankAccount.last4 - ) - } else { - fallthrough - } - default: - return type.displayName - } - } - - @objc public var isReusable: Bool { - switch type { - case .card, .link, .USBankAccount: - return true - case .alipay, // Careful! Revisit this if/when we support recurring Alipay - .AUBECSDebit, - .bacsDebit, .SEPADebit, .iDEAL, .FPX, .cardPresent, .giropay, .EPS, .payPal, - .przelewy24, .bancontact, - .OXXO, .sofort, .grabPay, .netBanking, .UPI, .afterpayClearpay, .blik, - .weChatPay, .boleto, .klarna, .affirm, .cashApp, .paynow, .zip, .revolutPay, .amazonPay, - .alma, .mobilePay, .konbini, .promptPay, .swish, .twint, .multibanco, .sunbit, .billie, - .satispay, - .unknown: - return false - - @unknown default: - return false - } - } -} - -extension String { - var toCardBrand: STPCardBrand? { - return STPCard.brand(from: self) - } -} - -extension STPPaymentMethodCard { - var preferredDisplayBrand: STPCardBrand { - return networks?.preferred?.toCardBrand ?? displayBrand?.toCardBrand ?? brand - } -} diff --git a/Stripe/StripeiOS/Source/STPPaymentMethodParams+BasicUI.swift b/Stripe/StripeiOS/Source/STPPaymentMethodParams+BasicUI.swift deleted file mode 100644 index 197f9c0156b..00000000000 --- a/Stripe/StripeiOS/Source/STPPaymentMethodParams+BasicUI.swift +++ /dev/null @@ -1,57 +0,0 @@ -// -// STPPaymentMethodParams+BasicUI.swift -// StripeiOS -// -// Created by David Estes on 6/30/22. -// Copyright © 2022 Stripe, Inc. All rights reserved. -// - -import Foundation -@_spi(STP) import StripePayments -@_spi(STP) import StripePaymentsUI -import UIKit - -extension STPPaymentMethodParams: STPPaymentOption { - // MARK: - STPPaymentOption - @objc public var image: UIImage { - if type == .card && card != nil { - let brand = card?.preferredDisplayBrand ?? .unknown - return STPImageLibrary.cardBrandImage(for: brand) - } else { - return STPImageLibrary.cardBrandImage(for: .unknown) - } - } - - @objc public var templateImage: UIImage { - if type == .card && card != nil { - let brand = card?.preferredDisplayBrand ?? .unknown - return STPImageLibrary.templatedBrandImage(for: brand) - } else if type == .FPX { - return STPImageLibrary.bankIcon() - } else { - return STPImageLibrary.templatedBrandImage(for: .unknown) - } - } - - @objc public var isReusable: Bool { - switch type { - case .card, .link, .USBankAccount: - return true - case .alipay, .AUBECSDebit, .bacsDebit, .SEPADebit, .iDEAL, .FPX, .cardPresent, .giropay, - .grabPay, .EPS, .przelewy24, .bancontact, .netBanking, .OXXO, .payPal, .sofort, .UPI, - .afterpayClearpay, .blik, .weChatPay, .boleto, .klarna, .affirm, .cashApp, .paynow, - .zip, .revolutPay, .amazonPay, .alma, .mobilePay, .konbini, .promptPay, .swish, .twint, - .multibanco, .sunbit, .billie, .satispay, - .unknown: - return false - @unknown default: - return false - } - } -} - -extension STPPaymentMethodCardParams { - var preferredDisplayBrand: STPCardBrand { - return networks?.preferred?.toCardBrand ?? STPCardValidator.brand(forNumber: number ?? "") - } -} diff --git a/Stripe/StripeiOS/Source/STPPaymentOption.swift b/Stripe/StripeiOS/Source/STPPaymentOption.swift deleted file mode 100644 index 278c3d38628..00000000000 --- a/Stripe/StripeiOS/Source/STPPaymentOption.swift +++ /dev/null @@ -1,36 +0,0 @@ -// -// STPPaymentOption.swift -// StripeiOS -// -// Created by Ben Guo on 4/19/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -import UIKit - -/// This protocol represents a payment method that a user can select and use to -/// pay. -/// The classes that conform to it and are supported by the UI: -/// - `STPApplePay`, which represents that the user wants to pay with -/// Apple Pay -/// - `STPPaymentMethod`. Only `STPPaymentMethod.type == STPPaymentMethodTypeCard` and -/// `STPPaymentMethod.type == STPPaymentMethodTypeFPX` are supported by `STPPaymentContext` -/// and `STPPaymentOptionsViewController` -/// - `STPPaymentMethodParams`. This should be used with non-reusable payment method, such -/// as FPX and iDEAL. Instead of reaching out to Stripe to create a PaymentMethod, you can -/// pass an STPPaymentMethodParams directly to Stripe when confirming a PaymentIntent. -/// @note card-based Sources, Cards, and FPX support this protocol for use -/// in a custom integration. -@objc public protocol STPPaymentOption: NSObjectProtocol { - /// A small (32 x 20 points) logo image representing the payment method. For - /// example, the Visa logo for a Visa card, or the Apple Pay logo. - var image: UIImage { get } - /// A small (32 x 20 points) logo image representing the payment method that can be - /// used as template for tinted icons. - var templateImage: UIImage { get } - /// A string describing the payment method, such as "Apple Pay" or "Visa 4242". - var label: String { get } - /// Describes whether this payment option may be used multiple times. If it is not reusable, - /// the payment method must be discarded after use. - var isReusable: Bool { get } -} diff --git a/Stripe/StripeiOS/Source/STPPaymentOptionTableViewCell.swift b/Stripe/StripeiOS/Source/STPPaymentOptionTableViewCell.swift deleted file mode 100644 index 9d6bb81ccbe..00000000000 --- a/Stripe/StripeiOS/Source/STPPaymentOptionTableViewCell.swift +++ /dev/null @@ -1,326 +0,0 @@ -// -// STPPaymentOptionTableViewCell.swift -// StripeiOS -// -// Created by Ben Guo on 8/30/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -@_spi(STP) import StripeCore -@_spi(STP) import StripePaymentsUI -import UIKit - -class STPPaymentOptionTableViewCell: UITableViewCell { - @objc(configureForNewCardRowWithTheme:) func configureForNewCardRow(with theme: STPTheme) { - paymentOption = nil - self.theme = theme - - backgroundColor = theme.secondaryBackgroundColor - - // Left icon - leftIcon.image = STPLegacyImageLibrary.addIcon() - leftIcon.tintColor = theme.accentColor - - // Title label - titleLabel.font = theme.font - titleLabel.textColor = theme.accentColor - titleLabel.text = STPLocalizedString("Add New Card…", "Button to add a new credit card.") - - // Checkmark icon - checkmarkIcon.isHidden = true - - setNeedsLayout() - } - - @objc(configureWithPaymentOption:theme:selected:) func configure( - with paymentOption: STPPaymentOption?, - theme: STPTheme, - selected: Bool - ) { - self.paymentOption = paymentOption - self.theme = theme - - backgroundColor = theme.secondaryBackgroundColor - - // Left icon - leftIcon.image = paymentOption?.templateImage - leftIcon.tintColor = primaryColorForPaymentOption(withSelected: selected) - - // Title label - titleLabel.font = theme.font - titleLabel.attributedText = buildAttributedString(with: paymentOption, selected: selected) - - // Checkmark icon - checkmarkIcon.tintColor = theme.accentColor - checkmarkIcon.isHidden = !selected - - // Accessibility - if selected { - accessibilityTraits.insert(.selected) - } else { - accessibilityTraits.remove(.selected) - } - - setNeedsLayout() - } - - @objc(configureForFPXRowWithTheme:) func configureForFPXRow(with theme: STPTheme) { - paymentOption = nil - self.theme = theme - - backgroundColor = theme.secondaryBackgroundColor - - // Left icon - leftIcon.image = STPImageLibrary.bankIcon() - leftIcon.tintColor = primaryColorForPaymentOption(withSelected: false) - - // Title label - titleLabel.font = theme.font - titleLabel.textColor = self.theme.primaryForegroundColor - titleLabel.text = STPLocalizedString( - "Online Banking (FPX)", - "Button to pay with a Bank Account (using FPX)." - ) - - // Checkmark icon - checkmarkIcon.isHidden = true - accessoryType = .disclosureIndicator - setNeedsLayout() - } - - private var paymentOption: STPPaymentOption? - private var theme: STPTheme = .defaultTheme - private var leftIcon = UIImageView() - private var titleLabel = UILabel() - private var checkmarkIcon = UIImageView(image: STPLegacyImageLibrary.checkmarkIcon()) - - override init( - style: UITableViewCell.CellStyle, - reuseIdentifier: String? - ) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - // Left icon - leftIcon.translatesAutoresizingMaskIntoConstraints = false - contentView.addSubview(leftIcon) - - // Title label - titleLabel.translatesAutoresizingMaskIntoConstraints = false - contentView.addSubview(titleLabel) - - // Checkmark icon - checkmarkIcon.translatesAutoresizingMaskIntoConstraints = false - contentView.addSubview(checkmarkIcon) - - NSLayoutConstraint.activate( - [ - self.leftIcon.centerXAnchor.constraint( - equalTo: contentView.leadingAnchor, - constant: kPadding + 0.5 * kDefaultIconWidth - ), - self.leftIcon.centerYAnchor.constraint( - lessThanOrEqualTo: contentView.centerYAnchor - ), - self.checkmarkIcon.widthAnchor.constraint(equalToConstant: kCheckmarkWidth), - self.checkmarkIcon.heightAnchor.constraint( - equalTo: self.checkmarkIcon.widthAnchor, - multiplier: 1.0 - ), - self.checkmarkIcon.centerXAnchor.constraint( - equalTo: contentView.trailingAnchor, - constant: -kPadding - ), - self.checkmarkIcon.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - // Constrain label to leadingAnchor with the default - // icon width so that the text always aligns vertically - // even if the icond widths differ - self.titleLabel.leadingAnchor.constraint( - equalTo: contentView.leadingAnchor, - constant: 2.0 * kPadding + kDefaultIconWidth - ), - self.titleLabel.trailingAnchor.constraint( - equalTo: self.checkmarkIcon.leadingAnchor, - constant: -kPadding - ), - self.titleLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - ]) - accessibilityTraits.insert(.button) - isAccessibilityElement = true - } - - func primaryColorForPaymentOption(withSelected selected: Bool) -> UIColor { - let fadedColor: UIColor = UIColor(dynamicProvider: { _ in - return self.theme.primaryForegroundColor.withAlphaComponent(0.6) - }) - - return (selected ? theme.accentColor : fadedColor) - } - - func buildAttributedString( - with paymentOption: STPPaymentOption?, - selected: Bool - ) - -> NSAttributedString - { - if let paymentOption = paymentOption as? STPCard { - return buildAttributedString(with: paymentOption, selected: selected) - } else if let source = paymentOption as? STPSource { - if source.type == .card && source.cardDetails != nil { - return buildAttributedString(withCardSource: source, selected: selected) - } - } else if let paymentMethod = paymentOption as? STPPaymentMethod { - if paymentMethod.type == .card && paymentMethod.card != nil { - return buildAttributedString( - withCardPaymentMethod: paymentMethod, - selected: selected - ) - } - if paymentMethod.type == .FPX && paymentMethod.fpx != nil { - return buildAttributedString( - with: STPFPXBank.brandFrom(paymentMethod.fpx?.bankIdentifierCode), - selected: selected - ) - } - } else if paymentOption is STPApplePayPaymentOption { - let label = String.Localized.apple_pay - let primaryColor = primaryColorForPaymentOption(withSelected: selected) - return NSAttributedString( - string: label, - attributes: [ - NSAttributedString.Key.foregroundColor: primaryColor - ] - ) - } else if let paymentMethodParams = paymentOption as? STPPaymentMethodParams { - if paymentMethodParams.type == .card && paymentMethodParams.card != nil { - return buildAttributedString( - withCardPaymentMethodParams: paymentMethodParams, - selected: selected - ) - } - if paymentMethodParams.type == .FPX && paymentMethodParams.fpx != nil { - return buildAttributedString( - with: paymentMethodParams.fpx?.bank ?? STPFPXBankBrand.unknown, - selected: selected - ) - } - } - - // Unrecognized payment method - return NSAttributedString(string: "") - } - - func buildAttributedString(with card: STPCard, selected: Bool) -> NSAttributedString { - return buildAttributedString( - with: card.brand, - last4: card.last4, - selected: selected - ) - } - - func buildAttributedString(withCardSource card: STPSource, selected: Bool) -> NSAttributedString - { - return buildAttributedString( - with: card.cardDetails?.brand ?? .unknown, - last4: card.cardDetails?.last4 ?? "", - selected: selected - ) - } - - func buildAttributedString( - withCardPaymentMethod paymentMethod: STPPaymentMethod, - selected: Bool - ) - -> NSAttributedString - { - return buildAttributedString( - with: paymentMethod.card?.preferredDisplayBrand ?? .unknown, - last4: paymentMethod.card?.last4 ?? "", - selected: selected - ) - } - - func buildAttributedString( - withCardPaymentMethodParams paymentMethodParams: STPPaymentMethodParams, - selected: Bool - ) -> NSAttributedString { - let brand = paymentMethodParams.card?.preferredDisplayBrand ?? .unknown - return buildAttributedString( - with: brand, - last4: paymentMethodParams.card?.last4 ?? "", - selected: selected - ) - } - - func buildAttributedString( - with bankBrand: STPFPXBankBrand, - selected: Bool - ) - -> NSAttributedString - { - let label = (STPFPXBank.stringFrom(bankBrand) ?? "") + " (FPX)" - let primaryColor = primaryColorForPaymentOption(withSelected: selected) - return NSAttributedString( - string: label, - attributes: [ - NSAttributedString.Key.foregroundColor: primaryColor - ] - ) - } - - func buildAttributedString( - with brand: STPCardBrand, - last4: String, - selected: Bool - ) -> NSAttributedString { - let format = String.Localized.card_brand_ending_in_last_4 - let brandString = STPCard.string(from: brand) - let label = String(format: format, brandString, last4) - - let primaryColor = selected ? theme.accentColor : theme.primaryForegroundColor - - let secondaryColor = UIColor(dynamicProvider: { _ in - return primaryColor.withAlphaComponent(0.6) - }) - - let attributes: [NSAttributedString.Key: Any] = [ - NSAttributedString.Key.foregroundColor: secondaryColor, - NSAttributedString.Key.font: self.theme.font, - ] - - let attributedString = NSMutableAttributedString( - string: label, - attributes: attributes as [NSAttributedString.Key: Any] - ) - attributedString.addAttribute( - .foregroundColor, - value: primaryColor, - range: (label as NSString).range(of: brandString) - ) - attributedString.addAttribute( - .foregroundColor, - value: primaryColor, - range: (label as NSString).range(of: last4) - ) - attributedString.addAttribute( - .font, - value: theme.emphasisFont, - range: (label as NSString).range(of: brandString) - ) - attributedString.addAttribute( - .font, - value: theme.emphasisFont, - range: (label as NSString).range(of: last4) - ) - - return attributedString - } - - required init?( - coder aDecoder: NSCoder - ) { - super.init(coder: aDecoder) - } -} - -private let kDefaultIconWidth: CGFloat = 26.0 -private let kPadding: CGFloat = 15.0 -private let kCheckmarkWidth: CGFloat = 14.0 diff --git a/Stripe/StripeiOS/Source/STPPaymentOptionTuple.swift b/Stripe/StripeiOS/Source/STPPaymentOptionTuple.swift deleted file mode 100644 index 6084d1329a1..00000000000 --- a/Stripe/StripeiOS/Source/STPPaymentOptionTuple.swift +++ /dev/null @@ -1,88 +0,0 @@ -// -// STPPaymentOptionTuple.swift -// StripeiOS -// -// Created by Jack Flintermann on 5/17/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -import Foundation - -class STPPaymentOptionTuple: NSObject { - @objc - public convenience init( - paymentOptions: [STPPaymentOption], - selectedPaymentOption: STPPaymentOption? - ) { - self.init() - self.paymentOptions = paymentOptions - self.selectedPaymentOption = selectedPaymentOption - } - - @objc - public convenience init( - paymentOptions: [STPPaymentOption], - selectedPaymentOption: STPPaymentOption?, - addApplePayOption applePayEnabled: Bool, - addFPXOption fpxEnabled: Bool - ) { - var mutablePaymentOptions = paymentOptions - weak var selected = selectedPaymentOption - - if applePayEnabled { - let applePay = STPApplePayPaymentOption() - mutablePaymentOptions.append(applePay) - - if selected == nil { - selected = applePay - } - } - - if fpxEnabled { - let fpx = STPPaymentMethodFPXParams() - let fpxPaymentOption = STPPaymentMethodParams( - fpx: fpx, - billingDetails: nil, - metadata: nil - ) - mutablePaymentOptions.append(fpxPaymentOption) - } - - self.init( - paymentOptions: mutablePaymentOptions, - selectedPaymentOption: selected - ) - } - - /// Returns a tuple for the given array of STPPaymentMethod, filtered to only include the - /// the types supported by STPPaymentContext/STPPaymentOptionsViewController and adding - /// Apple Pay as a method if appropriate. - /// - Returns: A new tuple ready to be used by the SDK's UI elements - @objc(tupleFilteredForUIWithPaymentMethods:selectedPaymentMethod:configuration:) - public convenience init( - filteredForUIWith paymentMethods: [STPPaymentMethod], - selectedPaymentMethod selectedPaymentMethodID: String?, - configuration: STPPaymentConfiguration - ) { - var paymentOptions: [STPPaymentOption] = [] - var selectedPaymentMethod: STPPaymentMethod? - for paymentMethod in paymentMethods { - if paymentMethod.type == .card { - paymentOptions.append(paymentMethod) - if paymentMethod.stripeId == selectedPaymentMethodID { - selectedPaymentMethod = paymentMethod - } - } - } - - self.init( - paymentOptions: paymentOptions, - selectedPaymentOption: selectedPaymentMethod, - addApplePayOption: configuration.applePayEnabled, - addFPXOption: configuration.fpxEnabled - ) - } - - private(set) weak var selectedPaymentOption: STPPaymentOption? - private(set) var paymentOptions: [STPPaymentOption] = [] -} diff --git a/Stripe/StripeiOS/Source/STPPaymentOptionsInternalViewController.swift b/Stripe/StripeiOS/Source/STPPaymentOptionsInternalViewController.swift deleted file mode 100644 index 10bd0d4848b..00000000000 --- a/Stripe/StripeiOS/Source/STPPaymentOptionsInternalViewController.swift +++ /dev/null @@ -1,593 +0,0 @@ -// -// STPPaymentOptionsInternalViewController.swift -// StripeiOS -// -// Created by Jack Flintermann on 6/9/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -import Foundation -@_spi(STP) import StripeCore -import UIKit - -@objc protocol STPPaymentOptionsInternalViewControllerDelegate: AnyObject { - func internalViewControllerDidSelect(_ paymentOption: STPPaymentOption?) - func internalViewControllerDidDelete(_ paymentOption: STPPaymentOption?) - func internalViewControllerDidCreatePaymentOption( - _ paymentOption: STPPaymentOption?, - completion: @escaping STPErrorBlock - ) - func internalViewControllerDidCancel() -} - -class STPPaymentOptionsInternalViewController: STPCoreTableViewController, UITableViewDataSource, - UITableViewDelegate, STPAddCardViewControllerDelegate, STPBankSelectionViewControllerDelegate -{ - init( - configuration: STPPaymentConfiguration, - customerContext: STPCustomerContext?, - analyticsLogger: STPPaymentContext.AnalyticsLogger, - apiClient: STPAPIClient, - theme: STPTheme, - prefilledInformation: STPUserInformation?, - shippingAddress: STPAddress?, - paymentOptionTuple tuple: STPPaymentOptionTuple, - delegate: STPPaymentOptionsInternalViewControllerDelegate? - ) { - self.analyticsLogger = analyticsLogger - super.init(theme: theme) - self.configuration = configuration - // This parameter may be a custom API adapter, and not a CustomerContext. - apiAdapter = customerContext - self.apiClient = apiClient - self.prefilledInformation = prefilledInformation - self.shippingAddress = shippingAddress - paymentOptions = tuple.paymentOptions - selectedPaymentOption = tuple.selectedPaymentOption - self.delegate = delegate - - title = STPLocalizedString("Payment Method", "Title for Payment Method screen") - } - - func update(with tuple: STPPaymentOptionTuple) { - if let selectedPaymentOption = selectedPaymentOption, - selectedPaymentOption.isEqual(tuple.selectedPaymentOption) - { - return - } - - paymentOptions = tuple.paymentOptions - selectedPaymentOption = tuple.selectedPaymentOption - - // Reload card list section - let sections = NSMutableIndexSet(index: PaymentOptionSectionCardList) - tableView?.reloadSections(sections as IndexSet, with: .automatic) - } - - private var _customFooterView: UIView? - internal let analyticsLogger: STPPaymentContext.AnalyticsLogger - var customFooterView: UIView? { - get { - _customFooterView - } - set(footerView) { - _customFooterView = footerView - _didSetCustomFooterView() - } - } - func _didSetCustomFooterView() { - if isViewLoaded { - if let size = _customFooterView?.sizeThatFits( - CGSize(width: view.bounds.size.width, height: CGFloat.greatestFiniteMagnitude) - ) { - _customFooterView?.frame = CGRect( - x: 0, - y: 0, - width: size.width, - height: size.height - ) - } - - tableView?.tableFooterView = _customFooterView - } - } - - var addCardViewControllerCustomFooterView: UIView? - var prefilledInformation: STPUserInformation? - private var configuration: STPPaymentConfiguration? - private var apiAdapter: STPBackendAPIAdapter? - private var shippingAddress: STPAddress? - private var paymentOptions: [STPPaymentOption]? - private var apiClient: STPAPIClient = .shared - private var selectedPaymentOption: STPPaymentOption? - private weak var delegate: STPPaymentOptionsInternalViewControllerDelegate? - private var cardImageView: UIImageView? - - override func createAndSetupViews() { - super.createAndSetupViews() - - // Table view - tableView?.register( - STPPaymentOptionTableViewCell.self, - forCellReuseIdentifier: PaymentOptionCellReuseIdentifier - ) - - tableView?.dataSource = self - tableView?.delegate = self - tableView?.reloadData() - - // Table header view - let cardImageView = UIImageView(image: STPLegacyImageLibrary.largeCardFrontImage()) - cardImageView.contentMode = .center - cardImageView.frame = CGRect( - x: 0.0, - y: 0.0, - width: view.bounds.size.width, - height: cardImageView.bounds.size.height + (57.0 * 2.0) - ) - cardImageView.image = STPLegacyImageLibrary.largeCardFrontImage() - cardImageView.tintColor = theme.accentColor - self.cardImageView = cardImageView - - tableView?.tableHeaderView = cardImageView - - // Table view editing state - tableView?.setEditing(false, animated: false) - reloadRightBarButtonItem( - withTableViewIsEditing: tableView?.isEditing ?? false, - animated: false - ) - - stp_navigationItemProxy?.leftBarButtonItem?.accessibilityIdentifier = - "PaymentOptionsViewControllerCancelButtonIdentifier" - // re-set the custom footer view if it was added before we loaded - _didSetCustomFooterView() - } - - override func viewDidAppear(_ animated: Bool) { - super.viewDidAppear(animated) - analyticsLogger.logPaymentOptionsScreenAppeared() - } - - override func viewDidLayoutSubviews() { - super.viewDidLayoutSubviews() - - // Resetting it re-calculates the size based on new view width - // UITableView requires us to call setter again to actually pick up frame - // change on footers - if tableView?.tableFooterView != nil { - customFooterView = tableView?.tableFooterView - } - } - - func reloadRightBarButtonItem(withTableViewIsEditing tableViewIsEditing: Bool, animated: Bool) { - var barButtonItem: UIBarButtonItem? - - if !tableViewIsEditing { - if isAnyPaymentOptionDetachable() { - // Show edit button - barButtonItem = UIBarButtonItem( - barButtonSystemItem: .edit, - target: self, - action: #selector(handleEditButtonTapped(_:)) - ) - } else { - // Show no button - barButtonItem = nil - } - } else { - // Show done button - barButtonItem = UIBarButtonItem( - barButtonSystemItem: .done, - target: self, - action: #selector(handleDoneButtonTapped(_:)) - ) - } - - barButtonItem?.stp_setTheme(theme) - - stp_navigationItemProxy?.setRightBarButton(barButtonItem, animated: animated) - } - - func isAnyPaymentOptionDetachable() -> Bool { - for paymentOption in cardPaymentOptions() { - if isPaymentOptionDetachable(paymentOption) { - return true - } - } - - return false - } - - func isPaymentOptionDetachable(_ paymentOption: STPPaymentOption?) -> Bool { - if !(configuration?.canDeletePaymentOptions ?? false) { - // Feature is disabled - return false - } - - if apiAdapter == nil { - // Cannot detach payment methods without customer context - return false - } - - if !(apiAdapter?.responds( - to: #selector(STPCustomerContext.detachPaymentMethod(fromCustomer:completion:)) - ) - ?? false) - { - // Cannot detach payment methods if customerContext is an apiAdapter - // that doesn't implement detachPaymentMethod - return false - } - - if paymentOption == nil { - // Cannot detach non-existent payment method - return false - } - - if !(paymentOption is STPPaymentMethod) { - // Cannot detach non-payment method - return false - } - - // Payment method can be deleted from customer - return true - } - - func cardPaymentOptions() -> [STPPaymentOption] { - guard let paymentOptions = paymentOptions else { - return [] - } - - return paymentOptions.filter({ (o) -> Bool in - if o is STPPaymentMethodParams { - let paymentMethodParams = o as? STPPaymentMethodParams - if paymentMethodParams?.type != .card { - return false - } - } - return true - }) - } - - func apmPaymentOptions() -> [STPPaymentOption] { - guard let paymentOptions = paymentOptions else { - return [] - } - return paymentOptions.filter({ (o) -> Bool in - if (o) is STPPaymentMethodParams { - let paymentMethodParams = o as? STPPaymentMethodParams - if paymentMethodParams?.type == .FPX { - // Add other APMs as we gain support for them in Basic Integration - return true - } - } - return false - }) - } - - // MARK: - Button Handlers - @objc override func handleCancelTapped(_ sender: Any?) { - delegate?.internalViewControllerDidCancel() - } - - @objc func handleEditButtonTapped(_ sender: Any?) { - tableView?.setEditing(true, animated: true) - reloadRightBarButtonItem( - withTableViewIsEditing: tableView?.isEditing ?? false, - animated: true - ) - } - - @objc func handleDoneButtonTapped(_ sender: Any?) { - _endTableViewEditing() - reloadRightBarButtonItem( - withTableViewIsEditing: tableView?.isEditing ?? false, - animated: true - ) - } - - func _endTableViewEditing() { - tableView?.setEditing(false, animated: true) - } - - // MARK: - UITableViewDataSource - func numberOfSections(in tableView: UITableView) -> Int { - if apmPaymentOptions().count > 0 { - return 3 - } else { - return 2 - } - } - - func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - if section == PaymentOptionSectionCardList { - return cardPaymentOptions().count - } - - if section == PaymentOptionSectionAddCard { - return 1 - } - - if section == PaymentOptionSectionAPM { - return apmPaymentOptions().count - } - - return 0 - } - - func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = - tableView.dequeueReusableCell( - withIdentifier: PaymentOptionCellReuseIdentifier, - for: indexPath - ) - as? STPPaymentOptionTableViewCell - - if indexPath.section == PaymentOptionSectionCardList { - weak var paymentOption = - cardPaymentOptions().stp_boundSafeObject(at: indexPath.row) - let selected = paymentOption!.isEqual(selectedPaymentOption) - - cell?.configure(with: paymentOption!, theme: theme, selected: selected) - } else if indexPath.section == PaymentOptionSectionAddCard { - cell?.configureForNewCardRow(with: theme) - cell?.accessibilityIdentifier = "PaymentOptionsTableViewAddNewCardButtonIdentifier" - } else if indexPath.section == PaymentOptionSectionAPM { - weak var paymentOption = - apmPaymentOptions().stp_boundSafeObject(at: indexPath.row) - if paymentOption is STPPaymentMethodParams { - let paymentMethodParams = paymentOption as? STPPaymentMethodParams - if paymentMethodParams?.type == .FPX { - cell?.configureForFPXRow(with: theme) - cell?.accessibilityIdentifier = "PaymentOptionsTableViewFPXButtonIdentifier" - } - } - } - - return cell! - } - - func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { - if indexPath.section == PaymentOptionSectionCardList { - weak var paymentOption = - cardPaymentOptions().stp_boundSafeObject(at: indexPath.row) - - if isPaymentOptionDetachable(paymentOption) { - return true - } - } - - return false - } - - func tableView( - _ tableView: UITableView, - commit editingStyle: UITableViewCell.EditingStyle, - forRowAt indexPath: IndexPath - ) { - if indexPath.section == PaymentOptionSectionCardList { - if editingStyle != .delete { - // Showed the user a non-delete option when we shouldn't have - tableView.reloadData() - return - } - - if !(indexPath.row < cardPaymentOptions().count) { - // Data source and table view out of sync for some reason - tableView.reloadData() - return - } - - weak var paymentOptionToDelete = - cardPaymentOptions().stp_boundSafeObject(at: indexPath.row) - - if !isPaymentOptionDetachable(paymentOptionToDelete) { - // Showed the user a delete option for a payment method when we shouldn't have - tableView.reloadData() - return - } - - let paymentMethod = paymentOptionToDelete as? STPPaymentMethod - - // Kickoff request to delete payment method from customer - if let paymentMethod = paymentMethod { - apiAdapter?.detachPaymentMethod?(fromCustomer: paymentMethod, completion: nil) - } - - // Optimistically remove payment method from data source - var paymentOptions = self.paymentOptions - paymentOptions?.removeAll { $0 as AnyObject === paymentOptionToDelete as AnyObject } - self.paymentOptions = paymentOptions - - // Perform deletion animation for single row - tableView.deleteRows(at: [indexPath], with: .automatic) - - var tableViewIsEditing = tableView.isEditing - if !isAnyPaymentOptionDetachable() { - // we deleted the last available payment option, stop editing - // (but delay to next runloop because calling tableView setEditing:animated: - // in this function is not allowed) - DispatchQueue.main.async(execute: { - self._endTableViewEditing() - }) - // manually set the value passed to reloadRightBarButtonItemWithTableViewIsEditing - // below - tableViewIsEditing = false - } - - // Reload right bar button item text - reloadRightBarButtonItem(withTableViewIsEditing: tableViewIsEditing, animated: true) - - // Notify delegate - delegate?.internalViewControllerDidDelete(paymentOptionToDelete) - } - } - - // MARK: - UITableViewDelegate - func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - if indexPath.section == PaymentOptionSectionCardList { - // Update data source - weak var paymentOption = - cardPaymentOptions().stp_boundSafeObject(at: indexPath.row) - selectedPaymentOption = paymentOption - - // Perform selection animation - tableView.reloadSections( - NSIndexSet(index: PaymentOptionSectionCardList) as IndexSet, - with: .fade - ) - - // Notify delegate - delegate?.internalViewControllerDidSelect(paymentOption) - } else if indexPath.section == PaymentOptionSectionAddCard { - var paymentCardViewController: STPAddCardViewController? - if let configuration = configuration { - paymentCardViewController = STPAddCardViewController( - configuration: configuration, - theme: theme - ) - } - paymentCardViewController?.analyticsLogger = analyticsLogger - paymentCardViewController?.apiClient = apiClient - paymentCardViewController?.delegate = self - paymentCardViewController?.prefilledInformation = prefilledInformation - paymentCardViewController?.shippingAddress = shippingAddress - paymentCardViewController?.customFooterView = addCardViewControllerCustomFooterView - - if let paymentCardViewController = paymentCardViewController { - navigationController?.pushViewController(paymentCardViewController, animated: true) - } - } else if indexPath.section == PaymentOptionSectionAPM { - weak var paymentOption = - apmPaymentOptions().stp_boundSafeObject(at: indexPath.row) - if paymentOption is STPPaymentMethodParams { - if let paymentMethodParams = paymentOption as? STPPaymentMethodParams, - paymentMethodParams.type == .FPX - { - var bankSelectionViewController: STPBankSelectionViewController? - if let configuration = configuration { - bankSelectionViewController = STPBankSelectionViewController( - bankMethod: .FPX, - configuration: configuration, - theme: theme - ) - } - bankSelectionViewController?.apiClient = apiClient - bankSelectionViewController?.delegate = self - - if let bankSelectionViewController = bankSelectionViewController { - navigationController?.pushViewController( - bankSelectionViewController, - animated: true - ) - } - } - } - } - - tableView.deselectRow(at: indexPath, animated: true) - } - - func tableView( - _ tableView: UITableView, - willDisplay cell: UITableViewCell, - forRowAt indexPath: IndexPath - ) { - let isTopRow = indexPath.row == 0 - let isBottomRow = - self.tableView(tableView, numberOfRowsInSection: indexPath.section) - 1 == indexPath.row - - cell.stp_setBorderColor(theme.tertiaryBackgroundColor) - cell.stp_setTopBorderHidden(!isTopRow) - cell.stp_setBottomBorderHidden(!isBottomRow) - cell.stp_setFakeSeparatorColor(theme.quaternaryBackgroundColor) - cell.stp_setFakeSeparatorLeftInset(15.0) - } - - func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { - if self.tableView(tableView, numberOfRowsInSection: section) == 0 { - return 0.01 - } - - return 27.0 - } - - override func tableView( - _ tableView: UITableView, - heightForHeaderInSection section: Int - ) - -> CGFloat - { - return 0.01 - } - - func tableView( - _ tableView: UITableView, - editingStyleForRowAt indexPath: IndexPath - ) - -> UITableViewCell.EditingStyle - { - if indexPath.section == PaymentOptionSectionCardList { - return .delete - } - - return .none - } - - func tableView(_ tableView: UITableView, willBeginEditingRowAt indexPath: IndexPath) { - reloadRightBarButtonItem(withTableViewIsEditing: true, animated: true) - } - - func tableView(_ tableView: UITableView, didEndEditingRowAt indexPath: IndexPath?) { - reloadRightBarButtonItem(withTableViewIsEditing: tableView.isEditing, animated: true) - } - - // MARK: - STPAddCardViewControllerDelegate - func addCardViewControllerDidCancel(_ addCardViewController: STPAddCardViewController) { - navigationController?.popViewController(animated: true) - } - - @objc func addCardViewController( - _ addCardViewController: STPAddCardViewController, - didCreatePaymentMethod paymentMethod: STPPaymentMethod, - completion: @escaping STPErrorBlock - ) { - delegate?.internalViewControllerDidCreatePaymentOption( - paymentMethod, - completion: completion - ) - } - - @objc func bankSelectionViewController( - _ bankViewController: STPBankSelectionViewController, - didCreatePaymentMethodParams paymentMethodParams: STPPaymentMethodParams - ) { - delegate?.internalViewControllerDidCreatePaymentOption(paymentMethodParams) { _ in - } - } - - required init?( - coder aDecoder: NSCoder - ) { - fatalError("init(coder:) has not been implemented") - } - - required init( - nibName nibNameOrNil: String?, - bundle nibBundleOrNil: Bundle? - ) { - fatalError("init(nibName:bundle:) has not been implemented") - } - - required init( - theme: STPTheme? - ) { - fatalError("init(theme:) has not been implemented") - } -} - -private let PaymentOptionCellReuseIdentifier = "PaymentOptionCellReuseIdentifier" -private let PaymentOptionSectionCardList = 0 -private let PaymentOptionSectionAddCard = 1 -private let PaymentOptionSectionAPM = 2 diff --git a/Stripe/StripeiOS/Source/STPPaymentOptionsViewController.swift b/Stripe/StripeiOS/Source/STPPaymentOptionsViewController.swift deleted file mode 100644 index aa392eae4cc..00000000000 --- a/Stripe/StripeiOS/Source/STPPaymentOptionsViewController.swift +++ /dev/null @@ -1,662 +0,0 @@ -// -// STPPaymentOptionsViewController.swift -// StripeiOS -// -// Created by Jack Flintermann on 1/12/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -@_spi(STP) import StripeCore -@_spi(STP) import StripePaymentsUI -import UIKit - -/// This view controller presents a list of payment method options to the user, -/// which they can select between. They can also add credit cards to the list. -/// It must be displayed inside a `UINavigationController`, so you can either -/// create a `UINavigationController` with an `STPPaymentOptionsViewController` -/// as the `rootViewController` and then present the `UINavigationController`, -/// or push a new `STPPaymentOptionsViewController` onto an existing -/// `UINavigationController`'s stack. You can also have `STPPaymentContext` do this -/// for you automatically, by calling `presentPaymentOptionsViewController` -/// or `pushPaymentOptionsViewController` on it. -public class STPPaymentOptionsViewController: STPCoreViewController, - STPPaymentOptionsInternalViewControllerDelegate, STPAddCardViewControllerDelegate -{ - - /// The delegate for the view controller. - /// The delegate receives callbacks when the user selects a method or cancels, - /// and is responsible for dismissing the payments methods view controller when - /// it is finished. - @objc private(set) weak var delegate: STPPaymentOptionsViewControllerDelegate? - - /// Creates a new payment methods view controller. - /// - Parameter paymentContext: A payment context to power the view controller's view. - /// The payment context will in turn use its backend API adapter to fetch the - /// information it needs from your application. - /// - Returns: an initialized view controller. - @objc(initWithPaymentContext:) - public convenience init( - paymentContext: STPPaymentContext - ) { - self.init( - configuration: paymentContext.configuration, - apiAdapter: paymentContext.apiAdapter, - apiClient: paymentContext.apiClient, - analyticsLogger: paymentContext.analyticsLogger, - loadingPromise: paymentContext.currentValuePromise, - theme: paymentContext.theme, - shippingAddress: paymentContext.shippingAddress, - delegate: paymentContext - ) - } - - init( - configuration: STPPaymentConfiguration?, - apiAdapter: STPBackendAPIAdapter, - apiClient: STPAPIClient?, - analyticsLogger: STPPaymentContext.AnalyticsLogger, - loadingPromise: STPPromise?, - theme: STPTheme?, - shippingAddress: STPAddress?, - delegate: STPPaymentOptionsViewControllerDelegate - ) { - self.apiAdapter = apiAdapter - self.analyticsLogger = analyticsLogger - super.init(theme: theme) - commonInit( - configuration: configuration, - apiAdapter: apiAdapter, - apiClient: apiClient, - loadingPromise: loadingPromise, - shippingAddress: shippingAddress, - delegate: delegate - ) - } - - func commonInit( - configuration: STPPaymentConfiguration?, - apiAdapter: STPBackendAPIAdapter, - apiClient: STPAPIClient?, - loadingPromise: STPPromise?, - shippingAddress: STPAddress?, - delegate: STPPaymentOptionsViewControllerDelegate - ) { - STPAnalyticsClient.sharedClient.addClass( - toProductUsageIfNecessary: STPPaymentOptionsViewController.self - ) - - self.configuration = configuration - self.apiClient = apiClient ?? .shared - self.shippingAddress = shippingAddress - self.apiAdapter = apiAdapter - self.loadingPromise = loadingPromise - self.delegate = delegate - - navigationItem.title = STPLocalizedString( - "Loading…", - "Title for screen when data is still loading from the network." - ) - - weak var weakSelf = self - loadingPromise?.onSuccess({ tuple in - guard let strongSelf = weakSelf else { - return - } - var `internal`: UIViewController? - if (tuple.paymentOptions.count) > 0 { - let customerContext = strongSelf.apiAdapter as? STPCustomerContext - - var payMethodsInternal: STPPaymentOptionsInternalViewController? - if let configuration1 = strongSelf.configuration { - payMethodsInternal = STPPaymentOptionsInternalViewController( - configuration: configuration1, - customerContext: customerContext, - analyticsLogger: strongSelf.analyticsLogger, - apiClient: strongSelf.apiClient, - theme: strongSelf.theme, - prefilledInformation: strongSelf.prefilledInformation, - shippingAddress: strongSelf.shippingAddress, - paymentOptionTuple: tuple, - delegate: strongSelf - ) - } - if strongSelf.paymentOptionsViewControllerFooterView != nil { - payMethodsInternal?.customFooterView = - strongSelf.paymentOptionsViewControllerFooterView - } - if strongSelf.addCardViewControllerFooterView != nil { - payMethodsInternal?.addCardViewControllerCustomFooterView = - strongSelf.addCardViewControllerFooterView - } - `internal` = payMethodsInternal - } else { - var addCardViewController: STPAddCardViewController? - if let configuration1 = strongSelf.configuration { - addCardViewController = STPAddCardViewController( - configuration: configuration1, - theme: strongSelf.theme - ) - } - addCardViewController?.analyticsLogger = strongSelf.analyticsLogger - addCardViewController?.apiClient = strongSelf.apiClient - addCardViewController?.delegate = strongSelf - addCardViewController?.prefilledInformation = strongSelf.prefilledInformation - addCardViewController?.shippingAddress = strongSelf.shippingAddress - `internal` = addCardViewController - - if strongSelf.addCardViewControllerFooterView != nil { - addCardViewController?.customFooterView = - strongSelf.addCardViewControllerFooterView - } - } - - `internal`?.stp_navigationItemProxy = strongSelf.navigationItem - if let controller = `internal` { - strongSelf.addChild(controller) - } - `internal`?.view.alpha = 0 - if let view = `internal`?.view, let activityIndicator1 = strongSelf.activityIndicator { - strongSelf.view.insertSubview(view, belowSubview: activityIndicator1) - } - if let view = `internal`?.view { - strongSelf.view.addSubview(view) - } - `internal`?.view.frame = strongSelf.view.bounds - `internal`?.didMove(toParent: strongSelf) - UIView.animate( - withDuration: 0.2, - animations: { - strongSelf.activityIndicator?.alpha = 0 - `internal`?.view.alpha = 1 - } - ) { _ in - strongSelf.activityIndicator?.animating = false - } - strongSelf.navigationItem.setRightBarButton( - `internal`?.stp_navigationItemProxy?.rightBarButtonItem, - animated: true - ) - strongSelf.internalViewController = `internal` - }) - } - - /// Initializes a new payment methods view controller without using a - /// payment context. - /// - Parameters: - /// - configuration: The configuration to use to determine what types of - /// payment method to offer your user. - seealso: STPPaymentConfiguration.h - /// - theme: The theme to inform the appearance of the UI. - /// - customerContext: The customer context the view controller will use to - /// fetch and modify its Stripe customer - /// - delegate: A delegate that will be notified when the payment - /// methods view controller's selection changes. - /// - Returns: an initialized view controller. - @objc(initWithConfiguration:theme:customerContext:delegate:) - public convenience init( - configuration: STPPaymentConfiguration, - theme: STPTheme, - customerContext: STPCustomerContext, - delegate: STPPaymentOptionsViewControllerDelegate - ) { - self.init( - configuration: configuration, - theme: theme, - apiAdapter: customerContext, - delegate: delegate - ) - } - - /// Note: Instead of providing your own backend API adapter, we recommend using - /// `STPCustomerContext`, which will manage retrieving and updating a - /// Stripe customer for you. - seealso: STPCustomerContext.h - /// Initializes a new payment methods view controller without using - /// a payment context. - /// - Parameters: - /// - configuration: The configuration to use to determine what types of - /// payment method to offer your user. - /// - theme: The theme to inform the appearance of the UI. - /// - apiAdapter: The API adapter to use to retrieve a customer's stored - /// payment methods and save new ones. - /// - delegate: A delegate that will be notified when the payment methods - /// view controller's selection changes. - @objc(initWithConfiguration:theme:apiAdapter:delegate:) - public init( - configuration: STPPaymentConfiguration, - theme: STPTheme, - apiAdapter: STPBackendAPIAdapter, - delegate: STPPaymentOptionsViewControllerDelegate - ) { - self.apiAdapter = apiAdapter - super.init(theme: theme) - let promise = retrievePaymentMethods(with: configuration, apiAdapter: apiAdapter) - - commonInit( - configuration: configuration, - apiAdapter: apiAdapter, - apiClient: STPAPIClient.shared, - loadingPromise: promise, - shippingAddress: nil, - delegate: delegate - ) - } - - /// If you've already collected some information from your user, you can set it - /// here and it'll be automatically filled out when possible/appropriate in any UI - /// that the payment context creates. - @objc public var prefilledInformation: STPUserInformation? { - didSet { - if let payMethodsInternal = internalViewController as? STPPaymentOptionsInternalViewController { - payMethodsInternal.prefilledInformation = prefilledInformation - } else if let payMethodsInternal = internalViewController as? STPAddCardViewController { - payMethodsInternal.prefilledInformation = prefilledInformation - } - } - } - /// @note This is no longer recommended as of v18.3.0 - the SDK automatically saves the Stripe ID of the last selected - /// payment method using NSUserDefaults and displays it as the default pre-selected option. You can override this behavior - /// by setting this property. - /// The Stripe ID of a payment method to display as the default pre-selected option. - /// @note Setting this after the view controller's view has loaded has no effect. - @objc public var defaultPaymentMethod: String? - /// A view that will be placed as the footer of the view controller when it is - /// showing a list of saved payment methods to select from. - /// When the footer view needs to be resized, it will be sent a - /// `sizeThatFits:` call. The view should respond correctly to this method in order - /// to be sized and positioned properly. - @objc public var paymentOptionsViewControllerFooterView: UIView? { - didSet { - if let payMethodsInternal = internalViewController as? STPPaymentOptionsInternalViewController { - payMethodsInternal.customFooterView = paymentOptionsViewControllerFooterView - } - } - } - - /// A view that will be placed as the footer of the view controller when it is - /// showing the add card view. - /// When the footer view needs to be resized, it will be sent a - /// `sizeThatFits:` call. The view should respond correctly to this method in order - /// to be sized and positioned properly. - @objc public var addCardViewControllerFooterView: UIView? { - didSet { - if let payMethodsInternal = internalViewController as? STPPaymentOptionsInternalViewController { - payMethodsInternal.addCardViewControllerCustomFooterView = addCardViewControllerFooterView - } else if let payMethodsInternal = internalViewController as? STPAddCardViewController { - payMethodsInternal.customFooterView = addCardViewControllerFooterView - } - } - } - - /// The API Client to use to make requests. - /// Defaults to STPAPIClient.shared - public var apiClient: STPAPIClient = .shared - - /// If you're pushing `STPPaymentOptionsViewController` onto an existing - /// `UINavigationController`'s stack, you should use this method to dismiss it, - /// since it may have pushed an additional add card view controller onto the - /// navigation controller's stack. - /// - Parameter completion: The callback to run after the view controller is dismissed. - /// You may specify nil for this parameter. - @objc(dismissWithCompletion:) - public func dismiss(withCompletion completion: STPVoidBlock?) { - if stp_isAtRootOfNavigationController() { - presentingViewController?.dismiss(animated: true, completion: completion) - } else { - var previous = navigationController?.viewControllers.first - for viewController in navigationController?.viewControllers ?? [] { - if viewController == self { - break - } - previous = viewController - } - navigationController?.stp_pop( - to: previous, - animated: true, - completion: completion ?? {} - ) - } - } - - /// Use one of the initializers declared in this interface. - @available( - *, - unavailable, - message: "Use one of the initializers declared in this interface instead." - ) - @objc public required init( - theme: STPTheme? - ) { - fatalError("init(theme:) has not been implemented") - } - - /// Use one of the initializers declared in this interface. - @available( - *, - unavailable, - message: "Use one of the initializers declared in this interface instead." - ) - @objc public required init( - nibName nibNameOrNil: String?, - bundle nibBundleOrNil: Bundle? - ) { - fatalError("init(nibName:bundle:) has not been implemented") - } - - /// Use one of the initializers declared in this interface. - @available( - *, - unavailable, - message: "Use one of the initializers declared in this interface instead." - ) - @objc public required init?( - coder aDecoder: NSCoder - ) { - fatalError("init(coder:) has not been implemented") - } - - private var configuration: STPPaymentConfiguration? - private var shippingAddress: STPAddress? - private var apiAdapter: STPBackendAPIAdapter - var loadingPromise: STPPromise? - private var activityIndicator: STPPaymentActivityIndicatorView? - internal var internalViewController: UIViewController? - // Should be overwritten if this class is used by STPPaymentContext - internal var analyticsLogger: STPPaymentContext.AnalyticsLogger = .init(product: STPPaymentOptionsViewController.self) - - func retrievePaymentMethods( - with configuration: STPPaymentConfiguration, - apiAdapter: STPBackendAPIAdapter? - ) -> STPPromise { - let promise = STPPromise() - apiAdapter?.listPaymentMethodsForCustomer(completion: { paymentMethods, error in - // We don't use stpDispatchToMainThreadIfNecessary here because we want this completion block to always be called asynchronously, so that users can set self.defaultPaymentMethod in time. - DispatchQueue.main.async(execute: { - if let error = error { - promise.fail(error) - } else { - let defaultPaymentMethod = self.defaultPaymentMethod - if defaultPaymentMethod == nil && (apiAdapter is STPCustomerContext) { - // Retrieve the last selected payment method saved by STPCustomerContext - (apiAdapter as? STPCustomerContext)? - .retrieveLastSelectedPaymentMethodIDForCustomer( - completion: { paymentMethodID, _ in - var paymentTuple: STPPaymentOptionTuple? - if let paymentMethods = paymentMethods { - paymentTuple = STPPaymentOptionTuple.init( - filteredForUIWith: paymentMethods, - selectedPaymentMethod: paymentMethodID, - configuration: configuration - ) - } - promise.succeed(paymentTuple!) - }) - } - var paymentTuple: STPPaymentOptionTuple? - if let paymentMethods = paymentMethods { - paymentTuple = STPPaymentOptionTuple.init( - filteredForUIWith: paymentMethods, - selectedPaymentMethod: defaultPaymentMethod, - configuration: configuration - ) - } - promise.succeed(paymentTuple!) - } - }) - }) - return promise - } - - override func createAndSetupViews() { - super.createAndSetupViews() - - let activityIndicator = STPPaymentActivityIndicatorView() - activityIndicator.animating = true - view.addSubview(activityIndicator) - self.activityIndicator = activityIndicator - } - - /// :nodoc: - @objc - public override func viewDidLayoutSubviews() { - super.viewDidLayoutSubviews() - let centerX = (view.frame.size.width - (activityIndicator?.frame.size.width ?? 0.0)) / 2 - let centerY = (view.frame.size.height - (activityIndicator?.frame.size.height ?? 0.0)) / 2 - activityIndicator?.frame = CGRect( - x: centerX, - y: centerY, - width: activityIndicator?.frame.size.width ?? 0.0, - height: activityIndicator?.frame.size.height ?? 0.0 - ) - internalViewController?.view.frame = view.bounds - } - - /// :nodoc: - @objc - public override func viewDidAppear(_ animated: Bool) { - super.viewDidAppear(animated) - weak var weakSelf = self - loadingPromise?.onSuccess({ tuple in - let strongSelf = weakSelf - if strongSelf == nil { - return - } - - if tuple.selectedPaymentOption != nil { - if strongSelf?.delegate?.responds( - to: #selector( - STPPaymentOptionsViewControllerDelegate.paymentOptionsViewController( - _: - didSelect: - )) - ) - ?? false - { - if let strongSelf = strongSelf, - let selectedPaymentOption = tuple.selectedPaymentOption - { - strongSelf.delegate?.paymentOptionsViewController?( - strongSelf, - didSelect: selectedPaymentOption - ) - } - } - } - }).onFailure({ error in - let strongSelf = weakSelf - if strongSelf == nil { - return - } - - if let strongSelf = strongSelf { - strongSelf.delegate?.paymentOptionsViewController( - strongSelf, - didFailToLoadWithError: error - ) - } - }) - } - - @objc override func updateAppearance() { - super.updateAppearance() - - activityIndicator?.tintColor = theme.accentColor - } - - func finish(with paymentOption: STPPaymentOption?) { - let isReusablePaymentMethod = - (paymentOption is STPPaymentMethod) - && (paymentOption as? STPPaymentMethod)?.isReusable ?? false - - if apiAdapter is STPCustomerContext { - if isReusablePaymentMethod { - // Save the payment method - let paymentMethod = paymentOption as? STPPaymentMethod - (apiAdapter as? STPCustomerContext)?.saveLastSelectedPaymentMethodID( - forCustomer: paymentMethod?.stripeId ?? "", - completion: nil - ) - } else { - // The customer selected something else (like Apple Pay) - (apiAdapter as? STPCustomerContext)?.saveLastSelectedPaymentMethodID( - forCustomer: nil, - completion: nil - ) - } - } - - if delegate?.responds( - to: #selector( - STPPaymentOptionsViewControllerDelegate.paymentOptionsViewController(_:didSelect:)) - ) - ?? false - { - if let paymentOption = paymentOption { - delegate?.paymentOptionsViewController?(self, didSelect: paymentOption) - } - } - delegate?.paymentOptionsViewControllerDidFinish(self) - } - - func internalViewControllerDidSelect(_ paymentOption: STPPaymentOption?) { - finish(with: paymentOption) - } - - func internalViewControllerDidDelete(_ paymentOption: STPPaymentOption?) { - if delegate is STPPaymentContext { - // Notify payment context to update its copy of payment methods - if let paymentContext = delegate as? STPPaymentContext, - let paymentOption = paymentOption - { - paymentContext.remove(paymentOption) - } - } - } - - func internalViewControllerDidCreatePaymentOption( - _ paymentOption: STPPaymentOption?, - completion: @escaping STPErrorBlock - ) { - if !(paymentOption?.isReusable ?? false) { - // Don't save a non-reusable payment option - finish(with: paymentOption) - return - } - let paymentMethod = paymentOption as? STPPaymentMethod - if let paymentMethod = paymentMethod { - apiAdapter.attachPaymentMethod(toCustomer: paymentMethod) { error in - stpDispatchToMainThreadIfNecessary({ - completion(error) - if error == nil { - var promise: STPPromise? - if let configuration = self.configuration { - promise = self.retrievePaymentMethods( - with: configuration, - apiAdapter: self.apiAdapter - ) - } - weak var weakSelf = self - promise?.onSuccess({ tuple in - let strongSelf = weakSelf - if strongSelf == nil { - return - } - let paymentTuple = STPPaymentOptionTuple( - paymentOptions: tuple.paymentOptions, - selectedPaymentOption: paymentMethod - ) - if strongSelf?.internalViewController - is STPPaymentOptionsInternalViewController - { - let paymentOptionsVC = - strongSelf?.internalViewController - as? STPPaymentOptionsInternalViewController - paymentOptionsVC?.update(with: paymentTuple) - } - }) - self.finish(with: paymentMethod) - } - }) - } - } - } - - func internalViewControllerDidCancel() { - delegate?.paymentOptionsViewControllerDidCancel(self) - } - - @objc override func handleCancelTapped(_ sender: Any?) { - delegate?.paymentOptionsViewControllerDidCancel(self) - } - - @objc - public func addCardViewControllerDidCancel( - _ addCardViewController: STPAddCardViewController - ) { - // Add card is only our direct delegate if there are no other payment methods possible - // and we skipped directly to this screen. In this case, a cancel from it is the same as a cancel to us. - delegate?.paymentOptionsViewControllerDidCancel(self) - } - - @objc - public func addCardViewController( - _ addCardViewController: STPAddCardViewController, - didCreatePaymentMethod paymentMethod: STPPaymentMethod, - completion: @escaping STPErrorBlock - ) { - internalViewControllerDidCreatePaymentOption(paymentMethod, completion: completion) - } -} - -// MARK: - STPPaymentOptionsViewControllerDelegate - -/// An `STPPaymentOptionsViewControllerDelegate` responds when a user selects a -/// payment option from (or cancels) an `STPPaymentOptionsViewController`. In both -/// of these instances, you should dismiss the view controller (either by popping -/// it off the navigation stack, or dismissing it). -@objc public protocol STPPaymentOptionsViewControllerDelegate: NSObjectProtocol { - /// This is called when the view controller encounters an error fetching the user's - /// payment options from its API adapter. You should dismiss the view controller - /// when this is called. - /// - Parameters: - /// - paymentOptionsViewController: the view controller in question - /// - error: the error that occurred - func paymentOptionsViewController( - _ paymentOptionsViewController: STPPaymentOptionsViewController, - didFailToLoadWithError error: Error - ) - /// This is called when the user selects or adds a payment method, so it will often - /// be called immediately after calling `paymentOptionsViewController:didSelectPaymentOption:`. - /// You should dismiss the view controller when this is called. - /// - Parameter paymentOptionsViewController: the view controller that has finished - func paymentOptionsViewControllerDidFinish( - _ paymentOptionsViewController: STPPaymentOptionsViewController - ) - /// This is called when the user taps "cancel". - /// You should dismiss the view controller when this is called. - /// - Parameter paymentOptionsViewController: the view controller that has finished - func paymentOptionsViewControllerDidCancel( - _ paymentOptionsViewController: STPPaymentOptionsViewController - ) - - /// This is called when the user either makes a selection, or adds a new card. - /// This will be triggered after the view controller loads with the user's current - /// selection (if they have one) and then subsequently when they change their - /// choice. You should use this callback to update any necessary UI in your app - /// that displays the user's currently selected payment method. You should *not* - /// dismiss the view controller at this point, instead do this in - /// `paymentOptionsViewControllerDidFinish:`. `STPPaymentOptionsViewController` - /// will also call the necessary methods on your API adapter, so you don't need to - /// call them directly during this method. - /// - Parameters: - /// - paymentOptionsViewController: the view controller in question - /// - paymentOption: the selected payment method - @objc(paymentOptionsViewController:didSelectPaymentOption:) - optional func paymentOptionsViewController( - _ paymentOptionsViewController: STPPaymentOptionsViewController, - didSelect paymentOption: STPPaymentOption - ) -} - -/// :nodoc: -@_spi(STP) extension STPPaymentOptionsViewController: STPAnalyticsProtocol { - @_spi(STP) public static var stp_analyticsIdentifier = "STPPaymentOptionsViewController" -} diff --git a/Stripe/StripeiOS/Source/STPPaymentResult.swift b/Stripe/StripeiOS/Source/STPPaymentResult.swift deleted file mode 100644 index 0a170738518..00000000000 --- a/Stripe/StripeiOS/Source/STPPaymentResult.swift +++ /dev/null @@ -1,43 +0,0 @@ -// -// STPPaymentResult.swift -// StripeiOS -// -// Created by Jack Flintermann on 1/15/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -import Foundation - -/// When you're using `STPPaymentContext` to request your user's payment details, this is the object that will be returned to your application when they've successfully made a payment. -/// See https://stripe.com/docs/mobile/ios/basic#submit-payment-intents -public class STPPaymentResult: NSObject { - /// The payment method that the user has selected. This may come from a variety of different payment methods, such as an Apple Pay payment or a stored credit card. - seealso: STPPaymentMethod.h - /// If paymentMethod is nil, paymentMethodParams will be populated instead. - @objc public private(set) var paymentMethod: STPPaymentMethod? - /// The parameters for a payment method that the user has selected. This is - /// populated for non-reusable payment methods, such as FPX and iDEAL. - seealso: STPPaymentMethodParams.h - /// If paymentMethodParams is nil, paymentMethod will be populated instead. - @objc public private(set) var paymentMethodParams: STPPaymentMethodParams? - /// The STPPaymentOption that was used to initialize this STPPaymentResult, either an STPPaymentMethod or an STPPaymentMethodParams. - - @objc public weak var paymentOption: STPPaymentOption? { - if paymentMethod != nil { - return paymentMethod - } else { - return paymentMethodParams - } - } - - /// Initializes the payment result with a given payment option. This is invoked by `STPPaymentContext` internally; you shouldn't have to call it directly. - @objc - public init( - paymentOption: STPPaymentOption? - ) { - super.init() - if paymentOption is STPPaymentMethod { - paymentMethod = paymentOption as? STPPaymentMethod - } else if paymentOption is STPPaymentMethodParams { - paymentMethodParams = paymentOption as? STPPaymentMethodParams - } - } -} diff --git a/Stripe/StripeiOS/Source/STPSectionHeaderView.swift b/Stripe/StripeiOS/Source/STPSectionHeaderView.swift deleted file mode 100644 index 2b45b2af198..00000000000 --- a/Stripe/StripeiOS/Source/STPSectionHeaderView.swift +++ /dev/null @@ -1,161 +0,0 @@ -// -// STPSectionHeaderView.swift -// StripeiOS -// -// Created by Ben Guo on 1/3/17. -// Copyright © 2017 Stripe, Inc. All rights reserved. -// - -import UIKit - -class STPSectionHeaderView: UIView { - private var _theme: STPTheme = STPTheme.defaultTheme - var theme: STPTheme { - get { - _theme - } - set(theme) { - _theme = theme - updateAppearance() - } - } - - private var _title: String? - var title: String? { - get { - _title - } - set(title) { - _title = title - if let title = title { - let style = NSMutableParagraphStyle() - style.firstLineHeadIndent = 15 - style.headIndent = style.firstLineHeadIndent - let attributes = [ - NSAttributedString.Key.paragraphStyle: style - ] - label?.attributedText = NSAttributedString( - string: title, - attributes: attributes - ) - } else { - label?.attributedText = nil - } - setNeedsLayout() - } - } - weak var button: UIButton? - - private var _buttonHidden = false - var buttonHidden: Bool { - get { - _buttonHidden - } - set(buttonHidden) { - _buttonHidden = buttonHidden - button?.alpha = buttonHidden ? 0 : 1 - } - } - private weak var label: UILabel? - private let buttonInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 15) - - override init( - frame: CGRect - ) { - super.init(frame: frame) - let label = UILabel() - label.numberOfLines = 0 - label.lineBreakMode = .byWordWrapping - label.accessibilityTraits.insert(.header) - addSubview(label) - self.label = label - let button = UIButton(type: .system) - button.contentHorizontalAlignment = .right - button.titleLabel?.numberOfLines = 0 - button.titleLabel?.lineBreakMode = .byWordWrapping - button.titleEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 15) - button.contentEdgeInsets = .zero - addSubview(button) - self.button = button - backgroundColor = UIColor.clear - updateAppearance() - } - - @objc func updateAppearance() { - label?.font = theme.smallFont - label?.textColor = theme.secondaryForegroundColor - button?.titleLabel?.font = theme.smallFont - button?.tintColor = theme.accentColor - } - - override func layoutSubviews() { - super.layoutSubviews() - let bounds = stp_boundsWithHorizontalSafeAreaInsets() - if buttonHidden { - label?.frame = bounds - } else { - let halfWidth = bounds.size.width / 2 - let heightThatFits = self.heightThatFits(bounds.size) - label?.frame = CGRect( - x: bounds.origin.x, - y: bounds.origin.y, - width: halfWidth, - height: heightThatFits - ) - button?.frame = CGRect( - x: bounds.origin.x + halfWidth, - y: bounds.origin.y, - width: halfWidth, - height: heightThatFits - ) - } - } - - func heightThatFits(_ size: CGSize) -> CGFloat { - let labelPadding: CGFloat = 16 - if buttonHidden { - let labelHeight = label?.sizeThatFits(size).height ?? 0.0 - return labelHeight + labelPadding - } else { - let halfSize = CGSize(width: size.width / 2, height: size.height) - let labelHeight = (label?.sizeThatFits(halfSize).height ?? 0.0) + labelPadding - let buttonHeight = height( - forButtonText: button?.titleLabel?.text, - width: halfSize.width - ) - return CGFloat(max(buttonHeight, labelHeight)) - } - } - - private func height(forButtonText text: String?, width: CGFloat) -> CGFloat { - let insets = buttonInsets - let textSize = CGSize( - width: width - insets.left - insets.right, - height: CGFloat.greatestFiniteMagnitude - ) - var attributes: [NSAttributedString.Key: Any]? - if let font1 = button?.titleLabel?.font { - attributes = [ - NSAttributedString.Key.font: font1 - ] - } - let buttonSize = - text?.boundingRect( - with: textSize, - options: .usesLineFragmentOrigin, - attributes: attributes, - context: nil - ).size ?? .zero - return buttonSize.height + insets.top + insets.bottom - } - - override func sizeThatFits(_ size: CGSize) -> CGSize { - return CGSize(width: size.width, height: heightThatFits(size)) - } - - required init?( - coder aDecoder: NSCoder - ) { - super.init(coder: aDecoder) - } -} diff --git a/Stripe/StripeiOS/Source/STPShippingAddressViewController.swift b/Stripe/StripeiOS/Source/STPShippingAddressViewController.swift deleted file mode 100644 index ac63189dcee..00000000000 --- a/Stripe/StripeiOS/Source/STPShippingAddressViewController.swift +++ /dev/null @@ -1,674 +0,0 @@ -// -// STPShippingAddressViewController.swift -// StripeiOS -// -// Created by Ben Guo on 8/29/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -import PassKit -@_spi(STP) import StripeCore -@_spi(STP) import StripePaymentsUI -@_spi(STP) import StripeUICore -import UIKit - -/// This view controller contains a shipping address collection form. It renders a right bar button item that submits the form, so it must be shown inside a `UINavigationController`. Depending on your configuration's shippingType, the view controller may present a shipping method selection form after the user enters an address. -public class STPShippingAddressViewController: STPCoreTableViewController { - - /// A convenience initializer; equivalent to calling `init(configuration: STPPaymentConfiguration.shared theme: STPTheme.defaultTheme currency:"" shippingAddress:nil selectedShippingMethod:nil prefilledInformation:nil)`. - @objc - public convenience init() { - self.init( - configuration: STPPaymentConfiguration.shared, - theme: STPTheme.defaultTheme, - currency: "", - shippingAddress: nil, - selectedShippingMethod: nil, - prefilledInformation: nil - ) - } - - /// Initializes a new `STPShippingAddressViewController` with the given payment context and sets the payment context as its delegate. - /// - Parameter paymentContext: The payment context to use. - @objc(initWithPaymentContext:) - public convenience init( - paymentContext: STPPaymentContext - ) { - STPAnalyticsClient.sharedClient.addClass( - toProductUsageIfNecessary: STPShippingAddressViewController.self - ) - - var billingAddress: STPAddress? - weak var paymentOption = paymentContext.selectedPaymentOption - if paymentOption is STPCard { - let card = paymentOption as? STPCard - billingAddress = card?.address - } else if paymentOption is STPPaymentMethod { - let paymentMethod = paymentOption as? STPPaymentMethod - if let billingDetails1 = paymentMethod?.billingDetails { - billingAddress = STPAddress(paymentMethodBillingDetails: billingDetails1) - } - } - var prefilledInformation: STPUserInformation? - if paymentContext.prefilledInformation != nil { - prefilledInformation = paymentContext.prefilledInformation - } else { - prefilledInformation = STPUserInformation() - } - prefilledInformation?.billingAddress = billingAddress - self.init( - configuration: paymentContext.configuration, - theme: paymentContext.theme, - currency: paymentContext.paymentCurrency, - shippingAddress: paymentContext.shippingAddress, - selectedShippingMethod: paymentContext.selectedShippingMethod, - prefilledInformation: prefilledInformation - ) - - self.delegate = paymentContext - } - - /// Initializes a new `STPShippingAddressCardViewController` with the provided parameters. - /// - Parameters: - /// - configuration: The configuration to use (this determines the required shipping address fields and shipping type). - seealso: STPPaymentConfiguration - /// - theme: The theme to use to inform the view controller's visual appearance. - seealso: STPTheme - /// - currency: The currency to use when displaying amounts for shipping methods. The default is USD. - /// - shippingAddress: If set, the shipping address view controller will be pre-filled with this address. - seealso: STPAddress - /// - selectedShippingMethod: If set, the shipping methods view controller will use this method as the selected shipping method. If `selectedShippingMethod` is nil, the first shipping method in the array of methods returned by your delegate will be selected. - /// - prefilledInformation: If set, the shipping address view controller will be pre-filled with this information. - seealso: STPUserInformation - @objc( - initWithConfiguration: - theme: - currency: - shippingAddress: - selectedShippingMethod: - prefilledInformation: - ) - public init( - configuration: STPPaymentConfiguration, - theme: STPTheme, - currency: String?, - shippingAddress: STPAddress?, - selectedShippingMethod: PKShippingMethod?, - prefilledInformation: STPUserInformation? - ) { - STPAnalyticsClient.sharedClient.addClass( - toProductUsageIfNecessary: STPShippingAddressViewController.self - ) - addressViewModel = STPAddressViewModel( - requiredBillingFields: configuration.requiredBillingAddressFields, - availableCountries: configuration.availableCountries - ) - super.init(theme: theme) - assert( - (configuration.requiredShippingAddressFields?.count ?? 0) > 0, - "`requiredShippingAddressFields` must not be empty when initializing an STPShippingAddressViewController." - ) - self.configuration = configuration - self.currency = currency - self.selectedShippingMethod = selectedShippingMethod - billingAddress = prefilledInformation?.billingAddress - hasUsedBillingAddress = false - addressViewModel = STPAddressViewModel( - requiredShippingFields: configuration.requiredShippingAddressFields ?? [], - availableCountries: configuration.availableCountries - ) - addressViewModel.delegate = self - if let shippingAddress = shippingAddress { - addressViewModel.address = shippingAddress - } else if prefilledInformation?.shippingAddress != nil { - addressViewModel.address = prefilledInformation?.shippingAddress ?? STPAddress() - } - title = title(for: self.configuration?.shippingType ?? .shipping) - } - - /// The view controller's delegate. This must be set before showing the view controller in order for it to work properly. - seealso: STPShippingAddressViewControllerDelegate - @objc public weak var delegate: STPShippingAddressViewControllerDelegate? - - /// If you're pushing `STPShippingAddressViewController` onto an existing `UINavigationController`'s stack, you should use this method to dismiss it, since it may have pushed an additional shipping method view controller onto the navigation controller's stack. - /// - Parameter completion: The callback to run after the view controller is dismissed. You may specify nil for this parameter. - @objc(dismissWithCompletion:) - public func dismiss(withCompletion completion: STPVoidBlock?) { - if stp_isAtRootOfNavigationController() { - presentingViewController?.dismiss(animated: true, completion: completion ?? {}) - } else { - var previous = navigationController?.viewControllers.first - for viewController in navigationController?.viewControllers ?? [] { - if viewController == self { - break - } - previous = viewController - } - navigationController?.stp_pop( - to: previous, - animated: true, - completion: completion ?? {} - ) - } - } - - /// Use one of the initializers declared in this interface. - @available( - *, - unavailable, - message: "Use one of the initializers declared in this interface instead." - ) - @objc public required init( - theme: STPTheme? - ) { - let configuration = STPPaymentConfiguration.shared - addressViewModel = STPAddressViewModel( - requiredBillingFields: configuration.requiredBillingAddressFields, - availableCountries: configuration.availableCountries - ) - - super.init(theme: theme) - } - - /// Use one of the initializers declared in this interface. - @available( - *, - unavailable, - message: "Use one of the initializers declared in this interface instead." - ) - @objc public required init( - nibName nibNameOrNil: String?, - bundle nibBundleOrNil: Bundle? - ) { - let configuration = STPPaymentConfiguration.shared - addressViewModel = STPAddressViewModel( - requiredBillingFields: configuration.requiredBillingAddressFields, - availableCountries: configuration.availableCountries - ) - super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) - } - - /// Use one of the initializers declared in this interface. - @available( - *, - unavailable, - message: "Use one of the initializers declared in this interface instead." - ) - required init?( - coder aDecoder: NSCoder - ) { - let configuration = STPPaymentConfiguration.shared - addressViewModel = STPAddressViewModel( - requiredBillingFields: configuration.requiredBillingAddressFields, - availableCountries: configuration.availableCountries - ) - super.init(coder: aDecoder) - } - - private var configuration: STPPaymentConfiguration? - private var currency: String? - private var selectedShippingMethod: PKShippingMethod? - private weak var imageView: UIImageView? - private var nextItem: UIBarButtonItem? - - private var _loading = false - private var loading: Bool { - get { - _loading - } - set(loading) { - if loading == _loading { - return - } - _loading = loading - stp_navigationItemProxy?.setHidesBackButton(loading, animated: true) - stp_navigationItemProxy?.leftBarButtonItem?.isEnabled = !loading - activityIndicator?.animating = loading - if loading { - tableView?.endEditing(true) - var loadingItem: UIBarButtonItem? - if let activityIndicator = activityIndicator { - loadingItem = UIBarButtonItem(customView: activityIndicator) - } - stp_navigationItemProxy?.setRightBarButton(loadingItem, animated: true) - } else { - stp_navigationItemProxy?.setRightBarButton(nextItem, animated: true) - } - for cell in addressViewModel.addressCells { - cell.isUserInteractionEnabled = !loading - UIView.animate( - withDuration: 0.1, - animations: { - cell.alpha = loading ? 0.7 : 1.0 - } - ) - } - } - } - private var activityIndicator: STPPaymentActivityIndicatorView? - internal var addressViewModel: STPAddressViewModel - private var billingAddress: STPAddress? - private var hasUsedBillingAddress = false - private var addressHeaderView: STPSectionHeaderView? - - override func createAndSetupViews() { - super.createAndSetupViews() - - var nextItem: UIBarButtonItem? - switch configuration?.shippingType { - case .shipping: - nextItem = UIBarButtonItem( - title: STPLocalizedString("Next", "Button to move to the next text entry field"), - style: .done, - target: self, - action: #selector(next(_:)) - ) - case .delivery, .none, .some: - nextItem = UIBarButtonItem( - barButtonSystemItem: .done, - target: self, - action: #selector(next(_:)) - ) - } - self.nextItem = nextItem - stp_navigationItemProxy?.rightBarButtonItem = nextItem - stp_navigationItemProxy?.rightBarButtonItem?.isEnabled = false - stp_navigationItemProxy?.rightBarButtonItem?.accessibilityIdentifier = - "ShippingViewControllerNextButtonIdentifier" - - let imageView = UIImageView(image: STPLegacyImageLibrary.largeShippingImage()) - imageView.contentMode = .center - imageView.frame = CGRect( - x: 0, - y: 0, - width: view.bounds.size.width, - height: imageView.bounds.size.height + (57 * 2) - ) - self.imageView = imageView - tableView?.tableHeaderView = imageView - - activityIndicator = STPPaymentActivityIndicatorView( - frame: CGRect(x: 0, y: 0, width: 20.0, height: 20.0) - ) - - tableView?.dataSource = self - tableView?.delegate = self - tableView?.reloadData() - view.addGestureRecognizer( - UITapGestureRecognizer( - target: self, - action: #selector(NSMutableAttributedString.endEditing) - ) - ) - - let headerView = STPSectionHeaderView() - headerView.theme = theme - if let shippingType1 = configuration?.shippingType { - headerView.title = headerTitle(for: shippingType1) - } - headerView.button?.setTitle( - STPLocalizedString( - "Use Billing", - "Button to fill shipping address from billing address." - ), - for: .normal - ) - headerView.button?.addTarget( - self, - action: #selector(useBillingAddress(_:)), - for: .touchUpInside - ) - headerView.button?.accessibilityIdentifier = "ShippingAddressViewControllerUseBillingButton" - var buttonVisible = false - if let requiredFields = configuration?.requiredShippingAddressFields { - let needsAddress = - requiredFields.contains(.postalAddress) && !(addressViewModel.isValid) - buttonVisible = - needsAddress - && billingAddress?.containsContent(forShippingAddressFields: requiredFields) - ?? false - && !hasUsedBillingAddress - } - headerView.button?.alpha = buttonVisible ? 1 : 0 - headerView.setNeedsLayout() - addressHeaderView = headerView - - updateDoneButton() - } - - @objc func endEditing() { - view.endEditing(false) - } - - @objc override func updateAppearance() { - super.updateAppearance() - let navBarTheme = navigationController?.navigationBar.stp_theme ?? theme - nextItem?.stp_setTheme(navBarTheme) - - tableView?.allowsSelection = false - - imageView?.tintColor = theme.accentColor - activityIndicator?.tintColor = theme.accentColor - for cell in addressViewModel.addressCells { - cell.theme = theme - } - addressHeaderView?.theme = theme - } - - /// :nodoc: - @objc - public override func viewDidAppear(_ animated: Bool) { - super.viewDidAppear(animated) - stp_beginObservingKeyboardAndInsettingScrollView( - tableView, - onChange: nil - ) - firstEmptyField()?.becomeFirstResponder() - } - - func firstEmptyField() -> UIResponder? { - for cell in addressViewModel.addressCells { - if (cell.contents?.count ?? 0) == 0 { - return cell - } - } - return nil - } - - @objc override func handleCancelTapped(_ sender: Any?) { - delegate?.shippingAddressViewControllerDidCancel(self) - } - - @objc func next(_ sender: Any?) { - let address = addressViewModel.address - switch configuration?.shippingType { - case .shipping: - loading = true - delegate?.shippingAddressViewController(self, didEnter: address) { - status, - shippingValidationError, - shippingMethods, - selectedShippingMethod in - self.loading = false - if status == .valid { - if (shippingMethods?.count ?? 0) > 0 { - var nextViewController: STPShippingMethodsViewController? - if let shippingMethods = shippingMethods, - let selectedShippingMethod = selectedShippingMethod - { - nextViewController = STPShippingMethodsViewController( - shippingMethods: shippingMethods, - selectedShippingMethod: selectedShippingMethod, - currency: self.currency ?? "", - theme: self.theme - ) - } - nextViewController?.delegate = self - if let nextViewController = nextViewController { - self.navigationController?.pushViewController( - nextViewController, - animated: true - ) - } - } else { - self.delegate?.shippingAddressViewController( - self, - didFinishWith: address, - shippingMethod: nil - ) - } - } else { - self.handleShippingValidationError(shippingValidationError) - } - } - case .delivery, .none, .some: - delegate?.shippingAddressViewController( - self, - didFinishWith: address, - shippingMethod: nil - ) - } - } - - func updateDoneButton() { - stp_navigationItemProxy?.rightBarButtonItem?.isEnabled = addressViewModel.isValid - } - - func handleShippingValidationError(_ error: Error?) { - firstEmptyField()?.becomeFirstResponder() - var title = STPLocalizedString("Invalid Shipping Address", "Shipping form error message") - var message: String? - if let error = error { - title = error.localizedDescription - message = (error as NSError).localizedFailureReason - } - let alertController = UIAlertController( - title: title, - message: message, - preferredStyle: .alert - ) - alertController.addAction( - UIAlertAction( - title: String.Localized.ok, - style: .cancel, - handler: nil - ) - ) - present(alertController, animated: true) - } - - /// :nodoc: - @objc - public override func tableView( - _ tableView: UITableView, - heightForHeaderInSection section: Int - ) -> CGFloat { - let size = addressHeaderView?.sizeThatFits( - CGSize(width: view.bounds.size.width, height: CGFloat.greatestFiniteMagnitude) - ) - return size?.height ?? 0.0 - } - - @objc func useBillingAddress(_ sender: UIButton) { - guard let billingAddress = billingAddress else { - return - } - tableView?.beginUpdates() - addressViewModel.address = billingAddress - hasUsedBillingAddress = true - firstEmptyField()?.becomeFirstResponder() - UIView.animate( - withDuration: 0.2, - animations: { - self.addressHeaderView?.buttonHidden = true - } - ) - tableView?.endUpdates() - } - - func title(for type: STPShippingType) -> String { - if let shippingAddressFields = configuration?.requiredShippingAddressFields, - shippingAddressFields.contains(.postalAddress) - { - switch type { - case .shipping: - return STPLocalizedString("Shipping", "Title for shipping info form") - case .delivery: - return STPLocalizedString("Delivery", "Title for delivery info form") - } - } else { - return STPLocalizedString("Contact", "Title for contact info form") - } - } - - func headerTitle(for type: STPShippingType) -> String { - if let shippingAddressFields = configuration?.requiredShippingAddressFields, - shippingAddressFields.contains(.postalAddress) - { - switch type { - case .shipping: - return String.Localized.shipping_address - case .delivery: - return STPLocalizedString( - "Delivery Address", - "Title for delivery address entry section" - ) - } - } else { - return STPLocalizedString("Contact", "Title for contact info form") - } - } -} - -/// An `STPShippingAddressViewControllerDelegate` is notified when an `STPShippingAddressViewController` receives an address, completes with an address, or is cancelled. -@objc public protocol STPShippingAddressViewControllerDelegate: NSObjectProtocol { - /// Called when the user cancels entering a shipping address. You should dismiss (or pop) the view controller at this point. - /// - Parameter addressViewController: the view controller that has been cancelled - func shippingAddressViewControllerDidCancel( - _ addressViewController: STPShippingAddressViewController - ) - /// This is called when the user enters a shipping address and taps next. You - /// should validate the address and determine what shipping methods are available, - /// and call the `completion` block when finished. If an error occurrs, call - /// the `completion` block with the error. Otherwise, call the `completion` - /// block with a nil error and an array of available shipping methods. If you don't - /// need to collect a shipping method, you may pass an empty array or nil. - /// - Parameters: - /// - addressViewController: the view controller where the address was entered - /// - address: the address that was entered. - seealso: STPAddress - /// - completion: call this callback when you're done validating the address and determining available shipping methods. - - @objc(shippingAddressViewController:didEnterAddress:completion:) - func shippingAddressViewController( - _ addressViewController: STPShippingAddressViewController, - didEnter address: STPAddress, - completion: @escaping STPShippingMethodsCompletionBlock - ) - /// This is called when the user selects a shipping method. If no shipping methods are given, or if the shipping type doesn't require a shipping method, this will be called after the user has a shipping address and your validation has succeeded. After updating your app with the user's shipping info, you should dismiss (or pop) the view controller. Note that if `shippingMethod` is non-nil, there will be an additional shipping methods view controller on the navigation controller's stack. - /// - Parameters: - /// - addressViewController: the view controller where the address was entered - /// - address: the address that was entered. - seealso: STPAddress - /// - method: the shipping method that was selected. - @objc(shippingAddressViewController:didFinishWithAddress:shippingMethod:) - func shippingAddressViewController( - _ addressViewController: STPShippingAddressViewController, - didFinishWith address: STPAddress, - shippingMethod method: PKShippingMethod? - ) -} - -extension STPShippingAddressViewController: - STPAddressViewModelDelegate, UITableViewDelegate, UITableViewDataSource, - STPShippingMethodsViewControllerDelegate -{ - - // MARK: - UITableView - /// :nodoc: - @objc - public func numberOfSections(in tableView: UITableView) -> Int { - return 1 - } - - /// :nodoc: - @objc - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return addressViewModel.addressCells.count - } - - /// :nodoc: - @objc - public func tableView( - _ tableView: UITableView, - cellForRowAt indexPath: IndexPath - ) -> UITableViewCell { - let cell = - addressViewModel.addressCells.stp_boundSafeObject(at: indexPath.row) - cell?.backgroundColor = theme.secondaryBackgroundColor - cell?.contentView.backgroundColor = UIColor.clear - return cell! - } - - /// :nodoc: - @objc - public func tableView( - _ tableView: UITableView, - willDisplay cell: UITableViewCell, - forRowAt indexPath: IndexPath - ) { - let topRow = indexPath.row == 0 - let bottomRow = tableView.numberOfRows(inSection: indexPath.section) - 1 == indexPath.row - cell.stp_setBorderColor(theme.tertiaryBackgroundColor) - cell.stp_setTopBorderHidden(!topRow) - cell.stp_setBottomBorderHidden(!bottomRow) - cell.stp_setFakeSeparatorColor(theme.quaternaryBackgroundColor) - cell.stp_setFakeSeparatorLeftInset(15.0) - } - - /// :nodoc: - @objc - public func tableView( - _ tableView: UITableView, - heightForFooterInSection section: Int - ) - -> CGFloat - { - return 0.01 - } - - /// :nodoc: - @objc - public func tableView( - _ tableView: UITableView, - viewForFooterInSection section: Int - ) - -> UIView? - { - return UIView() - } - - /// :nodoc: - @objc - public func tableView( - _ tableView: UITableView, - viewForHeaderInSection section: Int - ) - -> UIView? - { - return addressHeaderView - } - - // MARK: - STPShippingMethodsViewControllerDelegate - func shippingMethodsViewController( - _ methodsViewController: STPShippingMethodsViewController, - didFinishWith method: PKShippingMethod - ) { - delegate?.shippingAddressViewController( - self, - didFinishWith: addressViewModel.address, - shippingMethod: method - ) - } - - // MARK: - STPAddressViewModelDelegate - func addressViewModel(_ addressViewModel: STPAddressViewModel, addedCellAt index: Int) { - let indexPath = IndexPath(row: index, section: 0) - tableView?.insertRows(at: [indexPath], with: .automatic) - } - - func addressViewModel(_ addressViewModel: STPAddressViewModel, removedCellAt index: Int) { - let indexPath = IndexPath(row: index, section: 0) - tableView?.deleteRows(at: [indexPath], with: .automatic) - } - - func addressViewModelDidChange(_ addressViewModel: STPAddressViewModel) { - updateDoneButton() - } - - func addressViewModelWillUpdate(_ addressViewModel: STPAddressViewModel) { - tableView?.beginUpdates() - } - - func addressViewModelDidUpdate(_ addressViewModel: STPAddressViewModel) { - tableView?.endUpdates() - } -} - -/// :nodoc: -@_spi(STP) extension STPShippingAddressViewController: STPAnalyticsProtocol { - @_spi(STP) public static var stp_analyticsIdentifier = "STPShippingAddressViewController" -} diff --git a/Stripe/StripeiOS/Source/STPShippingMethodTableViewCell.swift b/Stripe/StripeiOS/Source/STPShippingMethodTableViewCell.swift deleted file mode 100644 index f40c493c022..00000000000 --- a/Stripe/StripeiOS/Source/STPShippingMethodTableViewCell.swift +++ /dev/null @@ -1,147 +0,0 @@ -// -// STPShippingMethodTableViewCell.swift -// StripeiOS -// -// Created by Ben Guo on 8/30/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -import PassKit -@_spi(STP) import StripePayments -import UIKit - -class STPShippingMethodTableViewCell: UITableViewCell { - private var _theme: STPTheme? - var theme: STPTheme? { - get { - _theme - } - set(theme) { - _theme = theme - updateAppearance() - } - } - - func setShippingMethod(_ method: PKShippingMethod, currency: String) { - shippingMethod = method - titleLabel?.text = method.label - subtitleLabel?.text = method.detail - var localeInfo = [ - NSLocale.Key.currencyCode.rawValue: currency - ] - localeInfo[NSLocale.Key.languageCode.rawValue] = NSLocale.preferredLanguages.first ?? "" - let localeID = NSLocale.localeIdentifier(fromComponents: localeInfo) - let locale = NSLocale(localeIdentifier: localeID) - numberFormatter?.locale = locale as Locale - let amount = method.amount.stp_amount(withCurrency: currency) - if amount == 0 { - amountLabel?.text = STPLocalizedString("Free", "Label for free shipping method") - } else { - let number = NSDecimalNumber.stp_decimalNumber( - withAmount: amount, - currency: currency - ) - amountLabel?.text = numberFormatter?.string(from: number) - } - setNeedsLayout() - } - - private weak var titleLabel: UILabel? - private weak var subtitleLabel: UILabel? - private weak var amountLabel: UILabel? - private weak var checkmarkIcon: UIImageView? - private var shippingMethod: PKShippingMethod? - private var numberFormatter: NumberFormatter? - - override init( - style: UITableViewCell.CellStyle, - reuseIdentifier: String? - ) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - theme = STPTheme() - let titleLabel = UILabel() - self.titleLabel = titleLabel - let subtitleLabel = UILabel() - self.subtitleLabel = subtitleLabel - let amountLabel = UILabel() - self.amountLabel = amountLabel - let checkmarkIcon = UIImageView(image: STPLegacyImageLibrary.checkmarkIcon()) - self.checkmarkIcon = checkmarkIcon - let formatter = NumberFormatter() - formatter.numberStyle = .currency - formatter.usesGroupingSeparator = true - numberFormatter = formatter - contentView.addSubview(titleLabel) - contentView.addSubview(subtitleLabel) - contentView.addSubview(amountLabel) - contentView.addSubview(checkmarkIcon) - updateAppearance() - } - - override var isSelected: Bool { - get { - return super.isSelected - } - set(selected) { - super.isSelected = selected - updateAppearance() - } - } - - @objc func updateAppearance() { - contentView.backgroundColor = theme?.secondaryBackgroundColor - backgroundColor = UIColor.clear - titleLabel?.font = theme?.font - subtitleLabel?.font = theme?.smallFont - amountLabel?.font = theme?.font - titleLabel?.textColor = isSelected ? theme?.accentColor : theme?.primaryForegroundColor - amountLabel?.textColor = titleLabel?.textColor - var subduedAccentColor: UIColor? - if #available(iOS 13.0, *) { - subduedAccentColor = UIColor(dynamicProvider: { _ in - return self.theme?.accentColor.withAlphaComponent(0.6) ?? UIColor.clear - }) - } else { - subduedAccentColor = theme?.accentColor.withAlphaComponent(0.6) - } - subtitleLabel?.textColor = isSelected ? subduedAccentColor : theme?.secondaryForegroundColor - checkmarkIcon?.tintColor = theme?.accentColor - checkmarkIcon?.isHidden = !isSelected - } - - override func layoutSubviews() { - super.layoutSubviews() - let midY = bounds.midY - checkmarkIcon?.frame = CGRect(x: 0, y: 0, width: 14, height: 14) - checkmarkIcon?.center = CGPoint( - x: bounds.width - 15 - (checkmarkIcon?.bounds.midX ?? 0.0), - y: midY - ) - amountLabel?.sizeToFit() - amountLabel?.center = CGPoint( - x: (checkmarkIcon?.frame.minX ?? 0.0) - 15 - (amountLabel?.bounds.midX ?? 0.0), - y: midY - ) - let labelWidth = (amountLabel?.frame.minX ?? 0.0) - 30 - titleLabel?.sizeToFit() - titleLabel?.frame = CGRect( - x: 15, - y: 8, - width: labelWidth, - height: titleLabel?.frame.size.height ?? 0.0 - ) - subtitleLabel?.sizeToFit() - subtitleLabel?.frame = CGRect( - x: 15, - y: bounds.size.height - 8 - (subtitleLabel?.frame.size.height ?? 0.0), - width: labelWidth, - height: subtitleLabel?.frame.size.height ?? 0.0 - ) - } - - required init?( - coder aDecoder: NSCoder - ) { - super.init(coder: aDecoder) - } -} diff --git a/Stripe/StripeiOS/Source/STPShippingMethodsViewController.swift b/Stripe/StripeiOS/Source/STPShippingMethodsViewController.swift deleted file mode 100644 index 8d915855419..00000000000 --- a/Stripe/StripeiOS/Source/STPShippingMethodsViewController.swift +++ /dev/null @@ -1,211 +0,0 @@ -// -// STPShippingMethodsViewController.swift -// StripeiOS -// -// Created by Ben Guo on 8/29/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -import PassKit -@_spi(STP) import StripeCore -import UIKit - -class STPShippingMethodsViewController: STPCoreTableViewController, UITableViewDataSource, - UITableViewDelegate -{ - init( - shippingMethods methods: [PKShippingMethod], - selectedShippingMethod selectedMethod: PKShippingMethod, - currency: String, - theme: STPTheme - ) { - super.init(theme: theme) - shippingMethods = methods - if (methods.firstIndex(of: selectedMethod) ?? NSNotFound) != NSNotFound { - selectedShippingMethod = selectedMethod - } else { - selectedShippingMethod = methods.stp_boundSafeObject(at: 0) - } - - self.currency = currency - title = STPLocalizedString("Shipping", "Title for shipping info form") - } - - weak var delegate: STPShippingMethodsViewControllerDelegate? - private var shippingMethods: [PKShippingMethod]? - private var selectedShippingMethod: PKShippingMethod? - private var currency: String? - private weak var imageView: UIImageView? - private var doneItem: UIBarButtonItem? - private var headerView: STPSectionHeaderView? - - override func createAndSetupViews() { - super.createAndSetupViews() - - tableView?.register( - STPShippingMethodTableViewCell.self, - forCellReuseIdentifier: STPShippingMethodCellReuseIdentifier - ) - - let doneItem = UIBarButtonItem( - barButtonSystemItem: .done, - target: self, - action: #selector(done(_:)) - ) - self.doneItem = doneItem - stp_navigationItemProxy?.rightBarButtonItem = doneItem - stp_navigationItemProxy?.rightBarButtonItem?.accessibilityIdentifier = - "ShippingMethodsViewControllerDoneButtonIdentifier" - - let imageView = UIImageView(image: STPLegacyImageLibrary.largeShippingImage()) - imageView.contentMode = .center - imageView.frame = CGRect( - x: 0, - y: 0, - width: view.bounds.size.width, - height: imageView.bounds.size.height + (57 * 2) - ) - self.imageView = imageView - - tableView?.tableHeaderView = imageView - tableView?.dataSource = self - tableView?.delegate = self - tableView?.reloadData() - - let headerView = STPSectionHeaderView() - headerView.theme = theme - headerView.buttonHidden = true - headerView.title = STPLocalizedString("Shipping Method", "Label for shipping method form") - headerView.setNeedsLayout() - self.headerView = headerView - } - - @objc override func updateAppearance() { - super.updateAppearance() - - let navBarTheme = navigationController?.navigationBar.stp_theme ?? theme - doneItem?.stp_setTheme(navBarTheme) - - imageView?.tintColor = theme.accentColor - for cell in tableView?.visibleCells ?? [] { - let shippingCell = cell as? STPShippingMethodTableViewCell - shippingCell?.theme = theme - } - } - - @objc func done(_ sender: Any?) { - if let selectedShippingMethod = selectedShippingMethod { - delegate?.shippingMethodsViewController(self, didFinishWith: selectedShippingMethod) - } - } - - override func useSystemBackButton() -> Bool { - return true - } - - // MARK: - UITableView - func numberOfSections(in tableView: UITableView) -> Int { - return 1 - } - - func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return shippingMethods?.count ?? 0 - } - - func tableView( - _ tableView: UITableView, - cellForRowAt indexPath: IndexPath - ) -> UITableViewCell { - let cell = - tableView.dequeueReusableCell( - withIdentifier: STPShippingMethodCellReuseIdentifier, - for: indexPath - ) - as? STPShippingMethodTableViewCell - let method = - shippingMethods?.stp_boundSafeObject(at: indexPath.row) - cell?.theme = theme - if let method = method { - cell?.setShippingMethod(method, currency: currency ?? "") - } - cell?.isSelected = method?.identifier == selectedShippingMethod?.identifier - return cell! - } - - func tableView( - _ tableView: UITableView, - willDisplay cell: UITableViewCell, - forRowAt indexPath: IndexPath - ) { - let topRow = indexPath.row == 0 - let bottomRow = - self.tableView(tableView, numberOfRowsInSection: indexPath.section) - 1 == indexPath.row - cell.stp_setBorderColor(theme.tertiaryBackgroundColor) - cell.stp_setTopBorderHidden(!topRow) - cell.stp_setBottomBorderHidden(!bottomRow) - cell.stp_setFakeSeparatorColor(theme.quaternaryBackgroundColor) - cell.stp_setFakeSeparatorLeftInset(15.0) - } - - func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - return 57 - } - - func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { - return 27.0 - } - - override func tableView( - _ tableView: UITableView, - heightForHeaderInSection section: Int - ) - -> CGFloat - { - let size = headerView?.sizeThatFits( - CGSize(width: view.bounds.size.width, height: CGFloat.greatestFiniteMagnitude) - ) - return size?.height ?? 0.0 - } - - func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - return headerView - } - - func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - tableView.deselectRow(at: indexPath, animated: true) - selectedShippingMethod = - shippingMethods?.stp_boundSafeObject(at: indexPath.row) - tableView.reloadSections( - NSIndexSet(index: indexPath.section) as IndexSet, - with: .fade - ) - } - - required init?( - coder aDecoder: NSCoder - ) { - super.init(coder: aDecoder) - } - - required init( - nibName nibNameOrNil: String?, - bundle nibBundleOrNil: Bundle? - ) { - fatalError("init(nibName:bundle:) has not been implemented") - } - - required init( - theme: STPTheme? - ) { - fatalError("init(theme:) has not been implemented") - } -} - -@objc protocol STPShippingMethodsViewControllerDelegate: NSObjectProtocol { - func shippingMethodsViewController( - _ methodsViewController: STPShippingMethodsViewController, - didFinishWith method: PKShippingMethod - ) -} - -private let STPShippingMethodCellReuseIdentifier = "STPShippingMethodCellReuseIdentifier" diff --git a/Stripe/StripeiOS/Source/STPSource+BasicUI.swift b/Stripe/StripeiOS/Source/STPSource+BasicUI.swift deleted file mode 100644 index 67510e70e87..00000000000 --- a/Stripe/StripeiOS/Source/STPSource+BasicUI.swift +++ /dev/null @@ -1,74 +0,0 @@ -// -// STPSource+BasicUI.swift -// StripeiOS -// -// Created by David Estes on 6/30/22. -// Copyright © 2022 Stripe, Inc. All rights reserved. -// - -import Foundation -@_spi(STP) import StripePayments -import UIKit - -extension STPSource: STPPaymentOption { - // MARK: - STPPaymentOption - @objc public var image: UIImage { - if type == .card, let cardDetails = cardDetails { - return STPImageLibrary.cardBrandImage(for: cardDetails.brand) - } else { - return STPImageLibrary.cardBrandImage(for: .unknown) - } - } - - @objc public var templateImage: UIImage { - if type == .card, let cardDetails = cardDetails { - return STPImageLibrary.templatedBrandImage(for: cardDetails.brand) - } else { - return STPImageLibrary.templatedBrandImage(for: .unknown) - } - } - - @objc public var label: String { - switch type { - case .bancontact: - return STPPaymentMethodType.bancontact.displayName - case .card: - if let cardDetails = cardDetails { - let brand = STPCard.string(from: cardDetails.brand) - return "\(brand) \(cardDetails.last4 ?? "")" - } else { - return STPCard.string(from: .unknown) - } - case .giropay: - return STPPaymentMethodType.giropay.displayName - case .iDEAL: - return STPPaymentMethodType.iDEAL.displayName - case .SEPADebit: - return STPPaymentMethodType.SEPADebit.displayName - case .sofort: - return STPPaymentMethodType.sofort.displayName - case .threeDSecure: - return STPLocalizedString("3D Secure", "Source type brand name") - case .alipay: - return STPPaymentMethodType.alipay.displayName - case .P24: - return STPPaymentMethodType.przelewy24.displayName - case .EPS: - return STPPaymentMethodType.EPS.displayName - case .multibanco: - return STPLocalizedString("Multibanco", "Source type brand name") - case .weChatPay: - return STPPaymentMethodType.weChatPay.displayName - case .klarna: - return STPPaymentMethodType.klarna.displayName - case .unknown: - return STPPaymentMethodType.unknown.displayName - @unknown default: - return STPPaymentMethodType.unknown.displayName - } - } - - @objc public var isReusable: Bool { - return usage != .singleUse - } -} diff --git a/Stripe/StripeiOS/Source/STPTheme.swift b/Stripe/StripeiOS/Source/STPTheme.swift deleted file mode 100644 index 2a36f1ef2c4..00000000000 --- a/Stripe/StripeiOS/Source/STPTheme.swift +++ /dev/null @@ -1,212 +0,0 @@ -// -// STPTheme.swift -// StripeiOS -// -// Created by Jack Flintermann on 5/3/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -@_spi(STP) import StripeUICore -import UIKit - -// swift-format-ignore: DontRepeatTypeInStaticProperties -/// STPTheme objects can be used to visually style Stripe-provided UI. See https://stripe.com/docs/mobile/ios/basic#theming for more information. -final public class STPTheme: NSObject { - - /// The default theme used by all Stripe UI. All themable UI classes, such as `STPAddCardViewController`, have one initializer that takes a `theme` and one that does not. If you use the one that does not, the default theme will be used to customize that view controller's appearance. - @objc public static let defaultTheme = STPTheme() - - /// :nodoc: - @available(*, deprecated, message: "Use defaultTheme instead", renamed: "defaultTheme") - public static func `default`() -> STPTheme { - return STPTheme.defaultTheme - } - - /// The primary background color of the theme. This will be used as the `backgroundColor` for any views with this theme. - @objc public var primaryBackgroundColor: UIColor = STPThemeDefaultPrimaryBackgroundColor - - /// The secondary background color of this theme. This will be used as the `backgroundColor` for any supplemental views inside a view with this theme - for example, a `UITableView` will set it's cells' background color to this value. - @objc public var secondaryBackgroundColor: UIColor = STPThemeDefaultSecondaryBackgroundColor - - /// This color is automatically derived by reducing the alpha of the `primaryBackgroundColor` and is used as a section border color in table view cells. - @objc public var tertiaryBackgroundColor: UIColor { - let colorBlock: STPColorBlock = { - var hue: CGFloat = 0 - var saturation: CGFloat = 0 - var brightness: CGFloat = 0 - var alpha: CGFloat = 0 - self.primaryBackgroundColor.getHue( - &hue, - saturation: &saturation, - brightness: &brightness, - alpha: &alpha - ) - - return UIColor( - hue: hue, - saturation: saturation, - brightness: brightness - 0.09, - alpha: alpha - ) - } - return UIColor(dynamicProvider: { _ in - return colorBlock() - }) - } - - /// This color is automatically derived by reducing the brightness of the `primaryBackgroundColor` and is used as a separator color in table view cells. - @objc public var quaternaryBackgroundColor: UIColor { - let colorBlock: STPColorBlock = { - var hue: CGFloat = 0 - var saturation: CGFloat = 0 - var brightness: CGFloat = 0 - var alpha: CGFloat = 0 - self.primaryBackgroundColor.getHue( - &hue, - saturation: &saturation, - brightness: &brightness, - alpha: &alpha - ) - - return UIColor( - hue: hue, - saturation: saturation, - brightness: brightness - 0.03, - alpha: alpha - ) - } - return UIColor(dynamicProvider: { _ in - return colorBlock() - }) - } - - /// The primary foreground color of this theme. This will be used as the text color for any important labels in a view with this theme (such as the text color for a text field that the user needs to fill out). - @objc public var primaryForegroundColor: UIColor = STPThemeDefaultPrimaryForegroundColor - - /// The secondary foreground color of this theme. This will be used as the text color for any supplementary labels in a view with this theme (such as the placeholder color for a text field that the user needs to fill out). - @objc public var secondaryForegroundColor: UIColor = STPThemeDefaultSecondaryForegroundColor - - /// This color is automatically derived from the `secondaryForegroundColor` with a lower alpha component, used for disabled text. - @objc public var tertiaryForegroundColor: UIColor { - return UIColor(dynamicProvider: { _ in - return self.primaryForegroundColor.withAlphaComponent(0.25) - }) - } - - /// The accent color of this theme - it will be used for any buttons and other elements on a view that are important to highlight. - @objc public var accentColor: UIColor = STPThemeDefaultAccentColor - - /// The error color of this theme - it will be used for rendering any error messages or views. - @objc public var errorColor: UIColor = STPThemeDefaultErrorColor - - /// The font to be used for all views using this theme. Make sure to select an appropriate size. - @objc public var font: UIFont { - get { - if let _font = _font { - return _font - } else { - let fontMetrics = UIFontMetrics(forTextStyle: .body) - return fontMetrics.scaledFont(for: STPThemeDefaultFont) - } - } - set { - _font = newValue - } - } - private var _font: UIFont? - - /// The medium-weight font to be used for all bold text in views using this theme. Make sure to select an appropriate size. - @objc public var emphasisFont: UIFont { - get { - if let _emphasisFont = _emphasisFont { - return _emphasisFont - } else { - let fontMetrics = UIFontMetrics(forTextStyle: .body) - return fontMetrics.scaledFont(for: STPThemeDefaultMediumFont) - } - } - set { - _emphasisFont = newValue - } - } - private var _emphasisFont: UIFont? - - /// The navigation bar style to use for any view controllers presented modally - /// by the SDK. The default value will be determined based on the brightness - /// of the theme's `secondaryBackgroundColor`. - @objc public var barStyle: UIBarStyle { - get { - if let _barStyle = _barStyle { - return _barStyle - } else { - return barStyle(for: secondaryBackgroundColor) - } - } - set { - _barStyle = newValue - } - } - private var _barStyle: UIBarStyle? - - /// A Boolean value indicating whether the navigation bar for any view controllers - /// presented modally by the SDK should be translucent. The default value is YES. - @objc public var translucentNavigationBar = true - - /// This font is automatically derived from the font, with a slightly lower point size, and will be used for supplementary labels. - @objc public var smallFont: UIFont { - return font.withSize(max(font.pointSize - 2, 1)) - } - - /// This font is automatically derived from the font, with a larger point size, and will be used for large labels such as SMS code entry. - @objc public var largeFont: UIFont { - return font.withSize(font.pointSize + 15) - } - - private func barStyle(for color: UIColor) -> UIBarStyle { - if color.isBright { - return .default - } else { - return .black - } - } -} - -extension STPTheme: NSCopying { - /// :nodoc: - @objc - public func copy(with zone: NSZone? = nil) -> Any { - let otherTheme = STPTheme() - otherTheme.primaryBackgroundColor = primaryBackgroundColor - otherTheme.secondaryBackgroundColor = secondaryBackgroundColor - otherTheme.primaryForegroundColor = primaryForegroundColor - otherTheme.secondaryForegroundColor = secondaryForegroundColor - otherTheme.accentColor = accentColor - otherTheme.errorColor = errorColor - otherTheme.translucentNavigationBar = translucentNavigationBar - otherTheme._font = _font - otherTheme._emphasisFont = _emphasisFont - otherTheme._barStyle = _barStyle - - return otherTheme - } -} - -private typealias STPColorBlock = () -> UIColor - -// MARK: Default Colors - -private var STPThemeDefaultPrimaryBackgroundColor: UIColor = .secondarySystemBackground - -private var STPThemeDefaultSecondaryBackgroundColor: UIColor = .systemBackground - -private var STPThemeDefaultPrimaryForegroundColor: UIColor = .label - -private var STPThemeDefaultSecondaryForegroundColor: UIColor = .secondaryLabel - -private var STPThemeDefaultAccentColor: UIColor = .systemBlue - -private var STPThemeDefaultErrorColor: UIColor = .systemRed - -// MARK: Default Fonts -private let STPThemeDefaultFont = UIFont.systemFont(ofSize: 17) -private let STPThemeDefaultMediumFont = UIFont.systemFont(ofSize: 17, weight: .medium) diff --git a/Stripe/StripeiOS/Source/STPUserInformation.swift b/Stripe/StripeiOS/Source/STPUserInformation.swift deleted file mode 100644 index 5e6eb2cdb9d..00000000000 --- a/Stripe/StripeiOS/Source/STPUserInformation.swift +++ /dev/null @@ -1,42 +0,0 @@ -// -// STPUserInformation.swift -// StripeiOS -// -// Created by Jack Flintermann on 6/15/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -import Foundation - -/// You can use this class to specify information that you've already collected -/// from your user. You can then set the `prefilledInformation` property on -/// `STPPaymentContext`, `STPAddCardViewController`, etc and it will pre-fill -/// this information whenever possible. -public class STPUserInformation: NSObject, NSCopying { - /// The user's billing address. When set, the add card form will be filled with - /// this address. The user will also have the option to fill their shipping address - /// using this address. - /// @note Set this using `setBillingAddressWithBillingDetails:` to use the billing - /// details from an `STPPaymentMethod` or `STPPaymentMethodParams` instance. - @objc public var billingAddress: STPAddress? - /// The user's shipping address. When set, the shipping address form will be filled - /// with this address. The user will also have the option to fill their billing - /// address using this address. - @objc public var shippingAddress: STPAddress? - - /// A convenience method to populate `billingAddress` with a PaymentMethod's billing details. - /// @note Calling this overwrites the value of `billingAddress`. - @objc(setBillingAddressWithBillingDetails:) - public func setBillingAddress(with billingDetails: STPPaymentMethodBillingDetails) { - billingAddress = STPAddress(paymentMethodBillingDetails: billingDetails) - } - - /// :nodoc: - @objc - public func copy(with zone: NSZone? = nil) -> Any { - let copy = STPUserInformation() - copy.billingAddress = billingAddress - copy.shippingAddress = shippingAddress - return copy - } -} diff --git a/Stripe/StripeiOS/Source/String+Localized.swift b/Stripe/StripeiOS/Source/String+Localized.swift deleted file mode 100644 index 55bd59ddd9e..00000000000 --- a/Stripe/StripeiOS/Source/String+Localized.swift +++ /dev/null @@ -1,22 +0,0 @@ -// -// String+Localized.swift -// StripeiOS -// -// Created by Mel Ludowise on 7/6/21. -// Copyright © 2021 Stripe, Inc. All rights reserved. -// - -import Foundation -@_spi(STP) import StripeCore -@_spi(STP) import StripePaymentsUI -@_spi(STP) import StripeUICore - -// MARK: - Legacy strings - -/// Legacy strings -extension StripeSharedStrings { - static func localizedPostalCodeString(for countryCode: String?) -> String { - return countryCode == "US" - ? String.Localized.zip : String.Localized.postal_code - } -} diff --git a/Stripe/StripeiOS/Source/StripeBundleLocator.swift b/Stripe/StripeiOS/Source/StripeBundleLocator.swift deleted file mode 100644 index a6c6694fd37..00000000000 --- a/Stripe/StripeiOS/Source/StripeBundleLocator.swift +++ /dev/null @@ -1,20 +0,0 @@ -// -// StripeBundleLocator.swift -// StripeiOS -// -// Created by Mel Ludowise on 7/6/21. -// Copyright © 2021 Stripe, Inc. All rights reserved. -// - -import Foundation -@_spi(STP) import StripeCore - -/// :nodoc: -@_spi(STP) public final class StripeBundleLocator: BundleLocatorProtocol { - public static let internalClass: AnyClass = StripeBundleLocator.self - public static let bundleName = "StripeBundle" - #if SWIFT_PACKAGE - public static let spmResourcesBundle = Bundle.module - #endif - public static let resourcesBundle = StripeBundleLocator.computeResourcesBundle() -} diff --git a/Stripe/StripeiOS/Source/UIBarButtonItem+Stripe.swift b/Stripe/StripeiOS/Source/UIBarButtonItem+Stripe.swift deleted file mode 100644 index 2c792c1bcae..00000000000 --- a/Stripe/StripeiOS/Source/UIBarButtonItem+Stripe.swift +++ /dev/null @@ -1,54 +0,0 @@ -// -// UIBarButtonItem+Stripe.swift -// StripeiOS -// -// Created by Jack Flintermann on 5/18/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -@_spi(STP) import StripeUICore -import UIKit - -extension UIBarButtonItem { - @objc(stp_setTheme:) func stp_setTheme(_ theme: STPTheme) { - let image = backgroundImage(for: .normal, barMetrics: .default) - if let image = image { - let enabledImage: UIImage = STPLegacyImageLibrary.image( - withTintColor: theme.accentColor, - for: image - ) - let disabledImage: UIImage = STPLegacyImageLibrary.image( - withTintColor: theme.secondaryForegroundColor, - for: image - ) - setBackgroundImage(enabledImage, for: .normal, barMetrics: .default) - setBackgroundImage(disabledImage, for: .disabled, barMetrics: .default) - } - - tintColor = isEnabled ? theme.accentColor : theme.secondaryForegroundColor - - setTitleTextAttributes( - [ - NSAttributedString.Key.font: style == .plain ? theme.font : theme.emphasisFont, - NSAttributedString.Key.foregroundColor: theme.accentColor, - ], - for: .normal - ) - - setTitleTextAttributes( - [ - NSAttributedString.Key.font: style == .plain ? theme.font : theme.emphasisFont, - NSAttributedString.Key.foregroundColor: theme.secondaryForegroundColor, - ], - for: .disabled - ) - - setTitleTextAttributes( - [ - NSAttributedString.Key.font: style == .plain ? theme.font : theme.emphasisFont, - NSAttributedString.Key.foregroundColor: theme.accentColor, - ], - for: .highlighted - ) - } -} diff --git a/Stripe/StripeiOS/Source/UINavigationBar+Stripe_Theme.swift b/Stripe/StripeiOS/Source/UINavigationBar+Stripe_Theme.swift deleted file mode 100644 index d46ee524f29..00000000000 --- a/Stripe/StripeiOS/Source/UINavigationBar+Stripe_Theme.swift +++ /dev/null @@ -1,142 +0,0 @@ -// -// UINavigationBar+Stripe_Theme.swift -// StripeiOS -// -// Created by Jack Flintermann on 5/17/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -import ObjectiveC -import UIKit - -/// This allows quickly setting the appearance of a `UINavigationBar` to match your -/// application. This is useful if you're presenting an `STPAddCardViewController` -/// or `STPPaymentOptionsViewController` inside a `UINavigationController`. -extension UINavigationBar { - /// Sets the navigation bar's appearance to the desired theme. This will affect the - /// bar's `tintColor` and `barTintColor` properties, as well as the color of the - /// single-pixel line at the bottom of the navbar. - /// - Parameter theme: the theme to use to style the navigation bar. - seealso: STPTheme.h - /// @deprecated Use the `stp_theme` property instead - @available(*, deprecated, message: "Use the `stp_theme` property instead") - @objc - public func stp_setTheme(_ theme: STPTheme) { - stp_theme = theme - } - - /// Sets the navigation bar's appearance to the desired theme. This will affect the bar's `tintColor` and `barTintColor` properties, as well as the color of the single-pixel line at the bottom of the navbar. - /// Stripe view controllers will use their navigation bar's theme for their UIBarButtonItems instead of their own theme if it is not nil. - /// - seealso: STPTheme.h - - @objc public var stp_theme: STPTheme? { - get { - return objc_getAssociatedObject( - self, - UnsafeRawPointer(&kUINavigationBarSTPThemeObjectKey) - ) - as? STPTheme - } - set(theme) { - objc_setAssociatedObject( - self, - UnsafeRawPointer(&kUINavigationBarSTPThemeObjectKey), - theme, - .OBJC_ASSOCIATION_RETAIN_NONATOMIC - ) - - if let hairlineImageView = stp_hairlineImageView() { - hairlineImageView.isHidden = theme != nil - } - - guard let theme = theme else { - return - } - - stp_artificialHairlineView().backgroundColor = theme.tertiaryBackgroundColor - barTintColor = theme.secondaryBackgroundColor - tintColor = theme.accentColor - barStyle = theme.barStyle - isTranslucent = theme.translucentNavigationBar - - titleTextAttributes = [ - NSAttributedString.Key.font: theme.emphasisFont, - NSAttributedString.Key.foregroundColor: theme.primaryForegroundColor, - ] - - largeTitleTextAttributes = [ - NSAttributedString.Key.foregroundColor: theme.primaryForegroundColor - ] - - standardAppearance.backgroundColor = theme.secondaryBackgroundColor - if let titleTextAttributes = titleTextAttributes { - standardAppearance.titleTextAttributes = titleTextAttributes - } - if let largeTitleTextAttributes = largeTitleTextAttributes { - standardAppearance.largeTitleTextAttributes = largeTitleTextAttributes - } - standardAppearance.buttonAppearance.normal.titleTextAttributes = [ - NSAttributedString.Key.font: theme.font, - NSAttributedString.Key.foregroundColor: theme.accentColor, - ] - - standardAppearance.buttonAppearance.highlighted.titleTextAttributes = [ - NSAttributedString.Key.font: theme.font, - NSAttributedString.Key.foregroundColor: theme.accentColor, - ] - - standardAppearance.buttonAppearance.disabled.titleTextAttributes = [ - NSAttributedString.Key.font: theme.font, - NSAttributedString.Key.foregroundColor: theme.secondaryForegroundColor, - ] - - standardAppearance.doneButtonAppearance.normal.titleTextAttributes = [ - NSAttributedString.Key.font: theme.emphasisFont, - NSAttributedString.Key.foregroundColor: theme.accentColor, - ] - - standardAppearance.doneButtonAppearance.highlighted.titleTextAttributes = [ - NSAttributedString.Key.font: theme.emphasisFont, - NSAttributedString.Key.foregroundColor: theme.accentColor, - ] - - standardAppearance.doneButtonAppearance.disabled.titleTextAttributes = [ - NSAttributedString.Key.font: theme.emphasisFont, - NSAttributedString.Key.foregroundColor: theme.secondaryForegroundColor, - ] - scrollEdgeAppearance = standardAppearance - compactAppearance = standardAppearance - } - } - - func stp_artificialHairlineView() -> UIView { - var view = viewWithTag(STPNavigationBarHairlineViewTag) - if view == nil { - view = UIView(frame: CGRect(x: 0, y: bounds.maxY, width: bounds.width, height: 0.5)) - view?.autoresizingMask = [.flexibleWidth, .flexibleTopMargin] - view?.tag = STPNavigationBarHairlineViewTag - if let view = view { - addSubview(view) - } - } - return view! - } - - func stp_hairlineImageView() -> UIImageView? { - return stp_hairlineImageView(self) - } - - func stp_hairlineImageView(_ view: UIView) -> UIImageView? { - if (view is UIImageView) && view.bounds.size.height <= 1.0 { - return (view as? UIImageView)! - } - for subview in view.subviews { - if let imageView = stp_hairlineImageView(subview) { - return imageView - } - } - return nil - } -} - -private let STPNavigationBarHairlineViewTag = 787473 -private var kUINavigationBarSTPThemeObjectKey = 0 diff --git a/Stripe/StripeiOS/Source/UINavigationController+Stripe_Completion.swift b/Stripe/StripeiOS/Source/UINavigationController+Stripe_Completion.swift deleted file mode 100644 index f0ed82968ea..00000000000 --- a/Stripe/StripeiOS/Source/UINavigationController+Stripe_Completion.swift +++ /dev/null @@ -1,61 +0,0 @@ -// -// UINavigationController+Stripe_Completion.swift -// StripeiOS -// -// Created by Jack Flintermann on 3/23/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -import UIKit - -// See http://stackoverflow.com/questions/9906966/completion-handler-for-uinavigationcontroller-pushviewcontrolleranimated/33767837#33767837 for some discussion around why using CATransaction is unreliable here. - -extension UINavigationController { - func stp_push( - _ viewController: UIViewController?, - animated: Bool, - completion: @escaping STPVoidBlock - ) { - if let viewController = viewController { - pushViewController(viewController, animated: animated) - } - if transitionCoordinator != nil && animated { - transitionCoordinator?.animate(alongsideTransition: nil) { _ in - completion() - } - } else { - completion() - } - } - - func stp_popViewController( - animated: Bool, - completion: @escaping STPVoidBlock - ) { - popViewController(animated: animated) - if transitionCoordinator != nil && animated { - transitionCoordinator?.animate(alongsideTransition: nil) { _ in - completion() - } - } else { - completion() - } - } - - @objc(stp_popToViewController:animated:completion:) func stp_pop( - to viewController: UIViewController?, - animated: Bool, - completion: @escaping STPVoidBlock - ) { - if let viewController = viewController { - popToViewController(viewController, animated: animated) - } - if transitionCoordinator != nil && animated { - transitionCoordinator?.animate(alongsideTransition: nil) { _ in - completion() - } - } else { - completion() - } - } -} diff --git a/Stripe/StripeiOS/Source/UITableViewCell+Stripe_Borders.swift b/Stripe/StripeiOS/Source/UITableViewCell+Stripe_Borders.swift deleted file mode 100644 index c70200a0872..00000000000 --- a/Stripe/StripeiOS/Source/UITableViewCell+Stripe_Borders.swift +++ /dev/null @@ -1,103 +0,0 @@ -// -// UITableViewCell+Stripe_Borders.swift -// StripeiOS -// -// Created by Jack Flintermann on 5/16/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -import UIKit - -private let STPTableViewCellTopBorderTag = 787473 -private let STPTableViewCellBottomBorderTag = 787474 -private let STPTableViewCellFakeSeparatorTag = 787475 - -extension UITableViewCell { - @objc(stp_setBorderColor:) func stp_setBorderColor(_ color: UIColor?) { - stp_topBorderView()?.backgroundColor = color - stp_bottomBorderView()?.backgroundColor = color - } - - @objc(stp_setTopBorderHidden:) func stp_setTopBorderHidden(_ hidden: Bool) { - stp_topBorderView()?.isHidden = hidden - } - - @objc(stp_setBottomBorderHidden:) func stp_setBottomBorderHidden(_ hidden: Bool) { - stp_bottomBorderView()?.isHidden = hidden - stp_fakeSeparatorView()?.isHidden = !hidden - } - - @objc(stp_setFakeSeparatorLeftInset:) func stp_setFakeSeparatorLeftInset(_ leftInset: CGFloat) { - stp_fakeSeparatorView()?.frame = CGRect( - x: leftInset, - y: bounds.size.height - 0.5, - width: bounds.size.width - leftInset, - height: 0.5 - ) - } - - @objc(stp_setFakeSeparatorColor:) func stp_setFakeSeparatorColor(_ color: UIColor?) { - stp_fakeSeparatorView()?.backgroundColor = color - } - - func stp_topBorderView() -> UIView? { - var view = viewWithTag(STPTableViewCellTopBorderTag) - if view == nil { - view = UIView(frame: CGRect(x: 0, y: 0, width: bounds.size.width, height: 0.5)) - view?.autoresizingMask = [.flexibleWidth, .flexibleBottomMargin] - view?.tag = STPTableViewCellTopBorderTag - view?.backgroundColor = backgroundColor - view?.isHidden = true - view?.accessibilityIdentifier = "stp_topBorderView" - if let view = view { - addSubview(view) - } - } - return view - } - - func stp_bottomBorderView() -> UIView? { - var view = viewWithTag(STPTableViewCellBottomBorderTag) - if view == nil { - view = UIView( - frame: CGRect( - x: 0, - y: bounds.size.height - 0.5, - width: bounds.size.width, - height: 0.5 - ) - ) - view?.autoresizingMask = [.flexibleWidth, .flexibleTopMargin] - view?.tag = STPTableViewCellBottomBorderTag - view?.backgroundColor = backgroundColor - view?.isHidden = true - view?.accessibilityIdentifier = "stp_bottomBorderView" - if let view = view { - addSubview(view) - } - } - return view - } - - func stp_fakeSeparatorView() -> UIView? { - var view = viewWithTag(STPTableViewCellFakeSeparatorTag) - if view == nil { - view = UIView( - frame: CGRect( - x: 0, - y: bounds.size.height - 0.5, - width: bounds.size.width, - height: 0.5 - ) - ) - view?.autoresizingMask = [.flexibleWidth, .flexibleTopMargin] - view?.tag = STPTableViewCellFakeSeparatorTag - view?.backgroundColor = backgroundColor - view?.accessibilityIdentifier = "stp_fakeSeparatorView" - if let view = view { - addSubview(view) - } - } - return view - } -} diff --git a/Stripe/StripeiOS/Source/UIToolbar+Stripe_InputAccessory.swift b/Stripe/StripeiOS/Source/UIToolbar+Stripe_InputAccessory.swift deleted file mode 100644 index 4194764e07b..00000000000 --- a/Stripe/StripeiOS/Source/UIToolbar+Stripe_InputAccessory.swift +++ /dev/null @@ -1,38 +0,0 @@ -// -// UIToolbar+Stripe_InputAccessory.swift -// StripeiOS -// -// Created by Jack Flintermann on 4/22/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -import UIKit - -extension UIToolbar { - @objc(stp_inputAccessoryToolbarWithTarget:action:) class func stp_inputAccessoryToolbar( - withTarget target: Any?, - action: Selector - ) -> Self { - let toolbar = self.init() - let flexibleItem = UIBarButtonItem( - barButtonSystemItem: .flexibleSpace, - target: nil, - action: nil - ) - let nextItem = UIBarButtonItem( - title: STPLocalizedString("Next", "Button to move to the next text entry field"), - style: .done, - target: target, - action: action - ) - toolbar.items = [flexibleItem, nextItem] - toolbar.autoresizingMask = .flexibleHeight - return toolbar - } - - @objc(stp_setEnabled:) func stp_setEnabled(_ enabled: Bool) { - for barButtonItem in items ?? [] { - barButtonItem.isEnabled = enabled - } - } -} diff --git a/Stripe/StripeiOS/Source/UIView+Stripe_FirstResponder.swift b/Stripe/StripeiOS/Source/UIView+Stripe_FirstResponder.swift deleted file mode 100644 index 40267b0ac4c..00000000000 --- a/Stripe/StripeiOS/Source/UIView+Stripe_FirstResponder.swift +++ /dev/null @@ -1,24 +0,0 @@ -// -// UIView+Stripe_FirstResponder.swift -// StripeiOS -// -// Created by Jack Flintermann on 4/15/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -import UIKit - -extension UIView { - @objc func stp_findFirstResponder() -> UIView? { - if isFirstResponder { - return self - } - for subView in subviews { - let responder = subView.stp_findFirstResponder() - if let responder = responder { - return responder - } - } - return nil - } -} diff --git a/Stripe/StripeiOS/Source/UIView+Stripe_SafeAreaBounds.swift b/Stripe/StripeiOS/Source/UIView+Stripe_SafeAreaBounds.swift deleted file mode 100644 index d29b49b8d88..00000000000 --- a/Stripe/StripeiOS/Source/UIView+Stripe_SafeAreaBounds.swift +++ /dev/null @@ -1,24 +0,0 @@ -// -// UIView+Stripe_SafeAreaBounds.swift -// StripeiOS -// -// Created by Ben Guo on 12/12/17. -// Copyright © 2017 Stripe, Inc. All rights reserved. -// - -import UIKit - -extension UIView { - /// Returns this view's bounds inset to `safeAreaInsets.left` and `safeAreaInsets.right`. - /// Top and bottom safe area insets are ignored. On iOS <11, this returns self.bounds. - @objc func stp_boundsWithHorizontalSafeAreaInsets() -> CGRect { - let insets = safeAreaInsets - let safeBounds = CGRect( - x: bounds.origin.x + insets.left, - y: bounds.origin.y, - width: bounds.size.width - (insets.left + insets.right), - height: bounds.size.height - ) - return safeBounds - } -} diff --git a/Stripe/StripeiOS/Source/UIViewController+Stripe_KeyboardAvoiding.swift b/Stripe/StripeiOS/Source/UIViewController+Stripe_KeyboardAvoiding.swift deleted file mode 100644 index ce6408dc5ca..00000000000 --- a/Stripe/StripeiOS/Source/UIViewController+Stripe_KeyboardAvoiding.swift +++ /dev/null @@ -1,166 +0,0 @@ -// -// UIViewController+Stripe_KeyboardAvoiding.swift -// StripeiOS -// -// Created by Jack Flintermann on 4/15/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -import UIKit - -typealias STPKeyboardFrameBlock = (CGRect, UIView?) -> Void -extension UIViewController { - @objc(stp_beginObservingKeyboardAndInsettingScrollView:onChangeBlock:) - func stp_beginObservingKeyboardAndInsettingScrollView( - _ scrollView: UIScrollView?, - onChange block: STPKeyboardFrameBlock? - ) { - if let existing = stp_keyboardDetectingViewController() { - existing.removeFromParent() - existing.view.removeFromSuperview() - existing.didMove(toParent: nil) - } - let keyboardAvoiding = STPKeyboardDetectingViewController( - keyboardFrameBlock: block, - scrollView: scrollView - ) - addChild(keyboardAvoiding) - view.addSubview(keyboardAvoiding.view) - keyboardAvoiding.didMove(toParent: self) - } - - @objc func stp_keyboardDetectingViewController() -> STPKeyboardDetectingViewController? { - return - (children as NSArray).filtered( - using: NSPredicate(block: { viewController, _ in - return viewController is STPKeyboardDetectingViewController - }) - ).first as? STPKeyboardDetectingViewController - } -} - -// This is a private class that is only a UIViewController subclass by virtue of the fact -// that that makes it easier to attach to another UIViewController as a child. -class STPKeyboardDetectingViewController: UIViewController { - var lastKeyboardFrame = CGRect.zero - weak var lastResponder: UIView? - var keyboardFrameBlock: STPKeyboardFrameBlock? - weak var managedScrollView: UIScrollView? - var currentBottomInsetChange: CGFloat = 0.0 - - init( - keyboardFrameBlock block: STPKeyboardFrameBlock?, - scrollView: UIScrollView? - ) { - keyboardFrameBlock = block - super.init(nibName: nil, bundle: nil) - NotificationCenter.default.addObserver( - self, - selector: #selector(keyboardWillChangeFrame(_:)), - name: UIResponder.keyboardWillChangeFrameNotification, - object: nil - ) - NotificationCenter.default.addObserver( - self, - selector: #selector(textFieldWillBeginEditing(_:)), - name: UITextField.textDidBeginEditingNotification, - object: nil - ) - managedScrollView = scrollView - currentBottomInsetChange = 0 - } - - deinit { - NotificationCenter.default.removeObserver(self) - } - - override func loadView() { - let view = UIView() - view.backgroundColor = UIColor.clear - view.autoresizingMask = [] - self.view = view - } - - @objc func textFieldWillBeginEditing(_ notification: Notification) { - guard let textField = notification.object as? UITextField, let parentView = parent?.view, - textField.isDescendant(of: parentView) - else { - return - } - if let keyboardFrameBlock = keyboardFrameBlock, - textField != lastResponder && !lastKeyboardFrame.isEmpty - { - UIView.animate( - withDuration: 0.3, - delay: 0, - options: .curveEaseOut, - animations: { - keyboardFrameBlock(self.lastKeyboardFrame, textField) - } - ) - } - } - - @objc func keyboardWillChangeFrame(_ notification: Notification) { - // As of iOS 8, this all takes place inside the necessary animation block - // https://twitter.com/SmileyKeith/status/684100833823174656 - guard - var keyboardFrame = - (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)? - .cgRectValue, - let window = view.window - else { - return - } - keyboardFrame = window.convert(keyboardFrame, from: nil) - - if managedScrollView != nil { - if !lastKeyboardFrame.equalTo(keyboardFrame) { - let responder = parent?.view.stp_findFirstResponder() - lastResponder = responder - doKeyboardChangeAnimation(withNewFrame: keyboardFrame) - } - } - } - - func doKeyboardChangeAnimation(withNewFrame keyboardFrame: CGRect) { - lastKeyboardFrame = keyboardFrame - - if let managedScrollView = managedScrollView { - let scrollView = managedScrollView - let scrollViewSuperView = managedScrollView.superview - - var contentInsets = scrollView.contentInset - var scrollIndicatorInsets: UIEdgeInsets = .zero - #if !TARGET_OS_MACCATALYST - scrollIndicatorInsets = scrollView.verticalScrollIndicatorInsets - #else - scrollIndicatorInsets = scrollView.scrollIndicatorInsets - #endif - - let windowFrame = scrollViewSuperView?.convert( - scrollViewSuperView?.frame ?? CGRect.zero, - to: nil - ) - - let bottomIntersection = windowFrame?.intersection(keyboardFrame) - let bottomInsetDelta = - (bottomIntersection?.size.height ?? 0.0) - currentBottomInsetChange - contentInsets.bottom += bottomInsetDelta - scrollIndicatorInsets.bottom += bottomInsetDelta - currentBottomInsetChange += bottomInsetDelta - scrollView.contentInset = contentInsets - scrollView.scrollIndicatorInsets = scrollIndicatorInsets - } - - if let keyboardFrameBlock = keyboardFrameBlock { - keyboardFrameBlock(keyboardFrame, lastResponder) - } - } - - required init?( - coder aDecoder: NSCoder - ) { - super.init(coder: aDecoder) - } -} diff --git a/Stripe/StripeiOS/Source/UIViewController+Stripe_NavigationItemProxy.swift b/Stripe/StripeiOS/Source/UIViewController+Stripe_NavigationItemProxy.swift deleted file mode 100644 index 0b5fd9ee767..00000000000 --- a/Stripe/StripeiOS/Source/UIViewController+Stripe_NavigationItemProxy.swift +++ /dev/null @@ -1,38 +0,0 @@ -// -// UIViewController+Stripe_NavigationItemProxy.swift -// StripeiOS -// -// Created by Jack Flintermann on 6/9/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -import ObjectiveC -import UIKit - -extension UIViewController { - @objc var stp_navigationItemProxy: UINavigationItem? { - get { - return objc_getAssociatedObject(self, UnsafeRawPointer(&kSTPNavigationItemProxyKey)) - as? UINavigationItem ?? self.navigationItem - } - set(stp_navigationItemProxy) { - objc_setAssociatedObject( - self, - UnsafeRawPointer(&kSTPNavigationItemProxyKey), - stp_navigationItemProxy, - .OBJC_ASSOCIATION_RETAIN_NONATOMIC - ) - if navigationItem.leftBarButtonItem != nil { - stp_navigationItemProxy?.leftBarButtonItem = navigationItem.leftBarButtonItem - } - if navigationItem.rightBarButtonItem != nil { - stp_navigationItemProxy?.rightBarButtonItem = navigationItem.rightBarButtonItem - } - if navigationItem.title != nil { - stp_navigationItemProxy?.title = navigationItem.title - } - } - } -} - -private var kSTPNavigationItemProxyKey = 0 diff --git a/Stripe/StripeiOS/Source/UIViewController+Stripe_ParentViewController.swift b/Stripe/StripeiOS/Source/UIViewController+Stripe_ParentViewController.swift deleted file mode 100644 index 534172cbd69..00000000000 --- a/Stripe/StripeiOS/Source/UIViewController+Stripe_ParentViewController.swift +++ /dev/null @@ -1,50 +0,0 @@ -// -// UIViewController+Stripe_ParentViewController.swift -// StripeiOS -// -// Created by Jack Flintermann on 1/12/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -import UIKit - -extension UIViewController { - @objc(stp_parentViewControllerOfClass:) func stp_parentViewControllerOf( - _ klass: AnyClass - ) - -> UIViewController? - { - if let parent = parent, parent.isKind(of: klass) { - return parent - } - return parent?.stp_parentViewControllerOf(klass) - } - - @objc func stp_isTopNavigationController() -> Bool { - return navigationController?.topViewController == self - } - - @objc func stp_isAtRootOfNavigationController() -> Bool { - let viewController = navigationController?.viewControllers.first - var tested: UIViewController? = self - while tested != nil { - if tested == viewController { - return true - } - if let parent = tested?.parent { - tested = parent - } else { - return false - } - } - return false - } - - @objc func stp_previousViewControllerInNavigation() -> UIViewController? { - let index = navigationController?.viewControllers.firstIndex(of: self) ?? NSNotFound - if index == NSNotFound || index <= 0 { - return nil - } - return navigationController?.viewControllers[index - 1] - } -} diff --git a/Stripe/StripeiOS/Source/UserDefaults+Stripe.swift b/Stripe/StripeiOS/Source/UserDefaults+Stripe.swift deleted file mode 100644 index 72ee855f753..00000000000 --- a/Stripe/StripeiOS/Source/UserDefaults+Stripe.swift +++ /dev/null @@ -1,29 +0,0 @@ -// -// UserDefaults+Stripe.swift -// StripeiOS -// -// Created by Yuki Tokuhiro on 5/21/21. -// Copyright © 2021 Stripe, Inc. All rights reserved. -// - -import Foundation - -extension UserDefaults { - /// Canonical list of all UserDefaults keys the SDK uses - @_spi(STP) public enum StripeKeys: String { - /// The key for a dictionary of Customer id to their last selected payment method ID - case customerToLastSelectedPaymentMethod = "com.stripe.lib:STPStripeCustomerToLastSelectedPaymentMethodKey" - } - - @_spi(STP) public var customerToLastSelectedPaymentMethod: [String: String]? { - get { - let key = StripeKeys.customerToLastSelectedPaymentMethod.rawValue - return dictionary(forKey: key) as? [String: String] - } - set { - let key = StripeKeys.customerToLastSelectedPaymentMethod.rawValue - setValue(newValue, forKey: key) - } - } - -} diff --git a/Stripe/StripeiOSTests/FBSnapshotTestCase+STPViewControllerLoading.swift b/Stripe/StripeiOSTests/FBSnapshotTestCase+STPViewControllerLoading.swift index 3b75e218782..19fdc5781ea 100644 --- a/Stripe/StripeiOSTests/FBSnapshotTestCase+STPViewControllerLoading.swift +++ b/Stripe/StripeiOSTests/FBSnapshotTestCase+STPViewControllerLoading.swift @@ -40,40 +40,4 @@ extension FBSnapshotTestCase { return navController } - /// Returns a view for snapshot testing from the topViewController of the given - /// navigation controller, making necessary layout adjustments for - /// `STPCoreScrollViewController`. - @objc(stp_preparedAndSizedViewForSnapshotTestFromNavigationController:) - func stp_preparedAndSizedViewForSnapshotTest( - from navController: UINavigationController? - ) - -> UIView? - { - let viewController = navController?.topViewController - - // Test that views loaded properly + loads them on first call - XCTAssertNotNil(navController?.view) - XCTAssertNotNil(viewController?.view) - - if viewController is STPCoreScrollViewController { - guard let scrollView = (viewController as? STPCoreScrollViewController)?.scrollView, - let navController = navController - else { - return nil - } - navController.view.layoutIfNeeded() - - let topOffset = scrollView.convert(scrollView.frame.origin, to: navController.view).y - navController.view.frame = CGRect( - x: 0, - y: 0, - width: 320, - height: (topOffset) + (scrollView.contentSize.height) - + (scrollView.contentInset.top) - + (scrollView.contentInset.bottom) - ) - } - - return navController?.view - } } diff --git a/Stripe/StripeiOSTests/NSDecimalNumber+StripeTest.swift b/Stripe/StripeiOSTests/NSDecimalNumber+StripeTest.swift index 33ae8d48bf4..0f4cf48572a 100644 --- a/Stripe/StripeiOSTests/NSDecimalNumber+StripeTest.swift +++ b/Stripe/StripeiOSTests/NSDecimalNumber+StripeTest.swift @@ -77,27 +77,4 @@ class NSDecimalNumberStripeTest: XCTestCase { } } - func testAmount_twoDecimal() { - for twoDecimalPointCurrency in twoDecimalPointCurrencies { - let amount = NSDecimalNumber(value: 1000.12) - let decimalNumber = amount.stp_amount(withCurrency: twoDecimalPointCurrency) - XCTAssertEqual(decimalNumber, 100012) - } - } - - func testAmount_noDecimal() { - for noDecimalPointCurrency in noDecimalPointCurrencies { - let amount = NSDecimalNumber(value: 1000.12) - let decimalNumber = amount.stp_amount(withCurrency: noDecimalPointCurrency) - XCTAssertEqual(decimalNumber, 1000) - } - } - - func testAmount_threeDecimal() { - for threeDecimalPointCurrency in threeDecimalCurrencies { - let amount = NSDecimalNumber(value: 1000.12) - let decimalNumber = amount.stp_amount(withCurrency: threeDecimalPointCurrency) - XCTAssertEqual(decimalNumber, 1000120) - } - } } diff --git a/Stripe/StripeiOSTests/PaymentAnalyticTest.swift b/Stripe/StripeiOSTests/PaymentAnalyticTest.swift deleted file mode 100644 index b0ead1408bd..00000000000 --- a/Stripe/StripeiOSTests/PaymentAnalyticTest.swift +++ /dev/null @@ -1,30 +0,0 @@ -// -// PaymentAnalyticTest.swift -// StripeiOS Tests -// -// Created by Mel Ludowise on 5/26/21. -// Copyright © 2021 Stripe, Inc. All rights reserved. -// - -@_spi(STP) import StripeCore -import XCTest - -@testable@_spi(STP) import Stripe -@testable@_spi(STP) import StripeCore -@testable@_spi(STP) import StripePayments -@testable@_spi(STP) import StripePaymentSheet -@testable@_spi(STP) import StripePaymentsUI - -final class PaymentAnalyticTest: XCTestCase { - - func testParams() { - let analytic = GenericPaymentAnalytic( - event: .cardScanCancelled, - paymentConfiguration: STPPaymentConfiguration(), - additionalParams: [:] - ) - - XCTAssertNotNil(analytic.params["apple_pay_enabled"] as? NSNumber) - XCTAssertNotNil(analytic.params["ocr_type"] as? String) - } -} diff --git a/Stripe/StripeiOSTests/STPAPIClientTest.swift b/Stripe/StripeiOSTests/STPAPIClientTest.swift index 656381cf113..24f19f618cf 100644 --- a/Stripe/StripeiOSTests/STPAPIClientTest.swift +++ b/Stripe/StripeiOSTests/STPAPIClientTest.swift @@ -90,22 +90,6 @@ class STPAPIClientTest: XCTestCase { XCTAssertEqual(accountHeader, "acct_123") } - func testInitWithConfiguration() { - let config = STPPaymentConfiguration() - config.publishableKey = "pk_123" - config.stripeAccount = "acct_123" - - let sut = STPAPIClient(configuration: config) - XCTAssertEqual(sut.publishableKey, config.publishableKey) - XCTAssertEqual(sut.stripeAccount, config.stripeAccount) - - let accountHeader = sut.configuredRequest( - for: URL(string: "https://www.stripe.com")!, - additionalHeaders: [:] - ).allHTTPHeaderFields?["Stripe-Account"] - XCTAssertEqual(accountHeader, "acct_123") - } - private struct MockUAUsageClass: STPAnalyticsProtocol { static let stp_analyticsIdentifier = "MockUAUsageClass" } @@ -115,10 +99,10 @@ class STPAPIClientTest: XCTestCase { STPAnalyticsClient.sharedClient.addClass(toProductUsageIfNecessary: MockUAUsageClass.self) var params: [String: Any] = [:] params = STPAPIClient.paramsAddingPaymentUserAgent(params) - XCTAssertEqual(params["payment_user_agent"] as! String, "stripe-ios/\(StripeAPIConfiguration.STPSDKVersion); variant.legacy; MockUAUsageClass") + XCTAssertEqual(params["payment_user_agent"] as! String, "stripe-ios/\(StripeAPIConfiguration.STPSDKVersion); variant.paymentsheet; MockUAUsageClass") params = STPAPIClient.paramsAddingPaymentUserAgent(params, additionalValues: ["foo"]) - XCTAssertEqual(params["payment_user_agent"] as! String, "stripe-ios/\(StripeAPIConfiguration.STPSDKVersion); variant.legacy; MockUAUsageClass; foo") + XCTAssertEqual(params["payment_user_agent"] as! String, "stripe-ios/\(StripeAPIConfiguration.STPSDKVersion); variant.paymentsheet; MockUAUsageClass; foo") } func testSetAppInfo() { diff --git a/Stripe/StripeiOSTests/STPAPISettingsObjCBridgeTest.m b/Stripe/StripeiOSTests/STPAPISettingsObjCBridgeTest.m deleted file mode 100644 index 046c294a1d2..00000000000 --- a/Stripe/StripeiOSTests/STPAPISettingsObjCBridgeTest.m +++ /dev/null @@ -1,84 +0,0 @@ -// -// STPObjcBridgeTest.m -// StripeiOS Tests -// -// Created by David Estes on 9/21/21. -// Copyright © 2021 Stripe, Inc. All rights reserved. -// - -@import Stripe; -@import XCTest; -@import PassKit; -@import StripePaymentsObjcTestUtils; - -@interface StripeAPIBridgeTest : XCTestCase - -@end - -@implementation StripeAPIBridgeTest - -- (void)testStripeAPIBridge { - NSString *testKey = @"pk_test_123"; - StripeAPI.defaultPublishableKey = testKey; - XCTAssertEqualObjects(StripeAPI.defaultPublishableKey, testKey); - StripeAPI.defaultPublishableKey = nil; - - StripeAPI.advancedFraudSignalsEnabled = NO; - XCTAssertFalse(StripeAPI.advancedFraudSignalsEnabled); - StripeAPI.advancedFraudSignalsEnabled = YES; - - - StripeAPI.maxRetries = 2; - XCTAssertEqual(StripeAPI.maxRetries, 2); - StripeAPI.maxRetries = 3; - - // Check that this at least doesn't crash - [StripeAPI handleStripeURLCallbackWithURL:[NSURL URLWithString:@"https://example.com"]]; - - StripeAPI.jcbPaymentNetworkSupported = YES; - XCTAssertTrue(StripeAPI.jcbPaymentNetworkSupported); - StripeAPI.jcbPaymentNetworkSupported = NO; - - StripeAPI.additionalEnabledApplePayNetworks = @[PKPaymentNetworkJCB]; - XCTAssertTrue([StripeAPI.additionalEnabledApplePayNetworks containsObject:PKPaymentNetworkJCB]); - StripeAPI.additionalEnabledApplePayNetworks = @[]; - - PKPaymentRequest *request = [StripeAPI paymentRequestWithMerchantIdentifier:@"test" country:@"US" currency:@"USD"]; - request.paymentSummaryItems = @[[PKPaymentSummaryItem summaryItemWithLabel:@"bar" amount:[NSDecimalNumber decimalNumberWithString:@"1.00"]]]; - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wdeprecated" - PKPaymentRequest *request2 = [StripeAPI paymentRequestWithMerchantIdentifier:@"test"]; - request2.paymentSummaryItems = @[[PKPaymentSummaryItem summaryItemWithLabel:@"bar" amount:[NSDecimalNumber decimalNumberWithString:@"1.00"]]]; - #pragma clang diagnostic pop - - XCTAssertTrue([StripeAPI canSubmitPaymentRequest:request]); - XCTAssertTrue([StripeAPI canSubmitPaymentRequest:request2]); - - XCTAssertTrue([StripeAPI deviceSupportsApplePay]); -} - -- (void)testSTPAPIClientBridgeKeys { - NSString *testKey = @"pk_test_123"; - StripeAPI.defaultPublishableKey = testKey; - XCTAssertEqualObjects(testKey, StripeAPI.defaultPublishableKey); - StripeAPI.defaultPublishableKey = nil; -} - -- (void)testSTPAPIClientBridgeSettings { - STPAPIClient *client = [[STPAPIClient alloc] initWithPublishableKey:@"pk_test_123"]; - STPPaymentConfiguration *config = [[STPPaymentConfiguration alloc] init]; - client.configuration = config; - XCTAssertEqual(config, client.configuration); - - NSString *stripeAccount = @"acct_123"; - client.stripeAccount = stripeAccount; - XCTAssertEqualObjects(stripeAccount, client.stripeAccount); - - STPAppInfo *appInfo = [[STPAppInfo alloc] initWithName:@"test" partnerId:@"abc123" version:@"1.0" url:@"https://example.com"]; - client.appInfo = appInfo; - XCTAssertEqualObjects(appInfo.name, client.appInfo.name); - - XCTAssertNotNil(STPAPIClient.apiVersion); -} - -@end diff --git a/Stripe/StripeiOSTests/STPAddCardViewControllerLocalizationSnapshotTests.swift b/Stripe/StripeiOSTests/STPAddCardViewControllerLocalizationSnapshotTests.swift deleted file mode 100644 index 9ebaf74d8a0..00000000000 --- a/Stripe/StripeiOSTests/STPAddCardViewControllerLocalizationSnapshotTests.swift +++ /dev/null @@ -1,101 +0,0 @@ -// -// STPAddCardViewControllerLocalizationSnapshotTests.swift -// StripeiOS Tests -// -// Created by Brian Dorfman on 10/17/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -import iOSSnapshotTestCase -import StripeCoreTestUtils - -@testable@_spi(STP) import Stripe -@testable@_spi(STP) import StripeCore -@testable@_spi(STP) import StripePayments -@testable@_spi(STP) import StripePaymentSheet -@testable@_spi(STP) import StripePaymentsUI - -class STPAddCardViewControllerLocalizationSnapshotTests: STPSnapshotTestCase { - func performSnapshotTest(forLanguage language: String?, delivery: Bool) { - let config = STPPaymentConfiguration() - config.companyName = "Test Company" - config.requiredBillingAddressFields = .full - config.shippingType = delivery ? .delivery : .shipping - config.cardScanningEnabled = true - STPLocalizationUtils.overrideLanguage(to: language) - - let addCardVC = STPAddCardViewController( - configuration: config, - theme: STPTheme.defaultTheme - ) - addCardVC.shippingAddress = STPAddress() - addCardVC.shippingAddress?.line1 = "1" // trigger "use shipping address" button - - let viewToTest = stp_preparedAndSizedViewForSnapshotTest(from: addCardVC)! - - if delivery { - addCardVC.addressViewModel.addressFieldTableViewCountryCode = "INVALID" - STPSnapshotVerifyView(viewToTest, identifier: "delivery") - } else { - // This method rejects nil or empty country codes to stop strange looking behavior - // when scrolling to the top "unset" position in the picker, so put in - // an invalid country code instead to test seeing the "Country" placeholder - addCardVC.addressViewModel.addressFieldTableViewCountryCode = "INVALID" - STPSnapshotVerifyView(viewToTest, identifier: "no_country") - - addCardVC.addressViewModel.addressFieldTableViewCountryCode = "US" - STPSnapshotVerifyView(viewToTest, identifier: "US") - - addCardVC.addressViewModel.addressFieldTableViewCountryCode = "GB" - STPSnapshotVerifyView(viewToTest, identifier: "GB") - - addCardVC.addressViewModel.addressFieldTableViewCountryCode = "CA" - STPSnapshotVerifyView(viewToTest, identifier: "CA") - - addCardVC.addressViewModel.addressFieldTableViewCountryCode = "MX" - STPSnapshotVerifyView(viewToTest, identifier: "MX") - } - - STPLocalizationUtils.overrideLanguage(to: nil) - } - - func testGerman() { - performSnapshotTest(forLanguage: "de", delivery: false) - performSnapshotTest(forLanguage: "de", delivery: true) - } - - func testEnglish() { - performSnapshotTest(forLanguage: "en", delivery: false) - performSnapshotTest(forLanguage: "en", delivery: true) - } - - func testSpanish() { - performSnapshotTest(forLanguage: "es", delivery: false) - performSnapshotTest(forLanguage: "es", delivery: true) - } - - func testFrench() { - performSnapshotTest(forLanguage: "fr", delivery: false) - performSnapshotTest(forLanguage: "fr", delivery: true) - } - - func testItalian() { - performSnapshotTest(forLanguage: "it", delivery: false) - performSnapshotTest(forLanguage: "it", delivery: true) - } - - func testJapanese() { - performSnapshotTest(forLanguage: "ja", delivery: false) - performSnapshotTest(forLanguage: "ja", delivery: true) - } - - func testDutch() { - performSnapshotTest(forLanguage: "nl", delivery: false) - performSnapshotTest(forLanguage: "nl", delivery: true) - } - - func testChinese() { - performSnapshotTest(forLanguage: "zh-Hans", delivery: false) - performSnapshotTest(forLanguage: "zh-Hans", delivery: true) - } -} diff --git a/Stripe/StripeiOSTests/STPAddCardViewControllerTest.swift b/Stripe/StripeiOSTests/STPAddCardViewControllerTest.swift deleted file mode 100644 index 16b50807c90..00000000000 --- a/Stripe/StripeiOSTests/STPAddCardViewControllerTest.swift +++ /dev/null @@ -1,290 +0,0 @@ -// -// STPAddCardViewControllerTest.swift -// StripeiOS Tests -// -// Created by Ben Guo on 7/5/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -import OHHTTPStubs -import OHHTTPStubsSwift -import StripeCoreTestUtils - -@testable@_spi(STP) import Stripe -@testable@_spi(STP) import StripeCore -@testable@_spi(STP) import StripePayments -@testable@_spi(STP) import StripePaymentSheet -@testable@_spi(STP) import StripePaymentsUI - -class MockDelegate: NSObject, STPAddCardViewControllerDelegate { - func addCardViewControllerDidCancel(_ addCardViewController: STPAddCardViewController) { - - } - - var addCardViewControllerDidCreatePaymentMethodBlock: - (STPAddCardViewController, STPPaymentMethod, STPErrorBlock) -> Void = { _, _, _ in } - func addCardViewController( - _ addCardViewController: STPAddCardViewController, - didCreatePaymentMethod paymentMethod: STPPaymentMethod, - completion: @escaping STPErrorBlock - ) { - addCardViewControllerDidCreatePaymentMethodBlock( - addCardViewController, - paymentMethod, - completion - ) - } -} - -class STPAddCardViewControllerTest: APIStubbedTestCase { - - func paymentMethodAPIFilter( - expectedCardParams: STPPaymentMethodCardParams, - urlRequest: URLRequest - ) -> Bool { - if urlRequest.url?.absoluteString.contains("payment_methods") ?? false { - let cardNumber = urlRequest.queryItems?.first(where: { item in - item.name == "card[number]" - }) - XCTAssertEqual(cardNumber!.value, expectedCardParams.number) - return true - } - return false - } - - func buildAddCardViewController() -> STPAddCardViewController? { - let config = STPPaymentConfiguration() - let theme = STPTheme.defaultTheme - let vc = STPAddCardViewController( - configuration: config, - theme: theme - ) - XCTAssertNotNil(vc.view) - return vc - } - - func testPrefilledBillingAddress_removeAddress() { - let config = STPPaymentConfiguration() - config.requiredBillingAddressFields = .postalCode - let sut = STPAddCardViewController( - configuration: config, - theme: STPTheme.defaultTheme - ) - let address = STPAddress() - address.name = "John Smith Doe" - address.phone = "8885551212" - address.email = "foo@example.com" - address.line1 = "55 John St" - address.city = "Harare" - address.postalCode = "10002" - // Zimbabwe does not require zip codes, while the default locale for tests (US) does - address.country = "ZW" - // Sanity checks - XCTAssertFalse(STPPostalCodeValidator.postalCodeIsRequired(forCountryCode: "ZW")) - XCTAssertTrue(STPPostalCodeValidator.postalCodeIsRequired(forCountryCode: "US")) - - let prefilledInfo = STPUserInformation() - prefilledInfo.billingAddress = address - sut.prefilledInformation = prefilledInfo - - XCTAssertNoThrow(sut.loadView()) - XCTAssertNoThrow(sut.viewDidLoad()) - } - - func testPrefilledBillingAddress_viewDidLoadHappensBeforeSettingAddress() { - let config = STPPaymentConfiguration() - config.requiredBillingAddressFields = .full - let sut = STPAddCardViewController( - configuration: config, - theme: STPTheme.defaultTheme - ) - XCTAssertNoThrow(sut.loadView()) - XCTAssertNoThrow(sut.viewDidLoad()) - - let address = STPAddress() - address.name = "John Smith Doe" - address.line1 = "55 John St" - address.city = "Harare" - address.postalCode = "10002" - - let prefilledInfo = STPUserInformation() - prefilledInfo.billingAddress = address - sut.prefilledInformation = prefilledInfo - - let nameCell = sut.addressViewModel.addressCells.first { $0.type == .name }! - XCTAssertEqual( nameCell.contents, "John Smith Doe") - - let line1Cell = sut.addressViewModel.addressCells.first { $0.type == .line1 }! - XCTAssertEqual( line1Cell.contents, "55 John St") - - let cityCell = sut.addressViewModel.addressCells.first { $0.type == .city }! - XCTAssertEqual( cityCell.contents, "Harare") - - let zipCell = sut.addressViewModel.addressCells.first { $0.type == .zip }! - XCTAssertEqual( zipCell.contents, "10002") - } - - func testPrefilledBillingAddress_addAddress() { - // Zimbabwe does not require zip codes, while the default locale for tests (US) does - NSLocale.stp_withLocale(as: NSLocale(localeIdentifier: "en_ZW")) { - // Sanity checks - XCTAssertFalse(STPPostalCodeValidator.postalCodeIsRequired(forCountryCode: "ZW")) - XCTAssertTrue(STPPostalCodeValidator.postalCodeIsRequired(forCountryCode: "US")) - let config = STPPaymentConfiguration() - config.requiredBillingAddressFields = .postalCode - let sut = STPAddCardViewController( - configuration: config, - theme: STPTheme.defaultTheme - ) - let address = STPAddress() - address.name = "John Smith Doe" - address.phone = "8885551212" - address.email = "foo@example.com" - address.line1 = "55 John St" - address.city = "New York" - address.state = "NY" - address.postalCode = "10002" - address.country = "US" - - let prefilledInfo = STPUserInformation() - prefilledInfo.billingAddress = address - sut.prefilledInformation = prefilledInfo - - XCTAssertNoThrow(sut.loadView()) - XCTAssertNoThrow(sut.viewDidLoad()) - } - } - - func testNextWithCreatePaymentMethodError() { - let sut = buildAddCardViewController()! - let expectedCardParams = STPFixtures.paymentMethodCardParams() - sut.paymentCell?.paymentField!.perform(NSSelectorFromString("setCardParams:"), with: expectedCardParams) - - let exp = expectation(description: "createPaymentMethodWithCard network request") - stub { urlRequest in - return self.paymentMethodAPIFilter( - expectedCardParams: expectedCardParams, - urlRequest: urlRequest - ) - } response: { _ in - XCTAssertTrue(sut.loading) - let paymentMethod = ["error": "intentionally_invalid"] - defer { - exp.fulfill() - } - return HTTPStubsResponse(jsonObject: paymentMethod, statusCode: 200, headers: nil) - } - sut.apiClient = stubbedAPIClient() - // tap next button - let nextButton = sut.navigationItem.rightBarButtonItem - _ = nextButton?.target?.perform(nextButton?.action, with: nextButton) - - waitForExpectations(timeout: 2, handler: nil) - - // It takes a few more spins on the runloop before we get a response from - // the HTTP stubs, so we'll wait 0.5 seconds before checking the loading indicator. - let loadExp = expectation(description: "loading has stopped") - DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { - XCTAssertFalse(sut.loading) - loadExp.fulfill() - } - waitForExpectations(timeout: 1, handler: nil) - } - - func testNextWithCreatePaymentMethodSuccessAndDidCreatePaymentMethodError() { - let sut = buildAddCardViewController()! - let createPaymentMethodExp = expectation(description: "createPaymentMethodWithCard") - - let expectedCardParams = STPFixtures.paymentMethodCardParams() - let expectedPaymentMethod = STPFixtures.paymentMethod() - let expectedPaymentMethodData = STPFixtures.paymentMethodJSON() - - stub { urlRequest in - return self.paymentMethodAPIFilter( - expectedCardParams: expectedCardParams, - urlRequest: urlRequest - ) - } response: { _ in - XCTAssertTrue(sut.loading) - defer { - createPaymentMethodExp.fulfill() - } - return HTTPStubsResponse( - jsonObject: expectedPaymentMethodData, - statusCode: 200, - headers: nil - ) - } - - let mockDelegate = MockDelegate() - sut.apiClient = stubbedAPIClient() - sut.delegate = mockDelegate - sut.paymentCell?.paymentField!.perform(NSSelectorFromString("setCardParams:"), with: expectedCardParams) - - let didCreatePaymentMethodExp = expectation(description: "didCreatePaymentMethod") - - mockDelegate.addCardViewControllerDidCreatePaymentMethodBlock = { - (_, paymentMethod, completion) in - XCTAssertTrue(sut.loading) - let error = NSError.stp_genericFailedToParseResponseError() - XCTAssertEqual(paymentMethod.stripeId, expectedPaymentMethod.stripeId) - completion(error) - XCTAssertFalse(sut.loading) - didCreatePaymentMethodExp.fulfill() - } - - // tap next button - let nextButton = sut.navigationItem.rightBarButtonItem - _ = nextButton?.target?.perform(nextButton?.action, with: nextButton) - - waitForExpectations(timeout: 2, handler: nil) - } - - func testNextWithCreateTokenSuccessAndDidCreateTokenSuccess() { - let sut = buildAddCardViewController()! - - let createPaymentMethodExp = expectation(description: "createPaymentMethodWithCard") - - let expectedCardParams = STPFixtures.paymentMethodCardParams() - let expectedPaymentMethod = STPFixtures.paymentMethod() - let expectedPaymentMethodData = STPFixtures.paymentMethodJSON() - - stub { urlRequest in - return self.paymentMethodAPIFilter( - expectedCardParams: expectedCardParams, - urlRequest: urlRequest - ) - } response: { _ in - XCTAssertTrue(sut.loading) - defer { - createPaymentMethodExp.fulfill() - } - return HTTPStubsResponse( - jsonObject: expectedPaymentMethodData, - statusCode: 200, - headers: nil - ) - } - - let mockDelegate = MockDelegate() - sut.apiClient = stubbedAPIClient() - sut.delegate = mockDelegate - sut.paymentCell?.paymentField!.perform(NSSelectorFromString("setCardParams:"), with: expectedCardParams) - - let didCreatePaymentMethodExp = expectation(description: "didCreatePaymentMethod") - mockDelegate.addCardViewControllerDidCreatePaymentMethodBlock = { - (_, paymentMethod, completion) in - XCTAssertTrue(sut.loading) - XCTAssertEqual(paymentMethod.stripeId, expectedPaymentMethod.stripeId) - completion(nil) - XCTAssertFalse(sut.loading) - didCreatePaymentMethodExp.fulfill() - } - - // tap next button - let nextButton = sut.navigationItem.rightBarButtonItem - _ = nextButton?.target?.perform(nextButton?.action, with: nextButton) - - waitForExpectations(timeout: 2, handler: nil) - } -} diff --git a/Stripe/StripeiOSTests/STPAddressTests.swift b/Stripe/StripeiOSTests/STPAddressTests.swift index 9817de5102a..d89f70d1849 100644 --- a/Stripe/StripeiOSTests/STPAddressTests.swift +++ b/Stripe/StripeiOSTests/STPAddressTests.swift @@ -164,287 +164,6 @@ class STPAddressTests: XCTestCase { XCTAssertEqual(postalAddress?.country, "US") } - func testContainsRequiredFieldsNone() { - let address = STPAddress() - XCTAssertTrue(address.containsRequiredFields(.none)) - address.line1 = "55 John St" - address.city = "New York" - address.state = "NY" - address.postalCode = "10002" - address.country = "US" - address.phone = "8885551212" - address.email = "foo@example.com" - address.name = "John Doe" - XCTAssertTrue(address.containsRequiredFields(.none)) - address.country = "UK" - XCTAssertTrue(address.containsRequiredFields(.none)) - } - - func testContainsRequiredFieldsZip() { - let address = STPAddress() - - // nil country is treated as generic postal requirement - XCTAssertFalse(address.containsRequiredFields(.postalCode)) - address.country = "IE" // should pass for country which doesn't require zip/postal - XCTAssertTrue(address.containsRequiredFields(.postalCode)) - address.country = "US" - XCTAssertFalse(address.containsRequiredFields(.postalCode)) - address.postalCode = "10002" - XCTAssertTrue(address.containsRequiredFields(.postalCode)) - address.postalCode = "ABCDE" - XCTAssertFalse(address.containsRequiredFields(.postalCode)) - address.country = "UK" // should pass for alphanumeric countries - XCTAssertTrue(address.containsRequiredFields(.postalCode)) - address.country = nil // nil treated as alphanumeric - XCTAssertTrue(address.containsRequiredFields(.postalCode)) - } - - func testContainsRequiredFieldsFull() { - let address = STPAddress() - - /// Required fields for full are: - /// line1, city, country, state (US only) and a valid postal code (based on country) - - XCTAssertFalse(address.containsRequiredFields(.full)) - address.country = "US" - address.line1 = "55 John St" - - // Fail on partial - XCTAssertFalse(address.containsRequiredFields(.full)) - - address.city = "New York" - - // For US fail if missing state or zip - XCTAssertFalse(address.containsRequiredFields(.full)) - address.state = "NY" - XCTAssertFalse(address.containsRequiredFields(.full)) - address.postalCode = "ABCDE" - XCTAssertFalse(address.containsRequiredFields(.full)) - // postal must be numeric for US - address.postalCode = "10002" - XCTAssertTrue(address.containsRequiredFields(.full)) - address.phone = "8885551212" - address.email = "foo@example.com" - address.name = "John Doe" - // Name/phone/email should have no effect - XCTAssertTrue(address.containsRequiredFields(.full)) - - // Non US countries don't require state - address.country = "UK" - XCTAssertTrue(address.containsRequiredFields(.full)) - address.state = nil - XCTAssertTrue(address.containsRequiredFields(.full)) - // alphanumeric postal ok in some countries - address.postalCode = "ABCDE" - XCTAssertTrue(address.containsRequiredFields(.full)) - // UK requires ZIP - address.postalCode = nil - XCTAssertFalse(address.containsRequiredFields(.full)) - - address.country = "IE" // Doesn't require postal or state, but allows them - XCTAssertTrue(address.containsRequiredFields(.full)) - address.postalCode = "ABCDE" - XCTAssertTrue(address.containsRequiredFields(.full)) - address.state = "Test" - XCTAssertTrue(address.containsRequiredFields(.full)) - } - - func testContainsRequiredFieldsName() { - let address = STPAddress() - - XCTAssertFalse(address.containsRequiredFields(.name)) - address.name = "Jane Doe" - XCTAssertTrue(address.containsRequiredFields(.name)) - } - - func testContainsContentForBillingAddressFields() { - let address = STPAddress() - - // Empty address should return false for everything - XCTAssertFalse(address.containsContent(for: .none)) - XCTAssertFalse(address.containsContent(for: .postalCode)) - XCTAssertFalse(address.containsContent(for: .full)) - XCTAssertFalse(address.containsContent(for: .name)) - - // 1+ characters in postalCode will return true for .PostalCode && .Full - address.postalCode = "0" - XCTAssertFalse(address.containsContent(for: .none)) - XCTAssertTrue(address.containsContent(for: .postalCode)) - XCTAssertTrue(address.containsContent(for: .full)) - // empty string returns false - address.postalCode = "" - XCTAssertFalse(address.containsContent(for: .none)) - XCTAssertFalse(address.containsContent(for: .postalCode)) - XCTAssertFalse(address.containsContent(for: .full)) - address.postalCode = nil - - // 1+ characters in name will return true for .Name - address.name = "Jane Doe" - XCTAssertTrue(address.containsContent(for: .name)) - // empty string returns false - address.name = "" - XCTAssertFalse(address.containsContent(for: .name)) - address.name = 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 propertyName in ["line1", "line2", "city", "state", "country"] { - for testValue in ["a", "0", "Foo Bar"] { - address.setValue(testValue, forKey: propertyName) - XCTAssertFalse(address.containsContent(for: .none)) - XCTAssertFalse(address.containsContent(for: .postalCode)) - XCTAssertTrue(address.containsContent(for: .full)) - XCTAssertFalse(address.containsContent(for: .name)) - 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.containsContent(for: .none)) - XCTAssertFalse(address.containsContent(for: .postalCode)) - XCTAssertFalse(address.containsContent(for: .full)) - XCTAssertFalse(address.containsContent(for: .name)) - address.setValue(nil, forKey: propertyName) - } - - // ensure it still returns false for everything since it has been cleared - XCTAssertFalse(address.containsContent(for: .none)) - XCTAssertFalse(address.containsContent(for: .postalCode)) - XCTAssertFalse(address.containsContent(for: .full)) - XCTAssertFalse(address.containsContent(for: .name)) - } - - func testContainsRequiredShippingAddressFields() { - let address = STPAddress() - XCTAssertTrue(address.containsRequiredShippingAddressFields(nil)) - let allFields = Set([ - STPContactField.postalAddress, - STPContactField.emailAddress, - STPContactField.phoneNumber, - STPContactField.name, - ]) - XCTAssertFalse(address.containsRequiredShippingAddressFields(allFields)) - - address.name = "John Smith" - XCTAssertTrue((address.containsRequiredShippingAddressFields(Set([STPContactField.name])))) - XCTAssertFalse((address.containsRequiredShippingAddressFields(Set([STPContactField.emailAddress])))) - - address.email = "john@example.com" - XCTAssertTrue((address.containsRequiredShippingAddressFields(Set([STPContactField.name, STPContactField.emailAddress])))) - XCTAssertFalse((address.containsRequiredShippingAddressFields(allFields))) - - address.phone = "5555555555" - XCTAssertTrue((address.containsRequiredShippingAddressFields(Set([ - STPContactField.name, - STPContactField.emailAddress, - STPContactField.phoneNumber, - ])))) - address.phone = "555" - XCTAssertFalse((address.containsRequiredShippingAddressFields(Set([ - STPContactField.name, - STPContactField.emailAddress, - STPContactField.phoneNumber, - ])))) - XCTAssertFalse((address.containsRequiredShippingAddressFields(allFields))) - address.country = "GB" - XCTAssertTrue((address.containsRequiredShippingAddressFields(Set([STPContactField.name, STPContactField.emailAddress])))) - address.phone = "5555555555" - XCTAssertTrue((address.containsRequiredShippingAddressFields(Set([ - STPContactField.name, - STPContactField.emailAddress, - STPContactField.phoneNumber, - ])))) - - address.country = "US" - address.phone = "5555555555" - address.line1 = "55 John St" - address.city = "New York" - address.state = "NY" - address.postalCode = "12345" - XCTAssertTrue(address.containsRequiredShippingAddressFields(allFields)) - } - - func testContainsContentForShippingAddressFields() { - let address = STPAddress() - - // Empty address should return false for everything - XCTAssertFalse((address.containsContent(forShippingAddressFields: nil))) - XCTAssertFalse((address.containsContent(forShippingAddressFields: Set([STPContactField.name])))) - XCTAssertFalse((address.containsContent(forShippingAddressFields: Set([STPContactField.phoneNumber])))) - XCTAssertFalse((address.containsContent(forShippingAddressFields: Set([STPContactField.emailAddress])))) - XCTAssertFalse((address.containsContent(forShippingAddressFields: Set([STPContactField.postalAddress])))) - - // Name - address.name = "Smith" - XCTAssertFalse((address.containsContent(forShippingAddressFields: nil))) - XCTAssertTrue((address.containsContent(forShippingAddressFields: Set([STPContactField.name])))) - XCTAssertFalse((address.containsContent(forShippingAddressFields: Set([STPContactField.phoneNumber])))) - XCTAssertFalse((address.containsContent(forShippingAddressFields: Set([STPContactField.emailAddress])))) - XCTAssertFalse((address.containsContent(forShippingAddressFields: Set([STPContactField.postalAddress])))) - address.name = "" - - // Phone - address.phone = "1" - XCTAssertFalse((address.containsContent(forShippingAddressFields: nil))) - XCTAssertFalse((address.containsContent(forShippingAddressFields: Set([STPContactField.name])))) - XCTAssertTrue((address.containsContent(forShippingAddressFields: Set([STPContactField.phoneNumber])))) - XCTAssertFalse((address.containsContent(forShippingAddressFields: Set([STPContactField.emailAddress])))) - XCTAssertFalse((address.containsContent(forShippingAddressFields: Set([STPContactField.postalAddress])))) - address.phone = "" - - // Email - address.email = "f" - XCTAssertFalse((address.containsContent(forShippingAddressFields: nil))) - XCTAssertFalse((address.containsContent(forShippingAddressFields: Set([STPContactField.name])))) - XCTAssertFalse((address.containsContent(forShippingAddressFields: Set([STPContactField.phoneNumber])))) - XCTAssertTrue((address.containsContent(forShippingAddressFields: Set([STPContactField.emailAddress])))) - XCTAssertFalse((address.containsContent(forShippingAddressFields: Set([STPContactField.postalAddress])))) - 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 propertyName in ["line1", "line2", "city", "state", "postalCode", "country"] { - for testValue in ["a", "0", "Foo Bar"] { - address.setValue(testValue, forKey: propertyName) - XCTAssertFalse((address.containsContent(forShippingAddressFields: nil))) - XCTAssertFalse((address.containsContent(forShippingAddressFields: Set([STPContactField.name])))) - XCTAssertFalse((address.containsContent(forShippingAddressFields: Set([STPContactField.phoneNumber])))) - XCTAssertFalse((address.containsContent(forShippingAddressFields: Set([STPContactField.emailAddress])))) - XCTAssertTrue((address.containsContent(forShippingAddressFields: Set([STPContactField.postalAddress])))) - address.setValue("", forKey: propertyName) - } - } - - // ensure it still returns false for everything with empty strings - XCTAssertFalse((address.containsContent(forShippingAddressFields: nil))) - XCTAssertFalse((address.containsContent(forShippingAddressFields: Set([STPContactField.name])))) - XCTAssertFalse((address.containsContent(forShippingAddressFields: Set([STPContactField.phoneNumber])))) - XCTAssertFalse((address.containsContent(forShippingAddressFields: Set([STPContactField.emailAddress])))) - XCTAssertFalse((address.containsContent(forShippingAddressFields: Set([STPContactField.postalAddress])))) - - // Try a hybrid address, and make sure some bitwise combinations work - address.name = "a" - address.phone = "1" - address.line1 = "_" - XCTAssertFalse((address.containsContent(forShippingAddressFields: nil))) - XCTAssertTrue((address.containsContent(forShippingAddressFields: Set([STPContactField.name])))) - XCTAssertTrue((address.containsContent(forShippingAddressFields: Set([STPContactField.phoneNumber])))) - XCTAssertFalse((address.containsContent(forShippingAddressFields: Set([STPContactField.emailAddress])))) - XCTAssertTrue((address.containsContent(forShippingAddressFields: Set([STPContactField.postalAddress])))) - - XCTAssertTrue((address.containsContent(forShippingAddressFields: Set([STPContactField.name, STPContactField.emailAddress])))) - XCTAssertTrue((address.containsContent(forShippingAddressFields: Set([STPContactField.phoneNumber, STPContactField.emailAddress])))) - XCTAssertTrue( - (address.containsContent( - forShippingAddressFields: Set([ - STPContactField.postalAddress, - STPContactField.emailAddress, - STPContactField.phoneNumber, - STPContactField.name, - ])))) - - } - func testShippingInfoForCharge() { let address = STPFixtures.address() let method = PKShippingMethod() diff --git a/Stripe/StripeiOSTests/STPAddressViewModelTest.swift b/Stripe/StripeiOSTests/STPAddressViewModelTest.swift deleted file mode 100644 index 429368e28d7..00000000000 --- a/Stripe/StripeiOSTests/STPAddressViewModelTest.swift +++ /dev/null @@ -1,205 +0,0 @@ -// -// STPAddressViewModelTest.swift -// StripeiOS Tests -// -// Created by Ben Guo on 10/21/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -@testable@_spi(STP) import Stripe -@testable@_spi(STP) import StripeCore -@testable@_spi(STP) import StripePayments -@testable@_spi(STP) import StripePaymentSheet -@testable@_spi(STP) import StripePaymentsUI - -class STPAddressViewModelTest: XCTestCase { - func testInitWithRequiredBillingFields() { - var sut = STPAddressViewModel(requiredBillingFields: .none, availableCountries: nil) - XCTAssertTrue(sut.addressCells.count == 0) - XCTAssertTrue(sut.isValid) - - sut = STPAddressViewModel(requiredBillingFields: .postalCode, availableCountries: nil) - XCTAssertTrue(sut.addressCells.count == 0) - - sut = STPAddressViewModel(requiredBillingFields: .full, availableCountries: nil) - XCTAssertTrue(sut.addressCells.count == 7) - let types: [STPAddressFieldType] = [ - .name, - .line1, - .line2, - .country, - .zip, - .city, - .state, - ] - for i in 0..(), - availableCountries: nil - ) - XCTAssertTrue(sut.addressCells.count == 0) - - sut = STPAddressViewModel( - requiredShippingFields: Set([.name]), - availableCountries: nil - ) - XCTAssertTrue(sut.addressCells.count == 1) - let cell1 = sut.addressCells[0] - XCTAssertEqual(cell1.type, .name) - - sut = STPAddressViewModel( - requiredShippingFields: Set([.name, .emailAddress]), - availableCountries: nil - ) - XCTAssertTrue(sut.addressCells.count == 2) - var types: [STPAddressFieldType] = [.name, .email] - for i in 0..([ - .postalAddress, .emailAddress, .phoneNumber, - ]), - availableCountries: nil - ) - XCTAssertTrue(sut.addressCells.count == 9) - types = [ - .email, - .name, - .line1, - .line2, - .country, - .zip, - .city, - .state, - .phone, - ] - for i in 0..([ - .postalAddress, - .emailAddress, - .phoneNumber, - ]), - availableCountries: nil - ) - sut.addressCells[0].contents = "foo@example.com" - sut.addressCells[1].contents = "John Smith" - sut.addressCells[2].contents = "55 John St" - sut.addressCells[3].contents = "#3B" - sut.addressCells[4].contents = "US" - sut.addressCells[5].contents = "10002" - sut.addressCells[6].contents = "New York" - sut.addressCells[7].contents = "NY" - sut.addressCells[8].contents = "555-555-5555" - - XCTAssertEqual(sut.address.email, "foo@example.com") - XCTAssertEqual(sut.address.name, "John Smith") - XCTAssertEqual(sut.address.line1, "55 John St") - XCTAssertEqual(sut.address.line2, "#3B") - XCTAssertEqual(sut.address.city, "New York") - XCTAssertEqual(sut.address.state, "NY") - XCTAssertEqual(sut.address.postalCode, "10002") - XCTAssertEqual(sut.address.country, "US") - XCTAssertEqual(sut.address.phone, "555-555-5555") - } - - func testSetAddress() { - let address = STPAddress() - address.email = "foo@example.com" - address.name = "John Smith" - address.line1 = "55 John St" - address.line2 = "#3B" - address.city = "New York" - address.state = "NY" - address.postalCode = "10002" - address.country = "US" - address.phone = "555-555-5555" - - let sut = STPAddressViewModel( - requiredShippingFields: Set([ - .postalAddress, - .emailAddress, - .phoneNumber, - ]), - availableCountries: nil - ) - sut.address = address - XCTAssertEqual(sut.addressCells[0].contents, "foo@example.com") - XCTAssertEqual(sut.addressCells[1].contents, "John Smith") - XCTAssertEqual(sut.addressCells[2].contents, "55 John St") - XCTAssertEqual(sut.addressCells[3].contents, "#3B") - XCTAssertEqual(sut.addressCells[4].contents, "US") - XCTAssertEqual(sut.addressCells[4].textField.text, "United States") - XCTAssertEqual(sut.addressCells[5].contents, "10002") - XCTAssertEqual(sut.addressCells[6].contents, "New York") - XCTAssertEqual(sut.addressCells[7].contents, "NY") - XCTAssertEqual(sut.addressCells[8].contents, "555-555-5555") - } - - func testIsValid_Zip() { - let sut = STPAddressViewModel(requiredBillingFields: .postalCode, availableCountries: nil) - - let address = STPAddress() - - address.country = "US" - sut.address = address - // The AddressViewModel shouldn't request any information when requesting ZIPs. - XCTAssertEqual(sut.addressCells.count, 0) - - address.postalCode = "94016" - sut.address = address - XCTAssertTrue(sut.isValid) - - address.country = "MO" // in Macao, postalCode is optional - address.postalCode = nil - sut.address = address - XCTAssertEqual(sut.addressCells.count, 0) - XCTAssertTrue(sut.isValid, "in Macao, postalCode is optional, valid without one") - } - - func testIsValid_Full() { - let sut = STPAddressViewModel(requiredBillingFields: .full, availableCountries: nil) - XCTAssertFalse(sut.isValid) - sut.addressCells[0].contents = "John Smith" - sut.addressCells[1].contents = "55 John St" - sut.addressCells[2].contents = "#3B" - XCTAssertFalse(sut.isValid) - sut.addressCells[3].contents = "10002" - sut.addressCells[4].contents = "New York" - sut.addressCells[5].contents = "NY" - sut.addressCells[6].contents = "US" - XCTAssertTrue(sut.isValid) - } - - func testIsValid_Name() { - let sut = STPAddressViewModel(requiredBillingFields: .name, availableCountries: nil) - - let address = STPAddress() - - address.name = "" - sut.address = address - XCTAssertEqual(sut.addressCells.count, 1) - XCTAssertFalse(sut.isValid) - - address.name = "Jane Doe" - sut.address = address - XCTAssertEqual(sut.addressCells.count, 1) - XCTAssertTrue(sut.isValid) - } -} diff --git a/Stripe/StripeiOSTests/STPAnalyticsClientPaymentsTest.swift b/Stripe/StripeiOSTests/STPAnalyticsClientPaymentsTest.swift index 5ab6e8b508d..536ee8b3972 100644 --- a/Stripe/StripeiOSTests/STPAnalyticsClientPaymentsTest.swift +++ b/Stripe/StripeiOSTests/STPAnalyticsClientPaymentsTest.swift @@ -32,10 +32,6 @@ class STPAnalyticsClientPaymentsTest: XCTestCase { client.addAdditionalInfo("how are you?") XCTAssertEqual(client.additionalInfo(), ["hello", "how are you?", "i'm additional info"]) - - // Clear it - client.clearAdditionalInfo() - XCTAssertEqual(client.additionalInfo(), []) } func testPayloadFromAnalytic() throws { @@ -125,80 +121,10 @@ class STPAnalyticsClientPaymentsTest: XCTestCase { ) } - func testPaymentContextAddsUsage() { - let keyManager = STPEphemeralKeyManager( - keyProvider: MockKeyProvider(), - apiVersion: "1", - performsEagerFetching: false - ) - let apiClient = STPAPIClient() - let customerContext = STPCustomerContext.init(keyManager: keyManager, apiClient: apiClient) - let paymentContext = STPPaymentContext(customerContext: customerContext) - XCTAssertTrue(STPAnalyticsClient.sharedClient.productUsage.contains("STPCustomerContext")) - XCTAssertEqual(paymentContext.analyticsLogger.product, "STPPaymentContext") - } - func testApplePayContextAddsUsage() { _ = STPApplePayContext(paymentRequest: STPFixtures.applePayRequest(), delegate: nil) XCTAssertTrue(STPAnalyticsClient.sharedClient.productUsage.contains("STPApplePayContext")) } - - func testCustomerContextAddsUsage() { - let keyManager = STPEphemeralKeyManager( - keyProvider: MockKeyProvider(), - apiVersion: "1", - performsEagerFetching: false - ) - let apiClient = STPAPIClient() - _ = STPCustomerContext(keyManager: keyManager, apiClient: apiClient) - XCTAssertTrue(STPAnalyticsClient.sharedClient.productUsage.contains("STPCustomerContext")) - } - - func testAddCardVCAddsUsage() { - let addCardVC = STPAddCardViewController() - XCTAssertTrue( - STPAnalyticsClient.sharedClient.productUsage.contains("STPAddCardViewController") - ) - XCTAssertEqual(addCardVC.analyticsLogger.product, "STPAddCardViewController") - } - - func testPaymentOptionsVCAddsUsage() { - let customerContext = Testing_StaticCustomerContext.init( - customer: STPFixtures.customerWithCardTokenAndSourceSources(), - paymentMethods: [] - ) - let delegate = MockSTPPaymentOptionsViewControllerDelegate() - let paymentOptionsVC = STPPaymentOptionsViewController(configuration: .shared, theme: .defaultTheme, customerContext: customerContext, delegate: delegate) - XCTAssertTrue( - STPAnalyticsClient.sharedClient.productUsage.contains("STPPaymentOptionsViewController") - ) - XCTAssertEqual(paymentOptionsVC.analyticsLogger.product, "STPPaymentOptionsViewController") - } - - func testBankSelectionVCAddsUsage() { - _ = STPBankSelectionViewController() - XCTAssertTrue( - STPAnalyticsClient.sharedClient.productUsage.contains("STPBankSelectionViewController") - ) - } - - func testShippingVCAddsUsage() { - let config = STPPaymentConfiguration() - config.requiredShippingAddressFields = [STPContactField.postalAddress] - _ = STPShippingAddressViewController( - configuration: config, - theme: .defaultTheme, - currency: nil, - shippingAddress: nil, - selectedShippingMethod: nil, - prefilledInformation: nil - ) - XCTAssertTrue( - STPAnalyticsClient.sharedClient.productUsage.contains( - "STPShippingAddressViewController" - ) - ) - } } // MARK: - Helpers @@ -234,14 +160,3 @@ private struct MockAnalyticsClass1: STPAnalyticsProtocol { private struct MockAnalyticsClass2: STPAnalyticsProtocol { static let stp_analyticsIdentifier = "MockAnalyticsClass2" } - -private class MockKeyProvider: NSObject, STPCustomerEphemeralKeyProvider { - func createCustomerKey( - withAPIVersion apiVersion: String, - completion: @escaping STPJSONResponseCompletionBlock - ) { - guard apiVersion == "1" else { return } - - completion(nil, NSError.stp_genericConnectionError()) - } -} diff --git a/Stripe/StripeiOSTests/STPApplePayPaymentOptionTest.swift b/Stripe/StripeiOSTests/STPApplePayPaymentOptionTest.swift deleted file mode 100644 index b0893b29723..00000000000 --- a/Stripe/StripeiOSTests/STPApplePayPaymentOptionTest.swift +++ /dev/null @@ -1,40 +0,0 @@ -// Converted to Swift 5.8.1 by Swiftify v5.8.28463 - https://swiftify.com/ -// -// STPApplePayPaymentOptionTest.m -// Stripe -// -// Created by Joey Dong on 7/28/17. -// Copyright © 2017 Stripe, Inc. All rights reserved. -// - -class STPApplePayPaymentOptionTest: XCTestCase { - // MARK: - STPPaymentOption Tests - - func testImage() { - let applePay = STPApplePayPaymentOption() - XCTAssertNotNil(applePay.image) - } - - func testTemplateImage() { - let applePay = STPApplePayPaymentOption() - XCTAssertNotNil(applePay.templateImage) - } - - func testLabel() { - let applePay = STPApplePayPaymentOption() - XCTAssertEqual(applePay.label, "Apple Pay") - } - - // MARK: - Equality Tests - - func testApplePayEquals() { - let applePay1 = STPApplePayPaymentOption() - let applePay2 = STPApplePayPaymentOption() - - XCTAssertEqual(applePay1, applePay1) - XCTAssertEqual(applePay1, applePay2) - - XCTAssertEqual(applePay1.hash, applePay1.hash) - XCTAssertEqual(applePay1.hash, applePay2.hash) - } -} diff --git a/Stripe/StripeiOSTests/STPBlocks.h b/Stripe/StripeiOSTests/STPBlocks.h index d9be6f7231b..6b18f5a0a3f 100644 --- a/Stripe/StripeiOSTests/STPBlocks.h +++ b/Stripe/StripeiOSTests/STPBlocks.h @@ -19,36 +19,6 @@ @class STPSetupIntent; @class STPPaymentMethod; @class STPIssuingCardPin; -@class STPFPXBankStatusResponse; - -/** - These values control the labels used in the shipping info collection form. - */ -typedef NS_ENUM(NSUInteger, STPShippingType) { - /** - Shipping the purchase to the provided address using a third-party - shipping company. - */ - STPShippingTypeShipping, - /** - Delivering the purchase by the seller. - */ - STPShippingTypeDelivery, -}; - -/** - An enum representing the status of a shipping address validation. - */ -typedef NS_ENUM(NSUInteger, STPShippingStatus) { - /** - The shipping address is valid. - */ - STPShippingStatusValid, - /** - The shipping address is invalid. - */ - STPShippingStatusInvalid, -}; /** An enum representing the status of a payment requested from the user. @@ -152,17 +122,6 @@ typedef void (^STPPaymentMethodCompletionBlock)(STPPaymentMethod * __nullable pa */ typedef void (^STPPaymentMethodsCompletionBlock)(NSArray *__nullable paymentMethods, NSError * __nullable error); -/** - A callback to be run with a validation result and shipping methods for a - shipping address. - - @param status An enum representing whether the shipping address is valid. - @param shippingValidationError If the shipping address is invalid, an error describing the issue with the address. If no error is given and the address is invalid, the default error message will be used. - @param shippingMethods The shipping methods available for the address. - @param selectedShippingMethod The default selected shipping method for the address. - */ -typedef void (^STPShippingMethodsCompletionBlock)(STPShippingStatus status, NSError * __nullable shippingValidationError, NSArray* __nullable shippingMethods, PKShippingMethod * __nullable selectedShippingMethod); - /** A callback to be run with a file response from the Stripe API. @@ -230,14 +189,6 @@ typedef void (^STPPinCompletionBlock)(STPIssuingCardPin * __nullable cardPin, ST */ typedef void (^STP3DS2AuthenticateCompletionBlock)(STP3DS2AuthenticateResponse * _Nullable authenticateResponse, NSError * _Nullable error); -/** - A callback to be run with a response from the Stripe API containing information about the online status of FPX banks. - - @param bankStatusResponse The response from Stripe containing the status of the various banks. Will be nil if an error occurs. @see STPFPXBankStatusResponse - @param error The error returned from the response, or nil if none occurs. - */ -typedef void (^STPFPXBankStatusCompletionBlock)(STPFPXBankStatusResponse * _Nullable bankStatusResponse, NSError * _Nullable error); - /** A block called with a payment status and an optional error. diff --git a/Stripe/StripeiOSTests/STPCardTest.swift b/Stripe/StripeiOSTests/STPCardTest.swift index e9fdf41b02a..6d6b3c80948 100644 --- a/Stripe/StripeiOSTests/STPCardTest.swift +++ b/Stripe/StripeiOSTests/STPCardTest.swift @@ -244,12 +244,6 @@ class STPCardTest: XCTestCase { XCTAssertEqual(card.stripeID, "card_103kbR2eZvKYlo2CDczLmw4K") } - // MARK: - STPPaymentOption Tests - func testLabel() { - let card = STPCard.decodedObject(fromAPIResponse: STPTestUtils.jsonNamed("Card"))! - XCTAssertEqual(card.label, "Visa 4242") - } - // MARK: - func forEachBrand(_ block: @escaping (_ brand: STPCardBrand) -> Void) { let values: [STPCardBrand] = [ diff --git a/Stripe/StripeiOSTests/STPCustomerContextTest.swift b/Stripe/StripeiOSTests/STPCustomerContextTest.swift deleted file mode 100644 index f622ac96ce8..00000000000 --- a/Stripe/StripeiOSTests/STPCustomerContextTest.swift +++ /dev/null @@ -1,671 +0,0 @@ -// -// STPCustomerContextTest.swift -// StripeiOS Tests -// -// Created by David Estes on 9/20/21. -// Copyright © 2021 Stripe, Inc. All rights reserved. -// - -import Foundation -import OHHTTPStubs -import OHHTTPStubsSwift -import StripeCoreTestUtils - -@testable@_spi(STP) import Stripe -@testable@_spi(STP) import StripeCore -@testable@_spi(STP) import StripePayments - -class MockEphemeralKeyManager: STPEphemeralKeyManagerProtocol { - var ephemeralKey: STPEphemeralKey? - var error: Error? - - init( - key: STPEphemeralKey?, - error: Error? - ) { - self.ephemeralKey = key - self.error = error - } - - func getOrCreateKey(_ completion: @escaping STPEphemeralKeyCompletionBlock) { - completion(ephemeralKey, error) - } -} - -class STPCustomerContextTests: APIStubbedTestCase { - func stubRetrieveCustomers( - key: STPEphemeralKey, - returningCustomerJSON: [AnyHashable: Any], - expectedCount: Int, - apiClient: STPAPIClient - ) { - let exp = expectation(description: "retrieveCustomer") - exp.expectedFulfillmentCount = expectedCount - - stub { urlRequest in - return urlRequest.url?.absoluteString.contains("/customers") ?? false - && urlRequest.httpMethod == "GET" - } response: { _ in - DispatchQueue.main.async { - // Fulfill after response is sent - exp.fulfill() - } - return HTTPStubsResponse( - jsonObject: returningCustomerJSON, - statusCode: 200, - headers: nil - ) - } - } - - func stubListPaymentMethods( - key: STPEphemeralKey, - paymentMethodJSONs: [[AnyHashable: Any]], - expectedCount: Int, - apiClient: STPAPIClient - ) { - let exp = expectation(description: "listPaymentMethod") - exp.expectedFulfillmentCount = expectedCount - stub { urlRequest in - if urlRequest.url?.absoluteString.contains("/payment_methods") ?? false - && urlRequest.httpMethod == "GET" - { - // Check to make sure we pass the ephemeral key correctly - let keyFromHeader = urlRequest.allHTTPHeaderFields!["Authorization"]? - .replacingOccurrences(of: "Bearer ", with: "") - XCTAssertEqual(keyFromHeader, key.secret) - return true - } - return false - } response: { _ in - let paymentMethodsJSON = """ - { - "object": "list", - "url": "/v1/payment_methods", - "has_more": false, - "data": [ - ] - } - """ - var pmList = - try! JSONSerialization.jsonObject( - with: paymentMethodsJSON.data(using: .utf8)!, - options: [] - ) as! [AnyHashable: Any] - pmList["data"] = paymentMethodJSONs - DispatchQueue.main.async { - // Fulfill after response is sent - exp.fulfill() - } - return HTTPStubsResponse(jsonObject: pmList, statusCode: 200, headers: nil) - } - } - - func testGetOrCreateKeyErrorForwardedToRetrieveCustomer() { - let exp = expectation(description: "retrieveCustomer") - let expectedError = NSError(domain: "test", code: 123, userInfo: nil) - let apiClient = stubbedAPIClient() - stub { urlRequest in - return urlRequest.url?.absoluteString.contains("/customers") ?? false - } response: { _ in - XCTFail("Retrieve customer should not be called") - return HTTPStubsResponse(error: NSError(domain: "test", code: 100, userInfo: nil)) - } - let ekm = MockEphemeralKeyManager(key: nil, error: expectedError) - let sut = STPCustomerContext(keyManager: ekm, apiClient: apiClient) - sut.retrieveCustomer { customer, error in - XCTAssertNil(customer) - XCTAssertEqual((error as NSError?)?.domain, expectedError.domain) - exp.fulfill() - } - waitForExpectations(timeout: 2, handler: nil) - } - - func testInitRetrievesResourceKeyAndCustomerAndPaymentMethods() { - let customerKey = STPFixtures.ephemeralKey() - let expectedCustomerJSON = STPFixtures.customerWithSingleCardTokenSourceJSON() - let apiClient = stubbedAPIClient() - stubRetrieveCustomers( - key: customerKey, - returningCustomerJSON: expectedCustomerJSON, - expectedCount: 1, - apiClient: apiClient - ) - stubListPaymentMethods( - key: customerKey, - paymentMethodJSONs: [], - expectedCount: 1, - apiClient: apiClient - ) - - let ekm = MockEphemeralKeyManager(key: customerKey, error: nil) - let sut = STPCustomerContext(keyManager: ekm, apiClient: apiClient) - XCTAssertNotNil(sut) - waitForExpectations(timeout: 2, handler: nil) - } - - func testRetrieveCustomerUsesCachedCustomerIfNotExpired() { - let customerKey = STPFixtures.ephemeralKey() - let expectedCustomer = STPFixtures.customerWithSingleCardTokenSource() - let expectedCustomerJSON = STPFixtures.customerWithSingleCardTokenSourceJSON() - let apiClient = stubbedAPIClient() - - // apiClient.retrieveCustomer should be called once, when the context is initialized. - // When sut.retrieveCustomer is called below, the cached customer will be used. - stubRetrieveCustomers( - key: customerKey, - returningCustomerJSON: expectedCustomerJSON, - expectedCount: 1, - apiClient: apiClient - ) - stubListPaymentMethods( - key: customerKey, - paymentMethodJSONs: [], - expectedCount: 1, - apiClient: apiClient - ) - let ekm = MockEphemeralKeyManager(key: customerKey, error: nil) - let sut = STPCustomerContext(keyManager: ekm, apiClient: apiClient) - // Give the mocked API request a little time to complete and cache the customer, then check cache - waitForExpectations(timeout: 2, handler: nil) - let exp2 = expectation(description: "retrieveCustomer again") - DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + ohhttpDelay) { - sut.retrieveCustomer { customer, _ in - XCTAssertEqual(customer!.stripeID, expectedCustomer.stripeID) - exp2.fulfill() - } - } - waitForExpectations(timeout: 2, handler: nil) - } - - func testRetrieveCustomerDoesNotUseCachedCustomerIfExpired() { - let customerKey = STPFixtures.ephemeralKey() - let expectedCustomer = STPFixtures.customerWithSingleCardTokenSource() - let expectedCustomerJSON = STPFixtures.customerWithSingleCardTokenSourceJSON() - let apiClient = stubbedAPIClient() - - // apiClient.retrieveCustomer should be called twice: - // - when the context is initialized, - // - when sut.retrieveCustomer is called below, as the cached customer has expired. - stubRetrieveCustomers( - key: customerKey, - returningCustomerJSON: expectedCustomerJSON, - expectedCount: 2, - apiClient: apiClient - ) - stubListPaymentMethods( - key: customerKey, - paymentMethodJSONs: [], - expectedCount: 1, - apiClient: apiClient - ) - - let ekm = MockEphemeralKeyManager(key: customerKey, error: nil) - let sut = STPCustomerContext(keyManager: ekm, apiClient: apiClient) - // Give the mocked API request a little time to complete and cache the customer, then reset and check cache - let exp2 = expectation(description: "retrieveCustomer again") - DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + ohhttpDelay) { - sut.customerRetrievedDate = Date(timeIntervalSinceNow: -70) - sut.retrieveCustomer { customer, _ in - XCTAssertEqual(customer!.stripeID, expectedCustomer.stripeID) - exp2.fulfill() - } - } - waitForExpectations(timeout: 2, handler: nil) - } - - func testRetrieveCustomerDoesNotUseCachedCustomerAfterClearingCache() { - let customerKey = STPFixtures.ephemeralKey() - let expectedCustomer = STPFixtures.customerWithSingleCardTokenSource() - let expectedCustomerJSON = STPFixtures.customerWithSingleCardTokenSourceJSON() - let apiClient = stubbedAPIClient() - - // apiClient.retrieveCustomer should be called twice: - // - when the context is initialized, - // - when sut.retrieveCustomer is called below, as the cached customer has been cleared. - stubRetrieveCustomers( - key: customerKey, - returningCustomerJSON: expectedCustomerJSON, - expectedCount: 2, - apiClient: apiClient - ) - stubListPaymentMethods( - key: customerKey, - paymentMethodJSONs: [], - expectedCount: 1, - apiClient: apiClient - ) - - let ekm = MockEphemeralKeyManager(key: customerKey, error: nil) - let sut = STPCustomerContext(keyManager: ekm, apiClient: apiClient) - // Give the mocked API request a little time to complete and cache the customer, then reset and check cache - let exp2 = expectation(description: "retrieveCustomer again") - DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + ohhttpDelay) { - sut.clearCache() - sut.retrieveCustomer { customer, _ in - XCTAssertEqual(customer!.stripeID, expectedCustomer.stripeID) - exp2.fulfill() - } - } - waitForExpectations(timeout: 2, handler: nil) - } - - func testRetrievePaymentMethodsUsesCacheIfNotExpired() { - let customerKey = STPFixtures.ephemeralKey() - let expectedCustomerJSON = STPFixtures.customerWithSingleCardTokenSourceJSON() - let expectedPaymentMethods = [STPFixtures.paymentMethod()] - let expectedPaymentMethodsJSON = [STPFixtures.paymentMethodJSON()] - let apiClient = stubbedAPIClient() - - // apiClient.listPaymentMethods should be called once, when the context is initialized. - // When sut.listPaymentMethods is called below, the cached list will be used. - stubRetrieveCustomers( - key: customerKey, - returningCustomerJSON: expectedCustomerJSON, - expectedCount: 1, - apiClient: apiClient - ) - stubListPaymentMethods( - key: customerKey, - paymentMethodJSONs: expectedPaymentMethodsJSON, - expectedCount: 1, - apiClient: apiClient - ) - - let ekm = MockEphemeralKeyManager(key: customerKey, error: nil) - let sut = STPCustomerContext(keyManager: ekm, apiClient: apiClient) - // Give the mocked API request a little time to complete and cache the customer, then check cache - let exp2 = expectation(description: "listPaymentMethods") - DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + ohhttpDelay) { - sut.listPaymentMethodsForCustomer { paymentMethods, _ in - XCTAssertEqual(paymentMethods!.count, expectedPaymentMethods.count) - exp2.fulfill() - } - } - waitForExpectations(timeout: 2, handler: nil) - } - - func testRetrievePaymentMethodsDoesNotUseCacheIfExpired() { - let customerKey = STPFixtures.ephemeralKey() - let expectedCustomerJSON = STPFixtures.customerWithSingleCardTokenSourceJSON() - let expectedPaymentMethods = [STPFixtures.paymentMethod()] - let expectedPaymentMethodsJSON = [STPFixtures.paymentMethodJSON()] - let apiClient = stubbedAPIClient() - - // apiClient.listPaymentMethods should be called twice: - // - when the context is initialized, - // - when sut.listPaymentMethods is called below, as the cached list has expired. - stubRetrieveCustomers( - key: customerKey, - returningCustomerJSON: expectedCustomerJSON, - expectedCount: 1, - apiClient: apiClient - ) - stubListPaymentMethods( - key: customerKey, - paymentMethodJSONs: expectedPaymentMethodsJSON, - expectedCount: 2, - apiClient: apiClient - ) - - let ekm = MockEphemeralKeyManager(key: customerKey, error: nil) - let sut = STPCustomerContext(keyManager: ekm, apiClient: apiClient) - // Give the mocked API request a little time to complete and cache the customer, then check cache - let exp2 = expectation(description: "listPaymentMethods") - DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + ohhttpDelay) { - sut.paymentMethodsRetrievedDate = Date(timeIntervalSinceNow: -70) - sut.listPaymentMethodsForCustomer { paymentMethods, _ in - XCTAssertEqual(paymentMethods!.count, expectedPaymentMethods.count) - exp2.fulfill() - } - } - waitForExpectations(timeout: 2, handler: nil) - } - - func testRetrievePaymentMethodsDoesNotUseCacheAfterClearingCache() { - let customerKey = STPFixtures.ephemeralKey() - let expectedCustomerJSON = STPFixtures.customerWithSingleCardTokenSourceJSON() - let expectedPaymentMethods = [STPFixtures.paymentMethod()] - let expectedPaymentMethodsJSON = [STPFixtures.paymentMethodJSON()] - let apiClient = stubbedAPIClient() - - // apiClient.listPaymentMethods should be called twice: - // - when the context is initialized, - // - when sut.listPaymentMethods is called below, as the cached list has been cleared - stubRetrieveCustomers( - key: customerKey, - returningCustomerJSON: expectedCustomerJSON, - expectedCount: 1, - apiClient: apiClient - ) - stubListPaymentMethods( - key: customerKey, - paymentMethodJSONs: expectedPaymentMethodsJSON, - expectedCount: 2, - apiClient: apiClient - ) - - let ekm = MockEphemeralKeyManager(key: customerKey, error: nil) - let sut = STPCustomerContext(keyManager: ekm, apiClient: apiClient) - // Give the mocked API request a little time to complete and cache the customer, then check cache - let exp2 = expectation(description: "listPaymentMethods") - DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + ohhttpDelay) { - sut.clearCache() - sut.listPaymentMethodsForCustomer { paymentMethods, _ in - XCTAssertEqual(paymentMethods!.count, expectedPaymentMethods.count) - exp2.fulfill() - } - } - waitForExpectations(timeout: 2, handler: nil) - } - - func testSetCustomerShippingCallsAPIClientCorrectly() { - let address = STPFixtures.address() - let customerKey = STPFixtures.ephemeralKey() - let expectedCustomerJSON = STPFixtures.customerWithSingleCardTokenSourceJSON() - let apiClient = stubbedAPIClient() - - stubRetrieveCustomers( - key: customerKey, - returningCustomerJSON: expectedCustomerJSON, - expectedCount: 1, - apiClient: apiClient - ) - stubListPaymentMethods( - key: customerKey, - paymentMethodJSONs: [], - expectedCount: 1, - apiClient: apiClient - ) - - let exp = expectation(description: "updateCustomer") - stub { urlRequest in - if urlRequest.url?.absoluteString.contains("/customers") ?? false - && urlRequest.httpMethod == "POST" - { - let state = urlRequest.queryItems?.first(where: { item in - item.name == "shipping[address][state]" - })! - XCTAssertEqual(state?.value, address.state) - return true - } - return false - } response: { _ in - exp.fulfill() - return HTTPStubsResponse( - jsonObject: expectedCustomerJSON, - statusCode: 200, - headers: nil - ) - } - - let ekm = MockEphemeralKeyManager(key: customerKey, error: nil) - let sut = STPCustomerContext(keyManager: ekm, apiClient: apiClient) - let exp2 = expectation(description: "updateCustomerWithShipping") - sut.updateCustomer(withShippingAddress: address) { error in - XCTAssertNil(error) - exp2.fulfill() - } - waitForExpectations(timeout: 2, handler: nil) - } - - func testAttachPaymentMethodCallsAPIClientCorrectly() { - let customerKey = STPFixtures.ephemeralKey() - let expectedCustomerJSON = STPFixtures.customerWithSingleCardTokenSourceJSON() - let apiClient = stubbedAPIClient() - let expectedPaymentMethod = STPFixtures.paymentMethod() - let expectedPaymentMethodJSON = STPFixtures.paymentMethodJSON() - let expectedPaymentMethods = [STPFixtures.paymentMethod()] - - stubRetrieveCustomers( - key: customerKey, - returningCustomerJSON: expectedCustomerJSON, - expectedCount: 1, - apiClient: apiClient - ) - stubListPaymentMethods( - key: customerKey, - paymentMethodJSONs: [], - expectedCount: 1, - apiClient: apiClient - ) - - let exp = expectation(description: "payment method attach") - // We're attaching 2 payment methods: - exp.expectedFulfillmentCount = 2 - stub { urlRequest in - if urlRequest.url?.absoluteString.contains("/payment_method") ?? false - && urlRequest.httpMethod == "POST" - { - return true - } - return false - } response: { _ in - exp.fulfill() - return HTTPStubsResponse( - jsonObject: expectedPaymentMethodJSON, - statusCode: 200, - headers: nil - ) - } - - let ekm = MockEphemeralKeyManager(key: customerKey, error: nil) - let sut = STPCustomerContext(keyManager: ekm, apiClient: apiClient) - let exp2 = expectation(description: "CustomerContext attachPaymentMethod") - sut.attachPaymentMethod(toCustomer: expectedPaymentMethods.first!) { error in - XCTAssertNil(error) - exp2.fulfill() - } - - let exp3 = expectation(description: "CustomerContext attachPaymentMethod with ID") - sut.attachPaymentMethodToCustomer(paymentMethodId: expectedPaymentMethod.stripeId) { - error in - XCTAssertNil(error) - exp3.fulfill() - } - - waitForExpectations(timeout: 2, handler: nil) - } - - func testDetachPaymentMethodCallsAPIClientCorrectly() { - let customerKey = STPFixtures.ephemeralKey() - let expectedCustomerJSON = STPFixtures.customerWithSingleCardTokenSourceJSON() - let apiClient = stubbedAPIClient() - let expectedPaymentMethod = STPFixtures.paymentMethod() - let expectedPaymentMethodJSON = STPFixtures.paymentMethodJSON() - let expectedPaymentMethods = [STPFixtures.paymentMethod()] - - stubRetrieveCustomers( - key: customerKey, - returningCustomerJSON: expectedCustomerJSON, - expectedCount: 1, - apiClient: apiClient - ) - stubListPaymentMethods( - key: customerKey, - paymentMethodJSONs: [], - expectedCount: 1, - apiClient: apiClient - ) - - let exp = expectation(description: "payment method detach") - // We're detaching 2 payment methods: - exp.expectedFulfillmentCount = 2 - stub { urlRequest in - if urlRequest.url?.absoluteString.contains("/payment_method") ?? false - && urlRequest.httpMethod == "POST" - { - return true - } - return false - } response: { _ in - exp.fulfill() - return HTTPStubsResponse( - jsonObject: expectedPaymentMethodJSON, - statusCode: 200, - headers: nil - ) - } - - let ekm = MockEphemeralKeyManager(key: customerKey, error: nil) - let sut = STPCustomerContext(keyManager: ekm, apiClient: apiClient) - let exp2 = expectation(description: "CustomerContext detachPaymentMethod") - sut.detachPaymentMethod(fromCustomer: expectedPaymentMethods.first!) { error in - XCTAssertNil(error) - exp2.fulfill() - } - - let exp3 = expectation(description: "CustomerContext detachPaymentMethod with ID") - sut.detachPaymentMethodFromCustomer(paymentMethodId: expectedPaymentMethod.stripeId) { - error in - XCTAssertNil(error) - exp3.fulfill() - } - - waitForExpectations(timeout: 2, handler: nil) - } - - func testFiltersApplePayPaymentMethodsByDefault() { - let customerKey = STPFixtures.ephemeralKey() - let expectedCustomerJSON = STPFixtures.customerWithSingleCardTokenSourceJSON() - let expectedPaymentMethodsJSON = [ - STPFixtures.paymentMethodJSON(), STPFixtures.applePayPaymentMethodJSON(), - ] - let apiClient = stubbedAPIClient() - - stubRetrieveCustomers( - key: customerKey, - returningCustomerJSON: expectedCustomerJSON, - expectedCount: 1, - apiClient: apiClient - ) - stubListPaymentMethods( - key: customerKey, - paymentMethodJSONs: expectedPaymentMethodsJSON, - expectedCount: 1, - apiClient: apiClient - ) - - let ekm = MockEphemeralKeyManager(key: customerKey, error: nil) - let sut = STPCustomerContext(keyManager: ekm, apiClient: apiClient) - // Give the mocked API request a little time to complete and cache the customer, then check cache - let exp2 = expectation(description: "listPaymentMethods") - DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + ohhttpDelay) { - sut.listPaymentMethodsForCustomer { paymentMethods, _ in - // Apple Pay should be filtered out - XCTAssertEqual(paymentMethods!.count, 1) - exp2.fulfill() - } - } - waitForExpectations(timeout: 2, handler: nil) - } - - func testIncludesApplePayPaymentMethods() { - let customerKey = STPFixtures.ephemeralKey() - let expectedCustomerJSON = STPFixtures.customerWithSingleCardTokenSourceJSON() - let expectedPaymentMethodsJSON = [ - STPFixtures.paymentMethodJSON(), STPFixtures.applePayPaymentMethodJSON(), - ] - let apiClient = stubbedAPIClient() - - stubRetrieveCustomers( - key: customerKey, - returningCustomerJSON: expectedCustomerJSON, - expectedCount: 1, - apiClient: apiClient - ) - stubListPaymentMethods( - key: customerKey, - paymentMethodJSONs: expectedPaymentMethodsJSON, - expectedCount: 1, - apiClient: apiClient - ) - - let ekm = MockEphemeralKeyManager(key: customerKey, error: nil) - let sut = STPCustomerContext(keyManager: ekm, apiClient: apiClient) - sut.includeApplePayPaymentMethods = true - // Give the mocked API request a little time to complete and cache the customer, then check cache - let exp2 = expectation(description: "listPaymentMethods") - DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + ohhttpDelay) { - sut.listPaymentMethodsForCustomer { paymentMethods, _ in - // Apple Pay should be included - XCTAssertEqual(paymentMethods!.count, 2) - exp2.fulfill() - } - } - waitForExpectations(timeout: 2, handler: nil) - } - - func testFiltersApplePaySourcesByDefault() { - let customerKey = STPFixtures.ephemeralKey() - let expectedCustomerJSON = STPFixtures.customerWithCardAndApplePaySourcesJSON() - let expectedPaymentMethodsJSON = [ - STPFixtures.paymentMethodJSON(), STPFixtures.applePayPaymentMethodJSON(), - ] - let apiClient = stubbedAPIClient() - - stubRetrieveCustomers( - key: customerKey, - returningCustomerJSON: expectedCustomerJSON, - expectedCount: 1, - apiClient: apiClient - ) - stubListPaymentMethods( - key: customerKey, - paymentMethodJSONs: expectedPaymentMethodsJSON, - expectedCount: 1, - apiClient: apiClient - ) - - let ekm = MockEphemeralKeyManager(key: customerKey, error: nil) - let sut = STPCustomerContext(keyManager: ekm, apiClient: apiClient) - // Give the mocked API request a little time to complete and cache the customer, then check cache - let exp = expectation(description: "retrieveCustomer") - DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + ohhttpDelay) { - sut.retrieveCustomer { customer, _ in - // Apple Pay should be filtered out - XCTAssertEqual(customer!.sources.count, 1) - exp.fulfill() - } - } - waitForExpectations(timeout: 2, handler: nil) - } - - func testIncludeApplePaySources() { - let customerKey = STPFixtures.ephemeralKey() - let expectedCustomerJSON = STPFixtures.customerWithCardAndApplePaySourcesJSON() - let expectedPaymentMethodsJSON = [ - STPFixtures.paymentMethodJSON(), STPFixtures.applePayPaymentMethodJSON(), - ] - let apiClient = stubbedAPIClient() - - stubRetrieveCustomers( - key: customerKey, - returningCustomerJSON: expectedCustomerJSON, - expectedCount: 1, - apiClient: apiClient - ) - stubListPaymentMethods( - key: customerKey, - paymentMethodJSONs: expectedPaymentMethodsJSON, - expectedCount: 1, - apiClient: apiClient - ) - - let ekm = MockEphemeralKeyManager(key: customerKey, error: nil) - let sut = STPCustomerContext(keyManager: ekm, apiClient: apiClient) - sut.includeApplePayPaymentMethods = true - // Give the mocked API request a little time to complete and cache the customer, then check cache - let exp = expectation(description: "retrieveCustomer") - DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + ohhttpDelay) { - sut.retrieveCustomer { customer, _ in - // Apple Pay should be filtered out - XCTAssertEqual(customer!.sources.count, 2) - exp.fulfill() - } - } - waitForExpectations(timeout: 2, handler: nil) - } - - let ohhttpDelay = 0.1 -} diff --git a/Stripe/StripeiOSTests/STPEphemeralKeyTest.swift b/Stripe/StripeiOSTests/STPEphemeralKeyTest.swift index b424c92adac..da37c4de265 100644 --- a/Stripe/StripeiOSTests/STPEphemeralKeyTest.swift +++ b/Stripe/StripeiOSTests/STPEphemeralKeyTest.swift @@ -27,6 +27,5 @@ class STPEphemeralKeyTest: XCTestCase { Date(timeIntervalSince1970: TimeInterval((json["expires"] as! NSNumber).doubleValue)) ) XCTAssertEqual(key.livemode, (json["livemode"] as! NSNumber).boolValue) - XCTAssertEqual(key.customerID, "cus_123") } } diff --git a/Stripe/StripeiOSTests/STPImageLibraryTest.swift b/Stripe/StripeiOSTests/STPImageLibraryTest.swift index b90d6e5d223..368e8e61575 100644 --- a/Stripe/StripeiOSTests/STPImageLibraryTest.swift +++ b/Stripe/StripeiOSTests/STPImageLibraryTest.swift @@ -30,10 +30,6 @@ class STPImageLibraryTestSwift: XCTestCase { ] func testCardIconMethods() { - STPAssertEqualImages( - STPImageLibrary.applePayCardImage(), - STPImageLibrary.safeImageNamed("stp_card_applepay", templateIfAvailable: false) - ) STPAssertEqualImages( STPImageLibrary.amexCardImage(), STPImageLibrary.safeImageNamed("stp_card_amex", templateIfAvailable: false) @@ -125,84 +121,6 @@ class STPImageLibraryTestSwift: XCTestCase { } } - func testTemplatedBrandImageForCardBrand() { - for brand in Self.cardBrands { - let image = STPImageLibrary.templatedBrandImage(for: brand) - - switch brand { - case .visa: - STPAssertEqualImages( - image, - STPImageLibrary.safeImageNamed( - "stp_card_visa_template", - templateIfAvailable: true - ) - ) - case .amex: - STPAssertEqualImages( - image, - STPImageLibrary.safeImageNamed( - "stp_card_amex_template", - templateIfAvailable: true - ) - ) - case .mastercard: - STPAssertEqualImages( - image, - STPImageLibrary.safeImageNamed( - "stp_card_mastercard_template", - templateIfAvailable: true - ) - ) - case .discover: - STPAssertEqualImages( - image, - STPImageLibrary.safeImageNamed( - "stp_card_discover_template", - templateIfAvailable: true - ) - ) - case .JCB: - STPAssertEqualImages( - image, - STPImageLibrary.safeImageNamed( - "stp_card_jcb_template", - templateIfAvailable: true - ) - ) - case .dinersClub: - STPAssertEqualImages( - image, - STPImageLibrary.safeImageNamed( - "stp_card_diners_template", - templateIfAvailable: true - ) - ) - case .unionPay: - STPAssertEqualImages( - image, - STPImageLibrary.safeImageNamed( - "stp_card_unionpay_template", - templateIfAvailable: true - ) - ) - case .cartesBancaires: - STPAssertEqualImages( - image, - STPImageLibrary.safeImageNamed( - "stp_card_cartes_bancaires_template", - templateIfAvailable: true - ) - ) - case .unknown: - STPAssertEqualImages( - image, - STPImageLibrary.safeImageNamed("stp_card_unknown", templateIfAvailable: true) - ) - } - } - } - func testUnpaddedImageForCardBrands() { for brand in STPCardBrand.allCases { let image = STPImageLibrary.unpaddedCardBrandImage(for: brand) @@ -241,52 +159,10 @@ class STPImageLibraryTestSwift: XCTestCase { } func testMiscImages() { - STPAssertEqualImages( - STPLegacyImageLibrary.addIcon(), - STPLegacyImageLibrary.safeImageNamed("stp_icon_add", templateIfAvailable: false) - ) STPAssertEqualImages( STPImageLibrary.bankIcon(), STPImageLibrary.safeImageNamed("stp_icon_bank", templateIfAvailable: false) ) - STPAssertEqualImages( - STPLegacyImageLibrary.checkmarkIcon(), - STPLegacyImageLibrary.safeImageNamed("stp_icon_checkmark", templateIfAvailable: false) - ) - STPAssertEqualImages( - STPLegacyImageLibrary.largeCardFrontImage(), - STPLegacyImageLibrary.safeImageNamed("stp_card_form_front", templateIfAvailable: false) - ) - STPAssertEqualImages( - STPLegacyImageLibrary.largeCardBackImage(), - STPLegacyImageLibrary.safeImageNamed("stp_card_form_back", templateIfAvailable: false) - ) - STPAssertEqualImages( - STPLegacyImageLibrary.largeCardAmexCVCImage(), - STPLegacyImageLibrary.safeImageNamed( - "stp_card_form_amex_cvc", - templateIfAvailable: false - ) - ) - STPAssertEqualImages( - STPLegacyImageLibrary.largeShippingImage(), - STPLegacyImageLibrary.safeImageNamed("stp_shipping_form", templateIfAvailable: false) - ) - } - - func testFPXImages() { - // Probably better to make STPFPXBankBrand conform to CaseIterable, - // but let's not change behavior of a legacy product just for this test. - for i in 0...(STPFPXBankBrand.unknown.rawValue - 1) { - let brand = STPFPXBankBrand(rawValue: i)! - let bankIdentifier = STPFPXBank.identifierFrom(brand)! - let bankImageName = "stp_bank_fpx_" + bankIdentifier - STPAssertEqualImages( - STPLegacyImageLibrary.fpxBrandImage(for: brand), - STPLegacyImageLibrary.safeImageNamed(bankImageName, templateIfAvailable: false) - ) - - } } func testBankIconCodeImagesExist() { diff --git a/Stripe/StripeiOSTests/STPMocks.h b/Stripe/StripeiOSTests/STPMocks.h deleted file mode 100644 index 1b782caa656..00000000000 --- a/Stripe/StripeiOSTests/STPMocks.h +++ /dev/null @@ -1,34 +0,0 @@ -// -// STPMocks.h -// Stripe -// -// Created by Ben Guo on 4/5/17. -// Copyright © 2017 Stripe, Inc. All rights reserved. -// - -#import -#import -@import Stripe; - -@interface STPMocks : NSObject - -/** - A stateless customer context that always retrieves the same customer object. - */ -+ (STPCustomerContext *)staticCustomerContext; - -/** - A static customer context that always retrieves the given customer and the given payment methods. - Selecting a default source and attaching a source have no effect. - */ -+ (STPCustomerContext *)staticCustomerContextWithCustomer:(STPCustomer *)customer paymentMethods:(NSArray *)paymentMethods; - -/** - A PaymentConfiguration object with a fake publishable key and a fake apple - merchant identifier that ignores the true value of [StripeAPI deviceSupportsApplePay] - and bases its `applePayEnabled` value solely on what is set - in `additionalPaymentOptions` - */ -+ (STPPaymentConfiguration *)paymentConfigurationWithApplePaySupportingDevice; - -@end diff --git a/Stripe/StripeiOSTests/STPMocks.m b/Stripe/StripeiOSTests/STPMocks.m deleted file mode 100644 index 63787637994..00000000000 --- a/Stripe/StripeiOSTests/STPMocks.m +++ /dev/null @@ -1,55 +0,0 @@ -// -// STPMocks.m -// Stripe -// -// Created by Ben Guo on 4/5/17. -// Copyright © 2017 Stripe, Inc. All rights reserved. -// - -#import "STPMocks.h" - -@import StripePaymentsObjcTestUtils; -#import "StripeiOS_Tests-Swift.h" - -@interface STPPaymentConfiguration (STPMocks) - -/** - Mock apple pay enabled response to just be based on setting and not hardware - capability. - - `paymentConfigurationWithApplePaySupportingDevice` forwards calls to the - real method to this stub - */ -- (BOOL)stpmock_applePayEnabled; - -@end - -@implementation STPMocks - -+ (STPCustomerContext *)staticCustomerContext { - return [self staticCustomerContextWithCustomer:[STPFixtures customerWithSingleCardTokenSource] - paymentMethods:@[[STPFixtures paymentMethod]]]; -} - -+ (STPCustomerContext *)staticCustomerContextWithCustomer:(STPCustomer *)customer paymentMethods:(NSArray *)paymentMethods { - return [[Testing_StaticCustomerContext_Objc alloc] initWithCustomer:customer paymentMethods:paymentMethods]; -} - -+ (STPPaymentConfiguration *)paymentConfigurationWithApplePaySupportingDevice { - STPPaymentConfiguration *config = [STPPaymentConfiguration new]; - config.appleMerchantIdentifier = @"fake_apple_merchant_id"; - id partialMock = OCMPartialMock(config); - OCMStub([partialMock applePayEnabled]).andCall(partialMock, @selector(stpmock_applePayEnabled)); - return partialMock; -} - -@end - -@implementation STPPaymentConfiguration (STPMocks) - -- (BOOL)stpmock_applePayEnabled { - return self.applePayEnabled; -} - -@end - diff --git a/Stripe/StripeiOSTests/STPPaymentConfigurationTest.m b/Stripe/StripeiOSTests/STPPaymentConfigurationTest.m deleted file mode 100644 index 8f23a409830..00000000000 --- a/Stripe/StripeiOSTests/STPPaymentConfigurationTest.m +++ /dev/null @@ -1,141 +0,0 @@ -// -// STPPaymentConfigurationTest.m -// Stripe -// -// Created by Joey Dong on 7/18/17. -// Copyright © 2017 Stripe, Inc. All rights reserved. -// - -#import -#import - - -@import StripeCore; - - - - -@interface STPPaymentConfigurationTest : XCTestCase - -@end - -@implementation STPPaymentConfigurationTest - -- (void)testSharedConfiguration { - XCTAssertEqual([STPPaymentConfiguration sharedConfiguration], [STPPaymentConfiguration sharedConfiguration]); -} - -- (void)testInit { - STPPaymentConfiguration *paymentConfiguration = [[STPPaymentConfiguration alloc] init]; - - XCTAssertFalse(paymentConfiguration.fpxEnabled); - XCTAssertEqual(paymentConfiguration.requiredBillingAddressFields, STPBillingAddressFieldsPostalCode); - XCTAssertNil(paymentConfiguration.requiredShippingAddressFields); - XCTAssert(paymentConfiguration.verifyPrefilledShippingAddress); - XCTAssertEqual(paymentConfiguration.shippingType, STPShippingTypeShipping); - XCTAssertEqualObjects(paymentConfiguration.companyName, @"xctest"); - XCTAssertNil(paymentConfiguration.appleMerchantIdentifier); - XCTAssert(paymentConfiguration.canDeletePaymentOptions); - XCTAssertFalse(paymentConfiguration.cardScanningEnabled); -} - -- (void)testApplePayEnabledSatisfied { - id stripeMock = OCMClassMock([StripeAPI class]); - OCMStub([stripeMock deviceSupportsApplePay]).andReturn(YES); - - STPPaymentConfiguration *paymentConfiguration = [[STPPaymentConfiguration alloc] init]; - paymentConfiguration.appleMerchantIdentifier = @"appleMerchantIdentifier"; - - XCTAssert([paymentConfiguration applePayEnabled]); -} - -- (void)testApplePayEnabledMissingAppleMerchantIdentifier { - id stripeMock = OCMClassMock([StripeAPI class]); - OCMStub([stripeMock deviceSupportsApplePay]).andReturn(YES); - - STPPaymentConfiguration *paymentConfiguration = [[STPPaymentConfiguration alloc] init]; - paymentConfiguration.appleMerchantIdentifier = nil; - - XCTAssertFalse([paymentConfiguration applePayEnabled]); -} - -- (void)testApplePayEnabledDisallowAdditionalPaymentOptions { - id stripeMock = OCMClassMock([StripeAPI class]); - OCMStub([stripeMock deviceSupportsApplePay]).andReturn(YES); - - STPPaymentConfiguration *paymentConfiguration = [[STPPaymentConfiguration alloc] init]; - paymentConfiguration.appleMerchantIdentifier = @"appleMerchantIdentifier"; - paymentConfiguration.applePayEnabled = false; - - XCTAssertFalse([paymentConfiguration applePayEnabled]); -} - -- (void)testApplePayEnabledMisisngDeviceSupport { - // Change the supported networks list to reset the applePayEnabled cache - StripeAPI.additionalEnabledApplePayNetworks = @[PKPaymentNetworkJCB]; - id paymentAuthControllerMock = OCMClassMock([PKPaymentAuthorizationController class]); - OCMStub([paymentAuthControllerMock canMakePaymentsUsingNetworks:[OCMArg any]]).andReturn(NO); - - STPPaymentConfiguration *paymentConfiguration = [[STPPaymentConfiguration alloc] init]; - paymentConfiguration.appleMerchantIdentifier = @"appleMerchantIdentifier"; - - XCTAssertFalse([paymentConfiguration applePayEnabled]); - [paymentAuthControllerMock stopMocking]; - // Re-reset cache: - StripeAPI.additionalEnabledApplePayNetworks = @[]; -} - -#pragma mark - Description - -- (void)testDescription { - STPPaymentConfiguration *paymentConfiguration = [[STPPaymentConfiguration alloc] init]; - XCTAssert(paymentConfiguration.description); -} - -#pragma mark - NSCopying - -- (void)testCopyWithZone { - NSSet *allFields = [NSSet setWithArray:@[STPContactField.postalAddress, - STPContactField.emailAddress, - STPContactField.phoneNumber, - STPContactField.name]]; - - STPPaymentConfiguration *paymentConfigurationA = [[STPPaymentConfiguration alloc] init]; -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated" - paymentConfigurationA.publishableKey = @"publishableKey"; - paymentConfigurationA.stripeAccount = @"stripeAccount"; -#pragma clang diagnostic pop - paymentConfigurationA.applePayEnabled = YES; - 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"; - paymentConfigurationA.canDeletePaymentOptions = NO; - paymentConfigurationA.cardScanningEnabled = NO; - - STPPaymentConfiguration *paymentConfigurationB = [paymentConfigurationA copy]; - XCTAssertNotEqual(paymentConfigurationA, paymentConfigurationB); - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated" - XCTAssertEqualObjects(paymentConfigurationB.publishableKey, @"publishableKey"); - XCTAssertEqualObjects(paymentConfigurationB.stripeAccount, @"stripeAccount"); -#pragma clang diagnostic pop - XCTAssertTrue(paymentConfigurationB.applePayEnabled); - XCTAssertEqual(paymentConfigurationB.requiredBillingAddressFields, STPBillingAddressFieldsFull); - XCTAssertEqualObjects(paymentConfigurationB.requiredShippingAddressFields, allFields); - XCTAssertFalse(paymentConfigurationB.verifyPrefilledShippingAddress); - 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); - XCTAssertEqual(paymentConfigurationA.cardScanningEnabled, paymentConfigurationB.cardScanningEnabled); -} - -@end diff --git a/Stripe/StripeiOSTests/STPPaymentContextApplePayTest.swift b/Stripe/StripeiOSTests/STPPaymentContextApplePayTest.swift deleted file mode 100644 index 1e317ef3d38..00000000000 --- a/Stripe/StripeiOSTests/STPPaymentContextApplePayTest.swift +++ /dev/null @@ -1,204 +0,0 @@ -// -// STPPaymentContextApplePayTest.swift -// StripeiOS Tests -// -// Created by Brian Dorfman on 8/1/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -@testable@_spi(STP) import Stripe -@testable@_spi(STP) import StripeCore -@testable@_spi(STP) import StripePayments -@testable@_spi(STP) import StripePaymentSheet -@testable@_spi(STP) import StripePaymentsUI - -/// These tests cover STPPaymentContext's Apple Pay specific behavior: -/// - building a PKPaymentRequest -/// - determining paymentSummaryItems -class STPPaymentContextApplePayTest: XCTestCase { - func buildPaymentContext() -> STPPaymentContext { - let config = STPPaymentConfiguration() - config.appleMerchantIdentifier = "fake_merchant_id" - let theme = STPTheme.defaultTheme - let customerContext = Testing_StaticCustomerContext() - let paymentContext = STPPaymentContext( - customerContext: customerContext, - configuration: config, - theme: theme - ) - return paymentContext - } - - // MARK: - buildPaymentRequest - func testBuildPaymentRequest_totalAmount() { - let context = buildPaymentContext() - context.paymentAmount = 150 - let request = context.buildPaymentRequest() - - XCTAssertTrue( - (request?.paymentSummaryItems.last?.amount == NSDecimalNumber(string: "1.50")), - "PKPayment total is not equal to STPPaymentContext amount" - ) - } - - func testBuildPaymentRequest_USDDefault() { - let context = buildPaymentContext() - context.paymentAmount = 100 - let request = context.buildPaymentRequest() - - XCTAssertTrue( - (request?.currencyCode == "USD"), - "Default PKPaymentRequest currency code is not USD" - ) - } - - func testBuildPaymentRequest_currency() { - let context = buildPaymentContext() - context.paymentAmount = 100 - context.paymentCurrency = "GBP" - let request = context.buildPaymentRequest() - - XCTAssertTrue( - (request?.currencyCode == "GBP"), - "PKPaymentRequest currency code is not equal to STPPaymentContext currency" - ) - } - - func testBuildPaymentRequest_uppercaseCurrency() { - let context = buildPaymentContext() - context.paymentAmount = 100 - context.paymentCurrency = "eur" - let request = context.buildPaymentRequest() - - XCTAssertTrue( - (request?.currencyCode == "EUR"), - "PKPaymentRequest currency code is not uppercased" - ) - } - - func testSummaryItems() -> [PKPaymentSummaryItem]? { - return [ - PKPaymentSummaryItem( - label: "First item", - amount: NSDecimalNumber(mantissa: 20, exponent: 0, isNegative: false) - ), - PKPaymentSummaryItem( - label: "Second item", - amount: NSDecimalNumber(mantissa: 90, exponent: 0, isNegative: false) - ), - PKPaymentSummaryItem( - label: "Discount", - amount: NSDecimalNumber(mantissa: 10, exponent: 0, isNegative: true) - ), - PKPaymentSummaryItem( - label: "Total", - amount: NSDecimalNumber(mantissa: 100, exponent: 0, isNegative: false) - ), - ] - } - - func testBuildPaymentRequest_summaryItems() { - let context = buildPaymentContext() - context.paymentSummaryItems = testSummaryItems()! - let request = context.buildPaymentRequest() - - XCTAssertTrue((request?.paymentSummaryItems == context.paymentSummaryItems)) - } - - // MARK: - paymentSummaryItems - func testSetPaymentAmount_generateSummaryItems() { - let context = buildPaymentContext() - context.paymentAmount = 10000 - context.paymentCurrency = "USD" - let itemTotalAmount = context.paymentSummaryItems.last?.amount - let correctTotalAmount = NSDecimalNumber.stp_decimalNumber( - withAmount: context.paymentAmount, - currency: context.paymentCurrency - ) - - XCTAssertTrue((itemTotalAmount == correctTotalAmount)) - } - - func testSetPaymentAmount_generateSummaryItemsShippingMethod() { - let context = buildPaymentContext() - context.paymentAmount = 100 - context.configuration.companyName = "Foo Company" - let method = PKShippingMethod() - method.amount = NSDecimalNumber(string: "5.99") - method.label = "FedEx" - method.detail = "foo" - method.identifier = "123" - context.selectedShippingMethod = method - - let items = context.paymentSummaryItems - XCTAssertEqual(Int(items.count), 2) - let item1 = items[0] - XCTAssertEqual(item1.label, "FedEx") - XCTAssertEqual(item1.amount, NSDecimalNumber(string: "5.99")) - let item2 = items[1] - XCTAssertEqual(item2.label, "Foo Company") - XCTAssertEqual(item2.amount, NSDecimalNumber(string: "6.99")) - } - - func testSummaryItemsToSummaryItems_shippingMethod() { - let context = buildPaymentContext() - let item1 = PKPaymentSummaryItem() - item1.amount = NSDecimalNumber(string: "1.00") - item1.label = "foo" - let item2 = PKPaymentSummaryItem() - item2.amount = NSDecimalNumber(string: "9.00") - item2.label = "bar" - let item3 = PKPaymentSummaryItem() - item3.amount = NSDecimalNumber(string: "10.00") - item3.label = "baz" - context.paymentSummaryItems = [item1, item2, item3] - let method = PKShippingMethod() - method.amount = NSDecimalNumber(string: "5.99") - method.label = "FedEx" - method.detail = "foo" - method.identifier = "123" - context.selectedShippingMethod = method - - let items = context.paymentSummaryItems - XCTAssertEqual(Int(items.count), 4) - let resultItem1 = items[0] - XCTAssertEqual(resultItem1.label, "foo") - XCTAssertEqual(resultItem1.amount, NSDecimalNumber(string: "1.00")) - let resultItem2 = items[1] - XCTAssertEqual(resultItem2.label, "bar") - XCTAssertEqual(resultItem2.amount, NSDecimalNumber(string: "9.00")) - let resultItem3 = items[2] - XCTAssertEqual(resultItem3.label, "FedEx") - XCTAssertEqual(resultItem3.amount, NSDecimalNumber(string: "5.99")) - let resultItem4 = items[3] - XCTAssertEqual(resultItem4.label, "baz") - XCTAssertEqual(resultItem4.amount, NSDecimalNumber(string: "15.99")) - } - - func testAmountToAmount_shippingMethod_usd() { - let context = buildPaymentContext() - context.paymentAmount = 100 - let method = PKShippingMethod() - method.amount = NSDecimalNumber(string: "5.99") - method.label = "FedEx" - method.detail = "foo" - method.identifier = "123" - context.selectedShippingMethod = method - let amount = context.paymentAmount - XCTAssertEqual(amount, 699) - } - - func testSummaryItems_generateAmountDecimalCurrency() { - let context = buildPaymentContext() - context.paymentSummaryItems = testSummaryItems()! - context.paymentCurrency = "USD" - XCTAssertTrue(context.paymentAmount == 10000) - } - - func testSummaryItems_generateAmountNoDecimalCurrency() { - let context = buildPaymentContext() - context.paymentSummaryItems = testSummaryItems()! - context.paymentCurrency = "JPY" - XCTAssertTrue(context.paymentAmount == 100) - } -} diff --git a/Stripe/StripeiOSTests/STPPaymentContextSnapshotTests.swift b/Stripe/StripeiOSTests/STPPaymentContextSnapshotTests.swift deleted file mode 100644 index 319e9b9673c..00000000000 --- a/Stripe/StripeiOSTests/STPPaymentContextSnapshotTests.swift +++ /dev/null @@ -1,84 +0,0 @@ -// Converted to Swift 5.8.1 by Swiftify v5.8.28463 - https://swiftify.com/ -// -// STPPaymentContextSnapshotTests.m -// StripeiOS Tests -// -// Created by Ben Guo on 12/13/17. -// Copyright © 2017 Stripe, Inc. All rights reserved. -// - -import iOSSnapshotTestCaseCore -import StripeCoreTestUtils - -class STPPaymentContextSnapshotTests: STPSnapshotTestCase { - var customerContext: STPCustomerContext? - var config: STPPaymentConfiguration? - var hostViewController: UINavigationController? - var paymentContext: STPPaymentContext? - - override func setUp() { - super.setUp() - let config = STPPaymentConfiguration() - config.companyName = "Test Company" - config.requiredBillingAddressFields = .full - config.shippingType = .shipping - self.config = config - let customerContext = Testing_StaticCustomerContext_Objc.init(customer: STPFixtures.customerWithCardTokenAndSourceSources(), paymentMethods: [STPFixtures.paymentMethod(), STPFixtures.paymentMethod()]) - self.customerContext = customerContext - - let viewController = UIViewController() - hostViewController = stp_navigationControllerForSnapshotTest(withRootVC: viewController) - } - - func buildPaymentContext() { - let context = STPPaymentContext(customerContext: customerContext!) - context.hostViewController = hostViewController - context.configuration.requiredShippingAddressFields = Set([STPContactField.emailAddress]) - paymentContext = context - } - - func testPushPaymentOptionsSmallTitle() { - buildPaymentContext() - - hostViewController?.navigationBar.prefersLargeTitles = false - paymentContext?.largeTitleDisplayMode = UINavigationItem.LargeTitleDisplayMode.automatic - paymentContext?.pushPaymentOptionsViewController() - let view = stp_preparedAndSizedViewForSnapshotTest(from: hostViewController)! - STPSnapshotVerifyView(view, identifier: nil) - } - - // This test renders at a slightly larger size half the time. - // We're deprecating Basic Integration soon, and we've spent enough time on this, - // so these tests are being disabled for now. - // - (void)testPushPaymentOptionsLargeTitle { - // [self buildPaymentContext]; - // - // self.hostViewController.navigationBar.prefersLargeTitles = YES; - // self.paymentContext.largeTitleDisplayMode = UINavigationItemLargeTitleDisplayModeAutomatic; - // [self.paymentContext pushPaymentOptionsViewController]; - // UIView *view = [self stp_preparedAndSizedViewForSnapshotTestFromNavigationController:self.hostViewController]; - // STPSnapshotVerifyView(view, nil); - // } - - func testPushShippingAddressSmallTitle() { - buildPaymentContext() - - hostViewController?.navigationBar.prefersLargeTitles = false - paymentContext?.largeTitleDisplayMode = UINavigationItem.LargeTitleDisplayMode.automatic - paymentContext?.pushShippingViewController() - let view = stp_preparedAndSizedViewForSnapshotTest(from: hostViewController)! - STPSnapshotVerifyView(view, identifier: nil) - } - // This test renders at a slightly larger size half the time. - // We're deprecating Basic Integration soon, and we've spent enough time on this, - // so these tests are being disabled for now. - // - (void)testPushShippingAddressLargeTitle { - // [self buildPaymentContext]; - // - // self.hostViewController.navigationBar.prefersLargeTitles = YES; - // self.paymentContext.largeTitleDisplayMode = UINavigationItemLargeTitleDisplayModeAutomatic; - // [self.paymentContext pushShippingViewController]; - // UIView *view = [self stp_preparedAndSizedViewForSnapshotTestFromNavigationController:self.hostViewController]; - // STPSnapshotVerifyView(view, nil); - // } -} diff --git a/Stripe/StripeiOSTests/STPPaymentOptionsViewControllerLocalizationSnapshotTests.swift b/Stripe/StripeiOSTests/STPPaymentOptionsViewControllerLocalizationSnapshotTests.swift deleted file mode 100644 index 0853069526d..00000000000 --- a/Stripe/StripeiOSTests/STPPaymentOptionsViewControllerLocalizationSnapshotTests.swift +++ /dev/null @@ -1,102 +0,0 @@ -// -// STPPaymentOptionsViewControllerLocalizationSnapshotTests.swift -// StripeiOS Tests -// -// Created by Brian Dorfman on 10/17/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -import iOSSnapshotTestCase -import StripeCoreTestUtils - -@testable@_spi(STP) import Stripe -@testable@_spi(STP) import StripeCore -@testable@_spi(STP) import StripePayments -@testable@_spi(STP) import StripePaymentSheet -@testable@_spi(STP) import StripePaymentsUI - -class MockSTPPaymentOptionsViewControllerDelegate: NSObject, STPPaymentOptionsViewControllerDelegate -{ - func paymentOptionsViewController( - _ paymentOptionsViewController: STPPaymentOptionsViewController, - didFailToLoadWithError error: Error - ) { - } - - func paymentOptionsViewControllerDidFinish( - _ paymentOptionsViewController: STPPaymentOptionsViewController - ) { - } - - func paymentOptionsViewControllerDidCancel( - _ paymentOptionsViewController: STPPaymentOptionsViewController - ) { - } - -} - -class STPPaymentOptionsViewControllerLocalizationSnapshotTests: STPSnapshotTestCase { - - func performSnapshotTest(forLanguage language: String?) { - let config = STPPaymentConfiguration() - config.companyName = "Test Company" - config.requiredBillingAddressFields = .full - let theme = STPTheme.defaultTheme - let paymentMethods = [STPFixtures.paymentMethod(), STPFixtures.paymentMethod()] - let customerContext = Testing_StaticCustomerContext.init( - customer: STPFixtures.customerWithCardTokenAndSourceSources(), - paymentMethods: paymentMethods - ) - let delegate = MockSTPPaymentOptionsViewControllerDelegate() - STPLocalizationUtils.overrideLanguage(to: language) - let paymentOptionsVC = STPPaymentOptionsViewController( - configuration: config, - theme: theme, - customerContext: customerContext, - delegate: delegate - ) - let didLoadExpectation = expectation(description: "VC did load") - - paymentOptionsVC.loadingPromise?.onSuccess({ (_) in - didLoadExpectation.fulfill() - }) - wait(for: [didLoadExpectation].compactMap { $0 }, timeout: 2) - - let viewToTest = stp_preparedAndSizedViewForSnapshotTest(from: paymentOptionsVC)! - - STPSnapshotVerifyView(viewToTest, identifier: nil) - STPLocalizationUtils.overrideLanguage(to: nil) - } - - func testGerman() { - performSnapshotTest(forLanguage: "de") - } - - func testEnglish() { - performSnapshotTest(forLanguage: "en") - } - - func testSpanish() { - performSnapshotTest(forLanguage: "es") - } - - func testFrench() { - performSnapshotTest(forLanguage: "fr") - } - - func testItalian() { - performSnapshotTest(forLanguage: "it") - } - - func testJapanese() { - performSnapshotTest(forLanguage: "ja") - } - - func testDutch() { - performSnapshotTest(forLanguage: "nl") - } - - func testChinese() { - performSnapshotTest(forLanguage: "zh-Hans") - } -} diff --git a/Stripe/StripeiOSTests/STPPaymentOptionsViewControllerTest.swift b/Stripe/StripeiOSTests/STPPaymentOptionsViewControllerTest.swift deleted file mode 100644 index 0555fa9799a..00000000000 --- a/Stripe/StripeiOSTests/STPPaymentOptionsViewControllerTest.swift +++ /dev/null @@ -1,351 +0,0 @@ -// -// STPPaymentOptionsViewControllerTest.swift -// StripeiOS Tests -// -// Created by Brian Dorfman on 10/10/17. -// Copyright © 2017 Stripe, Inc. All rights reserved. -// - -import OCMock - -@testable@_spi(STP) import Stripe -@testable@_spi(STP) import StripeCore -@testable@_spi(STP) import StripePayments -@testable@_spi(STP) import StripePaymentSheet -@testable@_spi(STP) import StripePaymentsUI - -class STPPaymentOptionsViewControllerTest: XCTestCase { - class MockSTPPaymentOptionsViewControllerDelegate: NSObject, - STPPaymentOptionsViewControllerDelegate - { - var didFail = false - func paymentOptionsViewController( - _ paymentOptionsViewController: STPPaymentOptionsViewController, - didFailToLoadWithError error: Error - ) { - didFail = true - } - - var didFinish = false - func paymentOptionsViewControllerDidFinish( - _ paymentOptionsViewController: STPPaymentOptionsViewController - ) { - didFinish = true - } - - var didCancel = false - func paymentOptionsViewControllerDidCancel( - _ paymentOptionsViewController: STPPaymentOptionsViewController - ) { - didCancel = true - } - - var didSelect = false - func paymentOptionsViewController( - _ paymentOptionsViewController: STPPaymentOptionsViewController, - didSelect paymentOption: STPPaymentOption - ) { - didSelect = true - } - } - - func buildViewController( - with customer: STPCustomer, - paymentMethods: [STPPaymentMethod], - configuration config: STPPaymentConfiguration, - delegate: STPPaymentOptionsViewControllerDelegate - ) -> STPPaymentOptionsViewController { - let mockCustomerContext = Testing_StaticCustomerContext( - customer: customer, - paymentMethods: paymentMethods - ) - return buildViewController( - with: mockCustomerContext, - configuration: config, - delegate: delegate - ) - } - - func buildViewController( - with customerContext: STPCustomerContext, - configuration config: STPPaymentConfiguration, - delegate: STPPaymentOptionsViewControllerDelegate - ) -> STPPaymentOptionsViewController { - let theme = STPTheme.defaultTheme - let vc = STPPaymentOptionsViewController( - configuration: config, - theme: theme, - customerContext: customerContext, - delegate: delegate - ) - let didLoadExpectation = expectation(description: "VC did load") - vc.loadingPromise?.onSuccess({ (_) in - didLoadExpectation.fulfill() - }) - - wait(for: [didLoadExpectation], timeout: 2) - - return vc - } - - /// When the customer has no sources, and card is the sole available payment - /// method, STPAddCardViewController should be shown. - func testInitWithNoSourcesAndConfigWithUseSourcesOffAndCardAvailable() { - let customer = STPFixtures.customerWithNoSources() - let config = STPPaymentConfiguration() - config.applePayEnabled = false - let delegate = MockSTPPaymentOptionsViewControllerDelegate() - let sut = buildViewController( - with: customer, - paymentMethods: [], - configuration: config, - delegate: delegate - ) - XCTAssertTrue((sut.internalViewController is STPAddCardViewController)) - } - - /// When the customer has a single card token source and the available payment methods - /// are card and apple pay, STPPaymentOptionsInternalVC should be shown. - func testInitWithSingleCardTokenSourceAndCardAvailable() { - let customer = STPFixtures.customerWithSingleCardTokenSource() - let paymentMethods = [STPFixtures.paymentMethod()] - let config = STPPaymentConfiguration() - let delegate = MockSTPPaymentOptionsViewControllerDelegate() - let sut = buildViewController( - with: customer, - paymentMethods: paymentMethods.compactMap { $0 }, - configuration: config, - delegate: delegate - ) - XCTAssertTrue((sut.internalViewController is STPPaymentOptionsInternalViewController)) - } - - /// When the customer has a single card source source and the available payment methods - /// are card only, STPPaymentOptionsInternalVC should be shown. - func testInitWithSingleCardSourceSourceAndCardAvailable() { - let customer = STPFixtures.customerWithSingleCardSourceSource() - let paymentMethods = [STPFixtures.paymentMethod()] - let config = STPPaymentConfiguration() - config.applePayEnabled = false - let delegate = MockSTPPaymentOptionsViewControllerDelegate() - let sut = buildViewController( - with: customer, - paymentMethods: paymentMethods.compactMap { $0 }, - configuration: config, - delegate: delegate - ) - XCTAssertTrue((sut.internalViewController is STPPaymentOptionsInternalViewController)) - } - - /// Tapping cancel in an internal AddCard view controller should result in a call to - /// didCancel: - func testAddCardCancelForwardsToDelegate() { - let customer = STPFixtures.customerWithNoSources() - let config = STPPaymentConfiguration() - let delegate = MockSTPPaymentOptionsViewControllerDelegate() - let sut = buildViewController( - with: customer, - paymentMethods: [], - configuration: config, - delegate: delegate - ) - XCTAssertTrue((sut.internalViewController is STPAddCardViewController)) - let cancelButton = sut.internalViewController?.navigationItem.leftBarButtonItem - _ = cancelButton?.target?.perform(cancelButton?.action, with: cancelButton) - - XCTAssertTrue(delegate.didCancel) - } - - /// Tapping cancel in an internal PaymentOptionsInternal view controller should - /// result in a call to didCancel: - func testInternalCancelForwardsToDelegate() { - let customer = STPFixtures.customerWithSingleCardTokenSource() - let paymentMethods = [STPFixtures.paymentMethod()] - let config = STPPaymentConfiguration() - let delegate = MockSTPPaymentOptionsViewControllerDelegate() - let sut = buildViewController( - with: customer, - paymentMethods: paymentMethods.compactMap { $0 }, - configuration: config, - delegate: delegate - ) - XCTAssertTrue((sut.internalViewController is STPPaymentOptionsInternalViewController)) - let cancelButton = sut.internalViewController?.navigationItem.leftBarButtonItem - _ = cancelButton?.target?.perform(cancelButton?.action, with: cancelButton) - - XCTAssertTrue(delegate.didCancel) - } - - /// When an AddCard view controller creates a card payment method, it should be attached to the - /// customer and the correct delegate methods should be called. - func testAddCardAttachesToCustomerAndFinishes() { - let config = STPPaymentConfiguration() - let customer = STPFixtures.customerWithNoSources() - let mockCustomerContext = Testing_StaticCustomerContext( - customer: customer, - paymentMethods: [] - ) - let delegate = MockSTPPaymentOptionsViewControllerDelegate() - let sut = buildViewController( - with: mockCustomerContext, - configuration: config, - delegate: delegate - ) - XCTAssertNotNil(sut.view) - XCTAssertTrue((sut.internalViewController is STPAddCardViewController)) - - let internalVC = sut.internalViewController as? STPAddCardViewController - let exp = expectation(description: "completion") - let expectedPaymentMethod = STPFixtures.paymentMethod() - internalVC?.delegate?.addCardViewController( - internalVC!, - didCreatePaymentMethod: expectedPaymentMethod - ) { error in - XCTAssertNil(error) - exp.fulfill() - } - - let _: ((Any?) -> Bool)? = { obj in - let paymentMethod = obj as? STPPaymentMethod - return paymentMethod?.stripeId == expectedPaymentMethod.stripeId - } - XCTAssertTrue(mockCustomerContext.didAttach) - XCTAssertTrue(delegate.didSelect) - XCTAssertTrue(delegate.didFinish) - waitForExpectations(timeout: 2, handler: nil) - } - - // Tests for race condition where the promise for fetching payment methods - // finishes in the context of intializing the sut, and `addCardViewControllerFooterView` - // is set directly after init, while internalViewController is `STPAddCardViewController` - func testSetAfterInit_addCardViewControllerFooterView_STPAddCardViewController() { - let customer = STPFixtures.customerWithNoSources() - let config = STPPaymentConfiguration() - config.applePayEnabled = false - let delegate = MockSTPPaymentOptionsViewControllerDelegate() - let sut = buildViewController( - with: customer, - paymentMethods: [], - configuration: config, - delegate: delegate - ) - sut.addCardViewControllerFooterView = UIView() - guard let payMethodsInternal = sut.internalViewController as? STPAddCardViewController else { - XCTFail() - return - } - XCTAssertNotNil(payMethodsInternal.customFooterView) - } - - // Tests for race condition where the promise for fetching payment methods - // finishes in the context of intializing the sut, and the `paymentOptionsViewControllerFooterView` - // is set directly after init, while internalViewController is `STPPaymentOptionsInternalViewController` - func testSetAfterInit_paymentOptionsViewControllerFooterView_STPPaymentOptionsInternalViewController() { - let customer = STPFixtures.customerWithSingleCardTokenSource() - let paymentMethods = [STPFixtures.paymentMethod()] - let config = STPPaymentConfiguration() - let delegate = MockSTPPaymentOptionsViewControllerDelegate() - let sut = buildViewController( - with: customer, - paymentMethods: paymentMethods.compactMap { $0 }, - configuration: config, - delegate: delegate - ) - sut.paymentOptionsViewControllerFooterView = UIView() - guard let payMethodsInternal = sut.internalViewController as? STPPaymentOptionsInternalViewController else { - XCTFail() - return - } -#if compiler(>=5.7) - XCTAssertNotNil(payMethodsInternal.customFooterView) -#endif - } - - // Tests for race condition where the promise for fetching payment methods - // finishes in the context of init the sut, and the `addCardViewControllerFooterView` - // is set directly after init, while internalViewController is `STPPaymentOptionsInternalViewController` - func testSetAfterInit_addCardViewControllerFooterView_STPPaymentOptionsInternalViewController() { - let customer = STPFixtures.customerWithSingleCardTokenSource() - let paymentMethods = [STPFixtures.paymentMethod()] - let config = STPPaymentConfiguration() - let delegate = MockSTPPaymentOptionsViewControllerDelegate() - let sut = buildViewController( - with: customer, - paymentMethods: paymentMethods.compactMap { $0 }, - configuration: config, - delegate: delegate - ) - sut.addCardViewControllerFooterView = UIView() - guard let payMethodsInternal = sut.internalViewController as? STPPaymentOptionsInternalViewController else { - XCTFail() - return - } -#if compiler(>=5.7) - XCTAssertNotNil(payMethodsInternal.addCardViewControllerCustomFooterView) -#endif - } - - // Tests for race condition where the promise for fetching payment methods - // finishes in the context of init the sut, and the `prefilledInformation` - // is set directly after init, while internalViewController is `STPPaymentOptionsInternalViewController` - func testSetAfterInit_prefilledInformation_STPPaymentOptionsInternalViewController() { - let customer = STPFixtures.customerWithSingleCardTokenSource() - let paymentMethods = [STPFixtures.paymentMethod()] - let config = STPPaymentConfiguration() - let delegate = MockSTPPaymentOptionsViewControllerDelegate() - let sut = buildViewController( - with: customer, - paymentMethods: paymentMethods.compactMap { $0 }, - configuration: config, - delegate: delegate - ) - let userInformation = STPUserInformation() - let address = STPAddress() - address.name = "John Doe" - address.line1 = "123 Main" - address.city = "Seattle" - address.state = "Washington" - address.postalCode = "98104" - address.phone = "2065551234" - userInformation.billingAddress = address - sut.prefilledInformation = userInformation - guard let payMethodsInternal = sut.internalViewController as? STPPaymentOptionsInternalViewController else { - XCTFail() - return - } -#if compiler(>=5.7) - XCTAssertNotNil(payMethodsInternal.prefilledInformation) -#endif - } - - // Tests for race condition where the promise for fetching payment methods - // finishes in the context of init the sut, and the `prefilledInformation` - // is set directly after init, while internalViewController is `STPAddCardViewController` - func testSetAfterInit_prefilledInformation_STPAddCardViewController() { - let customer = STPFixtures.customerWithNoSources() - let config = STPPaymentConfiguration() - config.applePayEnabled = false - let delegate = MockSTPPaymentOptionsViewControllerDelegate() - let sut = buildViewController( - with: customer, - paymentMethods: [], - configuration: config, - delegate: delegate - ) - let userInformation = STPUserInformation() - let address = STPAddress() - address.name = "John Doe" - address.line1 = "123 Main" - address.city = "Seattle" - address.state = "Washington" - address.postalCode = "98104" - address.phone = "2065551234" - userInformation.billingAddress = address - sut.prefilledInformation = userInformation - guard let payMethodsInternal = sut.internalViewController as? STPAddCardViewController else { - XCTFail() - return - } - XCTAssertNotNil(payMethodsInternal.prefilledInformation) - } -} diff --git a/Stripe/StripeiOSTests/STPPhoneNumberValidatorTest.swift b/Stripe/StripeiOSTests/STPPhoneNumberValidatorTest.swift index a1baab25f62..66ffe6336b2 100644 --- a/Stripe/StripeiOSTests/STPPhoneNumberValidatorTest.swift +++ b/Stripe/StripeiOSTests/STPPhoneNumberValidatorTest.swift @@ -14,51 +14,6 @@ private let kUSCountryCode = "US" private let kUKCountryCode = "UK" class STPPhoneNumberValidatorTest: XCTestCase { - func testValidPhoneNumbers() { - XCTAssertTrue( - STPPhoneNumberValidator.stringIsValidPhoneNumber( - "555-555-5555", - forCountryCode: kUSCountryCode - ) - ) - XCTAssertTrue( - STPPhoneNumberValidator.stringIsValidPhoneNumber( - "5555555555", - forCountryCode: kUSCountryCode - ) - ) - XCTAssertTrue( - STPPhoneNumberValidator.stringIsValidPhoneNumber( - "(555) 555-5555", - forCountryCode: kUSCountryCode - ) - ) - } - - func testInvalidPhoneNumbers() { - XCTAssertFalse( - STPPhoneNumberValidator.stringIsValidPhoneNumber("", forCountryCode: kUSCountryCode) - ) - XCTAssertFalse( - STPPhoneNumberValidator.stringIsValidPhoneNumber( - "555-555-555", - forCountryCode: kUSCountryCode - ) - ) - XCTAssertFalse( - STPPhoneNumberValidator.stringIsValidPhoneNumber( - "555-555-A555", - forCountryCode: kUSCountryCode - ) - ) - XCTAssertTrue( - STPPhoneNumberValidator.stringIsValidPhoneNumber( - "55555555555", - forCountryCode: kUSCountryCode - ) - ) - } - func testFormattedSanitizedPhoneNumberForString() { XCTAssertEqual( STPPhoneNumberValidator.formattedSanitizedPhoneNumber( diff --git a/Stripe/StripeiOSTests/STPShippingAddressViewControllerLocalizationSnapshotTests.swift b/Stripe/StripeiOSTests/STPShippingAddressViewControllerLocalizationSnapshotTests.swift deleted file mode 100644 index 1760b7a0d41..00000000000 --- a/Stripe/StripeiOSTests/STPShippingAddressViewControllerLocalizationSnapshotTests.swift +++ /dev/null @@ -1,113 +0,0 @@ -// -// STPShippingAddressViewControllerLocalizationSnapshotTests.swift -// StripeiOS Tests -// -// Created by Ben Guo on 11/3/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -import iOSSnapshotTestCase -import StripeCoreTestUtils - -@testable@_spi(STP) import Stripe -@testable@_spi(STP) import StripeCore -@testable@_spi(STP) import StripePayments -@testable@_spi(STP) import StripePaymentSheet -@testable@_spi(STP) import StripePaymentsUI - -class STPShippingAddressViewControllerLocalizationSnapshotTests: STPSnapshotTestCase { - - func performSnapshotTest( - forLanguage language: String?, - shippingType: STPShippingType, - contact: Bool - ) { - var identifier = (shippingType == .shipping) ? "shipping" : "delivery" - let config = STPPaymentConfiguration() - config.companyName = "Test Company" - config.requiredShippingAddressFields = Set([ - .postalAddress, - .emailAddress, - .phoneNumber, - .name, - ]) - if contact { - config.requiredShippingAddressFields = Set([.emailAddress]) - identifier = "contact" - } - config.shippingType = shippingType - - STPLocalizationUtils.overrideLanguage(to: language) - let info = STPUserInformation() - info.billingAddress = STPAddress() - info.billingAddress!.email = "@" // trigger "use billing address" button - - let shippingVC = STPShippingAddressViewController( - configuration: config, - theme: STPTheme.defaultTheme, - currency: nil, - shippingAddress: nil, - selectedShippingMethod: nil, - prefilledInformation: info - ) - - /// This method rejects nil or empty country codes to stop strange looking behavior - /// when scrolling to the top "unset" position in the picker, so put in - /// an invalid country code instead to test seeing the "Country" placeholder - shippingVC.addressViewModel.addressFieldTableViewCountryCode = "INVALID" - - let viewToTest = stp_preparedAndSizedViewForSnapshotTest(from: shippingVC)! - - STPSnapshotVerifyView(viewToTest, identifier: identifier) - - STPLocalizationUtils.overrideLanguage(to: nil) - } - - func testGerman() { - performSnapshotTest(forLanguage: "de", shippingType: .shipping, contact: false) - performSnapshotTest(forLanguage: "de", shippingType: .shipping, contact: true) - performSnapshotTest(forLanguage: "de", shippingType: .delivery, contact: false) - } - - func testEnglish() { - performSnapshotTest(forLanguage: "en", shippingType: .shipping, contact: false) - performSnapshotTest(forLanguage: "en", shippingType: .shipping, contact: true) - performSnapshotTest(forLanguage: "en", shippingType: .delivery, contact: false) - } - - func testSpanish() { - performSnapshotTest(forLanguage: "es", shippingType: .shipping, contact: false) - performSnapshotTest(forLanguage: "es", shippingType: .shipping, contact: true) - performSnapshotTest(forLanguage: "es", shippingType: .delivery, contact: false) - } - - func testFrench() { - performSnapshotTest(forLanguage: "fr", shippingType: .shipping, contact: false) - performSnapshotTest(forLanguage: "fr", shippingType: .shipping, contact: true) - performSnapshotTest(forLanguage: "fr", shippingType: .delivery, contact: false) - } - - func testItalian() { - performSnapshotTest(forLanguage: "it", shippingType: .shipping, contact: false) - performSnapshotTest(forLanguage: "it", shippingType: .shipping, contact: true) - performSnapshotTest(forLanguage: "it", shippingType: .delivery, contact: false) - } - - func testJapanese() { - performSnapshotTest(forLanguage: "ja", shippingType: .shipping, contact: false) - performSnapshotTest(forLanguage: "ja", shippingType: .shipping, contact: true) - performSnapshotTest(forLanguage: "ja", shippingType: .delivery, contact: false) - } - - func testDutch() { - performSnapshotTest(forLanguage: "nl", shippingType: .shipping, contact: false) - performSnapshotTest(forLanguage: "nl", shippingType: .shipping, contact: true) - performSnapshotTest(forLanguage: "nl", shippingType: .delivery, contact: false) - } - - func testChinese() { - performSnapshotTest(forLanguage: "zh-Hans", shippingType: .shipping, contact: false) - performSnapshotTest(forLanguage: "zh-Hans", shippingType: .shipping, contact: true) - performSnapshotTest(forLanguage: "zh-Hans", shippingType: .delivery, contact: false) - } -} diff --git a/Stripe/StripeiOSTests/STPShippingAddressViewControllerTest.swift b/Stripe/StripeiOSTests/STPShippingAddressViewControllerTest.swift deleted file mode 100644 index cc473049d34..00000000000 --- a/Stripe/StripeiOSTests/STPShippingAddressViewControllerTest.swift +++ /dev/null @@ -1,114 +0,0 @@ -// -// STPShippingAddressViewControllerTest.swift -// StripeiOS Tests -// -// Created by Cameron Sabol on 8/7/18. -// Copyright © 2018 Stripe, Inc. All rights reserved. -// - -import Stripe - -@testable@_spi(STP) import Stripe -@testable@_spi(STP) import StripeCore -@testable@_spi(STP) import StripePayments -@testable@_spi(STP) import StripePaymentSheet -@testable@_spi(STP) import StripePaymentsUI - -class STPShippingAddressViewControllerTest: XCTestCase { - func testPrefilledBillingAddress_removeAddress() { - let config = STPPaymentConfiguration() - config.requiredShippingAddressFields = Set([.postalAddress]) - - let address = STPAddress() - address.name = "John Smith Doe" - address.phone = "8885551212" - address.email = "foo@example.com" - address.line1 = "55 John St" - address.city = "Harare" - address.postalCode = "10002" - // Zimbabwe does not require zip codes, while the default locale for tests (US) does - address.country = "ZW" - // Sanity checks - XCTAssertFalse(STPPostalCodeValidator.postalCodeIsRequired(forCountryCode: "ZW")) - XCTAssertTrue(STPPostalCodeValidator.postalCodeIsRequired(forCountryCode: "US")) - - let sut = STPShippingAddressViewController( - configuration: config, - theme: STPTheme.defaultTheme, - currency: nil, - shippingAddress: address, - selectedShippingMethod: nil, - prefilledInformation: nil - ) - - XCTAssertNoThrow(sut.loadView()) - XCTAssertNoThrow(sut.viewDidLoad()) - } - - func testPrefilledBillingAddress_addAddressWithLimitedCountries() { - // Zimbabwe does not require zip codes, while the default locale for tests (US) does - NSLocale.stp_withLocale(as: NSLocale(localeIdentifier: "en_ZW")) { - // Sanity checks - XCTAssertFalse(STPPostalCodeValidator.postalCodeIsRequired(forCountryCode: "ZW")) - XCTAssertTrue(STPPostalCodeValidator.postalCodeIsRequired(forCountryCode: "US")) - let config = STPPaymentConfiguration() - config.requiredShippingAddressFields = Set([.postalAddress]) - config.availableCountries = Set(["CA", "BT"]) - - let address = STPAddress() - address.name = "John Smith Doe" - address.phone = "8885551212" - address.email = "foo@example.com" - address.line1 = "55 John St" - address.city = "New York" - address.state = "NY" - address.postalCode = "10002" - address.country = "US" - - let sut = STPShippingAddressViewController( - configuration: config, - theme: STPTheme.defaultTheme, - currency: nil, - shippingAddress: address, - selectedShippingMethod: nil, - prefilledInformation: nil - ) - - XCTAssertNoThrow(sut.loadView()) - XCTAssertNoThrow(sut.viewDidLoad()) - } - } - - func testPrefilledBillingAddress_addAddress() { - // Zimbabwe does not require zip codes, while the default locale for tests (US) does - NSLocale.stp_withLocale(as: NSLocale(localeIdentifier: "en_ZW")) { - // Sanity checks - XCTAssertFalse(STPPostalCodeValidator.postalCodeIsRequired(forCountryCode: "ZW")) - XCTAssertTrue(STPPostalCodeValidator.postalCodeIsRequired(forCountryCode: "US")) - let config = STPPaymentConfiguration() - config.requiredShippingAddressFields = Set([.postalAddress]) - - let address = STPAddress() - address.name = "John Smith Doe" - address.phone = "8885551212" - address.email = "foo@example.com" - address.line1 = "55 John St" - address.city = "New York" - address.state = "NY" - address.postalCode = "10002" - address.country = "US" - - let sut = STPShippingAddressViewController( - configuration: config, - theme: STPTheme.defaultTheme, - currency: nil, - shippingAddress: address, - selectedShippingMethod: nil, - prefilledInformation: nil - ) - - XCTAssertNoThrow(sut.loadView()) - XCTAssertNoThrow(sut.viewDidLoad()) - } - } -} diff --git a/Stripe/StripeiOSTests/STPShippingMethodsViewControllerLocalizationSnapshotTests.swift b/Stripe/StripeiOSTests/STPShippingMethodsViewControllerLocalizationSnapshotTests.swift deleted file mode 100644 index f9b256b34ee..00000000000 --- a/Stripe/StripeiOSTests/STPShippingMethodsViewControllerLocalizationSnapshotTests.swift +++ /dev/null @@ -1,76 +0,0 @@ -// -// STPShippingMethodsViewControllerLocalizationSnapshotTests.swift -// StripeiOS Tests -// -// Created by Ben Guo on 11/3/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -import iOSSnapshotTestCase -import StripeCoreTestUtils - -@testable@_spi(STP) import Stripe -@testable@_spi(STP) import StripeCore -@testable@_spi(STP) import StripePayments -@testable@_spi(STP) import StripePaymentSheet -@testable@_spi(STP) import StripePaymentsUI - -class STPShippingMethodsViewControllerLocalizationSnapshotTests: STPSnapshotTestCase { - - func performSnapshotTest(forLanguage language: String?) { - STPLocalizationUtils.overrideLanguage(to: language) - - let method1 = PKShippingMethod() - method1.label = "UPS Ground" - method1.detail = "Arrives in 3-5 days" - method1.amount = NSDecimalNumber(string: "0.00") - method1.identifier = "ups_ground" - let method2 = PKShippingMethod() - method2.label = "FedEx" - method2.detail = "Arrives tomorrow" - method2.amount = NSDecimalNumber(string: "5.99") - method2.identifier = "fedex" - - let shippingVC = STPShippingMethodsViewController( - shippingMethods: [method1, method2], - selectedShippingMethod: method1, - currency: "usd", - theme: STPTheme.defaultTheme - ) - let viewToTest = stp_preparedAndSizedViewForSnapshotTest(from: shippingVC)! - STPSnapshotVerifyView(viewToTest, identifier: nil) - STPLocalizationUtils.overrideLanguage(to: nil) - } - - func testGerman() { - performSnapshotTest(forLanguage: "de") - } - - func testEnglish() { - performSnapshotTest(forLanguage: "en") - } - - func testSpanish() { - performSnapshotTest(forLanguage: "es") - } - - func testFrench() { - performSnapshotTest(forLanguage: "fr") - } - - func testItalian() { - performSnapshotTest(forLanguage: "it") - } - - func testJapanese() { - performSnapshotTest(forLanguage: "ja") - } - - func testDutch() { - performSnapshotTest(forLanguage: "nl") - } - - func testChinese() { - performSnapshotTest(forLanguage: "zh-Hans") - } -} diff --git a/Stripe/StripeiOSTests/STPSourceTest.swift b/Stripe/StripeiOSTests/STPSourceTest.swift index b441e583e0c..51d35f93319 100644 --- a/Stripe/StripeiOSTests/STPSourceTest.swift +++ b/Stripe/StripeiOSTests/STPSourceTest.swift @@ -410,8 +410,6 @@ class STPSourceTest: XCTestCase { XCTAssertNotNil(source?.sepaDebitDetails) // STPSourceSEPADebitDetailsTest } - // MARK: - STPPaymentOption Tests - func possibleAPIResponses() -> [[AnyHashable: Any]] { return [ STPTestUtils.jsonNamed(STPTestJSONSourceCard), @@ -428,68 +426,4 @@ class STPSourceTest: XCTestCase { ] } - func testPaymentOptionImage() { - for response in possibleAPIResponses() { - let source = STPSource.decodedObject(fromAPIResponse: response) - - switch source!.type { - case STPSourceType.card: - STPAssertEqualImages(source?.image, STPImageLibrary.cardBrandImage(for: source?.cardDetails?.brand ?? .unknown)) - default: - STPAssertEqualImages(source?.image, STPImageLibrary.cardBrandImage(for: STPCardBrand.unknown)) - } - } - } - - func testPaymentOptionTemplateImage() { - for response in possibleAPIResponses() { - let source = STPSource.decodedObject(fromAPIResponse: response) - - switch source!.type { - case STPSourceType.card: - STPAssertEqualImages(source?.templateImage, STPImageLibrary.templatedBrandImage(for: source?.cardDetails?.brand ?? .unknown)) - default: - STPAssertEqualImages(source?.templateImage, STPImageLibrary.templatedBrandImage(for: STPCardBrand.unknown)) - } - } - } - - func testPaymentOptionLabel() { - for response in possibleAPIResponses() { - let source = STPSource.decodedObject(fromAPIResponse: response) - - switch source!.type { - case STPSourceType.bancontact: - XCTAssertEqual(source?.label, "Bancontact") - case STPSourceType.card: - XCTAssertEqual(source?.label, "Visa 5556") - case STPSourceType.giropay: - XCTAssertEqual(source?.label, "giropay") - case STPSourceType.iDEAL: - XCTAssertEqual(source?.label, "iDEAL") - case STPSourceType.SEPADebit: - XCTAssertEqual(source?.label, "SEPA Debit") - case STPSourceType.sofort: - XCTAssertEqual(source?.label, "Sofort") - case STPSourceType.threeDSecure: - XCTAssertEqual(source?.label, "3D Secure") - case STPSourceType.alipay: - XCTAssertEqual(source?.label, "Alipay") - case STPSourceType.P24: - XCTAssertEqual(source?.label, "Przelewy24") - case STPSourceType.EPS: - XCTAssertEqual(source?.label, "EPS") - case STPSourceType.multibanco: - XCTAssertEqual(source?.label, "Multibanco") - case STPSourceType.weChatPay: - XCTAssertEqual(source?.label, "WeChat Pay") - case STPSourceType.klarna: - XCTAssertEqual(source?.label, "Klarna") - case STPSourceType.unknown: - XCTAssertEqual(source?.label, STPCard.string(from: .unknown)) - default: - break - } - } - } } diff --git a/Stripe/StripeiOSTests/STPSwiftFixtures.swift b/Stripe/StripeiOSTests/STPSwiftFixtures.swift index f522531e350..1005db9ba80 100644 --- a/Stripe/StripeiOSTests/STPSwiftFixtures.swift +++ b/Stripe/StripeiOSTests/STPSwiftFixtures.swift @@ -9,7 +9,6 @@ import Foundation @testable@_spi(STP) import Stripe -@testable@_spi(STP) import StripeCore @testable@_spi(STP) import StripePayments @testable@_spi(STP) import StripePaymentSheet @testable@_spi(STP) import StripePaymentsUI @@ -33,75 +32,3 @@ extension STPFixtures { return .decodedObject(fromAPIResponse: response)! } } - -class MockEphemeralKeyProvider: NSObject, STPCustomerEphemeralKeyProvider { - func createCustomerKey( - withAPIVersion apiVersion: String, - completion: @escaping STPJSONResponseCompletionBlock - ) { - completion(STPFixtures.ephemeralKey().allResponseFields, nil) - } -} - -@objcMembers -@objc class Testing_StaticCustomerContext_Objc: Testing_StaticCustomerContext { - -} - -@objcMembers -class Testing_StaticCustomerContext: STPCustomerContext { - var customer: STPCustomer - var paymentMethods: [STPPaymentMethod] - convenience init() { - let customer = STPFixtures.customerWithSingleCardTokenSource() - let paymentMethods = [STPFixtures.paymentMethod()].compactMap { $0 } - self.init( - customer: customer, - paymentMethods: paymentMethods - ) - } - init( - customer: STPCustomer, - paymentMethods: [STPPaymentMethod] - ) { - self.customer = customer - self.paymentMethods = paymentMethods - super.init( - keyManager: STPEphemeralKeyManager( - keyProvider: MockEphemeralKeyProvider(), - apiVersion: "1", - performsEagerFetching: false - ), - apiClient: STPAPIClient.shared - ) - } - - override func retrieveCustomer(_ completion: STPCustomerCompletionBlock?) { - if let completion = completion { - completion(customer, nil) - } - } - - override func listPaymentMethodsForCustomer(completion: STPPaymentMethodsCompletionBlock?) { - if let completion = completion { - completion(paymentMethods, nil) - } - } - - var didAttach = false - override func attachPaymentMethod( - toCustomer paymentMethod: STPPaymentMethod, - completion: STPErrorBlock? - ) { - didAttach = true - if let completion = completion { - completion(nil) - } - } - - override func retrieveLastSelectedPaymentMethodIDForCustomer( - completion: @escaping (String?, Error?) -> Void - ) { - completion(nil, nil) - } -} diff --git a/Stripe/StripeiOSTests/STPUIVCStripeParentViewControllerTests.swift b/Stripe/StripeiOSTests/STPUIVCStripeParentViewControllerTests.swift deleted file mode 100644 index 63f00064198..00000000000 --- a/Stripe/StripeiOSTests/STPUIVCStripeParentViewControllerTests.swift +++ /dev/null @@ -1,39 +0,0 @@ -// Converted to Swift 5.8.1 by Swiftify v5.8.28463 - https://swiftify.com/ -// -// STPUIVCStripeParentViewControllerTests.m -// Stripe -// -// Created by Jack Flintermann on 1/19/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -@testable import Stripe -import UIKit -import XCTest - -class TestViewController: UIViewController { -} - -class STPUIVCStripeParentViewControllerTests: XCTestCase { - func testNilParent() { - let vc = UIViewController() - XCTAssertNil(vc.stp_parentViewControllerOf(UIViewController.self)) - } - - func testNavigationController() { - let vc = UIViewController() - let nav = UINavigationController(rootViewController: vc) - let parent = vc.stp_parentViewControllerOf(UINavigationController.self) as? UINavigationController - XCTAssertEqual(nav, parent) - } - - func testDeepHeirarchy() { - let topLevel = TestViewController() - let vc = UIViewController() - let nav = UINavigationController(rootViewController: vc) - topLevel.addChild(nav) - nav.didMove(toParent: topLevel) - let parent = vc.stp_parentViewControllerOf(TestViewController.self) as? TestViewController - XCTAssertEqual(topLevel, parent) - } -} diff --git a/Stripe/StripeiOSTests/StripeiOS Tests-Bridging-Header.h b/Stripe/StripeiOSTests/StripeiOS Tests-Bridging-Header.h index 8a95b39af7a..ad4027efb0f 100644 --- a/Stripe/StripeiOSTests/StripeiOS Tests-Bridging-Header.h +++ b/Stripe/StripeiOSTests/StripeiOS Tests-Bridging-Header.h @@ -3,5 +3,3 @@ // @import StripePaymentsObjcTestUtils; - -#import "STPMocks.h" diff --git a/Stripe/StripeiOSTests/UINavigationBar+StripeTest.m b/Stripe/StripeiOSTests/UINavigationBar+StripeTest.m deleted file mode 100644 index bc5a2bd8679..00000000000 --- a/Stripe/StripeiOSTests/UINavigationBar+StripeTest.m +++ /dev/null @@ -1,52 +0,0 @@ -// -// UINavigationBar+StripeTest.m -// Stripe -// -// Created by Brian Dorfman on 12/9/16. -// Copyright © 2016 Stripe, Inc. All rights reserved. -// - -#import -#import -@import Stripe; -#import "STPMocks.h" -@import StripePaymentsObjcTestUtils; - -@interface UINavigationBar_StripeTest : XCTestCase - -@end - -@implementation UINavigationBar_StripeTest - -- (STPPaymentOptionsViewController *)buildPaymentOptionsViewController { - id customerContext = [STPMocks staticCustomerContext]; - STPPaymentConfiguration *config = [STPPaymentConfiguration new]; - STPTheme *theme = [STPTheme defaultTheme]; - id delegate = OCMProtocolMock(@protocol(STPPaymentOptionsViewControllerDelegate)); - STPPaymentOptionsViewController *paymentOptionsVC = [[STPPaymentOptionsViewController alloc] initWithConfiguration:config - theme:theme - customerContext:customerContext - delegate:delegate]; - return paymentOptionsVC; -} - -- (void)testVCUsesNavigationBarColor { - STPPaymentOptionsViewController *paymentOptionsVC = [self buildPaymentOptionsViewController]; - STPTheme *navTheme = [STPTheme new]; - navTheme.accentColor = [UIColor purpleColor]; - - UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:paymentOptionsVC]; - navController.navigationBar.stp_theme = navTheme; - __unused UIView *view = paymentOptionsVC.view; - XCTAssertEqualObjects(paymentOptionsVC.navigationItem.leftBarButtonItem.tintColor, [UIColor purpleColor]); -} - -- (void)testVCDoesNotUseNavigationBarColor { - STPPaymentOptionsViewController *paymentOptionsVC = [self buildPaymentOptionsViewController]; - __unused UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:paymentOptionsVC]; - __unused UIView *view = paymentOptionsVC.view; - XCTAssertEqualObjects(paymentOptionsVC.navigationItem.leftBarButtonItem.tintColor, [STPTheme defaultTheme].accentColor); -} - - -@end diff --git a/Stripe/StripeiOSTests/UserDefaults+StripeTest.swift b/Stripe/StripeiOSTests/UserDefaults+StripeTest.swift index 4803d5df044..de944c1aadb 100644 --- a/Stripe/StripeiOSTests/UserDefaults+StripeTest.swift +++ b/Stripe/StripeiOSTests/UserDefaults+StripeTest.swift @@ -24,10 +24,4 @@ class UserDefaults_StripeTest: XCTestCase { UserDefaults.standard.fraudDetectionData = fraudDetectionData XCTAssertEqual(UserDefaults.standard.fraudDetectionData, fraudDetectionData) } - - func testCustomerToLastSelectedPaymentMethod() throws { - let c = [UUID().uuidString: UUID().uuidString] - UserDefaults.standard.customerToLastSelectedPaymentMethod = c - XCTAssertEqual(UserDefaults.standard.customerToLastSelectedPaymentMethod, c) - } } diff --git a/StripeCore/StripeCore/Source/Helpers/PaymentsSDKVariant.swift b/StripeCore/StripeCore/Source/Helpers/PaymentsSDKVariant.swift index 630920aa145..7a2d110a179 100644 --- a/StripeCore/StripeCore/Source/Helpers/PaymentsSDKVariant.swift +++ b/StripeCore/StripeCore/Source/Helpers/PaymentsSDKVariant.swift @@ -9,10 +9,6 @@ import Foundation @_spi(STP) public class PaymentsSDKVariant { @_spi(STP) public static let variant: String = { - if NSClassFromString("STPPaymentContext") != nil { - // This is the full legacy Payments SDK, including Basic Integration - return "legacy" - } if NSClassFromString("STP_Internal_PaymentSheetViewController") != nil { // This is the PaymentSheet SDK return "paymentsheet" diff --git a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentMethodType.swift b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentMethodType.swift index 486a29d526e..555d9483ae5 100644 --- a/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentMethodType.swift +++ b/StripePaymentSheet/StripePaymentSheet/Source/PaymentSheet/PaymentMethodType.swift @@ -445,15 +445,25 @@ extension STPPaymentMethod { extension STPPaymentMethodParams { var paymentSheetLabel: String { switch type { - case .unknown: - assertionFailure() - return rawTypeString ?? "" case .card: return "•••• \(card?.last4 ?? "")" + case .FPX: + if let fpx = fpx { + return STPFPXBank.stringFrom(fpx.bank) ?? "" + } else { + return "FPX" + } + case .paynow, .zip, .amazonPay, .alma, .mobilePay, .konbini, .promptPay, .swish, .sunbit, .billie, .satispay, .iDEAL, .SEPADebit, .bacsDebit, .AUBECSDebit, .giropay, .przelewy24, .EPS, .bancontact, .netBanking, .OXXO, .sofort, .UPI, .grabPay, .payPal, .afterpayClearpay, .blik, .weChatPay, .boleto, .link, .klarna, .affirm, .USBankAccount, .cashApp, .revolutPay, .twint, .multibanco, .alipay, .cardPresent: + // Use the label already defined in STPPaymentMethodType; the params object for these types don't contain additional information that affect the display label (like cards do) + return type.displayName + case .unknown: + fallthrough default: - return label + assertionFailure() + return rawTypeString ?? "" } } + } extension PaymentElementConfiguration { diff --git a/StripePayments/StripePayments/Source/API Bindings/Models/PaymentMethods/STPPaymentMethodParams.swift b/StripePayments/StripePayments/Source/API Bindings/Models/PaymentMethods/STPPaymentMethodParams.swift index a64ba13b12f..e33178c428e 100644 --- a/StripePayments/StripePayments/Source/API Bindings/Models/PaymentMethods/STPPaymentMethodParams.swift +++ b/StripePayments/StripePayments/Source/API Bindings/Models/PaymentMethods/STPPaymentMethodParams.swift @@ -1343,31 +1343,3 @@ extension STPPaymentMethodParams { } } } - -// MARK: - STPPaymentOption -// This should be in `STPPaymentMethodParams+BasicUI.swift` but there's some module issue -extension STPPaymentMethodParams { - @objc public var label: String { - switch type { - case .card: - if let card = card { - let brand = STPCardValidator.brand(forNumber: card.number ?? "") - let brandString = STPCardBrandUtilities.stringFrom(brand) - return "\(brandString ?? "") \(card.last4 ?? "")" - } else { - return STPCardBrandUtilities.stringFrom(.unknown) ?? "" - } - case .FPX: - if let fpx = fpx { - return STPFPXBank.stringFrom(fpx.bank) ?? "" - } else { - return "FPX" - } - case .paynow, .zip, .amazonPay, .alma, .mobilePay, .konbini, .promptPay, .swish, .sunbit, .billie, .satispay, .iDEAL, .SEPADebit, .bacsDebit, .AUBECSDebit, .giropay, .przelewy24, .EPS, .bancontact, .netBanking, .OXXO, .sofort, .UPI, .grabPay, .payPal, .afterpayClearpay, .blik, .weChatPay, .boleto, .link, .klarna, .affirm, .USBankAccount, .cashApp, .revolutPay, .twint, .multibanco, .alipay, .cardPresent, .unknown: - // Use the label already defined in STPPaymentMethodType; the params object for these types don't contain additional information that affect the display label (like cards do) - return type.displayName - @unknown default: - return STPLocalizedString("Unknown", "Default missing source type label") - } - } -} diff --git a/StripePaymentsUI/StripePaymentsUI/Resources/Localizations/en.lproj/Localizable.strings b/StripePaymentsUI/StripePaymentsUI/Resources/Localizations/en.lproj/Localizable.strings index f0c2b007948..21c368d816b 100644 --- a/StripePaymentsUI/StripePaymentsUI/Resources/Localizations/en.lproj/Localizable.strings +++ b/StripePaymentsUI/StripePaymentsUI/Resources/Localizations/en.lproj/Localizable.strings @@ -16,9 +16,6 @@ /* Label for Bank Account selection or detail entry form */ "Bank Account" = "Bank Account"; -/* Title for billing address entry section */ -"Billing Address" = "Billing Address"; - /* Billing address section title for card form entry. */ "Billing address" = "Billing address"; diff --git a/StripePaymentsUI/StripePaymentsUI/Source/Helpers/STPPhoneNumberValidator.swift b/StripePaymentsUI/StripePaymentsUI/Source/Helpers/STPPhoneNumberValidator.swift index d6a671d7e75..68c828ed599 100644 --- a/StripePaymentsUI/StripePaymentsUI/Source/Helpers/STPPhoneNumberValidator.swift +++ b/StripePaymentsUI/StripePaymentsUI/Source/Helpers/STPPhoneNumberValidator.swift @@ -9,29 +9,9 @@ import Foundation @_spi(STP) import StripeCore @_spi(STP) import StripePayments -@_spi(STP) import StripeUICore @_spi(STP) public class STPPhoneNumberValidator: NSObject { - class func stringIsValidPhoneNumber(_ string: String) -> Bool { - if string == "" { - return false - } - return self.stringIsValidPhoneNumber(string, forCountryCode: nil) - } - - @_spi(STP) public class func stringIsValidPhoneNumber( - _ string: String, - forCountryCode nillableCode: String? - ) -> Bool { - let countryCode = self.countryCodeOrCurrentLocaleCountry(from: nillableCode) - if let phoneNumber = PhoneNumber(number: string, countryCode: countryCode) { - return phoneNumber.isComplete - } else { - return !string.isEmpty - } - } - @objc(formattedSanitizedPhoneNumberForString:) class func formattedSanitizedPhoneNumber( for string: String ) -> String { diff --git a/StripePaymentsUI/StripePaymentsUI/Source/Helpers/STPPromise.swift b/StripePaymentsUI/StripePaymentsUI/Source/Helpers/STPPromise.swift index 4fbfc0450a3..7e221a26d3a 100644 --- a/StripePaymentsUI/StripePaymentsUI/Source/Helpers/STPPromise.swift +++ b/StripePaymentsUI/StripePaymentsUI/Source/Helpers/STPPromise.swift @@ -16,8 +16,6 @@ import Foundation @_spi(STP) public typealias STPPromiseCompletionBlock = (T?, Error?) -> Void - @_spi(STP) public typealias STPPromiseMapBlock = (T) -> Any? - @_spi(STP) public typealias STPPromiseFlatMapBlock = (T) -> STPPromise @_spi(STP) public var completed: Bool { @@ -111,16 +109,6 @@ import Foundation }) } - @discardableResult @_spi(STP) public func map(_ callback: @escaping STPPromiseMapBlock) -> STPPromise { - let wrapper = STPPromise.init() - onSuccess({ value in - wrapper.succeed(callback(value) as! T) - }).onFailure({ error in - wrapper.fail(error) - }) - return wrapper - } - @discardableResult func flatMap(_ callback: @escaping STPPromiseFlatMapBlock) -> STPPromise { let wrapper = STPPromise.init() onSuccess({ value in diff --git a/StripePaymentsUI/StripePaymentsUI/Source/Helpers/String+Localized.swift b/StripePaymentsUI/StripePaymentsUI/Source/Helpers/String+Localized.swift index f357fc66169..d363e4e6625 100644 --- a/StripePaymentsUI/StripePaymentsUI/Source/Helpers/String+Localized.swift +++ b/StripePaymentsUI/StripePaymentsUI/Source/Helpers/String+Localized.swift @@ -52,10 +52,6 @@ extension String.Localized { STPLocalizedString("Shipping Address", "Title for shipping address entry section") } - @_spi(STP) public static var billing_address: String { - STPLocalizedString("Billing Address", "Title for billing address entry section") - } - @_spi(STP) public static var billing_address_lowercase: String { STPLocalizedString("Billing address", "Billing address section title for card form entry.") } diff --git a/StripeUICore/StripeUICore/Resources/Localizations/en.lproj/Localizable.strings b/StripeUICore/StripeUICore/Resources/Localizations/en.lproj/Localizable.strings index 845ccd05825..375de00fb5f 100644 --- a/StripeUICore/StripeUICore/Resources/Localizations/en.lproj/Localizable.strings +++ b/StripeUICore/StripeUICore/Resources/Localizations/en.lproj/Localizable.strings @@ -129,9 +129,6 @@ Label of an address field */ /* Label of an address field */ "Parish" = "Parish"; -/* Caption for Phone field on address form */ -"Phone" = "Phone"; - /* Caption for Phone number field on address form */ "Phone number" = "Phone number"; diff --git a/StripeUICore/StripeUICore/Source/Helpers/String+Localized.swift b/StripeUICore/StripeUICore/Source/Helpers/String+Localized.swift index ddc07f9c545..86fafb39c9d 100644 --- a/StripeUICore/StripeUICore/Source/Helpers/String+Localized.swift +++ b/StripeUICore/StripeUICore/Source/Helpers/String+Localized.swift @@ -77,10 +77,6 @@ import Foundation // MARK: - Phone number - static var phone: String { - STPLocalizedString("Phone", "Caption for Phone field on address form") - } - static var phoneNumber: String { STPLocalizedString("Phone number", "Caption for Phone number field on address form") } diff --git a/Testers/IntegrationTester/Common/IntegrationMethods.swift b/Testers/IntegrationTester/Common/IntegrationMethods.swift index 7647be4a756..d4fd27fce4f 100644 --- a/Testers/IntegrationTester/Common/IntegrationMethods.swift +++ b/Testers/IntegrationTester/Common/IntegrationMethods.swift @@ -13,7 +13,6 @@ public enum IntegrationMethod: String, CaseIterable { case cardSetupIntents = "Card (SetupIntents)" case applePay = "Apple Pay" case sofort = "Sofort" - case fpx = "FPX" case sepaDebit = "SEPA Debit" case iDEAL case alipay = "Alipay" @@ -35,10 +34,6 @@ public enum IntegrationMethod: String, CaseIterable { extension IntegrationMethod { public var defaultPaymentMethodParams: STPPaymentMethodParams { switch self { - case .fpx: - let fpx = STPPaymentMethodFPXParams() - fpx.bank = .HSBC - return STPPaymentMethodParams(fpx: fpx, billingDetails: nil, metadata: nil) case .iDEAL: let ideal = STPPaymentMethodiDEALParams() return STPPaymentMethodParams(iDEAL: ideal, billingDetails: nil, metadata: nil) diff --git a/Testers/IntegrationTester/IntegrationTester.xcodeproj/project.pbxproj b/Testers/IntegrationTester/IntegrationTester.xcodeproj/project.pbxproj index 6eb1d74da9c..b97a2b17def 100644 --- a/Testers/IntegrationTester/IntegrationTester.xcodeproj/project.pbxproj +++ b/Testers/IntegrationTester/IntegrationTester.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 52; + objectVersion = 55; objects = { /* Begin PBXBuildFile section */ @@ -24,7 +24,6 @@ 61DB7CADBEC4D02E824EBCCB /* StripeApplePay.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 071CB368DEE3801C0ECF1755 /* StripeApplePay.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 6453D2766DC5C04D49617E98 /* Stripe.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = CA7414BE30CD6E4778C3982F /* Stripe.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 666B3478C24A96635D50189B /* Stripe.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = CA7414BE30CD6E4778C3982F /* Stripe.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 6B69932E6CC7BE9D71AF54C1 /* FPXView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D59BC76C0F4E0B96796F412 /* FPXView.swift */; }; 738352333BC65C77F28CCD6E /* Stripe.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CA7414BE30CD6E4778C3982F /* Stripe.framework */; }; 7D6A6F51B50CB5043BEE3454 /* CardSetupIntentsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F38BCBD16314976A7ABFB7D /* CardSetupIntentsView.swift */; }; 867577501F923D56CA61E0B7 /* PaymentButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD40F16C3CE95FEA4DC72EE1 /* PaymentButton.swift */; }; @@ -146,9 +145,8 @@ 813249BFF59CA231C04D1F85 /* CardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardView.swift; sourceTree = ""; }; 83C0EA0D81FD54F70BEAE289 /* AUBECSDebitView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AUBECSDebitView.swift; sourceTree = ""; }; 8894137E9BCC7581122C266D /* IntegrationTester-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "IntegrationTester-Release.xcconfig"; sourceTree = ""; }; - 8D59BC76C0F4E0B96796F412 /* FPXView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FPXView.swift; sourceTree = ""; }; 930A9EBA74E833322F991EED /* HelperViews.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelperViews.swift; sourceTree = ""; }; - 9A6DA4B0E69358D56D62752A /* IntegrationTester.xctestplan */ = {isa = PBXFileReference; path = IntegrationTester.xctestplan; sourceTree = ""; }; + 9A6DA4B0E69358D56D62752A /* IntegrationTester.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = IntegrationTester.xctestplan; sourceTree = ""; }; 9B6D71CE0D7D2D44BC809B50 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; AA26E77255E4C91995BA7F43 /* PaymentMethodWithShippingInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaymentMethodWithShippingInfoView.swift; sourceTree = ""; }; B74C265E4ED315E3CD020D5C /* StripePaymentsUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = StripePaymentsUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -246,7 +244,6 @@ 83C0EA0D81FD54F70BEAE289 /* AUBECSDebitView.swift */, 5F38BCBD16314976A7ABFB7D /* CardSetupIntentsView.swift */, 813249BFF59CA231C04D1F85 /* CardView.swift */, - 8D59BC76C0F4E0B96796F412 /* FPXView.swift */, F7EAA13BD7EC7EE3B6ED5D64 /* PaymentMethodView.swift */, C3E84A059F7377505F1CB1B8 /* PaymentMethodWithContactInfoView.swift */, AA26E77255E4C91995BA7F43 /* PaymentMethodWithShippingInfoView.swift */, @@ -496,7 +493,6 @@ BC8E1413DFD1087C296B141C /* ApplePayView.swift in Sources */, 7D6A6F51B50CB5043BEE3454 /* CardSetupIntentsView.swift in Sources */, 01333FBF3A01A5BE4C8B2619 /* CardView.swift in Sources */, - 6B69932E6CC7BE9D71AF54C1 /* FPXView.swift in Sources */, 3686EEE34F0EE2DB1B3D58EE /* PaymentMethodView.swift in Sources */, 0F6789DB19A22C8C533D4A69 /* PaymentMethodWithContactInfoView.swift in Sources */, 3E2DE871CC48D34F03B7F4CA /* PaymentMethodWithShippingInfoView.swift in Sources */, diff --git a/Testers/IntegrationTester/IntegrationTester/Source/MainMenu.swift b/Testers/IntegrationTester/IntegrationTester/Source/MainMenu.swift index 8d91958d9d2..9518d8056b3 100644 --- a/Testers/IntegrationTester/IntegrationTester/Source/MainMenu.swift +++ b/Testers/IntegrationTester/IntegrationTester/Source/MainMenu.swift @@ -19,8 +19,6 @@ struct IntegrationView: View { CardSetupIntentsView() case .applePay: ApplePayView() - case .fpx: - FPXView() case .aubecsDebit: AUBECSDebitView() case .sepaDebit: diff --git a/Testers/IntegrationTester/IntegrationTester/Source/Views/FPXView.swift b/Testers/IntegrationTester/IntegrationTester/Source/Views/FPXView.swift deleted file mode 100644 index a8cff68e2e1..00000000000 --- a/Testers/IntegrationTester/IntegrationTester/Source/Views/FPXView.swift +++ /dev/null @@ -1,81 +0,0 @@ -// -// CardView.swift -// IntegrationTester -// -// Created by David Estes on 2/8/21. -// - -import Stripe -import SwiftUI - -struct FPXView: View { - @StateObject var model = MyPIModel() - @State var isConfirmingPayment = false - - var body: some View { - VStack { - if let paymentStatus = model.paymentStatus { - PaymentHandlerStatusView(actionStatus: paymentStatus, lastPaymentError: model.lastPaymentError) - } else { - if let paymentIntent = model.paymentIntentParams { - STPBankSelectionViewController.Representable(onCompletion: { paymentMethodParams in - paymentIntent.paymentMethodParams = paymentMethodParams - isConfirmingPayment = true - }).paymentConfirmationSheet(isConfirmingPayment: $isConfirmingPayment, - paymentIntentParams: paymentIntent, - onCompletion: model.onCompletion) - .disabled(isConfirmingPayment) - } else { - ProgressView() - } - } - }.onAppear { - model.integrationMethod = .fpx - model.preparePaymentIntent() - } - } -} - -struct FPXView_Preview: PreviewProvider { - static var previews: some View { - FPXView() - } -} - -extension STPBankSelectionViewController { - struct Representable: UIViewControllerRepresentable { - let onCompletion: (STPPaymentMethodParams?) -> Void - - public init(onCompletion: @escaping (STPPaymentMethodParams?) -> Void) { - self.onCompletion = onCompletion - } - - func makeCoordinator() -> Coordinator { - return Coordinator(parent: self) - } - - func makeUIViewController(context: Context) -> UIViewController { - return context.coordinator.vc - } - - func updateUIViewController(_ uiViewController: UIViewController, context: Context) { - context.coordinator.parent = self - } - - class Coordinator: NSObject, STPBankSelectionViewControllerDelegate { - func bankSelectionViewController(_ bankViewController: STPBankSelectionViewController, didCreatePaymentMethodParams paymentMethodParams: STPPaymentMethodParams) { - self.parent.onCompletion(paymentMethodParams) - } - - var parent: Representable - init(parent: Representable) { - self.parent = parent - vc = STPBankSelectionViewController(bankMethod: .FPX) - super.init() - vc.delegate = self - } - - let vc: STPBankSelectionViewController - } - } -} diff --git a/Testers/IntegrationTester/IntegrationTesterUITests/IntegrationTesterUITests.swift b/Testers/IntegrationTester/IntegrationTesterUITests/IntegrationTesterUITests.swift index 65e8c98ade5..57b954aaff4 100644 --- a/Testers/IntegrationTester/IntegrationTesterUITests/IntegrationTesterUITests.swift +++ b/Testers/IntegrationTester/IntegrationTesterUITests/IntegrationTesterUITests.swift @@ -127,7 +127,7 @@ class IntegrationTesterUIPMTests: IntegrationTesterUITests { break case .bacsDebit, .sepaDebit: testNoInputIntegrationMethod(integrationMethod, shouldConfirm: false) - case .card, .cardSetupIntents, .aubecsDebit, .applePay, .klarna, .fpx: + case .card, .cardSetupIntents, .aubecsDebit, .applePay, .klarna: // Tested in method-specific functions. break case .grabpay: @@ -204,27 +204,6 @@ class IntegrationTesterUIPMTests: IntegrationTesterUITests { XCTAssertNotNil(statusView.label.range(of: "Payment complete")) } - func testFPX() { - self.popToMainMenu() - - let tablesQuery = app.collectionViews - let rowForPaymentMethod = tablesQuery.cells.buttons["FPX"] - rowForPaymentMethod.scrollToAndTap(in: app) - - let maybank = app.tables.staticTexts["Maybank2U"] - XCTAssertTrue(maybank.waitForExistence(timeout: 60.0)) - maybank.tap() - - let webViewsQuery = app.webViews - let completeAuth = webViewsQuery.descendants(matching: .any)["AUTHORIZE TEST PAYMENT"].firstMatch - XCTAssertTrue(completeAuth.waitForExistence(timeout: 60.0)) - completeAuth.forceTapElement() - - let statusView = app.staticTexts["Payment status view"] - XCTAssertTrue(statusView.waitForExistence(timeout: 10.0)) - XCTAssertNotNil(statusView.label.range(of: "Payment complete")) - } - func testKlarna() { self.popToMainMenu() let tablesQuery = app.collectionViews diff --git a/modules.yaml b/modules.yaml index 0d49aa38414..0a185c6f4dc 100644 --- a/modules.yaml +++ b/modules.yaml @@ -71,7 +71,6 @@ modules: - podspec: Stripe.podspec scheme: StripeiOS framework_name: Stripe - localization_dir: Stripe/StripeiOS custom_string_convertible_dir: Stripe/StripeiOS/Source supports_catalyst: true docs: