react-native-hyperswitch-dev-sdk 0.4.1
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/HyperswitchSdkReactNative.podspec +42 -0
- package/LICENSE +201 -0
- package/android/build.gradle +161 -0
- package/android/gradle.properties +5 -0
- package/android/hyperswitch_autolinking.gradle +378 -0
- package/android/proguard-rules.pro +72 -0
- package/android/src/legacy/java/com/facebook/react/viewmanagers/GooglePayButtonManagerDelegate.java +41 -0
- package/android/src/legacy/java/com/facebook/react/viewmanagers/GooglePayButtonManagerInterface.java +20 -0
- package/android/src/legacy/java/com/facebook/react/viewmanagers/NativePaymentWidgetManagerDelegate.java +38 -0
- package/android/src/legacy/java/com/facebook/react/viewmanagers/NativePaymentWidgetManagerInterface.java +21 -0
- package/android/src/legacy/java/com/hyperswitchsdkreactnative/NativeHyperswitchSdkNativeSpec.java +106 -0
- package/android/src/legacy/java/com/hyperswitchsdkreactnative/NativeHyperswitchSdkReactNativeSpec.java +77 -0
- package/android/src/legacy/java/com/hyperswitchsdkreactnative/NativePaymentWidgetNativeSpec.java +36 -0
- package/android/src/main/AndroidManifest.xml +15 -0
- package/android/src/main/assets/hyperswitch.bundle +1535 -0
- package/android/src/main/java/com/hyperswitchsdkreactnative/HyperswitchSdkReactNativePackage.kt +47 -0
- package/android/src/main/java/com/hyperswitchsdkreactnative/modules/NativePaymentWidgetModule.kt +173 -0
- package/android/src/main/java/com/hyperswitchsdkreactnative/modules/ReactNativeHyperswitchModule.kt +396 -0
- package/android/src/main/java/com/hyperswitchsdkreactnative/views/PaymentElementViewManager.kt +99 -0
- package/android/src/main/java/io/hyperswitch/HyperswitchReactPackageProvider.kt +19 -0
- package/android/src/main/java/io/hyperswitch/PaymentEventType.kt +18 -0
- package/android/src/main/java/io/hyperswitch/model/ElementConfiguration.kt +58 -0
- package/android/src/main/java/io/hyperswitch/paymentsession/ExitHeadlessCallBackManager.kt +47 -0
- package/android/src/main/java/io/hyperswitch/paymentsession/GetPaymentSessionCallBackManager.kt +23 -0
- package/android/src/main/java/io/hyperswitch/paymentsession/PaymentMethod.kt +167 -0
- package/android/src/main/java/io/hyperswitch/paymentsession/PaymentSessionHandler.kt +68 -0
- package/android/src/main/java/io/hyperswitch/paymentsession/PaymentSessionHandlerImpl.kt +179 -0
- package/android/src/main/java/io/hyperswitch/paymentsession/PaymentSessionReactLauncher.kt +226 -0
- package/android/src/main/java/io/hyperswitch/paymentsession/PaymentSheetCallbackManager.kt +40 -0
- package/android/src/main/java/io/hyperswitch/paymentsheet/PaymentResult.kt +63 -0
- package/android/src/main/java/io/hyperswitch/react/GooglePayButtonManager.kt +54 -0
- package/android/src/main/java/io/hyperswitch/react/HyperActivity.kt +73 -0
- package/android/src/main/java/io/hyperswitch/react/HyperEventEmitter.kt +144 -0
- package/android/src/main/java/io/hyperswitch/react/HyperFragment.kt +429 -0
- package/android/src/main/java/io/hyperswitch/react/HyperFragmentManager.kt +155 -0
- package/android/src/main/java/io/hyperswitch/react/HyperHeadlessModule.kt +43 -0
- package/android/src/main/java/io/hyperswitch/react/HyperModule.kt +405 -0
- package/android/src/main/java/io/hyperswitch/react/HyperPackage.kt +16 -0
- package/android/src/main/java/io/hyperswitch/react/ReactNativeController.kt +251 -0
- package/android/src/main/java/io/hyperswitch/utils/ConversionUtils.kt +256 -0
- package/android/src/main/java/io/hyperswitch/utils/StandardResult.kt +45 -0
- package/android/src/main/java/io/hyperswitch/view/GooglePayButtonView.kt +59 -0
- package/android/src/main/java/io/hyperswitch/view/PaymentWidgetView.kt +405 -0
- package/android/src/main/res/values/attrs.xml +6 -0
- package/android/src/main/res/values/strings.xml +5 -0
- package/android/src/main/res/values/theme.xml +16 -0
- package/ios/Modules/ReactNative/HyperswitchModule.swift +470 -0
- package/ios/Modules/ReactNative/HyperswitchSdkReactNative.h +5 -0
- package/ios/Modules/ReactNative/HyperswitchSdkReactNative.mm +121 -0
- package/ios/Modules/ReactNative/NativeHyperswitchModule.h +18 -0
- package/ios/Modules/ReactNative/NativeHyperswitchModule.mm +165 -0
- package/ios/Modules/ReactNative/NativeHyperswitchModuleImpl.swift +290 -0
- package/ios/Modules/ReactNative/NativePaymentElementModule.mm +129 -0
- package/ios/Views/Fabric/ApplePayView.h +14 -0
- package/ios/Views/Fabric/ApplePayView.mm +89 -0
- package/ios/Views/Fabric/NativePaymentElementView.h +21 -0
- package/ios/Views/Fabric/NativePaymentElementView.mm +200 -0
- package/ios/Views/Fabric/NativePaymentWidgetViewRegistry.h +37 -0
- package/ios/Views/Fabric/NativePaymentWidgetViewRegistry.m +45 -0
- package/ios/Views/Native/NativePaymentWidget.m +26 -0
- package/ios/Views/Native/NativePaymentWidget.swift +420 -0
- package/ios/hyperswitchSDK/Core/ApplePay/ApplePayHandler.swift +261 -0
- package/ios/hyperswitchSDK/Core/ApplePay/ApplePayViewManager.m +18 -0
- package/ios/hyperswitchSDK/Core/ApplePay/ApplePayViewManager.swift +126 -0
- package/ios/hyperswitchSDK/Core/DeviceDataCollection/HeadlessWebView.swift +144 -0
- package/ios/hyperswitchSDK/Core/HyperCVCWidget/CVCWidget.swift +136 -0
- package/ios/hyperswitchSDK/Core/HyperExpressCheckout/ExpressCheckoutLauncher.swift +116 -0
- package/ios/hyperswitchSDK/Core/HyperExpressCheckout/ExpressCheckoutWidget.swift +42 -0
- package/ios/hyperswitchSDK/Core/HyperPaymentCardTextField/PaymentCardTextField+SwiftUI.swift +67 -0
- package/ios/hyperswitchSDK/Core/HyperPaymentCardTextField/PaymentCardTextField.swift +44 -0
- package/ios/hyperswitchSDK/Core/HyperPaymentCardTextField/PaymentHandler.swift +59 -0
- package/ios/hyperswitchSDK/Core/HyperPaymentCardTextField/PaymentIntentParams.swift +31 -0
- package/ios/hyperswitchSDK/Core/HyperPaymentCardTextField/PaymentMethodParams.swift +25 -0
- package/ios/hyperswitchSDK/Core/HyperPaymentMethodManagement/PaymentManagementConfiguration.swift +213 -0
- package/ios/hyperswitchSDK/Core/HyperPaymentMethodManagement/PaymentMethodManagementWidget.swift +92 -0
- package/ios/hyperswitchSDK/Core/HyperPaymentSheet/PaymentSheet+Events.swift +36 -0
- package/ios/hyperswitchSDK/Core/HyperPaymentSheet/PaymentSheetView+SwiftUI.swift +49 -0
- package/ios/hyperswitchSDK/Core/HyperPaymentSheet/PaymentSheetView+UIKit.swift +49 -0
- package/ios/hyperswitchSDK/Core/HyperPaymentSheet/PaymentSheetView.swift +68 -0
- package/ios/hyperswitchSDK/Core/HyperPaymentWidget/PaymentWidget.swift +212 -0
- package/ios/hyperswitchSDK/Core/HyperSession/PaymentSession+UIKit.swift +228 -0
- package/ios/hyperswitchSDK/Core/HyperSession/PaymentSessionTypes.swift +174 -0
- package/ios/hyperswitchSDK/Core/NativeModule/HyperHeadless.m +15 -0
- package/ios/hyperswitchSDK/Core/NativeModule/HyperHeadless.swift +108 -0
- package/ios/hyperswitchSDK/Core/NativeModule/HyperModule.m +31 -0
- package/ios/hyperswitchSDK/Core/NativeModule/HyperModule.swift +343 -0
- package/ios/hyperswitchSDK/Core/NativeModule/OTAServices.swift +117 -0
- package/ios/hyperswitchSDK/Core/NativeModule/RNHeadlessManager.swift +47 -0
- package/ios/hyperswitchSDK/Core/NativeModule/RNResponseHandler.swift +12 -0
- package/ios/hyperswitchSDK/Core/NativeModule/RNViewManager.swift +55 -0
- package/ios/hyperswitchSDK/Core/NativeModule/WidgetAction.swift +30 -0
- package/ios/hyperswitchSDK/Core/NativeModule/WidgetResponseRegistry.swift +92 -0
- package/ios/hyperswitchSDK/Core/NativeModule/hyper-Bridging-Header.h +12 -0
- package/ios/hyperswitchSDK/Core/Resources/HyperOTA.plist +20 -0
- package/ios/hyperswitchSDK/Core/Resources/hyperswitch.bundle +1531 -0
- package/ios/hyperswitchSDK/CoreLite/ApplePayHandlerLite.swift +251 -0
- package/ios/hyperswitchSDK/CoreLite/PaymentSession+Lite.swift +25 -0
- package/ios/hyperswitchSDK/CoreLite/PaymentSheetView+Lite.swift +45 -0
- package/ios/hyperswitchSDK/CoreLite/SwiftUI+Lite.swift +48 -0
- package/ios/hyperswitchSDK/CoreLite/WebViewController.swift +278 -0
- package/ios/hyperswitchSDK/Shared/APIClient.swift +22 -0
- package/ios/hyperswitchSDK/Shared/Codable+UIKit.swift +75 -0
- package/ios/hyperswitchSDK/Shared/CustomEndpointConfiguration.swift +67 -0
- package/ios/hyperswitchSDK/Shared/DictionaryConverter.swift +104 -0
- package/ios/hyperswitchSDK/Shared/Environment.swift +24 -0
- package/ios/hyperswitchSDK/Shared/Extensions.swift +101 -0
- package/ios/hyperswitchSDK/Shared/Helper.swift +40 -0
- package/ios/hyperswitchSDK/Shared/HyperEvents/PaymentEventData.swift +125 -0
- package/ios/hyperswitchSDK/Shared/HyperEvents/PaymentEventSubscriptionBuilder.swift +45 -0
- package/ios/hyperswitchSDK/Shared/HyperEvents/PaymentEventType.swift +30 -0
- package/ios/hyperswitchSDK/Shared/HyperNetworking.swift +151 -0
- package/ios/hyperswitchSDK/Shared/HyperParams.swift +44 -0
- package/ios/hyperswitchSDK/Shared/HyperUIViewController.swift +27 -0
- package/ios/hyperswitchSDK/Shared/Hyperswitch.swift +20 -0
- package/ios/hyperswitchSDK/Shared/HyperswitchConfigurationSchema.swift +54 -0
- package/ios/hyperswitchSDK/Shared/HyperswitchEnvironment.swift +11 -0
- package/ios/hyperswitchSDK/Shared/NativeLogger/Debouncer.swift +37 -0
- package/ios/hyperswitchSDK/Shared/NativeLogger/LogBuilder.swift +113 -0
- package/ios/hyperswitchSDK/Shared/NativeLogger/LogFileManager.swift +76 -0
- package/ios/hyperswitchSDK/Shared/NativeLogger/LogManager.swift +113 -0
- package/ios/hyperswitchSDK/Shared/NativeLogger/LogPayload.swift +91 -0
- package/ios/hyperswitchSDK/Shared/PaymentMethodType.swift +15 -0
- package/ios/hyperswitchSDK/Shared/PaymentSession.swift +98 -0
- package/ios/hyperswitchSDK/Shared/PaymentSessionConfiguration.swift +14 -0
- package/ios/hyperswitchSDK/Shared/PaymentSheet.swift +33 -0
- package/ios/hyperswitchSDK/Shared/PaymentSheetAppearance+Codable.swift +182 -0
- package/ios/hyperswitchSDK/Shared/PaymentSheetAppearance.swift +238 -0
- package/ios/hyperswitchSDK/Shared/PaymentSheetConfiguration.swift +161 -0
- package/ios/hyperswitchSDK/Shared/SDKParams.swift +43 -0
- package/ios/hyperswitchSDK/Shared/SavedPaymentMethodsConfiguration.swift +20 -0
- package/ios/hyperswitchSDK/Shared/SwiftUIManager.swift +28 -0
- package/ios/hyperswitchSDK/Shared/Version.swift +12 -0
- package/lib/bs/JuspayTechReactNativeHyperswitch.cmi +0 -0
- package/lib/bs/JuspayTechReactNativeHyperswitch.cmj +0 -0
- package/lib/bs/JuspayTechReactNativeHyperswitch.cmt +0 -0
- package/lib/bs/JuspayTechReactNativeHyperswitch.mlmap +0 -0
- package/lib/bs/build.ninja +8 -0
- package/lib/bs/install.ninja +9 -0
- package/lib/bs/src/context/HyperProvider-JuspayTechReactNativeHyperswitch.cmt +0 -0
- package/lib/bs/src/context/WidgetRegistry-JuspayTechReactNativeHyperswitch.cmt +0 -0
- package/lib/bs/src/core/Hyper-JuspayTechReactNativeHyperswitch.cmt +0 -0
- package/lib/bs/src/core/HyperElements-JuspayTechReactNativeHyperswitch.cmt +0 -0
- package/lib/bs/src/hooks/usePaymentSession-JuspayTechReactNativeHyperswitch.cmt +0 -0
- package/lib/bs/src/hooks/useWidget-JuspayTechReactNativeHyperswitch.cmt +0 -0
- package/lib/bs/src/modules/NativeHyperswitchSdk-JuspayTechReactNativeHyperswitch.cmt +0 -0
- package/lib/bs/src/types/HyperTypes-JuspayTechReactNativeHyperswitch.cmt +0 -0
- package/lib/bs/src/types/NativeModuleTypes-JuspayTechReactNativeHyperswitch.cmt +0 -0
- package/lib/bs/src/types/PaymentSheetConfiguration-JuspayTechReactNativeHyperswitch.cmt +0 -0
- package/lib/bs/src/utils/AppearanceTransformer-JuspayTechReactNativeHyperswitch.cmt +0 -0
- package/lib/bs/src/utils/EventValidator-JuspayTechReactNativeHyperswitch.cmt +0 -0
- package/lib/bs/src/utils/NewArchUtils-JuspayTechReactNativeHyperswitch.cmt +0 -0
- package/lib/bs/src/utils/PaymentSheetEventManager-JuspayTechReactNativeHyperswitch.cmt +0 -0
- package/lib/bs/src/utils/ReactNativeUtils-JuspayTechReactNativeHyperswitch.cmt +0 -0
- package/lib/bs/src/utils/ResponseHandler-JuspayTechReactNativeHyperswitch.cmt +0 -0
- package/lib/bs/src/views/CVCElement-JuspayTechReactNativeHyperswitch.cmt +0 -0
- package/lib/bs/src/views/NativePaymentWidget-JuspayTechReactNativeHyperswitch.cmt +0 -0
- package/lib/bs/src/views/NativePaymentWidgetImpl-JuspayTechReactNativeHyperswitch.cmt +0 -0
- package/lib/bs/src/views/PaymentElement-JuspayTechReactNativeHyperswitch.cmt +0 -0
- package/lib/commonjs/index.bundle.js +2 -0
- package/lib/commonjs/index.bundle.js.map +1 -0
- package/lib/module/index.bundle.js +2 -0
- package/lib/module/index.bundle.js.map +1 -0
- package/lib/typescript/babel.config.d.ts +10 -0
- package/lib/typescript/babel.config.d.ts.map +1 -0
- package/lib/typescript/eslint.config.d.mts +3 -0
- package/lib/typescript/eslint.config.d.mts.map +1 -0
- package/lib/typescript/rollup.config.d.ts +23 -0
- package/lib/typescript/rollup.config.d.ts.map +1 -0
- package/lib/typescript/scripts/bootstrap.d.ts +2 -0
- package/lib/typescript/scripts/bootstrap.d.ts.map +1 -0
- package/lib/typescript/src/context/Elements.d.ts +7 -0
- package/lib/typescript/src/context/Elements.d.ts.map +1 -0
- package/lib/typescript/src/context/HyperElements.d.ts +23 -0
- package/lib/typescript/src/context/HyperElements.d.ts.map +1 -0
- package/lib/typescript/src/context/PaymentSession.d.ts +15 -0
- package/lib/typescript/src/context/PaymentSession.d.ts.map +1 -0
- package/lib/typescript/src/context/SavedPaymentMethods.d.ts +5 -0
- package/lib/typescript/src/context/SavedPaymentMethods.d.ts.map +1 -0
- package/lib/typescript/src/context/WidgetRegistry.d.ts +8 -0
- package/lib/typescript/src/context/WidgetRegistry.d.ts.map +1 -0
- package/lib/typescript/src/context/hooks.d.ts +5 -0
- package/lib/typescript/src/context/hooks.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +10 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/modules/NativeHyperswitchSdk.d.ts +61 -0
- package/lib/typescript/src/modules/NativeHyperswitchSdk.d.ts.map +1 -0
- package/lib/typescript/src/specs/ApplePayViewNativeComponent.d.ts +10 -0
- package/lib/typescript/src/specs/ApplePayViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/specs/NativeHyperHeadless.d.ts +14 -0
- package/lib/typescript/src/specs/NativeHyperHeadless.d.ts.map +1 -0
- package/lib/typescript/src/specs/NativeHyperswitchModule.d.ts +32 -0
- package/lib/typescript/src/specs/NativeHyperswitchModule.d.ts.map +1 -0
- package/lib/typescript/src/specs/NativeHyperswitchSdkNative.d.ts +33 -0
- package/lib/typescript/src/specs/NativeHyperswitchSdkNative.d.ts.map +1 -0
- package/lib/typescript/src/specs/NativePaymentElementModule.d.ts +9 -0
- package/lib/typescript/src/specs/NativePaymentElementModule.d.ts.map +1 -0
- package/lib/typescript/src/specs/PaymentElementNativeComponent.d.ts +19 -0
- package/lib/typescript/src/specs/PaymentElementNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/specs/utils.d.ts +15 -0
- package/lib/typescript/src/specs/utils.d.ts.map +1 -0
- package/lib/typescript/src/types/NativeModuleTypes.d.ts +67 -0
- package/lib/typescript/src/types/NativeModuleTypes.d.ts.map +1 -0
- package/lib/typescript/src/types/PaymentSheetConfiguration.d.ts +255 -0
- package/lib/typescript/src/types/PaymentSheetConfiguration.d.ts.map +1 -0
- package/lib/typescript/src/types/definitions.d.ts +85 -0
- package/lib/typescript/src/types/definitions.d.ts.map +1 -0
- package/lib/typescript/src/types/elements/index.d.ts +23 -0
- package/lib/typescript/src/types/elements/index.d.ts.map +1 -0
- package/lib/typescript/src/types/paymentresult/index.d.ts +5 -0
- package/lib/typescript/src/types/paymentresult/index.d.ts.map +1 -0
- package/lib/typescript/src/types/savedPaymentMethods/index.d.ts +69 -0
- package/lib/typescript/src/types/savedPaymentMethods/index.d.ts.map +1 -0
- package/lib/typescript/src/utils/EventValidator.d.ts +9 -0
- package/lib/typescript/src/utils/EventValidator.d.ts.map +1 -0
- package/lib/typescript/src/utils/InitializationState.d.ts +13 -0
- package/lib/typescript/src/utils/InitializationState.d.ts.map +1 -0
- package/lib/typescript/src/utils/LaunchOptions.d.ts +7 -0
- package/lib/typescript/src/utils/LaunchOptions.d.ts.map +1 -0
- package/lib/typescript/src/utils/NewArchUtils.d.ts +7 -0
- package/lib/typescript/src/utils/NewArchUtils.d.ts.map +1 -0
- package/lib/typescript/src/utils/ReactNativeUtils.d.ts +3 -0
- package/lib/typescript/src/utils/ReactNativeUtils.d.ts.map +1 -0
- package/lib/typescript/src/views/CVCElement.d.ts +15 -0
- package/lib/typescript/src/views/CVCElement.d.ts.map +1 -0
- package/lib/typescript/src/views/NativePaymentWidget.d.ts +3 -0
- package/lib/typescript/src/views/NativePaymentWidget.d.ts.map +1 -0
- package/lib/typescript/src/views/NativePaymentWidgetImpl.d.ts +5 -0
- package/lib/typescript/src/views/NativePaymentWidgetImpl.d.ts.map +1 -0
- package/lib/typescript/src/views/PaymentElement.d.ts +18 -0
- package/lib/typescript/src/views/PaymentElement.d.ts.map +1 -0
- package/package.json +184 -0
- package/src/context/Elements.ts +80 -0
- package/src/context/HyperElements.tsx +81 -0
- package/src/context/PaymentSession.ts +121 -0
- package/src/context/SavedPaymentMethods.ts +80 -0
- package/src/context/WidgetRegistry.ts +74 -0
- package/src/context/hooks.ts +79 -0
- package/src/index.ts +53 -0
- package/src/modules/NativeHyperswitchSdk.ts +155 -0
- package/src/specs/ApplePayViewNativeComponent.ts +11 -0
- package/src/specs/NativeHyperHeadless.ts +22 -0
- package/src/specs/NativeHyperswitchModule.ts +51 -0
- package/src/specs/NativeHyperswitchSdkNative.ts +62 -0
- package/src/specs/NativePaymentElementModule.ts +25 -0
- package/src/specs/PaymentElementNativeComponent.ts +21 -0
- package/src/specs/utils.ts +15 -0
- package/src/types/NativeModuleTypes.ts +73 -0
- package/src/types/PaymentSheetConfiguration.ts +360 -0
- package/src/types/definitions.ts +109 -0
- package/src/types/elements/index.ts +33 -0
- package/src/types/paymentresult/index.ts +4 -0
- package/src/types/savedPaymentMethods/index.ts +74 -0
- package/src/utils/EventValidator.ts +39 -0
- package/src/utils/InitializationState.ts +28 -0
- package/src/utils/LaunchOptions.ts +41 -0
- package/src/utils/NewArchUtils.ts +18 -0
- package/src/utils/ReactNativeUtils.ts +13 -0
- package/src/views/CVCElement.tsx +122 -0
- package/src/views/NativePaymentWidget.ts +2 -0
- package/src/views/NativePaymentWidgetImpl.ts +16 -0
- package/src/views/PaymentElement.tsx +189 -0
- package/tsconfig.build.json +21 -0
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
//
|
|
2
|
+
// NativePaymentWidget.swift
|
|
3
|
+
// Hyperswitch
|
|
4
|
+
//
|
|
5
|
+
// Created by Harshit Srivastava on 05/03/26.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import React
|
|
9
|
+
import UIKit
|
|
10
|
+
|
|
11
|
+
@objc(NativePaymentWidget)
|
|
12
|
+
internal class NativePaymentWidget: RCTViewManager {
|
|
13
|
+
|
|
14
|
+
override func view() -> NativePaymentWidgetView {
|
|
15
|
+
return NativePaymentWidgetView()
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@objc override static func requiresMainQueueSetup() -> Bool {
|
|
19
|
+
return false
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@objc func showWidget(_ reactTag: NSNumber) {
|
|
23
|
+
// bridge.uiManager.addUIBlock { uiManager, viewRegistry in
|
|
24
|
+
// guard let view = viewRegistry?[reactTag] as? NativePaymentWidgetView else { return }
|
|
25
|
+
// view.showWidget()
|
|
26
|
+
// }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@objc func removeWidget(_ reactTag: NSNumber) {
|
|
30
|
+
// bridge.uiManager.addUIBlock { uiManager, viewRegistry in
|
|
31
|
+
// guard let view = viewRegistry?[reactTag] as? NativePaymentWidgetView else { return }
|
|
32
|
+
// view.removeWidget()
|
|
33
|
+
// }
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@objc func confirmPayment(_ reactTag: NSNumber, _ rnCallback: @escaping RCTResponseSenderBlock) {
|
|
37
|
+
bridge.uiManager.addUIBlock { _, viewRegistry in
|
|
38
|
+
// Old-arch path: the view is NativePaymentWidgetView directly.
|
|
39
|
+
if let view = viewRegistry?[reactTag] as? NativePaymentWidgetView {
|
|
40
|
+
view.confirmPayment(rnCallback)
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
// New-arch (Fabric) path: the Fabric NativePaymentElementView registered
|
|
44
|
+
// the inner NativePaymentWidgetView in the shared registry by the same tag.
|
|
45
|
+
if let view = NativePaymentWidgetViewRegistry.shared.view(forTag: reactTag) as? NativePaymentWidgetView {
|
|
46
|
+
view.confirmPayment(rnCallback)
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
rnCallback([["status": "failed", "message": "Widget view not found for tag \(reactTag)"]])
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@objc func updateIntentInitForWidget(_ rootTag: NSNumber, _ rnCallback: @escaping RCTResponseSenderBlock) {
|
|
54
|
+
bridge.uiManager.addUIBlock { _, viewRegistry in
|
|
55
|
+
if let view = viewRegistry?[rootTag] as? NativePaymentWidgetView {
|
|
56
|
+
view.updateIntentInit(rnCallback)
|
|
57
|
+
return
|
|
58
|
+
}
|
|
59
|
+
if let view = NativePaymentWidgetViewRegistry.shared.view(forTag: rootTag) as? NativePaymentWidgetView {
|
|
60
|
+
view.updateIntentInit(rnCallback)
|
|
61
|
+
return
|
|
62
|
+
}
|
|
63
|
+
rnCallback([["status": "failed", "message": "Widget view not found for tag \(rootTag)"]])
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@objc func updateIntentCompleteForWidget(
|
|
68
|
+
_ rootTag: NSNumber,
|
|
69
|
+
_ sdkAuthorization: String,
|
|
70
|
+
_ rnCallback: @escaping RCTResponseSenderBlock
|
|
71
|
+
) {
|
|
72
|
+
bridge.uiManager.addUIBlock { _, viewRegistry in
|
|
73
|
+
if let view = viewRegistry?[rootTag] as? NativePaymentWidgetView {
|
|
74
|
+
view.updateIntentComplete(sdkAuthorization: sdkAuthorization, resolve: rnCallback)
|
|
75
|
+
return
|
|
76
|
+
}
|
|
77
|
+
if let view = NativePaymentWidgetViewRegistry.shared.view(forTag: rootTag) as? NativePaymentWidgetView {
|
|
78
|
+
view.updateIntentComplete(sdkAuthorization: sdkAuthorization, resolve: rnCallback)
|
|
79
|
+
return
|
|
80
|
+
}
|
|
81
|
+
rnCallback([["status": "failed", "message": "Widget view not found for tag \(rootTag)"]])
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
@objc func confirmPaymentCVC(
|
|
86
|
+
_ reactTag: NSNumber,
|
|
87
|
+
_ paymentToken: String,
|
|
88
|
+
_ paymentMethodId: String,
|
|
89
|
+
_ rnCallback: @escaping RCTResponseSenderBlock
|
|
90
|
+
) {
|
|
91
|
+
bridge.uiManager.addUIBlock { _, viewRegistry in
|
|
92
|
+
if let view = viewRegistry?[reactTag] as? NativePaymentWidgetView {
|
|
93
|
+
view.confirmCVCPayment(paymentToken: paymentToken, paymentMethodId: paymentMethodId, resolve: rnCallback)
|
|
94
|
+
return
|
|
95
|
+
}
|
|
96
|
+
if let view = NativePaymentWidgetViewRegistry.shared.view(forTag: reactTag) as? NativePaymentWidgetView {
|
|
97
|
+
view.confirmCVCPayment(paymentToken: paymentToken, paymentMethodId: paymentMethodId, resolve: rnCallback)
|
|
98
|
+
return
|
|
99
|
+
}
|
|
100
|
+
rnCallback([["status": "failed", "message": "Widget view not found for tag \(reactTag)"]])
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// @objc exposes this class to Objective-C++ so the Fabric component
|
|
106
|
+
// (NativePaymentElementView.mm) can instantiate it and type-check it.
|
|
107
|
+
@objc(NativePaymentWidgetView)
|
|
108
|
+
internal class NativePaymentWidgetView: UIView {
|
|
109
|
+
|
|
110
|
+
private var paymentWidget: PaymentWidget?
|
|
111
|
+
private var cvcWidget: CVCWidget?
|
|
112
|
+
internal var cvcWidgetRef: CVCWidget? { cvcWidget }
|
|
113
|
+
// Internal (not private) so the Fabric wrapper can set these via the ObjC bridge.
|
|
114
|
+
@objc var widgetType: String?
|
|
115
|
+
@objc var sdkAuthorization: String?
|
|
116
|
+
@objc var options: [String: Any]?
|
|
117
|
+
@objc var onPaymentEvent: RCTDirectEventBlock?
|
|
118
|
+
@objc var onPaymentResult: RCTDirectEventBlock?
|
|
119
|
+
private var responseSenderCallback: RCTResponseSenderBlock?
|
|
120
|
+
private var appliedConfigKey: String?
|
|
121
|
+
|
|
122
|
+
internal var rctRootTag: NSNumber?
|
|
123
|
+
|
|
124
|
+
private func callbackPayload(_ data: Any?) -> Any {
|
|
125
|
+
guard let stringData = data as? String,
|
|
126
|
+
let jsonData = stringData.data(using: .utf8),
|
|
127
|
+
let json = try? JSONSerialization.jsonObject(with: jsonData) as? [String: Any]
|
|
128
|
+
else {
|
|
129
|
+
return data ?? NSNull()
|
|
130
|
+
}
|
|
131
|
+
return json
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
private func nonEmptyString(_ value: String?) -> String? {
|
|
135
|
+
guard let value = value, !value.isEmpty else { return nil }
|
|
136
|
+
return value
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
private func optionString(_ key: String) -> String? {
|
|
140
|
+
return options?[key] as? String
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
private func effectiveSdkAuthorization() -> String? {
|
|
144
|
+
return nonEmptyString(sdkAuthorization)
|
|
145
|
+
?? nonEmptyString(optionString("sdkAuthorization"))
|
|
146
|
+
?? nonEmptyString(PaymentSession.activeSession?.paymentSessionConfiguration.sdkAuthorization)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
private func effectivePublishableKey() -> String? {
|
|
150
|
+
return nonEmptyString(optionString("publishableKey"))
|
|
151
|
+
?? nonEmptyString(HyperswitchModule.getActivePublishableKey())
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
private func effectiveProfileId() -> String? {
|
|
155
|
+
return nonEmptyString(optionString("profileId"))
|
|
156
|
+
?? nonEmptyString(HyperswitchModule.getActiveProfileId())
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
private func isSupportedWidgetType() -> Bool {
|
|
160
|
+
return widgetType == "cvcWidget" || widgetType == "paymentElement" || widgetType == "widgetPaymentSheet"
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
private func activeOrNewHyperswitch() -> Hyperswitch? {
|
|
164
|
+
if let active = HyperswitchModule.getActiveHyperswitch(), nonEmptyString(optionString("publishableKey")) == nil {
|
|
165
|
+
return active
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
guard let publishableKey = effectivePublishableKey() else { return nil }
|
|
169
|
+
return Hyperswitch(
|
|
170
|
+
configuration: HyperswitchConfiguration(
|
|
171
|
+
publishableKey: publishableKey,
|
|
172
|
+
profileId: effectiveProfileId()
|
|
173
|
+
)
|
|
174
|
+
)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
private func activeOrNewPaymentSession(sdkAuthorization: String) -> PaymentSession? {
|
|
178
|
+
if let activeSession = HyperswitchModule.getActivePaymentSession(), nonEmptyString(optionString("sdkAuthorization")) == nil {
|
|
179
|
+
return activeSession
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return activeOrNewHyperswitch()?.initPaymentSession(
|
|
183
|
+
configuration: PaymentSessionConfiguration(sdkAuthorization: sdkAuthorization)
|
|
184
|
+
)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
private func subscribedEvents() -> [String] {
|
|
188
|
+
return options?["subscribedEvents"] as? [String] ?? []
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
private func clearWidget() {
|
|
192
|
+
paymentWidget?.removeFromSuperview()
|
|
193
|
+
cvcWidget?.removeFromSuperview()
|
|
194
|
+
paymentWidget = nil
|
|
195
|
+
cvcWidget = nil
|
|
196
|
+
rctRootTag = nil
|
|
197
|
+
responseSenderCallback = nil
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
private func paymentResultPayload(_ result: PaymentResult) -> String {
|
|
201
|
+
let payload = paymentResultMap(result)
|
|
202
|
+
|
|
203
|
+
guard let data = try? JSONSerialization.data(withJSONObject: payload),
|
|
204
|
+
let json = String(data: data, encoding: .utf8)
|
|
205
|
+
else {
|
|
206
|
+
return "{\"status\":\"failed\",\"message\":\"Invalid payment result\"}"
|
|
207
|
+
}
|
|
208
|
+
return json
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
private func paymentResultMap(_ result: PaymentResult) -> [String: Any] {
|
|
212
|
+
switch result {
|
|
213
|
+
case .completed(let data):
|
|
214
|
+
return [
|
|
215
|
+
"status": "success",
|
|
216
|
+
"message": "Payment confirmed successfully",
|
|
217
|
+
"data": data,
|
|
218
|
+
]
|
|
219
|
+
case .canceled(let data):
|
|
220
|
+
return [
|
|
221
|
+
"status": "cancelled",
|
|
222
|
+
"message": "Payment confirmation cancelled",
|
|
223
|
+
"data": data,
|
|
224
|
+
]
|
|
225
|
+
case .failed(let error as NSError):
|
|
226
|
+
return [
|
|
227
|
+
"status": "failed",
|
|
228
|
+
"code": error.domain,
|
|
229
|
+
"message": error.userInfo["message"] as? String ?? error.localizedDescription,
|
|
230
|
+
]
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
private func handlePaymentResult(_ result: PaymentResult) {
|
|
235
|
+
let payload = paymentResultPayload(result)
|
|
236
|
+
if let callback = responseSenderCallback {
|
|
237
|
+
callback([paymentResultMap(result)])
|
|
238
|
+
responseSenderCallback = nil
|
|
239
|
+
return
|
|
240
|
+
}
|
|
241
|
+
onPaymentResult?(["result": payload])
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
internal func handleConfirmPaymentNotification(_ result: PaymentResult) {
|
|
245
|
+
guard let callback = responseSenderCallback else { return }
|
|
246
|
+
switch result {
|
|
247
|
+
case .failed:
|
|
248
|
+
callback([paymentResultMap(result)])
|
|
249
|
+
responseSenderCallback = nil
|
|
250
|
+
default:
|
|
251
|
+
break
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
@objc func didSetProps() {
|
|
256
|
+
guard isSupportedWidgetType(), let sdkAuthorization = effectiveSdkAuthorization() else { return }
|
|
257
|
+
|
|
258
|
+
let configKey = [widgetType ?? "", effectivePublishableKey() ?? "", effectiveProfileId() ?? "", sdkAuthorization].joined(separator: ":")
|
|
259
|
+
if paymentWidget != nil || cvcWidget != nil, appliedConfigKey == configKey {
|
|
260
|
+
return
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
clearWidget()
|
|
264
|
+
appliedConfigKey = configKey
|
|
265
|
+
|
|
266
|
+
var configuration = options ?? [:]
|
|
267
|
+
if widgetType != "cvcWidget" {
|
|
268
|
+
configuration["hideConfirmButton"] = true
|
|
269
|
+
}
|
|
270
|
+
configuration["subscribedEvents"] = subscribedEvents()
|
|
271
|
+
|
|
272
|
+
let listener = PaymentEventListener { [weak self] event in
|
|
273
|
+
self?.onPaymentEvent?([
|
|
274
|
+
"eventName": event.type,
|
|
275
|
+
"payload": event.payload,
|
|
276
|
+
])
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
let widget: UIView?
|
|
280
|
+
if widgetType == "cvcWidget" {
|
|
281
|
+
guard let hyperswitch = activeOrNewHyperswitch() else { return }
|
|
282
|
+
let cvc = CVCWidget(
|
|
283
|
+
hyperswitch: hyperswitch,
|
|
284
|
+
configurationDict: configuration,
|
|
285
|
+
subscribe: nil
|
|
286
|
+
)
|
|
287
|
+
cvc.setPaymentEventListener(listener)
|
|
288
|
+
cvcWidget = cvc
|
|
289
|
+
widget = cvc
|
|
290
|
+
} else {
|
|
291
|
+
guard let session = activeOrNewPaymentSession(sdkAuthorization: sdkAuthorization) else { return }
|
|
292
|
+
let payment = PaymentWidget(
|
|
293
|
+
paymentSession: session,
|
|
294
|
+
configurationDict: configuration,
|
|
295
|
+
completion: { [weak self] result in
|
|
296
|
+
self?.handlePaymentResult(result)
|
|
297
|
+
},
|
|
298
|
+
subscribe: nil
|
|
299
|
+
)
|
|
300
|
+
payment.setPaymentEventListener(listener)
|
|
301
|
+
paymentWidget = payment
|
|
302
|
+
widget = payment
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
guard let widget = widget else { return }
|
|
306
|
+
addSubview(widget)
|
|
307
|
+
widget.translatesAutoresizingMaskIntoConstraints = false
|
|
308
|
+
NSLayoutConstraint.activate([
|
|
309
|
+
widget.topAnchor.constraint(equalTo: topAnchor),
|
|
310
|
+
widget.bottomAnchor.constraint(equalTo: bottomAnchor),
|
|
311
|
+
widget.leadingAnchor.constraint(equalTo: leadingAnchor),
|
|
312
|
+
widget.trailingAnchor.constraint(equalTo: trailingAnchor),
|
|
313
|
+
])
|
|
314
|
+
|
|
315
|
+
if let paymentWidget = widget as? PaymentWidget {
|
|
316
|
+
rctRootTag = paymentWidget.rootReactTag
|
|
317
|
+
} else if let cvcWidget = widget as? CVCWidget {
|
|
318
|
+
rctRootTag = cvcWidget.rootReactTag
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
override func didSetProps(_ changedProps: [String]) {
|
|
323
|
+
self.didSetProps()
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
override init(frame: CGRect) {
|
|
327
|
+
super.init(frame: frame)
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
required init?(coder: NSCoder) {
|
|
331
|
+
fatalError("init(coder:) has not been implemented")
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
internal override func layoutSubviews() {
|
|
335
|
+
super.layoutSubviews()
|
|
336
|
+
paymentWidget?.frame = bounds
|
|
337
|
+
cvcWidget?.frame = bounds
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
internal func confirmPayment(_ rnCallback: @escaping RCTResponseSenderBlock) {
|
|
341
|
+
// avoiding duplicate confirm calls (confirmPayment triggered multiple times from RN layer)
|
|
342
|
+
if self.responseSenderCallback != nil {
|
|
343
|
+
let response = ["status": "failed", "error": "invalid call"]
|
|
344
|
+
rnCallback([response])
|
|
345
|
+
return
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
self.responseSenderCallback = rnCallback
|
|
349
|
+
guard let paymentWidget = paymentWidget else {
|
|
350
|
+
self.responseSenderCallback = nil
|
|
351
|
+
rnCallback([[
|
|
352
|
+
"status": "failed",
|
|
353
|
+
"code": "WIDGET_NOT_READY",
|
|
354
|
+
"message": "Widget not ready",
|
|
355
|
+
]])
|
|
356
|
+
return
|
|
357
|
+
}
|
|
358
|
+
paymentWidget.confirm()
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
internal func updateIntentInit(_ resolve: @escaping RCTResponseSenderBlock) {
|
|
362
|
+
guard let tag = rctRootTag else {
|
|
363
|
+
resolve([["status": "failed", "message": "Widget root tag not found"]])
|
|
364
|
+
return
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
WidgetResponseRegistry.shared.register(rootTag: tag, action: .updateIntentInit) { [weak self] response, _ in
|
|
368
|
+
guard let self = self else { return }
|
|
369
|
+
resolve([self.callbackPayload(response["data"])])
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
let eventData: [String: Any] = ["rootTag": tag]
|
|
373
|
+
RNViewManager.sharedInstance.bridge.enqueueJSCall(
|
|
374
|
+
"RCTDeviceEventEmitter",
|
|
375
|
+
method: "emit",
|
|
376
|
+
args: ["updateIntentInit", eventData],
|
|
377
|
+
completion: nil
|
|
378
|
+
)
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
internal func updateIntentComplete(sdkAuthorization: String, resolve: @escaping RCTResponseSenderBlock) {
|
|
382
|
+
guard let tag = rctRootTag else {
|
|
383
|
+
resolve([["status": "failed", "message": "Widget root tag not found"]])
|
|
384
|
+
return
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
WidgetResponseRegistry.shared.register(rootTag: tag, action: .updateIntentComplete) { [weak self] response, _ in
|
|
388
|
+
guard let self = self else { return }
|
|
389
|
+
resolve([self.callbackPayload(response["data"])])
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
let eventData: [String: Any] = [
|
|
393
|
+
"rootTag": tag,
|
|
394
|
+
"sdkAuthorization": sdkAuthorization,
|
|
395
|
+
]
|
|
396
|
+
RNViewManager.sharedInstance.bridge.enqueueJSCall(
|
|
397
|
+
"RCTDeviceEventEmitter",
|
|
398
|
+
method: "emit",
|
|
399
|
+
args: ["updateIntentComplete", eventData],
|
|
400
|
+
completion: nil
|
|
401
|
+
)
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
internal func confirmCVCPayment(paymentToken: String, paymentMethodId: String, resolve: @escaping RCTResponseSenderBlock) {
|
|
405
|
+
if let tag = rctRootTag {
|
|
406
|
+
WidgetResponseRegistry.shared.register(rootTag: tag, action: .confirmCVCPayment) { [weak self] response, shouldRemoveView in
|
|
407
|
+
guard let self = self else { return }
|
|
408
|
+
resolve([self.callbackPayload(response["data"])])
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
if let sdkAuthorization = effectiveSdkAuthorization(), let cvcWidget = cvcWidget {
|
|
413
|
+
cvcWidget.confirm(sdkAuthorization: sdkAuthorization, paymentToken: paymentToken, paymentMethodId: paymentMethodId)
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
deinit {
|
|
418
|
+
clearWidget()
|
|
419
|
+
}
|
|
420
|
+
}
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
//
|
|
2
|
+
// ApplePayHandler.swift
|
|
3
|
+
// Hyperswitch
|
|
4
|
+
//
|
|
5
|
+
// Created by Shivam Shashank on 10/12/22.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
import PassKit
|
|
10
|
+
import React
|
|
11
|
+
|
|
12
|
+
internal class ApplePayHandler: NSObject {
|
|
13
|
+
|
|
14
|
+
var paymentStatus: PKPaymentAuthorizationStatus? = .failure
|
|
15
|
+
var callback: RCTResponseSenderBlock?
|
|
16
|
+
|
|
17
|
+
internal func startPayment(rnMessage: String, rnCallback: @escaping RCTResponseSenderBlock, presentCallback: RCTResponseSenderBlock?) {
|
|
18
|
+
|
|
19
|
+
callback = rnCallback
|
|
20
|
+
var requiredBillingContactFields: Set<PKContactField>?
|
|
21
|
+
var requiredShippingContactFields: Set<PKContactField>?
|
|
22
|
+
|
|
23
|
+
guard let dict = rnMessage.toJSON() as? [String: AnyObject] else {
|
|
24
|
+
presentCallback?([])
|
|
25
|
+
callback?([["status": "Failed", "message": "ApplePay: missing field payment_request_data"]])
|
|
26
|
+
callback = nil
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
guard let payment_request_data = dict["payment_request_data"] else {
|
|
31
|
+
presentCallback?([])
|
|
32
|
+
callback?([["status": "Failed", "message": "ApplePay: missing field payment_request_data"]])
|
|
33
|
+
callback = nil
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
guard let countryCode = payment_request_data["country_code"] as? String else {
|
|
38
|
+
presentCallback?([])
|
|
39
|
+
callback?([["status": "Failed", "message": "ApplePay: missing field country_code"]])
|
|
40
|
+
callback = nil
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
guard let currencyCode = payment_request_data["currency_code"] as? String else {
|
|
45
|
+
presentCallback?([])
|
|
46
|
+
callback?([["status": "Failed", "message": "ApplePay: missing field currency_code"]])
|
|
47
|
+
callback = nil
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
guard let total = payment_request_data["total"] as? [String: AnyObject] else {
|
|
51
|
+
presentCallback?([])
|
|
52
|
+
callback?([["status": "Failed", "message": "ApplePay: missing field total"]])
|
|
53
|
+
callback = nil
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
guard let amount = total["amount"] as? String,
|
|
58
|
+
let label = total["label"] as? String,
|
|
59
|
+
let type = total["type"] as? String
|
|
60
|
+
else {
|
|
61
|
+
presentCallback?([])
|
|
62
|
+
callback?([["status": "Failed", "message": "ApplePay: missing fields amount, label, type"]])
|
|
63
|
+
callback = nil
|
|
64
|
+
return
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
guard let merchant_capabilities_array = payment_request_data["merchant_capabilities"] as? [String] else {
|
|
68
|
+
presentCallback?([])
|
|
69
|
+
callback?([["status": "Failed", "message": "ApplePay: missing field merchant_capabilities"]])
|
|
70
|
+
callback = nil
|
|
71
|
+
return
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
guard let merchantIdentifier = payment_request_data["merchant_identifier"] as? String else {
|
|
75
|
+
presentCallback?([])
|
|
76
|
+
callback?([["status": "Failed", "message": "ApplePay: missing field merchant_identifier"]])
|
|
77
|
+
callback = nil
|
|
78
|
+
return
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
guard let supported_networks_array = payment_request_data["supported_networks"] as? [String] else {
|
|
82
|
+
presentCallback?([])
|
|
83
|
+
callback?([["status": "Failed", "message": "ApplePay: missing field supported_networks"]])
|
|
84
|
+
callback = nil
|
|
85
|
+
return
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
let supportedNetworks = supported_networks_array.compactMap { (string) -> PKPaymentNetwork? in
|
|
89
|
+
switch string {
|
|
90
|
+
case "visa":
|
|
91
|
+
return .visa
|
|
92
|
+
case "masterCard":
|
|
93
|
+
return .masterCard
|
|
94
|
+
case "amex":
|
|
95
|
+
return .amex
|
|
96
|
+
case "discover":
|
|
97
|
+
return .discover
|
|
98
|
+
case "quicPay":
|
|
99
|
+
return .quicPay
|
|
100
|
+
default:
|
|
101
|
+
return nil
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if let required_billing_contact_fields = payment_request_data["required_billing_contact_fields"] as? [String] {
|
|
106
|
+
requiredBillingContactFields = Set(required_billing_contact_fields.compactMap(mapToPKContactField))
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if let required_shipping_contact_fields = payment_request_data["required_shipping_contact_fields"] as? [String] {
|
|
110
|
+
requiredShippingContactFields = Set(required_shipping_contact_fields.compactMap(mapToPKContactField))
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
let paymentSummaryItems = PKPaymentSummaryItem(
|
|
114
|
+
label: label,
|
|
115
|
+
amount: NSDecimalNumber(string: amount),
|
|
116
|
+
type: (type == "final") ? .final : .pending
|
|
117
|
+
)
|
|
118
|
+
let paymentRequest = PKPaymentRequest()
|
|
119
|
+
paymentRequest.paymentSummaryItems = [paymentSummaryItems]
|
|
120
|
+
paymentRequest.merchantIdentifier = merchantIdentifier
|
|
121
|
+
paymentRequest.countryCode = countryCode
|
|
122
|
+
paymentRequest.currencyCode = currencyCode
|
|
123
|
+
paymentRequest.requiredShippingContactFields = requiredShippingContactFields ?? []
|
|
124
|
+
paymentRequest.requiredBillingContactFields = requiredBillingContactFields ?? []
|
|
125
|
+
paymentRequest.supportedNetworks = supportedNetworks
|
|
126
|
+
for val in merchant_capabilities_array {
|
|
127
|
+
paymentRequest.merchantCapabilities = (val == "supports3DS") ? .threeDSecure : .debit
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/// Create and present the PKPaymentAuthorizationController
|
|
131
|
+
guard
|
|
132
|
+
PKPaymentAuthorizationController.canMakePayments(),
|
|
133
|
+
!paymentRequest.merchantIdentifier.isEmpty,
|
|
134
|
+
PKPaymentAuthorizationViewController(paymentRequest: paymentRequest) != nil
|
|
135
|
+
else {
|
|
136
|
+
presentCallback?([])
|
|
137
|
+
callback?([["status": "Failed", "message": "ApplePay: cannot make payments"]])
|
|
138
|
+
callback = nil
|
|
139
|
+
return
|
|
140
|
+
}
|
|
141
|
+
let paymentController = PKPaymentAuthorizationController(paymentRequest: paymentRequest)
|
|
142
|
+
paymentController.delegate = self
|
|
143
|
+
paymentController.present(completion: { presented in
|
|
144
|
+
presentCallback?([])
|
|
145
|
+
if presented {
|
|
146
|
+
self.paymentStatus = nil
|
|
147
|
+
} else {
|
|
148
|
+
self.callback?([["status": "Failed", "message": "ApplePay: unable to present"]])
|
|
149
|
+
self.callback = nil
|
|
150
|
+
}
|
|
151
|
+
})
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/// Extension to conform to PKPaymentAuthorizationControllerDelegate
|
|
156
|
+
extension ApplePayHandler: PKPaymentAuthorizationControllerDelegate {
|
|
157
|
+
|
|
158
|
+
/// Handle successful payment authorization
|
|
159
|
+
internal func paymentAuthorizationController(
|
|
160
|
+
_ controller: PKPaymentAuthorizationController,
|
|
161
|
+
didAuthorizePayment payment: PKPayment,
|
|
162
|
+
handler completion: @escaping (PKPaymentAuthorizationResult) -> Void
|
|
163
|
+
) {
|
|
164
|
+
|
|
165
|
+
let errors = [Error]()
|
|
166
|
+
let status = PKPaymentAuthorizationStatus.success
|
|
167
|
+
self.paymentStatus = status
|
|
168
|
+
|
|
169
|
+
let dataString = payment.token.paymentData.base64EncodedString()
|
|
170
|
+
|
|
171
|
+
var paymentType = "debit"
|
|
172
|
+
switch payment.token.paymentMethod.type {
|
|
173
|
+
case .debit: paymentType = "debit"
|
|
174
|
+
case .credit: paymentType = "credit"
|
|
175
|
+
case .store: paymentType = "store"
|
|
176
|
+
case .prepaid: paymentType = "prepaid"
|
|
177
|
+
case .eMoney: paymentType = "eMoney"
|
|
178
|
+
default: paymentType = "unknown"
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
self.callback?(
|
|
182
|
+
[
|
|
183
|
+
[
|
|
184
|
+
"status": "Success",
|
|
185
|
+
"payment_data": dataString,
|
|
186
|
+
"payment_method": [
|
|
187
|
+
"type": paymentType,
|
|
188
|
+
"network": payment.token.paymentMethod.network ?? "",
|
|
189
|
+
"display_name": payment.token.paymentMethod.displayName ?? "",
|
|
190
|
+
],
|
|
191
|
+
"transaction_identifier": payment.token.transactionIdentifier,
|
|
192
|
+
"billing_contact": convertPKContactToDictionary(payment.billingContact),
|
|
193
|
+
"shipping_contact": convertPKContactToDictionary(payment.shippingContact),
|
|
194
|
+
]
|
|
195
|
+
]
|
|
196
|
+
)
|
|
197
|
+
completion(PKPaymentAuthorizationResult(status: paymentStatus ?? .failure, errors: errors))
|
|
198
|
+
}
|
|
199
|
+
/// Handle completion of the payment authorization flow
|
|
200
|
+
internal func paymentAuthorizationControllerDidFinish(_ controller: PKPaymentAuthorizationController) {
|
|
201
|
+
controller.dismiss {
|
|
202
|
+
DispatchQueue.main.async {
|
|
203
|
+
if self.paymentStatus == .failure {
|
|
204
|
+
self.callback?([["status": "Failed", "message": "ApplePay: payment failed"]])
|
|
205
|
+
} else if self.paymentStatus == nil {
|
|
206
|
+
self.callback?([["status": "Cancelled"]])
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
private func mapToPKContactField(_ string: String) -> PKContactField? {
|
|
213
|
+
switch string {
|
|
214
|
+
case "postalAddress": return .postalAddress
|
|
215
|
+
case "email": return .emailAddress
|
|
216
|
+
case "phone": return .phoneNumber
|
|
217
|
+
case "name": return .name
|
|
218
|
+
case "phoneticName": return .phoneticName
|
|
219
|
+
default: return nil
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
private func convertPKContactToDictionary(_ contact: PKContact?) -> [String: Any] {
|
|
224
|
+
var contactDict = [String: Any]()
|
|
225
|
+
|
|
226
|
+
if let name = contact?.name {
|
|
227
|
+
var nameDict = [String: Any]()
|
|
228
|
+
nameDict["givenName"] = name.givenName
|
|
229
|
+
nameDict["familyName"] = name.familyName
|
|
230
|
+
nameDict["namePrefix"] = name.namePrefix
|
|
231
|
+
nameDict["nameSuffix"] = name.nameSuffix
|
|
232
|
+
nameDict["nickname"] = name.nickname
|
|
233
|
+
nameDict["middleName"] = name.middleName
|
|
234
|
+
// nameDict["phoneticRepresentation"] = name.phoneticRepresentation
|
|
235
|
+
contactDict["name"] = nameDict
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if let postalAddress = contact?.postalAddress {
|
|
239
|
+
var addressDict = [String: Any]()
|
|
240
|
+
addressDict["street"] = postalAddress.street
|
|
241
|
+
addressDict["city"] = postalAddress.city
|
|
242
|
+
addressDict["state"] = postalAddress.state
|
|
243
|
+
addressDict["postalCode"] = postalAddress.postalCode
|
|
244
|
+
addressDict["country"] = postalAddress.country
|
|
245
|
+
addressDict["subLocality"] = postalAddress.subLocality
|
|
246
|
+
addressDict["subAdministrativeArea"] = postalAddress.subAdministrativeArea
|
|
247
|
+
addressDict["isoCountryCode"] = postalAddress.isoCountryCode
|
|
248
|
+
contactDict["postalAddress"] = addressDict
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
if let phoneNumber = contact?.phoneNumber {
|
|
252
|
+
contactDict["phoneNumber"] = phoneNumber.stringValue
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if let emailAddress = contact?.emailAddress {
|
|
256
|
+
contactDict["emailAddress"] = emailAddress
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return contactDict
|
|
260
|
+
}
|
|
261
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//
|
|
2
|
+
// ApplePayViewManager.m
|
|
3
|
+
// Hyperswitch
|
|
4
|
+
//
|
|
5
|
+
// Created by Harshit Srivastava on 20/06/24.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#import <React/RCTViewManager.h>
|
|
9
|
+
|
|
10
|
+
@interface RCT_EXTERN_MODULE(ApplePayViewManager, RCTViewManager)
|
|
11
|
+
|
|
12
|
+
RCT_EXPORT_VIEW_PROPERTY(buttonStyle, NSString)
|
|
13
|
+
RCT_EXPORT_VIEW_PROPERTY(buttonType, NSString)
|
|
14
|
+
RCT_EXPORT_VIEW_PROPERTY(color, NSString)
|
|
15
|
+
RCT_EXPORT_VIEW_PROPERTY(cornerRadius,CGFloat)
|
|
16
|
+
RCT_EXPORT_VIEW_PROPERTY(onPaymentResultCallback, RCTDirectEventBlock)
|
|
17
|
+
|
|
18
|
+
@end
|