@stripe/stripe-react-native 0.23.2 → 0.24.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.
Files changed (66) hide show
  1. package/CHANGELOG.md +39 -9
  2. package/android/gradle.properties +2 -2
  3. package/android/src/main/java/com/reactnativestripesdk/PaymentLauncherFragment.kt +2 -1
  4. package/android/src/main/java/com/reactnativestripesdk/PaymentSheetFragment.kt +72 -16
  5. package/android/src/main/java/com/reactnativestripesdk/StripeSdkModule.kt +19 -2
  6. package/android/src/main/java/com/reactnativestripesdk/utils/Errors.kt +1 -1
  7. package/android/src/main/java/com/reactnativestripesdk/utils/Mappers.kt +1 -1
  8. package/ios/ApplePayButtonManager.m +1 -0
  9. package/ios/ApplePayButtonView.swift +2 -0
  10. package/ios/ApplePayUtils.swift +116 -15
  11. package/ios/ApplePayViewController.swift +13 -0
  12. package/ios/Errors.swift +1 -0
  13. package/ios/StripeSdk+PaymentSheet.swift +166 -0
  14. package/ios/StripeSdk-Bridging-Header.h +1 -0
  15. package/ios/StripeSdk.m +17 -1
  16. package/ios/StripeSdk.swift +67 -134
  17. package/lib/commonjs/NativeStripeSdk.js.map +1 -1
  18. package/lib/commonjs/components/PlatformPayButton.js +1 -1
  19. package/lib/commonjs/components/PlatformPayButton.js.map +1 -1
  20. package/lib/commonjs/functions.js +1 -1
  21. package/lib/commonjs/functions.js.map +1 -1
  22. package/lib/commonjs/hooks/usePaymentSheet.js +1 -1
  23. package/lib/commonjs/hooks/usePaymentSheet.js.map +1 -1
  24. package/lib/commonjs/hooks/useStripe.js +1 -1
  25. package/lib/commonjs/hooks/useStripe.js.map +1 -1
  26. package/lib/commonjs/types/Errors.js +1 -1
  27. package/lib/commonjs/types/Errors.js.map +1 -1
  28. package/lib/commonjs/types/PaymentSheet.js.map +1 -1
  29. package/lib/commonjs/types/PlatformPay.js +1 -1
  30. package/lib/commonjs/types/PlatformPay.js.map +1 -1
  31. package/lib/commonjs/types/components/ApplePayButtonComponent.js.map +1 -1
  32. package/lib/module/NativeStripeSdk.js.map +1 -1
  33. package/lib/module/components/PlatformPayButton.js +1 -1
  34. package/lib/module/components/PlatformPayButton.js.map +1 -1
  35. package/lib/module/functions.js +1 -1
  36. package/lib/module/functions.js.map +1 -1
  37. package/lib/module/hooks/usePaymentSheet.js +1 -1
  38. package/lib/module/hooks/usePaymentSheet.js.map +1 -1
  39. package/lib/module/hooks/useStripe.js +1 -1
  40. package/lib/module/hooks/useStripe.js.map +1 -1
  41. package/lib/module/types/Errors.js +1 -1
  42. package/lib/module/types/Errors.js.map +1 -1
  43. package/lib/module/types/PaymentSheet.js.map +1 -1
  44. package/lib/module/types/PlatformPay.js +1 -1
  45. package/lib/module/types/PlatformPay.js.map +1 -1
  46. package/lib/module/types/components/ApplePayButtonComponent.js.map +1 -1
  47. package/lib/typescript/src/NativeStripeSdk.d.ts +3 -1
  48. package/lib/typescript/src/components/PlatformPayButton.d.ts +6 -1
  49. package/lib/typescript/src/functions.d.ts +1 -1
  50. package/lib/typescript/src/hooks/usePaymentSheet.d.ts +1 -1
  51. package/lib/typescript/src/hooks/useStripe.d.ts +1 -1
  52. package/lib/typescript/src/types/Errors.d.ts +2 -1
  53. package/lib/typescript/src/types/PaymentSheet.d.ts +17 -1
  54. package/lib/typescript/src/types/PlatformPay.d.ts +64 -1
  55. package/lib/typescript/src/types/components/ApplePayButtonComponent.d.ts +1 -0
  56. package/package.json +2 -2
  57. package/src/NativeStripeSdk.tsx +13 -1
  58. package/src/components/PlatformPayButton.tsx +31 -3
  59. package/src/functions.ts +34 -21
  60. package/src/hooks/usePaymentSheet.tsx +2 -2
  61. package/src/hooks/useStripe.tsx +8 -4
  62. package/src/types/Errors.ts +1 -0
  63. package/src/types/PaymentSheet.ts +33 -3
  64. package/src/types/PlatformPay.ts +72 -1
  65. package/src/types/components/ApplePayButtonComponent.ts +1 -0
  66. package/stripe-react-native.podspec +1 -1
package/CHANGELOG.md CHANGED
@@ -2,15 +2,45 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.24.0 - 2023-02-17
6
+
7
+ ### Breaking changes
8
+
9
+ - [#1248](https://github.com/stripe/stripe-react-native/pull/1248) Renamed the `paymentSummaryItems` field in `initPaymentSheet()`'s `applePay` params to `cartItems`. So your change will look like this:
10
+
11
+ ```diff
12
+ initPaymentSheet({
13
+ ...
14
+ applePay: {
15
+ - paymentSummaryItems: [
16
+ + cartItems: [
17
+ }
18
+ ...
19
+ })
20
+ ```
21
+
22
+ ### New Features
23
+
24
+ - Added the `setOrderTracking` property to the `PlatformPayButton` component and the `initPaymentSheet` method. Use this callback for setting the order details to give users the ability to track and manage their purchases in Wallet. To learn more about order tracking, see [Apple’s Wallet Orders documentation](https://developer.apple.com/documentation/walletorders). [#1248](https://github.com/stripe/stripe-react-native/pull/1248)
25
+ - Added the `buttonType` field to `initPaymentSheet()`'s `applePay` params. Use this to set the text displayed by the call to action button in the Apple Pay sheet.[#1248](https://github.com/stripe/stripe-react-native/pull/1248)
26
+ - Added the `request` field to `initPaymentSheet()`'s, `confirmPlatformPayPayment()`'s, and `confirmPlatformPaySetupIntent`'s `applePay` params. Use this to support different types of payment requests, like `RecurringPaymentRequest`, `AutomaticReloadPaymentRequest`, and `MultiMerchantRequest`.[#1248](https://github.com/stripe/stripe-react-native/pull/1248)
27
+ - Added an `options` argument to `presentPaymentSheet` which includes a `timeout` property. [#1287](https://github.com/stripe/stripe-react-native/pull/1287)
28
+
29
+ ## 0.23.3 - 2023-02-07
30
+
31
+ ### Fixes
32
+
33
+ - Fixes a build failure on Android when using `stripe-android` v20.19.2. [#1289](https://github.com/stripe/stripe-react-native/pull/1289)
34
+
5
35
  ## 0.23.2 - 2023-02-06
6
36
 
7
- ## Fixes
37
+ ### Fixes
8
38
 
9
39
  - Fixed a bug on Android where `canAddCardToWallet` wouldn't correctly return the `details.token` object. [#1282](https://github.com/stripe/stripe-react-native/pull/1282)
10
40
 
11
41
  ## 0.23.1 - 2023-01-25
12
42
 
13
- ## Fixes
43
+ ### Fixes
14
44
 
15
45
  - Fixed an issue with `confirmPlatformPaySetupIntent` on iOS. [#1266](https://github.com/stripe/stripe-react-native/pull/1266)
16
46
  - Fixed types so that Klarna accepts the `shippingDetails` property. [#1272](https://github.com/stripe/stripe-react-native/pull/1272)
@@ -23,7 +53,7 @@
23
53
  - `createPlatformPayPaymentMethod` no longer returns a `token` object. [#1236](https://github.com/stripe/stripe-react-native/issues/1236)
24
54
  - If your integration depends on Stripe's Tokens API, please use `createPlatformPayToken`, which accepts identical arguments.
25
55
 
26
- ## Fixes
56
+ ### Fixes
27
57
 
28
58
  - Fixed an issue with `createPlatformPayPaymentMethod` on iOS where a "Canceled" error could be returned in production. [#1236](https://github.com/stripe/stripe-react-native/issues/1236)
29
59
  - Fixed an issue where the `PlatformPayButton` with `type={PlatformPay.ButtonType.GooglePayMark}` would be unclickable. [#1236](https://github.com/stripe/stripe-react-native/issues/1236)
@@ -32,7 +62,7 @@
32
62
 
33
63
  ## 0.22.1 - 2022-12-07
34
64
 
35
- ## Fixes
65
+ ### Fixes
36
66
 
37
67
  - Fixed the `ShippingMethod` type to contain the `isPending` field instead of a `type` field (which previously was never correct). This reflects the inputs accepted. [#1227](https://github.com/stripe/stripe-react-native/pull/1227)
38
68
  - Fixed the `ShippingMethod` type to contain the `startDate` and `endDate` keys, if applicable. [#1227](https://github.com/stripe/stripe-react-native/pull/1227)
@@ -48,7 +78,7 @@
48
78
  - Added the `hasPairedAppleWatch` option to `canAddCardToWallet`. [#1219](https://github.com/stripe/stripe-react-native/pull/1219)
49
79
  - Added new functions and a new component to streamline integrating with Apple and Google Pay and add more feature support. See the [Migrating to Platform Pay guide](https://github.com/stripe/stripe-react-native/blob/master/docs/Platform-Pay-Migration.md) for more details. The old Apple and Google Pay APIs are marked as `deprecated` and will be removed in a future release, but are still supported in this version.
50
80
 
51
- ## Fixes
81
+ ### Fixes
52
82
 
53
83
  - Fixed an issue where builds would error with the message `'const' enums are not supported.` [see commit](https://github.com/stripe/stripe-react-native/commit/f882bfa588aa6d23a980b4b43d2cca660ca1dd2a)
54
84
  - Fixed an issue where the `canAddCardToWallet` method would sometimes wrongly return `false` with a `details.status` of `MISSING_CONFIGURATION` in production builds. [#1215](https://github.com/stripe/stripe-react-native/pull/1215)
@@ -65,7 +95,7 @@
65
95
  - [Find the docs here](https://stripe.com/docs/elements/address-element?platform=react-native)
66
96
  - Added the `defaultShippingDetails` field to the `params` argument in `initPaymentSheet(params)`. This will allow you to collect shipping details (either in your own UI or using the new `<AddressSheet />` component) for payments in the Payment Sheet. [#1169](https://github.com/stripe/stripe-react-native/pull/1169)
67
97
 
68
- ## Fixes
98
+ ### Fixes
69
99
 
70
100
  - Fixed a build error on Android when using Kotlin version 1.7.10. [#1195](https://github.com/stripe/stripe-react-native/pull/1195)
71
101
 
@@ -83,7 +113,7 @@
83
113
  - Added support for custom fonts to `CardForm` and `CardView` on Android. [#1150](https://github.com/stripe/stripe-react-native/pull/1150)
84
114
  - Added support for customizing the call to action button label in Payment Sheet by providing the `primaryButtonLabel` property to `initPaymentSheet()`. [#1190](https://github.com/stripe/stripe-react-native/pull/1190)
85
115
 
86
- ## Fixes
116
+ ### Fixes
87
117
 
88
118
  - Fixed an issue on iOS where `confirmSetupIntent` would throw an error if the `Card` payment method was provided with the `paymentMethodId` parameter. [#1151](https://github.com/stripe/stripe-react-native/pull/1151)
89
119
  - Upgraded `stripe-android` to 20.15.+. [#1176](https://github.com/stripe/stripe-react-native/pull/1176)
@@ -103,7 +133,7 @@
103
133
 
104
134
  - Add `returnURL` as an optional parameter to `handleNextAction`. Use this so the Stripe SDK can redirect back to your app after authentication. [#1104](https://github.com/stripe/stripe-react-native/pull/1104)
105
135
 
106
- ## Fixes
136
+ ### Fixes
107
137
 
108
138
  - Fixed an issue where the error resolved on iOS wasn't the root error. [#1105](https://github.com/stripe/stripe-react-native/pull/1105)
109
139
  - Fix Expo Config Plugin support on SDK 46. [#1111](https://github.com/stripe/stripe-react-native/pull/1111)
@@ -115,7 +145,7 @@
115
145
 
116
146
  ### New features
117
147
 
118
- ## Fixes
148
+ ### Fixes
119
149
 
120
150
  - Fixed an issue where some promises on Android would never resolve when using React Native 0.65.x or under. [#1089](https://github.com/stripe/stripe-react-native/pull/1089).
121
151
 
@@ -1,2 +1,2 @@
1
- StripeSdk_kotlinVersion=1.6.21
2
- StripeSdk_stripeVersion=20.19.+
1
+ StripeSdk_kotlinVersion=1.8.0
2
+ StripeSdk_stripeVersion=[20.19.2, 20.20.0[
@@ -262,7 +262,8 @@ class PaymentLauncherFragment(
262
262
  StripeIntent.NextActionType.BlikAuthorize,
263
263
  StripeIntent.NextActionType.WeChatPayRedirect,
264
264
  StripeIntent.NextActionType.UpiAwaitNotification,
265
- null -> false
265
+ StripeIntent.NextActionType.CashAppRedirect,
266
+ null, -> false
266
267
  }
267
268
  }
268
269
  }
@@ -1,10 +1,14 @@
1
1
  package com.reactnativestripesdk
2
2
 
3
+ import android.app.Activity
4
+ import android.app.Application
3
5
  import android.content.Context
4
6
  import android.graphics.Bitmap
5
7
  import android.graphics.Canvas
6
8
  import android.graphics.Color
7
9
  import android.os.Bundle
10
+ import android.os.Handler
11
+ import android.os.Looper
8
12
  import android.util.Base64
9
13
  import android.view.LayoutInflater
10
14
  import android.view.View
@@ -21,10 +25,7 @@ import com.reactnativestripesdk.addresssheet.AddressSheetView
21
25
  import com.reactnativestripesdk.utils.*
22
26
  import com.reactnativestripesdk.utils.createError
23
27
  import com.reactnativestripesdk.utils.createResult
24
- import com.stripe.android.paymentsheet.PaymentOptionCallback
25
- import com.stripe.android.paymentsheet.PaymentSheet
26
- import com.stripe.android.paymentsheet.PaymentSheetResult
27
- import com.stripe.android.paymentsheet.PaymentSheetResultCallback
28
+ import com.stripe.android.paymentsheet.*
28
29
  import java.io.ByteArrayOutputStream
29
30
 
30
31
  class PaymentSheetFragment(
@@ -38,6 +39,7 @@ class PaymentSheetFragment(
38
39
  private lateinit var paymentSheetConfiguration: PaymentSheet.Configuration
39
40
  private var confirmPromise: Promise? = null
40
41
  private var presentPromise: Promise? = null
42
+ private var paymentSheetTimedOut = false
41
43
 
42
44
  override fun onCreateView(
43
45
  inflater: LayoutInflater,
@@ -84,23 +86,35 @@ class PaymentSheetFragment(
84
86
  option.putString("image", imageString)
85
87
  createResult("paymentOption", option)
86
88
  } ?: run {
87
- createError(PaymentSheetErrorType.Canceled.toString(), "The payment option selection flow has been canceled")
89
+ if (paymentSheetTimedOut) {
90
+ paymentSheetTimedOut = false
91
+ createError(PaymentSheetErrorType.Timeout.toString(), "The payment has timed out")
92
+ } else {
93
+ createError(PaymentSheetErrorType.Canceled.toString(), "The payment option selection flow has been canceled")
94
+ }
88
95
  }
89
96
  presentPromise?.resolve(result)
90
97
  }
91
98
 
92
99
  val paymentResultCallback = PaymentSheetResultCallback { paymentResult ->
93
- when (paymentResult) {
94
- is PaymentSheetResult.Canceled -> {
95
- resolvePaymentResult(createError(PaymentSheetErrorType.Canceled.toString(), "The payment flow has been canceled"))
96
- }
97
- is PaymentSheetResult.Failed -> {
98
- resolvePaymentResult(createError(PaymentSheetErrorType.Failed.toString(), paymentResult.error))
99
- }
100
- is PaymentSheetResult.Completed -> {
101
- resolvePaymentResult(WritableNativeMap())
102
- // Remove the fragment now, we can be sure it won't be needed again if an intent is successful
103
- removeFragment(context)
100
+ if (paymentSheetTimedOut) {
101
+ paymentSheetTimedOut = false
102
+ resolvePaymentResult(createError(PaymentSheetErrorType.Timeout.toString(), "The payment has timed out"))
103
+ } else {
104
+ when (paymentResult) {
105
+ is PaymentSheetResult.Canceled -> {
106
+ resolvePaymentResult(createError(PaymentSheetErrorType.Canceled.toString(), "The payment flow has been canceled"))
107
+ }
108
+ is PaymentSheetResult.Failed -> {
109
+ resolvePaymentResult(createError(PaymentSheetErrorType.Failed.toString(), paymentResult.error))
110
+ }
111
+ is PaymentSheetResult.Completed -> {
112
+ resolvePaymentResult(WritableNativeMap())
113
+ // Remove the fragment now, we can be sure it won't be needed again if an intent is successful
114
+ removeFragment(context)
115
+ paymentSheet = null
116
+ flowController = null
117
+ }
104
118
  }
105
119
  }
106
120
  }
@@ -155,7 +169,45 @@ class PaymentSheetFragment(
155
169
  }
156
170
  } else if(flowController != null) {
157
171
  flowController?.presentPaymentOptions()
172
+ } else {
173
+ promise.resolve(createMissingInitError())
174
+ }
175
+ }
176
+
177
+ fun presentWithTimeout(timeout: Long, promise: Promise) {
178
+ var paymentSheetActivity: Activity? = null
179
+
180
+ val activityLifecycleCallbacks = object : Application.ActivityLifecycleCallbacks {
181
+ override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
182
+ paymentSheetActivity = activity
183
+ }
184
+
185
+ override fun onActivityStarted(activity: Activity) {}
186
+
187
+ override fun onActivityResumed(activity: Activity) {}
188
+
189
+ override fun onActivityPaused(activity: Activity) {}
190
+
191
+ override fun onActivityStopped(activity: Activity) {}
192
+
193
+ override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
194
+
195
+ override fun onActivityDestroyed(activity: Activity) {
196
+ paymentSheetActivity = null
197
+ context.currentActivity?.application?.unregisterActivityLifecycleCallbacks(this)
198
+ }
158
199
  }
200
+
201
+ Handler(Looper.getMainLooper()).postDelayed({
202
+ paymentSheetActivity?.let {
203
+ it.finish()
204
+ paymentSheetTimedOut = true
205
+ }
206
+ }, timeout)
207
+
208
+ context.currentActivity?.application?.registerActivityLifecycleCallbacks(activityLifecycleCallbacks)
209
+
210
+ this.present(promise)
159
211
  }
160
212
 
161
213
  fun confirmPayment(promise: Promise) {
@@ -205,6 +257,10 @@ class PaymentSheetFragment(
205
257
  companion object {
206
258
  internal const val TAG = "payment_sheet_launch_fragment"
207
259
 
260
+ internal fun createMissingInitError(): WritableMap {
261
+ return createError(PaymentSheetErrorType.Failed.toString(), "No payment sheet has been initialized yet. You must call `initPaymentSheet` before `presentPaymentSheet`.")
262
+ }
263
+
208
264
  internal fun buildGooglePayConfig(params: Bundle?): PaymentSheet.GooglePayConfiguration? {
209
265
  if (params == null) {
210
266
  return null
@@ -172,12 +172,29 @@ class StripeSdkModule(reactContext: ReactApplicationContext) : ReactContextBaseJ
172
172
  }
173
173
 
174
174
  @ReactMethod
175
- fun presentPaymentSheet(promise: Promise) {
176
- paymentSheetFragment?.present(promise)
175
+ fun presentPaymentSheet(options: ReadableMap, promise: Promise) {
176
+ if (paymentSheetFragment == null) {
177
+ promise.resolve(PaymentSheetFragment.createMissingInitError())
178
+ return
179
+ }
180
+
181
+ val timeoutKey = "timeout"
182
+ if (options.hasKey(timeoutKey)) {
183
+ paymentSheetFragment?.presentWithTimeout(
184
+ options.getInt(timeoutKey).toLong(), promise
185
+ )
186
+ } else {
187
+ paymentSheetFragment?.present(promise)
188
+ }
177
189
  }
178
190
 
179
191
  @ReactMethod
180
192
  fun confirmPaymentSheetPayment(promise: Promise) {
193
+ if (paymentSheetFragment == null) {
194
+ promise.resolve(PaymentSheetFragment.createMissingInitError())
195
+ return
196
+ }
197
+
181
198
  paymentSheetFragment?.confirmPayment(promise)
182
199
  }
183
200
 
@@ -34,7 +34,7 @@ enum class RetrieveSetupIntentErrorType {
34
34
  }
35
35
 
36
36
  enum class PaymentSheetErrorType {
37
- Failed, Canceled
37
+ Failed, Canceled, Timeout
38
38
  }
39
39
 
40
40
  enum class GooglePayErrorType {
@@ -482,7 +482,7 @@ internal fun mapNextAction(type: NextActionType?, data: NextActionData?): Writab
482
482
  NextActionType.AlipayRedirect -> { // TODO: Can't access, private
483
483
  return null
484
484
  }
485
- NextActionType.BlikAuthorize, NextActionType.UseStripeSdk, NextActionType.UpiAwaitNotification, null -> {
485
+ NextActionType.CashAppRedirect, NextActionType.BlikAuthorize, NextActionType.UseStripeSdk, NextActionType.UpiAwaitNotification, null -> {
486
486
  return null
487
487
  }
488
488
  }
@@ -11,5 +11,6 @@ RCT_EXPORT_VIEW_PROPERTY(disabled, BOOL)
11
11
  RCT_EXPORT_VIEW_PROPERTY(onShippingMethodSelectedAction, RCTDirectEventBlock)
12
12
  RCT_EXPORT_VIEW_PROPERTY(onShippingContactSelectedAction, RCTDirectEventBlock)
13
13
  RCT_EXPORT_VIEW_PROPERTY(onCouponCodeEnteredAction, RCTDirectEventBlock)
14
+ RCT_EXPORT_VIEW_PROPERTY(onOrderTrackingAction, RCTDirectEventBlock)
14
15
 
15
16
  @end
@@ -10,6 +10,7 @@ class ApplePayButtonView: UIView {
10
10
  @objc var onShippingMethodSelectedAction: RCTDirectEventBlock?
11
11
  @objc var onShippingContactSelectedAction: RCTDirectEventBlock?
12
12
  @objc var onCouponCodeEnteredAction: RCTDirectEventBlock?
13
+ @objc var onOrderTrackingAction: RCTDirectEventBlock?
13
14
 
14
15
  @objc var type: NSNumber?
15
16
  @objc var buttonStyle: NSNumber?
@@ -33,6 +34,7 @@ class ApplePayButtonView: UIView {
33
34
  stripeSdk?.shippingMethodUpdateJSCallback = onShippingMethodSelectedAction
34
35
  stripeSdk?.shippingContactUpdateJSCallback = onShippingContactSelectedAction
35
36
  stripeSdk?.couponCodeEnteredJSCallback = onCouponCodeEnteredAction
37
+ stripeSdk?.platformPayOrderTrackingJSCallback = onOrderTrackingAction
36
38
  }
37
39
  }
38
40
 
@@ -19,11 +19,7 @@ class ApplePayUtils {
19
19
  }
20
20
 
21
21
  if let additionalEnabledNetworks = params["additionalEnabledNetworks"] as? [String] {
22
- do {
23
- StripeAPI.additionalEnabledApplePayNetworks = try ApplePayUtils.mapToArrayOfPaymentNetworks(arrayOfStrings: additionalEnabledNetworks)
24
- } catch {
25
- return (Errors.createError(ErrorType.Failed, error.localizedDescription), nil)
26
- }
22
+ StripeAPI.additionalEnabledApplePayNetworks = ApplePayUtils.mapToArrayOfPaymentNetworks(arrayOfStrings: additionalEnabledNetworks)
27
23
  } else if (params["jcbEnabled"] as? Bool == true) {
28
24
  StripeAPI.additionalEnabledApplePayNetworks = [.JCB]
29
25
  }
@@ -61,7 +57,7 @@ class ApplePayUtils {
61
57
  do {
62
58
  paymentRequest.paymentSummaryItems = try ApplePayUtils
63
59
  .buildPaymentSummaryItems(items: summaryItems as? [[String : Any]])
64
- } catch {
60
+ } catch {
65
61
  return (Errors.createError(ErrorType.Failed, error.localizedDescription), nil)
66
62
  }
67
63
 
@@ -84,10 +80,79 @@ class ApplePayUtils {
84
80
  paymentRequest.couponCode = couponCode
85
81
  }
86
82
  }
87
-
83
+
84
+ do {
85
+ try paymentRequest.configureRequestType(requestParams: params["request"] as? NSDictionary)
86
+ } catch {
87
+ return (Errors.createError(ErrorType.Failed, error.localizedDescription), nil)
88
+ }
89
+
88
90
  return (nil, paymentRequest)
89
91
  }
90
92
 
93
+ #if compiler(>=5.7)
94
+ @available(iOS 16.0, *)
95
+ internal class func buildRecurringPaymentRequest(params: NSDictionary) throws -> PKRecurringPaymentRequest {
96
+ guard let description = params["description"] as? String else {
97
+ throw ApplePayUtilsError.missingParameter(nil, "description")
98
+ }
99
+ guard let urlString = params["managementUrl"] as? String else {
100
+ throw ApplePayUtilsError.missingParameter(nil, "managementUrl")
101
+ }
102
+ guard let url = URL(string: urlString) else {
103
+ throw ApplePayUtilsError.invalidUrl(urlString)
104
+ }
105
+ let regularBilling = try ApplePayUtils.createRecurringPaymentSummaryItem(item: params["billing"] as? [String : Any] ?? [:])
106
+ let request = PKRecurringPaymentRequest(paymentDescription: description, regularBilling: regularBilling, managementURL: url)
107
+ if let trialParams = params["trialBilling"] as? [String : Any] {
108
+ request.trialBilling = try ApplePayUtils.createRecurringPaymentSummaryItem(item: trialParams)
109
+ }
110
+ if let tokenNotificationURL = params["tokenNotificationURL"] as? String {
111
+ request.tokenNotificationURL = URL(string: tokenNotificationURL)
112
+ }
113
+ request.billingAgreement = params["billingAgreement"] as? String
114
+ return request
115
+ }
116
+
117
+ @available(iOS 16.0, *)
118
+ internal class func buildAutomaticReloadPaymentRequest(params: NSDictionary) throws -> PKAutomaticReloadPaymentRequest {
119
+ guard let description = params["description"] as? String else {
120
+ throw ApplePayUtilsError.missingParameter(nil, "description")
121
+ }
122
+ guard let urlString = params["managementUrl"] as? String else {
123
+ throw ApplePayUtilsError.missingParameter(nil, "managementUrl")
124
+ }
125
+ guard let url = URL(string: urlString) else {
126
+ throw ApplePayUtilsError.invalidUrl(urlString)
127
+ }
128
+ let automaticReloadBilling = PKAutomaticReloadPaymentSummaryItem.init(label: params["label"] as? String ?? "", amount: NSDecimalNumber(string: params["reloadAmount"] as? String ?? ""))
129
+ guard let threshold = params["thresholdAmount"] as? String else {
130
+ throw ApplePayUtilsError.missingParameter(nil, "thresholdAmount")
131
+ }
132
+ automaticReloadBilling.thresholdAmount = NSDecimalNumber(string: threshold)
133
+ let request = PKAutomaticReloadPaymentRequest(paymentDescription: description, automaticReloadBilling: automaticReloadBilling, managementURL: url)
134
+ if let tokenNotificationURL = params["tokenNotificationURL"] as? String {
135
+ request.tokenNotificationURL = URL(string: tokenNotificationURL)
136
+ }
137
+ request.billingAgreement = params["billingAgreement"] as? String
138
+ return request
139
+ }
140
+
141
+ @available(iOS 16.0, *)
142
+ internal class func buildPaymentTokenContexts(items: [[String : Any]]) -> [PKPaymentTokenContext] {
143
+ var result: [PKPaymentTokenContext] = []
144
+ for item in items {
145
+ let context = PKPaymentTokenContext.init(merchantIdentifier: item["merchantIdentifier"] as? String ?? "",
146
+ externalIdentifier: item["externalIdentifier"] as? String ?? "",
147
+ merchantName: item["merchantName"] as? String ?? "",
148
+ merchantDomain: item["merchantDomain"] as? String,
149
+ amount: NSDecimalNumber(string: item["thresholdAmount"] as? String ?? ""))
150
+ result.append(context)
151
+ }
152
+ return result
153
+ }
154
+ #endif
155
+
91
156
  internal class func getMerchantCapabilityFrom(string: String?) -> PKMerchantCapability {
92
157
  switch string {
93
158
  case "supportsDebit":
@@ -119,7 +184,7 @@ class ApplePayUtils {
119
184
  }
120
185
 
121
186
  @available(iOS 15.0, *)
122
- internal class func createDeferredPaymentSummaryItem(item: [String : Any]) throws -> PKPaymentSummaryItem {
187
+ internal class func createDeferredPaymentSummaryItem(item: [String : Any]) throws -> PKDeferredPaymentSummaryItem {
123
188
  let label = item["label"] as? String ?? ""
124
189
  let amount = NSDecimalNumber(string: item["amount"] as? String ?? "")
125
190
 
@@ -135,7 +200,7 @@ class ApplePayUtils {
135
200
  }
136
201
 
137
202
  @available(iOS 15.0, *)
138
- internal class func createRecurringPaymentSummaryItem(item: [String : Any]) throws -> PKPaymentSummaryItem {
203
+ internal class func createRecurringPaymentSummaryItem(item: [String : Any]) throws -> PKRecurringPaymentSummaryItem {
139
204
  let label = item["label"] as? String ?? ""
140
205
  let amount = NSDecimalNumber(string: item["amount"] as? String ?? "")
141
206
 
@@ -285,8 +350,8 @@ class ApplePayUtils {
285
350
  return (shippingAddressErrors, couponCodeErrors)
286
351
  }
287
352
 
288
- internal class func mapToArrayOfPaymentNetworks(arrayOfStrings: [String]) throws -> [PKPaymentNetwork] {
289
- let validNetworks: [PKPaymentNetwork?] = try arrayOfStrings.map { networkString in
353
+ internal class func mapToArrayOfPaymentNetworks(arrayOfStrings: [String]) -> [PKPaymentNetwork] {
354
+ let validNetworks: [PKPaymentNetwork?] = arrayOfStrings.map { networkString in
290
355
  return PKPaymentNetwork.init(rawValue: networkString)
291
356
  }
292
357
  return validNetworks.compactMap { $0 }
@@ -295,7 +360,9 @@ class ApplePayUtils {
295
360
  public class func buildPaymentSheetApplePayConfig(
296
361
  merchantIdentifier: String?,
297
362
  merchantCountryCode: String?,
298
- paymentSummaryItems: [[String : Any]]?
363
+ paymentSummaryItems: [[String : Any]]?,
364
+ buttonType: NSNumber?,
365
+ customHandlers: PaymentSheet.ApplePayConfiguration.Handlers?
299
366
  ) throws -> PaymentSheet.ApplePayConfiguration {
300
367
  guard let merchantId = merchantIdentifier else {
301
368
  throw ApplePayUtilsError.missingMerchantId
@@ -306,20 +373,25 @@ class ApplePayUtils {
306
373
  let paymentSummaryItems = try ApplePayUtils.buildPaymentSummaryItems(
307
374
  items: paymentSummaryItems
308
375
  )
376
+
309
377
  return PaymentSheet.ApplePayConfiguration.init(
310
378
  merchantId: merchantId,
311
379
  merchantCountryCode: countryCode,
312
- paymentSummaryItems:paymentSummaryItems.count > 0 ? paymentSummaryItems : nil
380
+ buttonType: PKPaymentButtonType(rawValue: buttonType as? Int ?? 0) ?? .plain,
381
+ paymentSummaryItems: paymentSummaryItems.count > 0 ? paymentSummaryItems : nil,
382
+ customHandlers: customHandlers
313
383
  )
314
384
  }
315
385
  }
316
386
 
317
387
  enum ApplePayUtilsError : Error, Equatable {
318
388
  case invalidCartSummaryItemType(String)
319
- case missingParameter(String, String)
389
+ case missingParameter(String?, String)
320
390
  case invalidTimeInterval(String)
321
391
  case invalidPaymentNetwork(String)
322
392
  case invalidErrorType(String)
393
+ case invalidUrl(String)
394
+ case invalidRequestType(String)
323
395
  case missingMerchantId
324
396
  case missingCountryCode
325
397
  }
@@ -330,7 +402,11 @@ extension ApplePayUtilsError: LocalizedError {
330
402
  case .invalidCartSummaryItemType(let type):
331
403
  return "Failed to ceate Apple Pay summary item. Expected `type` to be one of 'Immediate', 'Recurring', or 'Deferred', but received: \(type)"
332
404
  case .missingParameter(let label, let parameter):
333
- return "Failed to create Apple Pay summary item with label: \(label). The \(parameter) item parameter is required, but none was provided."
405
+ if let label = label {
406
+ return "Failed to create Apple Pay summary item with label: \(label). The \(parameter) item parameter is required, but none was provided."
407
+ } else {
408
+ return "The \(parameter) item parameter is required, but none was provided."
409
+ }
334
410
  case .invalidTimeInterval(let providedInterval):
335
411
  return "Failed to create Apple Pay summary item. \(providedInterval) is not a valid timeInterval, must be one of: minute, hour, day, month, or year."
336
412
  case .invalidPaymentNetwork(let network):
@@ -341,6 +417,31 @@ extension ApplePayUtilsError: LocalizedError {
341
417
  return "`merchantIdentifier` is required, but none was found. Ensure you are passing this to initStripe your StripeProvider."
342
418
  case .missingCountryCode:
343
419
  return "`merchantCountryCode` is a required param, but was not provided."
420
+ case .invalidUrl(let url):
421
+ return "Invalid URL: \(url)."
422
+ case .invalidRequestType(let tyoe):
423
+ return "Apple Pay request type `\(tyoe)` is not supported."
424
+ }
425
+ }
426
+ }
427
+
428
+ extension PKPaymentRequest {
429
+ func configureRequestType(requestParams: NSDictionary?) throws -> Void {
430
+ #if compiler(>=5.7)
431
+ if #available(iOS 16.0, *) {
432
+ if let requestParams = requestParams {
433
+ switch requestParams["type"] as? String {
434
+ case "Recurring":
435
+ self.recurringPaymentRequest = try ApplePayUtils.buildRecurringPaymentRequest(params: requestParams)
436
+ case "AutomaticReload":
437
+ self.automaticReloadPaymentRequest = try ApplePayUtils.buildAutomaticReloadPaymentRequest(params: requestParams)
438
+ case "MultiMerchant":
439
+ self.multiTokenContexts = ApplePayUtils.buildPaymentTokenContexts(items: requestParams["merchants"] as? [[String : Any]] ?? [])
440
+ default:
441
+ throw ApplePayUtilsError.invalidRequestType(String(describing: requestParams["type"]))
442
+ }
443
+ }
344
444
  }
445
+ #endif
345
446
  }
346
447
  }
@@ -177,6 +177,19 @@ extension StripeSdk : PKPaymentAuthorizationViewControllerDelegate, STPApplePayC
177
177
  }
178
178
  }
179
179
 
180
+ func applePayContext(
181
+ _ context: STPApplePayContext,
182
+ willCompleteWithResult authorizationResult: PKPaymentAuthorizationResult,
183
+ handler: @escaping (PKPaymentAuthorizationResult) -> Void
184
+ ) {
185
+ if let callback = self.platformPayOrderTrackingJSCallback {
186
+ self.orderTrackingHandler = (authorizationResult, handler)
187
+ callback(nil)
188
+ } else {
189
+ handler(authorizationResult)
190
+ }
191
+ }
192
+
180
193
  func applePayContext(
181
194
  _ context: STPApplePayContext,
182
195
  didCompleteWith status: STPPaymentStatus,
package/ios/Errors.swift CHANGED
@@ -5,6 +5,7 @@ enum ErrorType {
5
5
  static let Failed = "Failed"
6
6
  static let Canceled = "Canceled"
7
7
  static let Unknown = "Unknown"
8
+ static let Timeout = "Timeout"
8
9
  }
9
10
 
10
11
  class Errors {