@stripe/stripe-react-native 0.19.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +46 -5
- package/README.md +2 -2
- package/android/build.gradle +1 -2
- package/android/gradle.properties +1 -1
- package/android/src/main/java/com/reactnativestripesdk/CardFieldView.kt +6 -3
- package/android/src/main/java/com/reactnativestripesdk/CardFormView.kt +22 -7
- package/android/src/main/java/com/reactnativestripesdk/CollectBankAccountLauncherFragment.kt +1 -1
- package/android/src/main/java/com/reactnativestripesdk/FinancialConnectionsSheetFragment.kt +5 -1
- package/android/src/main/java/com/reactnativestripesdk/GooglePayFragment.kt +1 -1
- package/android/src/main/java/com/reactnativestripesdk/PaymentLauncherFragment.kt +2 -1
- package/android/src/main/java/com/reactnativestripesdk/PaymentSheetAppearance.kt +10 -9
- package/android/src/main/java/com/reactnativestripesdk/PaymentSheetFragment.kt +11 -4
- package/android/src/main/java/com/reactnativestripesdk/StripeSdkModule.kt +27 -14
- package/android/src/main/java/com/reactnativestripesdk/StripeSdkPackage.kt +3 -1
- package/android/src/main/java/com/reactnativestripesdk/addresssheet/AddressLauncherFragment.kt +111 -0
- package/android/src/main/java/com/reactnativestripesdk/addresssheet/AddressSheetEvent.kt +28 -0
- package/android/src/main/java/com/reactnativestripesdk/addresssheet/AddressSheetView.kt +178 -0
- package/android/src/main/java/com/reactnativestripesdk/addresssheet/AddressSheetViewManager.kt +67 -0
- package/android/src/main/java/com/reactnativestripesdk/utils/Mappers.kt +3 -1
- package/ios/AddressSheet/AddressSheetUtils.swift +98 -0
- package/ios/AddressSheet/AddressSheetView.swift +131 -0
- package/ios/AddressSheet/AddressSheetViewManager.m +25 -0
- package/ios/AddressSheet/AddressSheetViewManager.swift +19 -0
- package/ios/ApplePayUtils.swift +1 -1
- package/ios/CardFieldView.swift +3 -3
- package/ios/FinancialConnections.swift +23 -22
- package/ios/Mappers.swift +10 -2
- package/ios/PaymentMethodFactory.swift +6 -7
- package/ios/PaymentSheetAppearance.swift +27 -26
- package/ios/{pushprovisioning → PushProvisioning}/AddToWalletButtonManager.m +0 -0
- package/ios/{pushprovisioning → PushProvisioning}/AddToWalletButtonManager.swift +0 -0
- package/ios/{pushprovisioning → PushProvisioning}/AddToWalletButtonView.swift +0 -0
- package/ios/{pushprovisioning → PushProvisioning}/PushProvisioningUtils.swift +0 -0
- package/ios/StripeSdk.m +5 -0
- package/ios/StripeSdk.swift +75 -27
- package/ios/Tests/AddressSheetUtilsTests.swift +279 -0
- package/jest/mock.js +2 -0
- package/lib/commonjs/NativeStripeSdk.js.map +1 -1
- package/lib/commonjs/components/AddressSheet.js +2 -0
- package/lib/commonjs/components/AddressSheet.js.map +1 -0
- package/lib/commonjs/functions.js +1 -1
- package/lib/commonjs/functions.js.map +1 -1
- package/lib/commonjs/hooks/usePaymentSheet.js +1 -1
- package/lib/commonjs/hooks/usePaymentSheet.js.map +1 -1
- package/lib/commonjs/hooks/useStripe.js +1 -1
- package/lib/commonjs/hooks/useStripe.js.map +1 -1
- package/lib/commonjs/index.js +1 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/types/Errors.js +1 -1
- package/lib/commonjs/types/Errors.js.map +1 -1
- package/lib/commonjs/types/FinancialConnections.js.map +1 -1
- package/lib/commonjs/types/index.js +1 -1
- package/lib/commonjs/types/index.js.map +1 -1
- package/lib/module/NativeStripeSdk.js.map +1 -1
- package/lib/module/components/AddressSheet.js +2 -0
- package/lib/module/components/AddressSheet.js.map +1 -0
- package/lib/module/functions.js +1 -1
- package/lib/module/functions.js.map +1 -1
- package/lib/module/hooks/usePaymentSheet.js +1 -1
- package/lib/module/hooks/usePaymentSheet.js.map +1 -1
- package/lib/module/hooks/useStripe.js +1 -1
- package/lib/module/hooks/useStripe.js.map +1 -1
- package/lib/module/index.js +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/types/Errors.js +1 -1
- package/lib/module/types/Errors.js.map +1 -1
- package/lib/module/types/FinancialConnections.js.map +1 -1
- package/lib/module/types/index.js +1 -1
- package/lib/module/types/index.js.map +1 -1
- package/lib/typescript/src/NativeStripeSdk.d.ts +1 -0
- package/lib/typescript/src/components/AddressSheet.d.ts +53 -0
- package/lib/typescript/src/functions.d.ts +6 -0
- package/lib/typescript/src/hooks/usePaymentSheet.d.ts +6 -0
- package/lib/typescript/src/hooks/useStripe.d.ts +6 -0
- package/lib/typescript/src/index.d.ts +1 -0
- package/lib/typescript/src/types/Common.d.ts +12 -0
- package/lib/typescript/src/types/Errors.d.ts +4 -0
- package/lib/typescript/src/types/FinancialConnections.d.ts +2 -2
- package/lib/typescript/src/types/PaymentMethod.d.ts +2 -0
- package/lib/typescript/src/types/PaymentSheet.d.ts +24 -1
- package/lib/typescript/src/types/index.d.ts +3 -6
- package/package.json +1 -1
- package/src/NativeStripeSdk.tsx +1 -0
- package/src/components/AddressSheet.tsx +82 -0
- package/src/functions.ts +9 -0
- package/src/hooks/usePaymentSheet.tsx +14 -0
- package/src/hooks/useStripe.tsx +11 -0
- package/src/index.tsx +4 -1
- package/src/types/Common.ts +13 -0
- package/src/types/Errors.ts +5 -0
- package/src/types/FinancialConnections.ts +4 -4
- package/src/types/PaymentMethod.ts +2 -0
- package/src/types/PaymentSheet.ts +26 -1
- package/src/types/index.ts +5 -10
- package/stripe-react-native.podspec +6 -2
- package/android/.gradle/7.1/dependencies-accessors/dependencies-accessors.lock +0 -0
- package/android/.gradle/7.1/dependencies-accessors/gc.properties +0 -0
- package/android/.gradle/7.1/fileChanges/last-build.bin +0 -0
- package/android/.gradle/7.1/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/7.1/gc.properties +0 -0
- package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
- package/android/.gradle/buildOutputCleanup/cache.properties +0 -2
- package/android/.gradle/checksums/checksums.lock +0 -0
- package/android/.gradle/vcs-1/gc.properties +0 -0
- package/android/.idea/gradle.xml +0 -13
- package/android/.idea/misc.xml +0 -9
- package/android/.idea/modules/android.iml +0 -18
- package/android/.idea/modules.xml +0 -8
- package/android/.idea/vcs.xml +0 -6
- package/android/local.properties +0 -8
- package/ios/StripeSdk.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
- package/ios/StripeSdk.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
- package/ios/StripeSdk.xcodeproj/project.xcworkspace/xcuserdata/charliecruzan.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/ios/StripeSdk.xcodeproj/xcuserdata/charliecruzan.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +0 -22
- package/ios/StripeSdk.xcodeproj/xcuserdata/charliecruzan.xcuserdatad/xcschemes/xcschememanagement.plist +0 -27
package/android/src/main/java/com/reactnativestripesdk/addresssheet/AddressLauncherFragment.kt
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
package com.reactnativestripesdk.addresssheet
|
|
2
|
+
|
|
3
|
+
import android.os.Bundle
|
|
4
|
+
import android.view.LayoutInflater
|
|
5
|
+
import android.view.View
|
|
6
|
+
import android.view.ViewGroup
|
|
7
|
+
import android.widget.FrameLayout
|
|
8
|
+
import androidx.appcompat.app.AppCompatActivity
|
|
9
|
+
import androidx.fragment.app.Fragment
|
|
10
|
+
import com.facebook.react.bridge.ReactContext
|
|
11
|
+
import com.facebook.react.bridge.WritableMap
|
|
12
|
+
import com.reactnativestripesdk.utils.ErrorType
|
|
13
|
+
import com.reactnativestripesdk.utils.createError
|
|
14
|
+
import com.stripe.android.paymentsheet.PaymentSheet
|
|
15
|
+
import com.stripe.android.paymentsheet.addresselement.AddressDetails
|
|
16
|
+
import com.stripe.android.paymentsheet.addresselement.AddressLauncher
|
|
17
|
+
import com.stripe.android.paymentsheet.addresselement.AddressLauncherResult
|
|
18
|
+
|
|
19
|
+
class AddressLauncherFragment : Fragment() {
|
|
20
|
+
companion object {
|
|
21
|
+
internal var publishableKey: String? = null
|
|
22
|
+
internal const val TAG = "address_launcher_fragment"
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
private lateinit var addressLauncher: AddressLauncher
|
|
26
|
+
private var configuration = AddressLauncher.Configuration()
|
|
27
|
+
private var callback: ((error: WritableMap?, address: AddressDetails?) -> Unit)? = null
|
|
28
|
+
|
|
29
|
+
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
|
30
|
+
savedInstanceState: Bundle?): View {
|
|
31
|
+
return FrameLayout(requireActivity()).also {
|
|
32
|
+
it.visibility = View.GONE
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
37
|
+
publishableKey?.let { publishableKey ->
|
|
38
|
+
addressLauncher = AddressLauncher(this,
|
|
39
|
+
::onAddressLauncherResult).also {
|
|
40
|
+
it.present(
|
|
41
|
+
publishableKey = publishableKey,
|
|
42
|
+
configuration = configuration
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
} ?: run {
|
|
46
|
+
callback?.invoke(
|
|
47
|
+
createError(ErrorType.Failed.toString(), "No publishable key set. Stripe has not been initialized. Initialize Stripe in your app with the StripeProvider component or the initStripe method."),
|
|
48
|
+
null
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
private fun onAddressLauncherResult(result: AddressLauncherResult) {
|
|
54
|
+
when (result) {
|
|
55
|
+
is AddressLauncherResult.Canceled -> {
|
|
56
|
+
callback?.invoke(
|
|
57
|
+
createError(ErrorType.Canceled.toString(), "The flow has been canceled."),
|
|
58
|
+
null
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
is AddressLauncherResult.Succeeded -> {
|
|
62
|
+
callback?.invoke(
|
|
63
|
+
null,
|
|
64
|
+
result.address
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
fun presentAddressSheet(
|
|
71
|
+
context: ReactContext,
|
|
72
|
+
appearance: PaymentSheet.Appearance,
|
|
73
|
+
defaultAddress: AddressDetails?,
|
|
74
|
+
allowedCountries: Set<String>,
|
|
75
|
+
buttonTitle: String?,
|
|
76
|
+
title: String?,
|
|
77
|
+
googlePlacesApiKey: String?,
|
|
78
|
+
autocompleteCountries: Set<String>,
|
|
79
|
+
additionalFields: AddressLauncher.AdditionalFieldsConfiguration?,
|
|
80
|
+
callback: ((error: WritableMap?, address: AddressDetails?) -> Unit)) {
|
|
81
|
+
configuration = AddressLauncher.Configuration(
|
|
82
|
+
appearance = appearance,
|
|
83
|
+
address = defaultAddress,
|
|
84
|
+
allowedCountries = allowedCountries,
|
|
85
|
+
buttonTitle = buttonTitle,
|
|
86
|
+
additionalFields = additionalFields,
|
|
87
|
+
title = title,
|
|
88
|
+
googlePlacesApiKey = googlePlacesApiKey,
|
|
89
|
+
autocompleteCountries = autocompleteCountries,
|
|
90
|
+
)
|
|
91
|
+
this.callback = callback
|
|
92
|
+
(context.currentActivity as? AppCompatActivity)?.let {
|
|
93
|
+
attemptToCleanupPreviousFragment(it)
|
|
94
|
+
commitFragmentAndStartFlow(it)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
private fun attemptToCleanupPreviousFragment(currentActivity: AppCompatActivity) {
|
|
99
|
+
currentActivity.supportFragmentManager.beginTransaction()
|
|
100
|
+
.remove(this)
|
|
101
|
+
.commitAllowingStateLoss()
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
private fun commitFragmentAndStartFlow(currentActivity: AppCompatActivity) {
|
|
105
|
+
try {
|
|
106
|
+
currentActivity.supportFragmentManager.beginTransaction()
|
|
107
|
+
.add(this, TAG)
|
|
108
|
+
.commit()
|
|
109
|
+
} catch (_: IllegalStateException) {}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
package com.reactnativestripesdk.addresssheet
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.WritableMap
|
|
4
|
+
import com.facebook.react.uimanager.events.Event
|
|
5
|
+
import com.facebook.react.uimanager.events.RCTEventEmitter
|
|
6
|
+
|
|
7
|
+
internal class AddressSheetEvent constructor(viewTag: Int, private val eventType: EventType, private val eventMap: WritableMap?) : Event<AddressSheetEvent>(viewTag) {
|
|
8
|
+
enum class EventType {
|
|
9
|
+
OnSubmit,
|
|
10
|
+
OnError
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
override fun dispatch(rctEventEmitter: RCTEventEmitter) {
|
|
14
|
+
rctEventEmitter.receiveEvent(viewTag, eventName, eventMap)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
companion object {
|
|
18
|
+
const val ON_SUBMIT = "onSubmitAction"
|
|
19
|
+
const val ON_ERROR = "onErrorAction"
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
override fun getEventName(): String {
|
|
23
|
+
return when (eventType) {
|
|
24
|
+
EventType.OnSubmit -> ON_SUBMIT
|
|
25
|
+
EventType.OnError -> ON_ERROR
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
package com.reactnativestripesdk.addresssheet
|
|
2
|
+
|
|
3
|
+
import android.os.Bundle
|
|
4
|
+
import android.util.Log
|
|
5
|
+
import android.widget.FrameLayout
|
|
6
|
+
import com.facebook.react.bridge.Arguments
|
|
7
|
+
import com.facebook.react.bridge.ReadableMap
|
|
8
|
+
import com.facebook.react.bridge.WritableMap
|
|
9
|
+
import com.facebook.react.bridge.WritableNativeMap
|
|
10
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
11
|
+
import com.facebook.react.uimanager.UIManagerModule
|
|
12
|
+
import com.facebook.react.uimanager.events.EventDispatcher
|
|
13
|
+
import com.reactnativestripesdk.buildPaymentSheetAppearance
|
|
14
|
+
import com.reactnativestripesdk.utils.ErrorType
|
|
15
|
+
import com.reactnativestripesdk.utils.PaymentSheetAppearanceException
|
|
16
|
+
import com.reactnativestripesdk.utils.createError
|
|
17
|
+
import com.reactnativestripesdk.utils.toBundleObject
|
|
18
|
+
import com.stripe.android.paymentsheet.PaymentSheet
|
|
19
|
+
import com.stripe.android.paymentsheet.addresselement.AddressDetails
|
|
20
|
+
import com.stripe.android.paymentsheet.addresselement.AddressLauncher
|
|
21
|
+
import com.stripe.android.paymentsheet.addresselement.AddressLauncherResult
|
|
22
|
+
|
|
23
|
+
class AddressSheetView(private val context: ThemedReactContext) : FrameLayout(context) {
|
|
24
|
+
private var eventDispatcher: EventDispatcher? = context.getNativeModule(UIManagerModule::class.java)?.eventDispatcher
|
|
25
|
+
private var isVisible = false
|
|
26
|
+
private var appearanceParams: ReadableMap? = null
|
|
27
|
+
private var defaultAddress: AddressDetails? = null
|
|
28
|
+
private var allowedCountries: Set<String> = emptySet()
|
|
29
|
+
private var buttonTitle: String? = null
|
|
30
|
+
private var sheetTitle: String? = null
|
|
31
|
+
private var googlePlacesApiKey: String? = null
|
|
32
|
+
private var autocompleteCountries: Set<String> = emptySet()
|
|
33
|
+
private var additionalFields: AddressLauncher.AdditionalFieldsConfiguration? = null
|
|
34
|
+
|
|
35
|
+
private fun onSubmit(params: WritableMap) {
|
|
36
|
+
eventDispatcher?.dispatchEvent(
|
|
37
|
+
AddressSheetEvent(id, AddressSheetEvent.EventType.OnSubmit, params)
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
private fun onError(params: WritableMap?) {
|
|
42
|
+
eventDispatcher?.dispatchEvent(
|
|
43
|
+
AddressSheetEvent(id, AddressSheetEvent.EventType.OnError, params)
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
fun setVisible(newVisibility: Boolean) {
|
|
48
|
+
if (newVisibility && !isVisible) {
|
|
49
|
+
launchAddressSheet()
|
|
50
|
+
} else if (!newVisibility && isVisible) {
|
|
51
|
+
Log.w("StripeReactNative", "Programmatically dismissing the Address Sheet is not supported on Android.")
|
|
52
|
+
}
|
|
53
|
+
isVisible = newVisibility
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
private fun launchAddressSheet() {
|
|
57
|
+
val appearance = try {
|
|
58
|
+
buildPaymentSheetAppearance(toBundleObject(appearanceParams), context)
|
|
59
|
+
} catch (error: PaymentSheetAppearanceException) {
|
|
60
|
+
onError(createError(ErrorType.Failed.toString(), error))
|
|
61
|
+
return
|
|
62
|
+
}
|
|
63
|
+
AddressLauncherFragment().presentAddressSheet(
|
|
64
|
+
context,
|
|
65
|
+
appearance,
|
|
66
|
+
defaultAddress,
|
|
67
|
+
allowedCountries,
|
|
68
|
+
buttonTitle,
|
|
69
|
+
sheetTitle,
|
|
70
|
+
googlePlacesApiKey,
|
|
71
|
+
autocompleteCountries,
|
|
72
|
+
additionalFields
|
|
73
|
+
) { error, address ->
|
|
74
|
+
if (address != null) {
|
|
75
|
+
onSubmit(buildResult(address))
|
|
76
|
+
} else {
|
|
77
|
+
onError(error)
|
|
78
|
+
}
|
|
79
|
+
isVisible = false
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
fun setAppearance(appearanceParams: ReadableMap) {
|
|
84
|
+
this.appearanceParams = appearanceParams
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
fun setDefaultValues(defaults: ReadableMap) {
|
|
88
|
+
defaultAddress = buildAddressDetails(defaults)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
fun setAdditionalFields(fields: ReadableMap) {
|
|
92
|
+
additionalFields = buildAdditionalFieldsConfiguration(fields)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
fun setAllowedCountries(countries: List<String>) {
|
|
96
|
+
allowedCountries = countries.toSet()
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
fun setAutocompleteCountries(countries: List<String>) {
|
|
100
|
+
autocompleteCountries = countries.toSet()
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
fun setPrimaryButtonTitle(title: String) {
|
|
104
|
+
buttonTitle = title
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
fun setSheetTitle(title: String) {
|
|
108
|
+
sheetTitle = title
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
fun setGooglePlacesApiKey(key: String) {
|
|
112
|
+
googlePlacesApiKey = key
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
companion object {
|
|
116
|
+
internal fun buildAddressDetails(bundle: Bundle): AddressDetails {
|
|
117
|
+
return AddressDetails(
|
|
118
|
+
name = bundle.getString("name"),
|
|
119
|
+
address = buildAddress(bundle.getBundle("address")),
|
|
120
|
+
phoneNumber = bundle.getString("phone"),
|
|
121
|
+
isCheckboxSelected = bundle.getBoolean("isCheckboxSelected"),
|
|
122
|
+
)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
internal fun buildAddressDetails(map: ReadableMap): AddressDetails {
|
|
126
|
+
return buildAddressDetails(toBundleObject(map))
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
internal fun buildAddress(bundle: Bundle?): PaymentSheet.Address? {
|
|
130
|
+
if (bundle == null) {
|
|
131
|
+
return null
|
|
132
|
+
}
|
|
133
|
+
return PaymentSheet.Address(
|
|
134
|
+
city = bundle.getString("city"),
|
|
135
|
+
country = bundle.getString("country"),
|
|
136
|
+
line1 = bundle.getString("line1"),
|
|
137
|
+
line2 = bundle.getString("line2"),
|
|
138
|
+
state = bundle.getString("state"),
|
|
139
|
+
postalCode = bundle.getString("postalCode")
|
|
140
|
+
)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
internal fun getFieldConfiguration(key: String?): AddressLauncher.AdditionalFieldsConfiguration.FieldConfiguration {
|
|
144
|
+
return when (key) {
|
|
145
|
+
"hidden" -> AddressLauncher.AdditionalFieldsConfiguration.FieldConfiguration.HIDDEN
|
|
146
|
+
"optional" -> AddressLauncher.AdditionalFieldsConfiguration.FieldConfiguration.OPTIONAL
|
|
147
|
+
"required" -> AddressLauncher.AdditionalFieldsConfiguration.FieldConfiguration.REQUIRED
|
|
148
|
+
else -> AddressLauncher.AdditionalFieldsConfiguration.FieldConfiguration.HIDDEN
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
internal fun buildAdditionalFieldsConfiguration(params: ReadableMap): AddressLauncher.AdditionalFieldsConfiguration {
|
|
153
|
+
val phoneConfiguration = getFieldConfiguration(params.getString("phoneNumber"))
|
|
154
|
+
|
|
155
|
+
return AddressLauncher.AdditionalFieldsConfiguration(
|
|
156
|
+
phone = phoneConfiguration,
|
|
157
|
+
checkboxLabel = params.getString("checkboxLabel")
|
|
158
|
+
)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
internal fun buildResult(addressDetails: AddressDetails): WritableMap {
|
|
162
|
+
val result = WritableNativeMap()
|
|
163
|
+
result.putString("name", addressDetails.name)
|
|
164
|
+
WritableNativeMap().let {
|
|
165
|
+
it.putString("city", addressDetails.address?.city)
|
|
166
|
+
it.putString("country", addressDetails.address?.country)
|
|
167
|
+
it.putString("line1", addressDetails.address?.line1)
|
|
168
|
+
it.putString("line2", addressDetails.address?.line2)
|
|
169
|
+
it.putString("postalCode", addressDetails.address?.postalCode)
|
|
170
|
+
it.putString("state", addressDetails.address?.state)
|
|
171
|
+
result.putMap("address", it)
|
|
172
|
+
}
|
|
173
|
+
result.putString("phone", addressDetails.phoneNumber)
|
|
174
|
+
result.putBoolean("isCheckboxSelected", addressDetails.isCheckboxSelected ?: false)
|
|
175
|
+
return result
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
package/android/src/main/java/com/reactnativestripesdk/addresssheet/AddressSheetViewManager.kt
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
package com.reactnativestripesdk.addresssheet
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.ReadableArray
|
|
4
|
+
import com.facebook.react.bridge.ReadableMap
|
|
5
|
+
import com.facebook.react.common.MapBuilder
|
|
6
|
+
import com.facebook.react.uimanager.SimpleViewManager
|
|
7
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
8
|
+
import com.facebook.react.uimanager.annotations.ReactProp
|
|
9
|
+
|
|
10
|
+
class AddressSheetViewManager : SimpleViewManager<AddressSheetView>() {
|
|
11
|
+
override fun getName() = "AddressSheetView"
|
|
12
|
+
|
|
13
|
+
override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> {
|
|
14
|
+
return MapBuilder.of(
|
|
15
|
+
AddressSheetEvent.ON_SUBMIT, MapBuilder.of("registrationName", "onSubmitAction"),
|
|
16
|
+
AddressSheetEvent.ON_ERROR, MapBuilder.of("registrationName", "onErrorAction"))
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@ReactProp(name = "visible")
|
|
20
|
+
fun setVisible(view: AddressSheetView, visibility: Boolean) {
|
|
21
|
+
view.setVisible(visibility)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@ReactProp(name = "appearance")
|
|
25
|
+
fun setAppearance(view: AddressSheetView, appearance: ReadableMap) {
|
|
26
|
+
view.setAppearance(appearance)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@ReactProp(name = "defaultValues")
|
|
30
|
+
fun setDefaultValues(view: AddressSheetView, defaults: ReadableMap) {
|
|
31
|
+
view.setDefaultValues(defaults)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@ReactProp(name = "additionalFields")
|
|
35
|
+
fun setAdditionalFields(view: AddressSheetView, fields: ReadableMap) {
|
|
36
|
+
view.setAdditionalFields(fields)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@ReactProp(name = "allowedCountries")
|
|
40
|
+
fun setAllowedCountries(view: AddressSheetView, countries: ReadableArray) {
|
|
41
|
+
view.setAllowedCountries(countries.toArrayList().filterIsInstance<String>())
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@ReactProp(name = "autocompleteCountries")
|
|
45
|
+
fun setAutocompleteCountries(view: AddressSheetView, countries: ReadableArray) {
|
|
46
|
+
view.setAutocompleteCountries(countries.toArrayList().filterIsInstance<String>())
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@ReactProp(name = "primaryButtonTitle")
|
|
50
|
+
fun setPrimaryButtonTitle(view: AddressSheetView, title: String) {
|
|
51
|
+
view.setPrimaryButtonTitle(title)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@ReactProp(name = "sheetTitle")
|
|
55
|
+
fun setSheetTitle(view: AddressSheetView, title: String) {
|
|
56
|
+
view.setSheetTitle(title)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
@ReactProp(name = "googlePlacesApiKey")
|
|
60
|
+
fun setGooglePlacesApiKey(view: AddressSheetView, key: String) {
|
|
61
|
+
view.setGooglePlacesApiKey(key)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
override fun createViewInstance(reactContext: ThemedReactContext): AddressSheetView {
|
|
65
|
+
return AddressSheetView(reactContext)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -347,6 +347,8 @@ internal fun mapFromPaymentMethod(paymentMethod: PaymentMethod): WritableMap {
|
|
|
347
347
|
card.putString("funding", paymentMethod.card?.funding)
|
|
348
348
|
card.putString("last4", paymentMethod.card?.last4)
|
|
349
349
|
card.putString("fingerprint", paymentMethod.card?.fingerprint)
|
|
350
|
+
card.putString("preferredNetwork", paymentMethod.card?.networks?.preferred)
|
|
351
|
+
card.putArray("availableNetworks", paymentMethod.card?.networks?.available?.toList() as? ReadableArray)
|
|
350
352
|
|
|
351
353
|
sepaDebit.putString("bankCode", paymentMethod.sepaDebit?.bankCode)
|
|
352
354
|
sepaDebit.putString("country", paymentMethod.sepaDebit?.country)
|
|
@@ -485,7 +487,7 @@ internal fun mapNextAction(type: NextActionType?, data: NextActionData?): Writab
|
|
|
485
487
|
NextActionType.AlipayRedirect -> { // TODO: Can't access, private
|
|
486
488
|
return null
|
|
487
489
|
}
|
|
488
|
-
NextActionType.BlikAuthorize, NextActionType.UseStripeSdk, null -> {
|
|
490
|
+
NextActionType.BlikAuthorize, NextActionType.UseStripeSdk, NextActionType.UpiAwaitNotification, null -> {
|
|
489
491
|
return null
|
|
490
492
|
}
|
|
491
493
|
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
//
|
|
2
|
+
// AddressSheetUtils.swift
|
|
3
|
+
// stripe-react-native
|
|
4
|
+
//
|
|
5
|
+
// Created by Charles Cruzan on 10/12/22.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
import StripePaymentSheet
|
|
10
|
+
|
|
11
|
+
class AddressSheetUtils {
|
|
12
|
+
internal class func buildDefaultValues(params: NSDictionary?) -> AddressViewController.Configuration.DefaultAddressDetails {
|
|
13
|
+
guard let params = params else {
|
|
14
|
+
return AddressViewController.Configuration.DefaultAddressDetails()
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return AddressViewController.Configuration.DefaultAddressDetails(
|
|
18
|
+
address: buildAddress(params: params["address"] as? NSDictionary),
|
|
19
|
+
name: params["name"] as? String,
|
|
20
|
+
phone: params["phone"] as? String,
|
|
21
|
+
isCheckboxSelected: params["isCheckboxSelected"] as? Bool
|
|
22
|
+
)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
internal class func buildAddressDetails(params: NSDictionary?) -> AddressViewController.AddressDetails {
|
|
26
|
+
guard let params = params else { return AddressViewController.AddressDetails(address: buildAddress(params: nil)) }
|
|
27
|
+
return AddressViewController.AddressDetails(
|
|
28
|
+
address: buildAddress(params: params["address"] as? NSDictionary),
|
|
29
|
+
name: params["name"] as? String,
|
|
30
|
+
phone: params["phone"] as? String,
|
|
31
|
+
isCheckboxSelected: params["isCheckboxSelected"] as? Bool)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
internal class func buildAddress(params: NSDictionary?) -> PaymentSheet.Address {
|
|
35
|
+
guard let params = params else { return PaymentSheet.Address() }
|
|
36
|
+
return PaymentSheet.Address(
|
|
37
|
+
city: params["city"] as? String,
|
|
38
|
+
country: params["country"] as? String,
|
|
39
|
+
line1: params["line1"] as? String,
|
|
40
|
+
line2: params["line2"] as? String,
|
|
41
|
+
postalCode: params["postalCode"] as? String,
|
|
42
|
+
state: params["state"] as? String
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
internal class func buildAddress(params: NSDictionary?) -> AddressViewController.AddressDetails.Address {
|
|
47
|
+
guard let params = params else { return AddressViewController.AddressDetails.Address(country: "", line1: "") }
|
|
48
|
+
return AddressViewController.AddressDetails.Address(
|
|
49
|
+
city: params["city"] as? String,
|
|
50
|
+
country: params["country"] as? String ?? "",
|
|
51
|
+
line1: params["line1"] as? String ?? "",
|
|
52
|
+
line2: params["line2"] as? String,
|
|
53
|
+
postalCode: params["postalCode"] as? String,
|
|
54
|
+
state: params["state"] as? String
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
internal class func buildAdditionalFieldsConfiguration(params: NSDictionary?) -> AddressViewController.Configuration.AdditionalFields {
|
|
59
|
+
guard let params = params else {
|
|
60
|
+
return AddressViewController.Configuration.AdditionalFields(phone: .hidden, checkboxLabel: nil)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return AddressViewController.Configuration.AdditionalFields(
|
|
64
|
+
phone: getFieldConfiguration(input: params["phoneNumber"] as? String, default: .hidden),
|
|
65
|
+
checkboxLabel: params["checkboxLabel"] as? String
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
internal class func getFieldConfiguration(input: String?, default: AddressViewController.Configuration.AdditionalFields.FieldConfiguration) -> AddressViewController.Configuration.AdditionalFields.FieldConfiguration {
|
|
70
|
+
switch (input) {
|
|
71
|
+
case "optional":
|
|
72
|
+
return .optional
|
|
73
|
+
case "required":
|
|
74
|
+
return .required
|
|
75
|
+
case "hidden":
|
|
76
|
+
return .hidden
|
|
77
|
+
default:
|
|
78
|
+
return `default`
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
internal class func buildResult(address: AddressViewController.AddressDetails) -> [AnyHashable : Any] {
|
|
83
|
+
return [
|
|
84
|
+
"name": address.name ?? NSNull(),
|
|
85
|
+
"address": [
|
|
86
|
+
"country": address.address.country,
|
|
87
|
+
"state": address.address.state,
|
|
88
|
+
"line1": address.address.line1,
|
|
89
|
+
"line2": address.address.line2,
|
|
90
|
+
"postalCode": address.address.postalCode,
|
|
91
|
+
"city": address.address.city,
|
|
92
|
+
],
|
|
93
|
+
"phone": address.phone ?? NSNull(),
|
|
94
|
+
"isCheckboxSelected": address.isCheckboxSelected ?? NSNull(),
|
|
95
|
+
] as [AnyHashable : Any]
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
//
|
|
2
|
+
// AddressSheetView.swift
|
|
3
|
+
// stripe-react-native
|
|
4
|
+
//
|
|
5
|
+
// Created by Charles Cruzan on 10/11/22.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
import StripePaymentSheet
|
|
10
|
+
|
|
11
|
+
@objc(AddressSheetView)
|
|
12
|
+
class AddressSheetView: UIView {
|
|
13
|
+
@objc var visible = false
|
|
14
|
+
@objc var presentationStyle: String = "popover"
|
|
15
|
+
@objc var animationStyle: String = ""
|
|
16
|
+
@objc var appearance: NSDictionary? = nil
|
|
17
|
+
@objc var defaultValues: NSDictionary? = nil
|
|
18
|
+
@objc var additionalFields: NSDictionary? = nil
|
|
19
|
+
@objc var allowedCountries: [String] = []
|
|
20
|
+
@objc var autocompleteCountries: [String] = []
|
|
21
|
+
@objc var primaryButtonTitle: String? = nil
|
|
22
|
+
@objc var sheetTitle: String? = nil
|
|
23
|
+
@objc var onSubmitAction: RCTDirectEventBlock?
|
|
24
|
+
@objc var onErrorAction: RCTDirectEventBlock?
|
|
25
|
+
|
|
26
|
+
private var wasVisible = false
|
|
27
|
+
private var addressViewController: AddressViewController? = nil
|
|
28
|
+
internal var addressDetails: AddressViewController.AddressDetails? = nil
|
|
29
|
+
|
|
30
|
+
override init(frame: CGRect) {
|
|
31
|
+
super.init(frame: frame)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
required init?(coder: NSCoder) {
|
|
35
|
+
fatalError("init(coder:) has not been implemented")
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
override func didSetProps(_ changedProps: [String]!) {
|
|
39
|
+
if (visible && !wasVisible) {
|
|
40
|
+
presentAddressSheet()
|
|
41
|
+
wasVisible = true
|
|
42
|
+
} else if (!visible && wasVisible) {
|
|
43
|
+
addressViewController?.dismiss(animated: true)
|
|
44
|
+
wasVisible = false
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private func presentAddressSheet() {
|
|
49
|
+
if (STPAPIClient.shared.publishableKey == nil) {
|
|
50
|
+
onErrorAction!(
|
|
51
|
+
Errors.createError(ErrorType.Failed, "No publishable key set. Stripe has not been initialized. Initialize Stripe in your app with the StripeProvider component or the initStripe method.") as? [AnyHashable : Any]
|
|
52
|
+
)
|
|
53
|
+
return
|
|
54
|
+
}
|
|
55
|
+
var config: AddressViewController.Configuration
|
|
56
|
+
do {
|
|
57
|
+
config = try buildAddressSheetConfiguration()
|
|
58
|
+
} catch {
|
|
59
|
+
onErrorAction!(
|
|
60
|
+
Errors.createError(ErrorType.Failed, error.localizedDescription) as? [AnyHashable : Any]
|
|
61
|
+
)
|
|
62
|
+
return
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
self.addressViewController = AddressViewController(
|
|
66
|
+
configuration: config,
|
|
67
|
+
delegate: self
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
let navigationController = UINavigationController(rootViewController: addressViewController!)
|
|
71
|
+
navigationController.modalPresentationStyle = getModalPresentationStyle()
|
|
72
|
+
navigationController.modalTransitionStyle = getModalTransitionStyle()
|
|
73
|
+
let vc = findViewControllerPresenter(from: UIApplication.shared.delegate?.window??.rootViewController ?? UIViewController())
|
|
74
|
+
vc.present(navigationController, animated: true)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
private func buildAddressSheetConfiguration() throws -> AddressViewController.Configuration {
|
|
78
|
+
let appearanceConfiguration = try PaymentSheetAppearance.buildAppearanceFromParams(userParams: appearance)
|
|
79
|
+
|
|
80
|
+
return AddressViewController.Configuration(
|
|
81
|
+
defaultValues: AddressSheetUtils.buildDefaultValues(params: defaultValues),
|
|
82
|
+
additionalFields: AddressSheetUtils.buildAdditionalFieldsConfiguration(params: additionalFields),
|
|
83
|
+
allowedCountries: allowedCountries,
|
|
84
|
+
appearance: appearanceConfiguration,
|
|
85
|
+
buttonTitle: primaryButtonTitle,
|
|
86
|
+
title: sheetTitle
|
|
87
|
+
)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
private func getModalPresentationStyle() -> UIModalPresentationStyle {
|
|
91
|
+
switch (presentationStyle) {
|
|
92
|
+
case "fullscreen":
|
|
93
|
+
return .fullScreen
|
|
94
|
+
case "popover":
|
|
95
|
+
fallthrough
|
|
96
|
+
default:
|
|
97
|
+
return .popover
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private func getModalTransitionStyle() -> UIModalTransitionStyle {
|
|
102
|
+
switch (animationStyle) {
|
|
103
|
+
case "flip":
|
|
104
|
+
return .flipHorizontal
|
|
105
|
+
case "curl":
|
|
106
|
+
return .partialCurl
|
|
107
|
+
case "dissolve":
|
|
108
|
+
return .crossDissolve
|
|
109
|
+
case "slide":
|
|
110
|
+
fallthrough
|
|
111
|
+
default:
|
|
112
|
+
return .coverVertical
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
extension AddressSheetView: AddressViewControllerDelegate {
|
|
118
|
+
func addressViewControllerDidFinish(_ addressViewController: AddressViewController, with address: AddressViewController.AddressDetails?) {
|
|
119
|
+
guard let address = address else {
|
|
120
|
+
onErrorAction!(
|
|
121
|
+
Errors.createError(
|
|
122
|
+
ErrorType.Canceled,
|
|
123
|
+
"The flow has been canceled."
|
|
124
|
+
) as? [AnyHashable : Any]
|
|
125
|
+
)
|
|
126
|
+
return
|
|
127
|
+
}
|
|
128
|
+
self.addressDetails = address
|
|
129
|
+
onSubmitAction!(AddressSheetUtils.buildResult(address: address))
|
|
130
|
+
}
|
|
131
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//
|
|
2
|
+
// AddressSheetViewManager.m
|
|
3
|
+
// stripe-react-native
|
|
4
|
+
//
|
|
5
|
+
// Created by Charles Cruzan on 10/11/22.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#import <Foundation/Foundation.h>
|
|
9
|
+
#import <React/RCTBridgeModule.h>
|
|
10
|
+
#import <React/RCTViewManager.h>
|
|
11
|
+
|
|
12
|
+
@interface RCT_EXTERN_MODULE(AddressSheetViewManager, RCTViewManager)
|
|
13
|
+
RCT_EXPORT_VIEW_PROPERTY(visible, BOOL)
|
|
14
|
+
RCT_EXPORT_VIEW_PROPERTY(presentationStyle, NSString)
|
|
15
|
+
RCT_EXPORT_VIEW_PROPERTY(animationStyle, NSString)
|
|
16
|
+
RCT_EXPORT_VIEW_PROPERTY(appearance, NSDictionary)
|
|
17
|
+
RCT_EXPORT_VIEW_PROPERTY(defaultValues, NSDictionary)
|
|
18
|
+
RCT_EXPORT_VIEW_PROPERTY(additionalFields, NSDictionary)
|
|
19
|
+
RCT_EXPORT_VIEW_PROPERTY(allowedCountries, NSArray)
|
|
20
|
+
RCT_EXPORT_VIEW_PROPERTY(autocompleteCountries, NSArray)
|
|
21
|
+
RCT_EXPORT_VIEW_PROPERTY(primaryButtonTitle, NSString)
|
|
22
|
+
RCT_EXPORT_VIEW_PROPERTY(sheetTitle, NSString)
|
|
23
|
+
RCT_EXPORT_VIEW_PROPERTY(onSubmitAction, RCTDirectEventBlock)
|
|
24
|
+
RCT_EXPORT_VIEW_PROPERTY(onErrorAction, RCTDirectEventBlock)
|
|
25
|
+
@end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
//
|
|
2
|
+
// AddressSheetViewManager.swift
|
|
3
|
+
// stripe-react-native
|
|
4
|
+
//
|
|
5
|
+
// Created by Charles Cruzan on 10/11/22.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
|
|
10
|
+
@objc(AddressSheetViewManager)
|
|
11
|
+
class AddressSheetViewManager : RCTViewManager {
|
|
12
|
+
override func view() -> UIView! {
|
|
13
|
+
return AddressSheetView()
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
override class func requiresMainQueueSetup() -> Bool {
|
|
17
|
+
return true
|
|
18
|
+
}
|
|
19
|
+
}
|