react-native-klarna-inapp-sdk 2.4.10 → 2.5.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/README.md +2 -1
- package/android/build.gradle +3 -1
- package/android/src/main/java/com/klarna/mobile/sdk/reactnative/KlarnaMobileSDKPackage.java +5 -1
- package/android/src/main/java/com/klarna/mobile/sdk/reactnative/checkout/KlarnaCheckoutViewManager.java +4 -10
- package/android/src/main/java/com/klarna/mobile/sdk/reactnative/common/WebViewResizeObserver.java +28 -0
- package/android/src/main/java/com/klarna/mobile/sdk/reactnative/common/event/ComponentEventSender.java +5 -1
- package/android/src/main/java/com/klarna/mobile/sdk/reactnative/common/ui/ResizeObserverWrapperView.java +2 -2
- package/android/src/main/java/com/klarna/mobile/sdk/reactnative/common/ui/WrapperView.java +2 -2
- package/android/src/main/java/com/klarna/mobile/sdk/reactnative/common/ui/YogaLayoutHelper.java +39 -0
- package/android/src/main/java/com/klarna/mobile/sdk/reactnative/expresscheckout/KlarnaExpressCheckoutViewCallback.kt +30 -0
- package/android/src/main/java/com/klarna/mobile/sdk/reactnative/expresscheckout/KlarnaExpressCheckoutViewEventSender.kt +80 -0
- package/android/src/main/java/com/klarna/mobile/sdk/reactnative/expresscheckout/KlarnaExpressCheckoutViewManager.java +544 -0
- package/android/src/main/java/com/klarna/mobile/sdk/reactnative/osm/KlarnaOSMViewEventHandler.java +30 -0
- package/android/src/main/java/com/klarna/mobile/sdk/reactnative/osm/KlarnaOSMViewEventSender.java +64 -0
- package/android/src/main/java/com/klarna/mobile/sdk/reactnative/osm/KlarnaOSMViewManager.java +356 -0
- package/android/src/newarch/java/com/klarna/mobile/sdk/reactnative/spec/RNKlarnaExpressCheckoutViewSpec.java +31 -0
- package/android/src/newarch/java/com/klarna/mobile/sdk/reactnative/spec/RNKlarnaOSMViewSpec.java +31 -0
- package/android/src/oldarch/java/com/klarna/mobile/sdk/reactnative/spec/RNKlarnaExpressCheckoutViewSpec.java +36 -0
- package/android/src/oldarch/java/com/klarna/mobile/sdk/reactnative/spec/RNKlarnaOSMViewSpec.java +32 -0
- package/android/src/test/java/com/klarna/mobile/sdk/reactnative/KlarnaMobileSDKPackageTest.java +5 -1
- package/android/src/test/java/com/klarna/mobile/sdk/reactnative/common/ui/YogaLayoutHelperTest.java +79 -0
- package/android/src/test/java/com/klarna/mobile/sdk/reactnative/expresscheckout/KlarnaExpressCheckoutViewManagerTest.java +259 -0
- package/android/src/test/java/com/klarna/mobile/sdk/reactnative/osm/KlarnaOSMViewEventHandlerTest.java +136 -0
- package/android/src/test/java/com/klarna/mobile/sdk/reactnative/osm/KlarnaOSMViewEventSenderTest.java +184 -0
- package/android/src/test/java/com/klarna/mobile/sdk/reactnative/osm/KlarnaOSMViewManagerTest.java +385 -0
- package/ios/RNKlarnaMobileSDK.xcodeproj/project.pbxproj +55 -1
- package/ios/Sources/KlarnaExpressCheckoutViewManager.h +5 -0
- package/ios/Sources/KlarnaExpressCheckoutViewManager.mm +39 -0
- package/ios/Sources/KlarnaOSMViewManager.h +5 -0
- package/ios/Sources/KlarnaOSMViewManager.mm +59 -0
- package/ios/Sources/view/KlarnaExpressCheckoutButtonDelegateProxy.swift +145 -0
- package/ios/Sources/view/KlarnaExpressCheckoutViewWrapper.h +41 -0
- package/ios/Sources/view/KlarnaOSMViewWrapper.h +48 -0
- package/ios/Sources/view/newarch/KlarnaExpressCheckoutViewWrapper.mm +228 -0
- package/ios/Sources/view/newarch/KlarnaOSMViewWrapper.mm +294 -0
- package/ios/Sources/view/newarch/KlarnaStandaloneWebViewWrapper.mm +20 -13
- package/ios/Sources/view/oldarch/KlarnaExpressCheckoutViewWrapper.mm +222 -0
- package/ios/Sources/view/oldarch/KlarnaOSMViewWrapper.mm +273 -0
- package/ios/Sources/view/oldarch/KlarnaStandaloneWebViewWrapper.mm +11 -13
- package/ios/Tests/KlarnaExpressCheckoutViewWrapperTests.m +391 -0
- package/ios/Tests/KlarnaOSMViewWrapperTests.m +450 -0
- package/ios/Tests/KlarnaStandaloneWebViewWrapperTests.m +105 -0
- package/lib/commonjs/KlarnaExpressCheckoutView.js +75 -0
- package/lib/commonjs/KlarnaExpressCheckoutView.js.map +1 -0
- package/lib/commonjs/KlarnaOSMView.js +94 -0
- package/lib/commonjs/KlarnaOSMView.js.map +1 -0
- package/lib/commonjs/index.js +99 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/specs/KlarnaExpressCheckoutViewNativeComponent.js +11 -0
- package/lib/commonjs/specs/KlarnaExpressCheckoutViewNativeComponent.js.map +1 -0
- package/lib/commonjs/specs/KlarnaOSMViewNativeComponent.js +16 -0
- package/lib/commonjs/specs/KlarnaOSMViewNativeComponent.js.map +1 -0
- package/lib/commonjs/types/button/KlarnaButtonShape.js +14 -0
- package/lib/commonjs/types/button/KlarnaButtonShape.js.map +1 -0
- package/lib/commonjs/types/button/KlarnaButtonStyle.js +13 -0
- package/lib/commonjs/types/button/KlarnaButtonStyle.js.map +1 -0
- package/lib/commonjs/types/button/KlarnaButtonTheme.js +14 -0
- package/lib/commonjs/types/button/KlarnaButtonTheme.js.map +1 -0
- package/lib/commonjs/types/common/KlarnaExpressCheckoutSessionOptions.js +9 -0
- package/lib/commonjs/types/common/KlarnaExpressCheckoutSessionOptions.js.map +1 -0
- package/lib/commonjs/types/common/KlarnaOSMPlacementKey.js +2 -0
- package/lib/commonjs/types/common/KlarnaOSMPlacementKey.js.map +1 -0
- package/lib/commonjs/types/common/KlarnaTheme.js +14 -0
- package/lib/commonjs/types/common/KlarnaTheme.js.map +1 -0
- package/lib/module/KlarnaExpressCheckoutView.js +64 -0
- package/lib/module/KlarnaExpressCheckoutView.js.map +1 -0
- package/lib/module/KlarnaOSMView.js +84 -0
- package/lib/module/KlarnaOSMView.js.map +1 -0
- package/lib/module/index.js +9 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/specs/KlarnaExpressCheckoutViewNativeComponent.js +3 -0
- package/lib/module/specs/KlarnaExpressCheckoutViewNativeComponent.js.map +1 -0
- package/lib/module/specs/KlarnaOSMViewNativeComponent.js +7 -0
- package/lib/module/specs/KlarnaOSMViewNativeComponent.js.map +1 -0
- package/lib/module/types/button/KlarnaButtonShape.js +7 -0
- package/lib/module/types/button/KlarnaButtonShape.js.map +1 -0
- package/lib/module/types/button/KlarnaButtonStyle.js +6 -0
- package/lib/module/types/button/KlarnaButtonStyle.js.map +1 -0
- package/lib/module/types/button/KlarnaButtonTheme.js +7 -0
- package/lib/module/types/button/KlarnaButtonTheme.js.map +1 -0
- package/lib/module/types/common/KlarnaExpressCheckoutSessionOptions.js +2 -0
- package/lib/module/types/common/KlarnaExpressCheckoutSessionOptions.js.map +1 -0
- package/lib/module/types/common/KlarnaOSMPlacementKey.js +2 -0
- package/lib/module/types/common/KlarnaOSMPlacementKey.js.map +1 -0
- package/lib/module/types/common/KlarnaTheme.js +7 -0
- package/lib/module/types/common/KlarnaTheme.js.map +1 -0
- package/lib/typescript/KlarnaExpressCheckoutView.d.ts +47 -0
- package/lib/typescript/KlarnaExpressCheckoutView.d.ts.map +1 -0
- package/lib/typescript/KlarnaOSMView.d.ts +36 -0
- package/lib/typescript/KlarnaOSMView.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +9 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/specs/KlarnaExpressCheckoutViewNativeComponent.d.ts +45 -0
- package/lib/typescript/specs/KlarnaExpressCheckoutViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/specs/KlarnaOSMViewNativeComponent.d.ts +35 -0
- package/lib/typescript/specs/KlarnaOSMViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/types/button/KlarnaButtonShape.d.ts +6 -0
- package/lib/typescript/types/button/KlarnaButtonShape.d.ts.map +1 -0
- package/lib/typescript/types/button/KlarnaButtonStyle.d.ts +5 -0
- package/lib/typescript/types/button/KlarnaButtonStyle.d.ts.map +1 -0
- package/lib/typescript/types/button/KlarnaButtonTheme.d.ts +6 -0
- package/lib/typescript/types/button/KlarnaButtonTheme.d.ts.map +1 -0
- package/lib/typescript/types/common/KlarnaExpressCheckoutSessionOptions.d.ts +10 -0
- package/lib/typescript/types/common/KlarnaExpressCheckoutSessionOptions.d.ts.map +1 -0
- package/lib/typescript/types/common/KlarnaOSMPlacementKey.d.ts +2 -0
- package/lib/typescript/types/common/KlarnaOSMPlacementKey.d.ts.map +1 -0
- package/lib/typescript/types/common/KlarnaTheme.d.ts +6 -0
- package/lib/typescript/types/common/KlarnaTheme.d.ts.map +1 -0
- package/package.json +5 -3
- package/react-native-klarna-inapp-sdk.podspec +2 -1
- package/src/KlarnaExpressCheckoutView.tsx +169 -0
- package/src/KlarnaOSMView.tsx +157 -0
- package/src/index.tsx +9 -0
- package/src/specs/KlarnaExpressCheckoutViewNativeComponent.ts +66 -0
- package/src/specs/KlarnaOSMViewNativeComponent.ts +50 -0
- package/src/types/button/KlarnaButtonShape.ts +5 -0
- package/src/types/button/KlarnaButtonStyle.ts +4 -0
- package/src/types/button/KlarnaButtonTheme.ts +5 -0
- package/src/types/common/KlarnaExpressCheckoutSessionOptions.ts +13 -0
- package/src/types/common/KlarnaOSMPlacementKey.ts +3 -0
- package/src/types/common/KlarnaTheme.ts +5 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#import <React/RCTUIManager.h>
|
|
2
|
+
#import <React/RCTLog.h>
|
|
3
|
+
#import "KlarnaOSMViewManager.h"
|
|
4
|
+
#import "view/KlarnaOSMViewWrapper.h"
|
|
5
|
+
|
|
6
|
+
@implementation KlarnaOSMViewManager
|
|
7
|
+
|
|
8
|
+
RCT_EXPORT_MODULE(RNKlarnaOSMView)
|
|
9
|
+
|
|
10
|
+
#pragma mark - View Properties
|
|
11
|
+
|
|
12
|
+
RCT_EXPORT_VIEW_PROPERTY(clientId, NSString)
|
|
13
|
+
RCT_EXPORT_VIEW_PROPERTY(placementKey, NSString)
|
|
14
|
+
RCT_EXPORT_VIEW_PROPERTY(locale, NSString)
|
|
15
|
+
RCT_EXPORT_VIEW_PROPERTY(purchaseAmount, NSString)
|
|
16
|
+
RCT_EXPORT_VIEW_PROPERTY(environment, NSString)
|
|
17
|
+
RCT_EXPORT_VIEW_PROPERTY(region, NSString)
|
|
18
|
+
RCT_EXPORT_VIEW_PROPERTY(theme, NSString)
|
|
19
|
+
RCT_REMAP_VIEW_PROPERTY(backgroundColor, osmBackgroundColor, NSString)
|
|
20
|
+
RCT_EXPORT_VIEW_PROPERTY(textColor, NSString)
|
|
21
|
+
RCT_EXPORT_VIEW_PROPERTY(returnUrl, NSString)
|
|
22
|
+
RCT_EXPORT_VIEW_PROPERTY(onError, RCTDirectEventBlock)
|
|
23
|
+
RCT_EXPORT_VIEW_PROPERTY(onResized, RCTDirectEventBlock)
|
|
24
|
+
RCT_EXPORT_VIEW_PROPERTY(onOSMViewReady, RCTDirectEventBlock)
|
|
25
|
+
|
|
26
|
+
#pragma mark - View Creation
|
|
27
|
+
|
|
28
|
+
- (UIView *)view
|
|
29
|
+
{
|
|
30
|
+
KlarnaOSMViewWrapper* wrapper = [KlarnaOSMViewWrapper new];
|
|
31
|
+
wrapper.uiManager = self.bridge.uiManager;
|
|
32
|
+
return wrapper;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
#pragma mark - Exported Methods to React Native
|
|
36
|
+
|
|
37
|
+
RCT_EXPORT_METHOD(render:(nonnull NSNumber *)reactTag)
|
|
38
|
+
{
|
|
39
|
+
[self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
|
|
40
|
+
KlarnaOSMViewWrapper *view = [self osmViewWrapperForTag:reactTag fromRegistry:viewRegistry];
|
|
41
|
+
if (view) {
|
|
42
|
+
[view render];
|
|
43
|
+
}
|
|
44
|
+
}];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
#pragma mark - Private Helper Methods
|
|
48
|
+
|
|
49
|
+
- (KlarnaOSMViewWrapper *)osmViewWrapperForTag:(NSNumber *)reactTag fromRegistry:(NSDictionary<NSNumber *, UIView *> *)viewRegistry
|
|
50
|
+
{
|
|
51
|
+
UIView *view = viewRegistry[reactTag];
|
|
52
|
+
if (!view || ![view isKindOfClass:[KlarnaOSMViewWrapper class]]) {
|
|
53
|
+
RCTLogError(@"Can't find KlarnaOSMViewWrapper with tag #%@", reactTag);
|
|
54
|
+
return nil;
|
|
55
|
+
}
|
|
56
|
+
return (KlarnaOSMViewWrapper *)view;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
@end
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import KlarnaCore
|
|
3
|
+
import KlarnaPayments
|
|
4
|
+
|
|
5
|
+
/// A Swift class that implements the pure-Swift `KlarnaExpressCheckoutButtonDelegate` protocol
|
|
6
|
+
/// and forwards events to closures that can be set from Obj-C++ wrapper code.
|
|
7
|
+
@objc public class KlarnaExpressCheckoutButtonDelegateProxy: NSObject, KlarnaExpressCheckoutButtonDelegate {
|
|
8
|
+
|
|
9
|
+
@objc public var onAuthorizedHandler: ((_ response: NSDictionary) -> Void)?
|
|
10
|
+
@objc public var onErrorHandler: ((_ name: String, _ message: String, _ isFatal: Bool) -> Void)?
|
|
11
|
+
|
|
12
|
+
public func onAuthorized(
|
|
13
|
+
view: KlarnaExpressCheckoutButton,
|
|
14
|
+
response: KlarnaExpressCheckoutButtonAuthorizationResponse
|
|
15
|
+
) {
|
|
16
|
+
let responseDict: NSDictionary = [
|
|
17
|
+
"showForm": response.showForm,
|
|
18
|
+
"approved": response.approved,
|
|
19
|
+
"finalizedRequired": response.finalizedRequired,
|
|
20
|
+
"clientToken": response.clientToken ?? "",
|
|
21
|
+
"authorizationToken": response.authorizationToken ?? "",
|
|
22
|
+
"sessionId": response.sessionId,
|
|
23
|
+
"collectedShippingAddress": response.collectedShippingAddress ?? "",
|
|
24
|
+
"merchantReference1": response.merchantReference1 ?? "",
|
|
25
|
+
"merchantReference2": response.merchantReference2 ?? "",
|
|
26
|
+
]
|
|
27
|
+
onAuthorizedHandler?(responseDict)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public func onError(
|
|
31
|
+
view: KlarnaExpressCheckoutButton,
|
|
32
|
+
error: KlarnaError
|
|
33
|
+
) {
|
|
34
|
+
onErrorHandler?(error.name, error.message, error.isFatal)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// MARK: - Helper to create KEC options from Obj-C++
|
|
39
|
+
|
|
40
|
+
@objc public class KlarnaExpressCheckoutHelper: NSObject {
|
|
41
|
+
|
|
42
|
+
@objc public static func createButton(
|
|
43
|
+
sessionType: String?,
|
|
44
|
+
clientId: String?,
|
|
45
|
+
clientToken: String?,
|
|
46
|
+
locale: String?,
|
|
47
|
+
returnUrl: String,
|
|
48
|
+
delegate: KlarnaExpressCheckoutButtonDelegateProxy,
|
|
49
|
+
theme: String?,
|
|
50
|
+
shape: String?,
|
|
51
|
+
buttonStyle: String?,
|
|
52
|
+
autoFinalize: Bool,
|
|
53
|
+
collectShippingAddress: Bool,
|
|
54
|
+
sessionData: String?,
|
|
55
|
+
environment: String?,
|
|
56
|
+
region: String?
|
|
57
|
+
) -> KlarnaExpressCheckoutButton? {
|
|
58
|
+
// Build session options based on the explicit sessionType.
|
|
59
|
+
let sessionOptions: KlarnaExpressCheckoutSessionOptions
|
|
60
|
+
if sessionType == "clientToken" {
|
|
61
|
+
sessionOptions = KlarnaExpressCheckoutSessionOptions.ServerSideSession(
|
|
62
|
+
clientToken: clientToken ?? "",
|
|
63
|
+
autoFinalize: autoFinalize,
|
|
64
|
+
collectShippingAddress: collectShippingAddress,
|
|
65
|
+
sessionData: sessionData
|
|
66
|
+
)
|
|
67
|
+
} else {
|
|
68
|
+
sessionOptions = KlarnaExpressCheckoutSessionOptions.ClientSideSession(
|
|
69
|
+
clientId: clientId ?? "",
|
|
70
|
+
sessionData: sessionData ?? "",
|
|
71
|
+
autoFinalize: autoFinalize,
|
|
72
|
+
collectShippingAddress: collectShippingAddress
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Build style configuration
|
|
77
|
+
var buttonTheme: KlarnaButtonTheme?
|
|
78
|
+
if let theme = theme {
|
|
79
|
+
switch theme {
|
|
80
|
+
case "light": buttonTheme = .light
|
|
81
|
+
case "dark": buttonTheme = .dark
|
|
82
|
+
case "auto": buttonTheme = .auto
|
|
83
|
+
default: break
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
var buttonShape: KlarnaButtonShape?
|
|
88
|
+
if let shape = shape {
|
|
89
|
+
switch shape {
|
|
90
|
+
case "roundedRect": buttonShape = .roundedRect
|
|
91
|
+
case "pill": buttonShape = .pill
|
|
92
|
+
case "rectangle": buttonShape = .rectangle
|
|
93
|
+
default: break
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
var klarnaButtonStyle: KlarnaButtonStyle?
|
|
98
|
+
if let buttonStyle = buttonStyle {
|
|
99
|
+
switch buttonStyle {
|
|
100
|
+
case "filled": klarnaButtonStyle = .filled
|
|
101
|
+
case "outlined": klarnaButtonStyle = .outlined
|
|
102
|
+
default: break
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
let styleConfig = KlarnaExpressCheckoutButtonStyleConfiguration(
|
|
107
|
+
theme: buttonTheme,
|
|
108
|
+
shape: buttonShape,
|
|
109
|
+
style: klarnaButtonStyle
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
// Build environment
|
|
113
|
+
var klarnaEnvironment: KlarnaEnvironment?
|
|
114
|
+
if let environment = environment {
|
|
115
|
+
switch environment {
|
|
116
|
+
case "playground": klarnaEnvironment = .playground
|
|
117
|
+
case "production": klarnaEnvironment = .production
|
|
118
|
+
default: break
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Build region
|
|
123
|
+
var klarnaRegion: KlarnaRegion?
|
|
124
|
+
if let region = region {
|
|
125
|
+
switch region {
|
|
126
|
+
case "eu": klarnaRegion = .eu
|
|
127
|
+
case "na": klarnaRegion = .na
|
|
128
|
+
case "oc": klarnaRegion = .oc
|
|
129
|
+
default: break
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
let options = KlarnaExpressCheckoutButtonOptions(
|
|
134
|
+
sessionOptions: sessionOptions,
|
|
135
|
+
returnUrl: returnUrl,
|
|
136
|
+
delegate: delegate,
|
|
137
|
+
locale: locale,
|
|
138
|
+
styleConfiguration: styleConfig,
|
|
139
|
+
environment: klarnaEnvironment,
|
|
140
|
+
region: klarnaRegion
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
return KlarnaExpressCheckoutButton(options: options)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#import <React/RCTUIManager.h>
|
|
2
|
+
#import <UIKit/UIKit.h>
|
|
3
|
+
|
|
4
|
+
#if RCT_NEW_ARCH_ENABLED
|
|
5
|
+
#import <React/RCTViewComponentView.h>
|
|
6
|
+
#else
|
|
7
|
+
#import <AVFoundation/AVFoundation.h>
|
|
8
|
+
#import <React/RCTView.h>
|
|
9
|
+
#endif
|
|
10
|
+
|
|
11
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
12
|
+
|
|
13
|
+
#if RCT_NEW_ARCH_ENABLED
|
|
14
|
+
@interface KlarnaExpressCheckoutViewWrapper : RCTViewComponentView
|
|
15
|
+
#else
|
|
16
|
+
@interface KlarnaExpressCheckoutViewWrapper : UIView
|
|
17
|
+
|
|
18
|
+
@property (nonatomic, copy) RCTDirectEventBlock onAuthorized;
|
|
19
|
+
@property (nonatomic, copy) RCTDirectEventBlock onError;
|
|
20
|
+
@property (nonatomic, copy) RCTDirectEventBlock onResized;
|
|
21
|
+
|
|
22
|
+
@property (nonatomic, strong) NSString* sessionType;
|
|
23
|
+
@property (nonatomic, strong) NSString* clientId;
|
|
24
|
+
@property (nonatomic, strong) NSString* clientToken;
|
|
25
|
+
@property (nonatomic, strong) NSString* locale;
|
|
26
|
+
@property (nonatomic, strong) NSString* environment;
|
|
27
|
+
@property (nonatomic, strong) NSString* region;
|
|
28
|
+
@property (nonatomic, strong) NSString* returnUrl;
|
|
29
|
+
@property (nonatomic, strong) NSString* theme;
|
|
30
|
+
@property (nonatomic, strong) NSString* shape;
|
|
31
|
+
@property (nonatomic, strong) NSString* buttonStyle;
|
|
32
|
+
@property (nonatomic, assign) BOOL autoFinalize;
|
|
33
|
+
@property (nonatomic, assign) BOOL collectShippingAddress;
|
|
34
|
+
@property (nonatomic, strong) NSString* sessionData;
|
|
35
|
+
#endif
|
|
36
|
+
|
|
37
|
+
@property (nonatomic, weak) RCTUIManager* uiManager;
|
|
38
|
+
|
|
39
|
+
@end
|
|
40
|
+
|
|
41
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#import <React/RCTUIManager.h>
|
|
2
|
+
#import <UIKit/UIKit.h>
|
|
3
|
+
|
|
4
|
+
#if RCT_NEW_ARCH_ENABLED
|
|
5
|
+
#import <React/RCTViewComponentView.h>
|
|
6
|
+
#endif
|
|
7
|
+
|
|
8
|
+
#if RCT_NEW_ARCH_ENABLED
|
|
9
|
+
|
|
10
|
+
@interface KlarnaOSMViewWrapper : RCTViewComponentView
|
|
11
|
+
|
|
12
|
+
#else
|
|
13
|
+
|
|
14
|
+
@interface KlarnaOSMViewWrapper : UIView
|
|
15
|
+
|
|
16
|
+
@property (nonatomic, copy) RCTDirectEventBlock onError;
|
|
17
|
+
@property (nonatomic, copy) RCTDirectEventBlock onResized;
|
|
18
|
+
@property (nonatomic, copy) RCTDirectEventBlock onOSMViewReady;
|
|
19
|
+
|
|
20
|
+
@property (nonatomic, strong) NSString* clientId;
|
|
21
|
+
@property (nonatomic, strong) NSString* placementKey;
|
|
22
|
+
@property (nonatomic, strong) NSString* locale;
|
|
23
|
+
@property (nonatomic, strong) NSString* purchaseAmount;
|
|
24
|
+
@property (nonatomic, strong) NSString* environment;
|
|
25
|
+
@property (nonatomic, strong) NSString* region;
|
|
26
|
+
@property (nonatomic, strong) NSString* theme;
|
|
27
|
+
@property (nonatomic, strong) NSString* osmBackgroundColor;
|
|
28
|
+
@property (nonatomic, strong) NSString* textColor;
|
|
29
|
+
@property (nullable, nonatomic, strong) NSString* returnUrl;
|
|
30
|
+
|
|
31
|
+
- (void)setClientId:(NSString * _Nonnull)clientId;
|
|
32
|
+
- (void)setPlacementKey:(NSString * _Nonnull)placementKey;
|
|
33
|
+
- (void)setLocale:(NSString * _Nonnull)locale;
|
|
34
|
+
- (void)setPurchaseAmount:(NSString * _Nonnull)purchaseAmount;
|
|
35
|
+
- (void)setEnvironment:(NSString * _Nonnull)environment;
|
|
36
|
+
- (void)setRegion:(NSString * _Nonnull)region;
|
|
37
|
+
- (void)setTheme:(NSString * _Nonnull)theme;
|
|
38
|
+
- (void)setOsmBackgroundColor:(NSString * _Nonnull)osmBackgroundColor;
|
|
39
|
+
- (void)setTextColor:(NSString * _Nonnull)textColor;
|
|
40
|
+
- (void)setReturnUrl:(NSString * _Nullable)returnUrl;
|
|
41
|
+
|
|
42
|
+
#endif
|
|
43
|
+
|
|
44
|
+
@property (nonatomic, weak) RCTUIManager* uiManager;
|
|
45
|
+
|
|
46
|
+
- (void)render;
|
|
47
|
+
|
|
48
|
+
@end
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
#if RCT_NEW_ARCH_ENABLED
|
|
2
|
+
|
|
3
|
+
#import <AVFoundation/AVFoundation.h>
|
|
4
|
+
#import <React/RCTLog.h>
|
|
5
|
+
#import <react/renderer/components/RNKlarnaMobileSDK/ComponentDescriptors.h>
|
|
6
|
+
#import <react/renderer/components/RNKlarnaMobileSDK/EventEmitters.h>
|
|
7
|
+
#import <react/renderer/components/RNKlarnaMobileSDK/Props.h>
|
|
8
|
+
#import <react/renderer/components/RNKlarnaMobileSDK/RCTComponentViewHelpers.h>
|
|
9
|
+
#import "../KlarnaExpressCheckoutViewWrapper.h"
|
|
10
|
+
#import "RCTFabricComponentsPlugins.h"
|
|
11
|
+
#import <KlarnaMobileSDK/KlarnaMobileSDK.h>
|
|
12
|
+
#import <KlarnaMobileSDK/KlarnaMobileSDK-Swift.h>
|
|
13
|
+
|
|
14
|
+
#if __has_include("react_native_klarna_inapp_sdk-Swift.h")
|
|
15
|
+
#import "react_native_klarna_inapp_sdk-Swift.h"
|
|
16
|
+
#elif __has_include("RNKlarnaMobileSDK-Swift.h")
|
|
17
|
+
#import "RNKlarnaMobileSDK-Swift.h"
|
|
18
|
+
#else
|
|
19
|
+
#import <RNKlarnaMobileSDK/RNKlarnaMobileSDK-Swift.h>
|
|
20
|
+
#endif
|
|
21
|
+
|
|
22
|
+
using namespace facebook::react;
|
|
23
|
+
|
|
24
|
+
@interface KlarnaExpressCheckoutViewWrapper () <RCTRNKlarnaExpressCheckoutViewViewProtocol>
|
|
25
|
+
|
|
26
|
+
@property (nonatomic, strong) KlarnaExpressCheckoutButton* expressCheckoutButton;
|
|
27
|
+
@property (nonatomic, strong) KlarnaExpressCheckoutButtonDelegateProxy* delegateProxy;
|
|
28
|
+
@property (nonatomic, assign) BOOL isButtonCreated;
|
|
29
|
+
|
|
30
|
+
// Store props for button creation
|
|
31
|
+
@property (nonatomic, strong) NSString* storedSessionType;
|
|
32
|
+
@property (nonatomic, strong) NSString* storedClientId;
|
|
33
|
+
@property (nonatomic, strong) NSString* storedClientToken;
|
|
34
|
+
@property (nonatomic, strong) NSString* storedLocale;
|
|
35
|
+
@property (nonatomic, strong) NSString* storedEnvironment;
|
|
36
|
+
@property (nonatomic, strong) NSString* storedRegion;
|
|
37
|
+
@property (nonatomic, strong) NSString* storedReturnUrl;
|
|
38
|
+
@property (nonatomic, strong) NSString* storedTheme;
|
|
39
|
+
@property (nonatomic, strong) NSString* storedShape;
|
|
40
|
+
@property (nonatomic, strong) NSString* storedButtonStyle;
|
|
41
|
+
@property (nonatomic, assign) BOOL storedAutoFinalize;
|
|
42
|
+
@property (nonatomic, assign) BOOL storedCollectShippingAddress;
|
|
43
|
+
@property (nonatomic, strong) NSString* storedSessionData;
|
|
44
|
+
|
|
45
|
+
@end
|
|
46
|
+
|
|
47
|
+
@implementation KlarnaExpressCheckoutViewWrapper
|
|
48
|
+
|
|
49
|
+
#pragma mark - Initialization
|
|
50
|
+
|
|
51
|
+
- (instancetype)initWithFrame:(CGRect)frame
|
|
52
|
+
{
|
|
53
|
+
self = [super initWithFrame:frame];
|
|
54
|
+
if (self) {
|
|
55
|
+
self.backgroundColor = [UIColor clearColor];
|
|
56
|
+
self.isButtonCreated = NO;
|
|
57
|
+
self.storedAutoFinalize = YES;
|
|
58
|
+
self.storedCollectShippingAddress = NO;
|
|
59
|
+
static const auto defaultProps = std::make_shared<const RNKlarnaExpressCheckoutViewProps>();
|
|
60
|
+
_props = defaultProps;
|
|
61
|
+
[self setupDelegateProxy];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return self;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
|
68
|
+
{
|
|
69
|
+
return concreteComponentDescriptorProvider<RNKlarnaExpressCheckoutViewComponentDescriptor>();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
Class<RCTComponentViewProtocol> RNKlarnaExpressCheckoutViewCls(void)
|
|
73
|
+
{
|
|
74
|
+
return KlarnaExpressCheckoutViewWrapper.class;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
- (void)setupDelegateProxy {
|
|
78
|
+
self.delegateProxy = [[KlarnaExpressCheckoutButtonDelegateProxy alloc] init];
|
|
79
|
+
|
|
80
|
+
__weak __typeof(self) weakSelf = self;
|
|
81
|
+
|
|
82
|
+
self.delegateProxy.onAuthorizedHandler = ^(NSDictionary * _Nonnull response) {
|
|
83
|
+
__strong __typeof(weakSelf) strongSelf = weakSelf;
|
|
84
|
+
if (!strongSelf || !strongSelf->_eventEmitter) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
auto emitter = std::dynamic_pointer_cast<const RNKlarnaExpressCheckoutViewEventEmitter>(strongSelf->_eventEmitter);
|
|
89
|
+
if (emitter) {
|
|
90
|
+
emitter->onAuthorized(RNKlarnaExpressCheckoutViewEventEmitter::OnAuthorized{
|
|
91
|
+
.authorizationResponse = {
|
|
92
|
+
.showForm = [[response objectForKey:@"showForm"] boolValue],
|
|
93
|
+
.approved = [[response objectForKey:@"approved"] boolValue],
|
|
94
|
+
.finalizedRequired = [[response objectForKey:@"finalizedRequired"] boolValue],
|
|
95
|
+
.clientToken = std::string([([response objectForKey:@"clientToken"] ?: @"") UTF8String]),
|
|
96
|
+
.authorizationToken = std::string([([response objectForKey:@"authorizationToken"] ?: @"") UTF8String]),
|
|
97
|
+
.sessionId = std::string([([response objectForKey:@"sessionId"] ?: @"") UTF8String]),
|
|
98
|
+
.collectedShippingAddress = std::string([([response objectForKey:@"collectedShippingAddress"] ?: @"") UTF8String]),
|
|
99
|
+
.merchantReference1 = std::string([([response objectForKey:@"merchantReference1"] ?: @"") UTF8String]),
|
|
100
|
+
.merchantReference2 = std::string([([response objectForKey:@"merchantReference2"] ?: @"") UTF8String]),
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
self.delegateProxy.onErrorHandler = ^(NSString * _Nonnull name, NSString * _Nonnull message, BOOL isFatal) {
|
|
107
|
+
__strong __typeof(weakSelf) strongSelf = weakSelf;
|
|
108
|
+
if (!strongSelf || !strongSelf->_eventEmitter) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
auto emitter = std::dynamic_pointer_cast<const RNKlarnaExpressCheckoutViewEventEmitter>(strongSelf->_eventEmitter);
|
|
113
|
+
if (emitter) {
|
|
114
|
+
emitter->onError(RNKlarnaExpressCheckoutViewEventEmitter::OnError{
|
|
115
|
+
.error = {
|
|
116
|
+
.name = std::string([name UTF8String]),
|
|
117
|
+
.message = std::string([message UTF8String]),
|
|
118
|
+
.isFatal = isFatal,
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
#pragma mark - Props Update
|
|
126
|
+
|
|
127
|
+
- (void)updateProps:(const facebook::react::Props::Shared &)props oldProps:(const facebook::react::Props::Shared &)oldProps {
|
|
128
|
+
const auto &newViewProps = *std::static_pointer_cast<RNKlarnaExpressCheckoutViewProps const>(props);
|
|
129
|
+
|
|
130
|
+
self.storedSessionType = [[NSString alloc] initWithUTF8String:newViewProps.sessionType.c_str()];
|
|
131
|
+
self.storedClientId = [[NSString alloc] initWithUTF8String:newViewProps.clientId.c_str()];
|
|
132
|
+
self.storedClientToken = [[NSString alloc] initWithUTF8String:newViewProps.clientToken.c_str()];
|
|
133
|
+
self.storedLocale = [[NSString alloc] initWithUTF8String:newViewProps.locale.c_str()];
|
|
134
|
+
self.storedEnvironment = [[NSString alloc] initWithUTF8String:newViewProps.environment.c_str()];
|
|
135
|
+
self.storedRegion = [[NSString alloc] initWithUTF8String:newViewProps.region.c_str()];
|
|
136
|
+
self.storedReturnUrl = [[NSString alloc] initWithUTF8String:newViewProps.returnUrl.c_str()];
|
|
137
|
+
self.storedTheme = [[NSString alloc] initWithUTF8String:newViewProps.theme.c_str()];
|
|
138
|
+
self.storedShape = [[NSString alloc] initWithUTF8String:newViewProps.shape.c_str()];
|
|
139
|
+
self.storedButtonStyle = [[NSString alloc] initWithUTF8String:newViewProps.buttonStyle.c_str()];
|
|
140
|
+
self.storedAutoFinalize = newViewProps.autoFinalize;
|
|
141
|
+
self.storedCollectShippingAddress = newViewProps.collectShippingAddress;
|
|
142
|
+
self.storedSessionData = [[NSString alloc] initWithUTF8String:newViewProps.sessionData.c_str()];
|
|
143
|
+
|
|
144
|
+
if (self.isButtonCreated) {
|
|
145
|
+
[self resetButton];
|
|
146
|
+
}
|
|
147
|
+
[self createButtonIfNeeded];
|
|
148
|
+
|
|
149
|
+
[super updateProps:props oldProps:oldProps];
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
#pragma mark - Button Creation
|
|
153
|
+
|
|
154
|
+
- (void)resetButton {
|
|
155
|
+
if (self.expressCheckoutButton) {
|
|
156
|
+
[self.expressCheckoutButton removeFromSuperview];
|
|
157
|
+
self.expressCheckoutButton = nil;
|
|
158
|
+
}
|
|
159
|
+
self.isButtonCreated = NO;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
- (void)createButtonIfNeeded {
|
|
163
|
+
if (self.isButtonCreated) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
KlarnaExpressCheckoutButton *button = [KlarnaExpressCheckoutHelper
|
|
168
|
+
createButtonWithSessionType:self.storedSessionType ?: @""
|
|
169
|
+
clientId:self.storedClientId ?: @""
|
|
170
|
+
clientToken:self.storedClientToken ?: @""
|
|
171
|
+
locale:self.storedLocale
|
|
172
|
+
returnUrl:self.storedReturnUrl ?: @""
|
|
173
|
+
delegate:self.delegateProxy
|
|
174
|
+
theme:self.storedTheme
|
|
175
|
+
shape:self.storedShape
|
|
176
|
+
buttonStyle:self.storedButtonStyle
|
|
177
|
+
autoFinalize:self.storedAutoFinalize
|
|
178
|
+
collectShippingAddress:self.storedCollectShippingAddress
|
|
179
|
+
sessionData:self.storedSessionData
|
|
180
|
+
environment:self.storedEnvironment
|
|
181
|
+
region:self.storedRegion];
|
|
182
|
+
|
|
183
|
+
if (button) {
|
|
184
|
+
self.expressCheckoutButton = button;
|
|
185
|
+
self.expressCheckoutButton.translatesAutoresizingMaskIntoConstraints = NO;
|
|
186
|
+
[self addSubview:self.expressCheckoutButton];
|
|
187
|
+
|
|
188
|
+
[NSLayoutConstraint activateConstraints:@[
|
|
189
|
+
[self.expressCheckoutButton.topAnchor constraintEqualToAnchor:self.topAnchor],
|
|
190
|
+
[self.expressCheckoutButton.bottomAnchor constraintEqualToAnchor:self.bottomAnchor],
|
|
191
|
+
[self.expressCheckoutButton.leadingAnchor constraintEqualToAnchor:self.leadingAnchor],
|
|
192
|
+
[self.expressCheckoutButton.trailingAnchor constraintEqualToAnchor:self.trailingAnchor],
|
|
193
|
+
]];
|
|
194
|
+
|
|
195
|
+
self.isButtonCreated = YES;
|
|
196
|
+
|
|
197
|
+
// Send resize event after layout
|
|
198
|
+
__weak __typeof(self) weakSelf = self;
|
|
199
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
200
|
+
__strong __typeof(weakSelf) strongSelf = weakSelf;
|
|
201
|
+
if (!strongSelf || !strongSelf->_eventEmitter || !strongSelf.expressCheckoutButton) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
CGFloat height = strongSelf.expressCheckoutButton.intrinsicContentSize.height;
|
|
205
|
+
if (height > 0) {
|
|
206
|
+
auto emitter = std::dynamic_pointer_cast<const RNKlarnaExpressCheckoutViewEventEmitter>(strongSelf->_eventEmitter);
|
|
207
|
+
if (emitter) {
|
|
208
|
+
emitter->onResized(RNKlarnaExpressCheckoutViewEventEmitter::OnResized{
|
|
209
|
+
.height = std::string([[[NSNumber numberWithFloat:height] stringValue] UTF8String]),
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
#pragma mark - UIView Lifecycle
|
|
218
|
+
|
|
219
|
+
- (void)didMoveToWindow {
|
|
220
|
+
[super didMoveToWindow];
|
|
221
|
+
if (!self.window) {
|
|
222
|
+
[self resetButton];
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
@end
|
|
227
|
+
|
|
228
|
+
#endif
|