react-native-klarna-inapp-sdk 2.3.15 → 2.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/README.md +1 -0
- package/android/src/main/java/com/klarna/mobile/sdk/reactnative/KlarnaMobileSDKPackage.java +2 -4
- package/android/src/main/java/com/klarna/mobile/sdk/reactnative/checkout/KlarnaCheckoutViewEventSender.java +7 -2
- package/android/src/main/java/com/klarna/mobile/sdk/reactnative/checkout/KlarnaCheckoutViewManager.java +51 -18
- package/android/src/main/java/com/klarna/mobile/sdk/reactnative/common/WebViewResizeObserver.java +9 -4
- package/android/src/main/java/com/klarna/mobile/sdk/reactnative/common/event/KlarnaEventHandlerEventsUtil.java +62 -3
- package/android/src/main/java/com/klarna/mobile/sdk/reactnative/common/ui/ResizeObserverWrapperView.java +3 -2
- package/android/src/main/java/com/klarna/mobile/sdk/reactnative/common/util/ArgumentsUtil.java +40 -0
- package/android/src/main/java/com/klarna/mobile/sdk/reactnative/payments/PaymentViewWrapper.java +1 -1
- package/android/src/main/java/com/klarna/mobile/sdk/reactnative/signin/KlarnaSignInData.java +15 -0
- package/android/src/main/java/com/klarna/mobile/sdk/reactnative/signin/KlarnaSignInEventsMapper.java +40 -0
- package/android/src/main/java/com/klarna/mobile/sdk/reactnative/signin/KlarnaSignInModuleImpl.java +124 -0
- package/android/src/newarch/java/com/klarna/mobile/sdk/reactnative/spec/RNKlarnaSignInModuleSpec.java +65 -0
- package/android/src/oldarch/java/com/klarna/mobile/sdk/reactnative/spec/RNKlarnaSignInModuleSpec.java +39 -0
- package/android/src/test/java/com/klarna/mobile/sdk/reactnative/KlarnaMobileSDKPackageTest.java +5 -4
- package/ios/Sources/KlarnaCheckoutViewManager.mm +32 -24
- package/ios/Sources/signIn/KlarnaSignInData.h +25 -0
- package/ios/Sources/signIn/KlarnaSignInData.mm +21 -0
- package/ios/Sources/signIn/KlarnaSignInEventsMapper.h +18 -0
- package/ios/Sources/signIn/KlarnaSignInEventsMapper.m +54 -0
- package/ios/Sources/signIn/KlarnaSignInModule.h +26 -0
- package/ios/Sources/signIn/KlarnaSignInModuleImpl.h +37 -0
- package/ios/Sources/signIn/KlarnaSignInModuleImpl.mm +244 -0
- package/ios/Sources/signIn/newarch/KlarnaSignInModule.mm +75 -0
- package/ios/Sources/signIn/oldarch/KlarnaSignInModule.mm +72 -0
- package/ios/Sources/view/KlarnaCheckoutViewWrapper.h +1 -3
- package/ios/Sources/view/newarch/KlarnaCheckoutViewWrapper.mm +53 -29
- package/ios/Sources/view/oldarch/KlarnaCheckoutViewWrapper.mm +58 -20
- package/lib/commonjs/KlarnaCheckoutView.js +16 -3
- package/lib/commonjs/KlarnaCheckoutView.js.map +1 -1
- package/lib/commonjs/KlarnaSignInSDK.js +80 -0
- package/lib/commonjs/KlarnaSignInSDK.js.map +1 -0
- package/lib/commonjs/index.js +11 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/specs/KlarnaCheckoutViewNativeComponent.js.map +1 -1
- package/lib/commonjs/specs/NativeKlarnaSignIn.js +10 -0
- package/lib/commonjs/specs/NativeKlarnaSignIn.js.map +1 -0
- package/lib/commonjs/types/common/KlarnaEnvironment.js +13 -0
- package/lib/commonjs/types/common/KlarnaEnvironment.js.map +1 -0
- package/lib/commonjs/types/common/KlarnaRegion.js +14 -0
- package/lib/commonjs/types/common/KlarnaRegion.js.map +1 -0
- package/lib/module/KlarnaCheckoutView.js +16 -3
- package/lib/module/KlarnaCheckoutView.js.map +1 -1
- package/lib/module/KlarnaSignInSDK.js +72 -0
- package/lib/module/KlarnaSignInSDK.js.map +1 -0
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/specs/KlarnaCheckoutViewNativeComponent.js.map +1 -1
- package/lib/module/specs/NativeKlarnaSignIn.js +3 -0
- package/lib/module/specs/NativeKlarnaSignIn.js.map +1 -0
- package/lib/module/types/common/KlarnaEnvironment.js +6 -0
- package/lib/module/types/common/KlarnaEnvironment.js.map +1 -0
- package/lib/module/types/common/KlarnaRegion.js +7 -0
- package/lib/module/types/common/KlarnaRegion.js.map +1 -0
- package/lib/typescript/KlarnaCheckoutView.d.ts +2 -0
- package/lib/typescript/KlarnaCheckoutView.d.ts.map +1 -1
- package/lib/typescript/KlarnaSignInSDK.d.ts +19 -0
- package/lib/typescript/KlarnaSignInSDK.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +1 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/specs/KlarnaCheckoutViewNativeComponent.d.ts +1 -0
- package/lib/typescript/specs/KlarnaCheckoutViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/specs/NativeKlarnaSignIn.d.ts +10 -0
- package/lib/typescript/specs/NativeKlarnaSignIn.d.ts.map +1 -0
- package/lib/typescript/types/common/KlarnaEnvironment.d.ts +5 -0
- package/lib/typescript/types/common/KlarnaEnvironment.d.ts.map +1 -0
- package/lib/typescript/types/common/KlarnaMobileSDKError.d.ts +4 -0
- package/lib/typescript/types/common/KlarnaMobileSDKError.d.ts.map +1 -1
- package/lib/typescript/types/common/KlarnaProductEvent.d.ts +1 -0
- package/lib/typescript/types/common/KlarnaProductEvent.d.ts.map +1 -1
- package/lib/typescript/types/common/KlarnaRegion.d.ts +6 -0
- package/lib/typescript/types/common/KlarnaRegion.d.ts.map +1 -0
- package/package.json +1 -1
- package/react-native-klarna-inapp-sdk.podspec +1 -1
- package/src/KlarnaCheckoutView.tsx +16 -3
- package/src/KlarnaSignInSDK.tsx +122 -0
- package/src/index.tsx +1 -0
- package/src/specs/KlarnaCheckoutViewNativeComponent.ts +1 -0
- package/src/specs/NativeKlarnaSignIn.ts +25 -0
- package/src/types/common/KlarnaEnvironment.ts +4 -0
- package/src/types/common/KlarnaMobileSDKError.ts +2 -0
- package/src/types/common/KlarnaProductEvent.ts +1 -0
- package/src/types/common/KlarnaRegion.ts +5 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
package com.klarna.mobile.sdk.reactnative.spec;
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.NonNull;
|
|
4
|
+
|
|
5
|
+
import com.facebook.react.bridge.Promise;
|
|
6
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
7
|
+
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
|
8
|
+
import com.facebook.react.bridge.ReactMethod;
|
|
9
|
+
import com.klarna.mobile.sdk.reactnative.signin.KlarnaSignInModuleImpl;
|
|
10
|
+
|
|
11
|
+
public class RNKlarnaSignInModuleSpec extends ReactContextBaseJavaModule {
|
|
12
|
+
private KlarnaSignInModuleImpl module;
|
|
13
|
+
|
|
14
|
+
public RNKlarnaSignInModuleSpec(ReactApplicationContext reactContext) {
|
|
15
|
+
super(reactContext);
|
|
16
|
+
this.module = new KlarnaSignInModuleImpl(reactContext);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@NonNull
|
|
20
|
+
@Override
|
|
21
|
+
public String getName() {
|
|
22
|
+
return KlarnaSignInModuleImpl.NAME;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
@ReactMethod(isBlockingSynchronousMethod = false)
|
|
26
|
+
public void init(String instanceId, String environment, String region, String returnUrl, Promise promise) {
|
|
27
|
+
module.init(instanceId, environment, region, returnUrl, promise);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@ReactMethod(isBlockingSynchronousMethod = false)
|
|
31
|
+
public void dispose(String instanceId, Promise promise) {
|
|
32
|
+
module.dispose(instanceId, promise);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@ReactMethod(isBlockingSynchronousMethod = false)
|
|
36
|
+
public void signIn(String instanceId, String clientId, String scope, String market, String locale, String tokenizationId, Promise promise) {
|
|
37
|
+
module.signIn(instanceId, clientId, scope, market, locale, tokenizationId, promise);
|
|
38
|
+
}
|
|
39
|
+
}
|
package/android/src/test/java/com/klarna/mobile/sdk/reactnative/KlarnaMobileSDKPackageTest.java
CHANGED
|
@@ -10,6 +10,7 @@ import com.facebook.react.uimanager.ViewManager;
|
|
|
10
10
|
import com.klarna.mobile.sdk.reactnative.KlarnaMobileSDKPackage;
|
|
11
11
|
import com.klarna.mobile.sdk.reactnative.checkout.KlarnaCheckoutViewManager;
|
|
12
12
|
import com.klarna.mobile.sdk.reactnative.payments.KlarnaPaymentViewManager;
|
|
13
|
+
import com.klarna.mobile.sdk.reactnative.spec.RNKlarnaSignInModuleSpec;
|
|
13
14
|
import com.klarna.mobile.sdk.reactnative.standalonewebview.KlarnaStandaloneWebViewManager;
|
|
14
15
|
|
|
15
16
|
import org.junit.Assert;
|
|
@@ -34,10 +35,10 @@ public class KlarnaMobileSDKPackageTest {
|
|
|
34
35
|
|
|
35
36
|
@Test
|
|
36
37
|
public void testCreateNativeModules() {
|
|
37
|
-
KlarnaMobileSDKPackage
|
|
38
|
-
List<NativeModule> nativeModules =
|
|
39
|
-
Assert.
|
|
40
|
-
Assert.assertTrue(nativeModules.
|
|
38
|
+
KlarnaMobileSDKPackage mobilePackage = new KlarnaMobileSDKPackage();
|
|
39
|
+
List<NativeModule> nativeModules = mobilePackage.createNativeModules(reactContext);
|
|
40
|
+
Assert.assertEquals(1, nativeModules.size());
|
|
41
|
+
Assert.assertTrue(nativeModules.get(0) instanceof RNKlarnaSignInModuleSpec);
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
@Test
|
|
@@ -1,20 +1,21 @@
|
|
|
1
|
-
#import "KlarnaCheckoutViewManager.h"
|
|
2
|
-
|
|
3
1
|
#import <React/RCTUIManager.h>
|
|
4
2
|
#import <React/RCTLog.h>
|
|
5
|
-
|
|
3
|
+
#import "KlarnaCheckoutViewManager.h"
|
|
6
4
|
#import "view/KlarnaCheckoutViewWrapper.h"
|
|
7
5
|
|
|
8
6
|
@implementation KlarnaCheckoutViewManager
|
|
9
7
|
|
|
10
8
|
RCT_EXPORT_MODULE(RNKlarnaCheckoutView)
|
|
11
9
|
|
|
12
|
-
#pragma mark - View
|
|
10
|
+
#pragma mark - View Properties
|
|
13
11
|
|
|
14
12
|
RCT_EXPORT_VIEW_PROPERTY(returnUrl, NSString)
|
|
15
13
|
RCT_EXPORT_VIEW_PROPERTY(onEvent, RCTDirectEventBlock)
|
|
16
14
|
RCT_EXPORT_VIEW_PROPERTY(onError, RCTDirectEventBlock)
|
|
17
15
|
RCT_EXPORT_VIEW_PROPERTY(onResized, RCTDirectEventBlock)
|
|
16
|
+
RCT_EXPORT_VIEW_PROPERTY(onCheckoutViewReady, RCTDirectEventBlock)
|
|
17
|
+
|
|
18
|
+
#pragma mark - View Creation
|
|
18
19
|
|
|
19
20
|
- (UIView *)view
|
|
20
21
|
{
|
|
@@ -23,39 +24,46 @@ RCT_EXPORT_VIEW_PROPERTY(onResized, RCTDirectEventBlock)
|
|
|
23
24
|
return wrapper;
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
#pragma mark - Exported Methods
|
|
27
|
+
#pragma mark - Exported Methods to React Native
|
|
27
28
|
|
|
28
|
-
RCT_EXPORT_METHOD(setSnippet:(nonnull NSNumber*)reactTag snippet:(NSString*)snippet)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
RCT_EXPORT_METHOD(setSnippet:(nonnull NSNumber *)reactTag snippet:(NSString *)snippet)
|
|
30
|
+
{
|
|
31
|
+
[self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
|
|
32
|
+
KlarnaCheckoutViewWrapper *view = [self checkoutViewWrapperForTag:reactTag fromRegistry:viewRegistry];
|
|
33
|
+
if (view) {
|
|
34
|
+
[view setSnippet:snippet];
|
|
34
35
|
}
|
|
35
|
-
[view setSnippet:snippet];
|
|
36
36
|
}];
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
RCT_EXPORT_METHOD(suspend:(nonnull NSNumber*)reactTag) {
|
|
39
|
+
RCT_EXPORT_METHOD(suspend:(nonnull NSNumber *)reactTag) {
|
|
40
40
|
[self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *,UIView *> *viewRegistry) {
|
|
41
|
-
KlarnaCheckoutViewWrapper*
|
|
42
|
-
if (
|
|
43
|
-
|
|
44
|
-
return;
|
|
41
|
+
KlarnaCheckoutViewWrapper *view = [self checkoutViewWrapperForTag:reactTag fromRegistry:viewRegistry];
|
|
42
|
+
if (view) {
|
|
43
|
+
[view suspend];
|
|
45
44
|
}
|
|
46
|
-
[view suspend];
|
|
47
45
|
}];
|
|
48
46
|
}
|
|
49
47
|
|
|
50
|
-
RCT_EXPORT_METHOD(resume:(nonnull NSNumber*)reactTag) {
|
|
48
|
+
RCT_EXPORT_METHOD(resume:(nonnull NSNumber *)reactTag) {
|
|
51
49
|
[self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *,UIView *> *viewRegistry) {
|
|
52
|
-
KlarnaCheckoutViewWrapper*
|
|
53
|
-
if (
|
|
54
|
-
|
|
55
|
-
return;
|
|
50
|
+
KlarnaCheckoutViewWrapper *view = [self checkoutViewWrapperForTag:reactTag fromRegistry:viewRegistry];
|
|
51
|
+
if (view) {
|
|
52
|
+
[view resume];
|
|
56
53
|
}
|
|
57
|
-
[view resume];
|
|
58
54
|
}];
|
|
59
55
|
}
|
|
60
56
|
|
|
57
|
+
#pragma mark - Private Helper Methods
|
|
58
|
+
|
|
59
|
+
- (KlarnaCheckoutViewWrapper *)checkoutViewWrapperForTag:(NSNumber *)reactTag fromRegistry:(NSDictionary<NSNumber *, UIView *> *)viewRegistry
|
|
60
|
+
{
|
|
61
|
+
UIView *view = viewRegistry[reactTag];
|
|
62
|
+
if (!view || ![view isKindOfClass:[KlarnaCheckoutViewWrapper class]]) {
|
|
63
|
+
RCTLogError(@"Can't find KlarnaCheckoutViewWrapper with tag #%@", reactTag);
|
|
64
|
+
return nil;
|
|
65
|
+
}
|
|
66
|
+
return (KlarnaCheckoutViewWrapper *)view;
|
|
67
|
+
}
|
|
68
|
+
|
|
61
69
|
@end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//
|
|
2
|
+
// KlarnaSignInData.h
|
|
3
|
+
// react-native-klarna-inapp-sdk
|
|
4
|
+
//
|
|
5
|
+
// Created by Jorge Palacio on 2025-03-12.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#import <Foundation/Foundation.h>
|
|
9
|
+
#import "KlarnaMobileSDK/KlarnaMobileSDK-Swift.h"
|
|
10
|
+
#import <React/RCTBridgeModule.h>
|
|
11
|
+
|
|
12
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
13
|
+
|
|
14
|
+
@interface KlarnaSignInData : NSObject
|
|
15
|
+
|
|
16
|
+
@property (nonatomic, strong) NSString *instanceID;
|
|
17
|
+
@property (nonatomic, strong) KlarnaSignInSDK *sdkInstance API_AVAILABLE(ios(13.0));
|
|
18
|
+
@property (nonatomic, copy) RCTPromiseResolveBlock resolver;
|
|
19
|
+
@property (nonatomic, copy) RCTPromiseRejectBlock rejecter;
|
|
20
|
+
|
|
21
|
+
-(instancetype)initWith:(NSString *)instanceID sdkInstance:(KlarnaSignInSDK *)sdkInstance;
|
|
22
|
+
|
|
23
|
+
@end
|
|
24
|
+
|
|
25
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
//
|
|
2
|
+
// KlarnaSignInData.m
|
|
3
|
+
// react-native-klarna-inapp-sdk
|
|
4
|
+
//
|
|
5
|
+
// Created by Jorge Palacio on 2025-03-12.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#import "KlarnaSignInData.h"
|
|
9
|
+
|
|
10
|
+
@implementation KlarnaSignInData
|
|
11
|
+
|
|
12
|
+
-(instancetype)initWith:(NSString *)instanceID sdkInstance:(KlarnaSignInSDK *)sdkInstance {
|
|
13
|
+
self = [super init];
|
|
14
|
+
if (self) {
|
|
15
|
+
_instanceID = instanceID;
|
|
16
|
+
_sdkInstance = sdkInstance;
|
|
17
|
+
}
|
|
18
|
+
return self;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//
|
|
2
|
+
// KlarnaSignInErrorsMapper.h
|
|
3
|
+
// react-native-klarna-inapp-sdk
|
|
4
|
+
//
|
|
5
|
+
// Created by Jorge Palacio on 2025-05-13.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#import <Foundation/Foundation.h>
|
|
9
|
+
|
|
10
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
11
|
+
|
|
12
|
+
@interface KlarnaSignInEventsMapper : NSObject
|
|
13
|
+
+(NSString *)mapSignInErrorName:(NSString *)errorName;
|
|
14
|
+
+(NSString *)mapSignInEventName:(NSString *)eventName;
|
|
15
|
+
+(NSString *)mapSignInParamName:(NSString *)paramName;
|
|
16
|
+
@end
|
|
17
|
+
|
|
18
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
//
|
|
2
|
+
// KlarnaSignInErrorsMapper.m
|
|
3
|
+
// react-native-klarna-inapp-sdk
|
|
4
|
+
//
|
|
5
|
+
// Created by Jorge Palacio on 2025-05-13.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#import "KlarnaSignInEventsMapper.h"
|
|
9
|
+
|
|
10
|
+
@implementation KlarnaSignInEventsMapper
|
|
11
|
+
+(NSString *)mapSignInErrorName:(NSString *)errorName {
|
|
12
|
+
NSDictionary *signInErrorsMap = @{
|
|
13
|
+
@"klarnaInvalidReturnURLError": @"KlarnaSignInInvalidReturnURL",
|
|
14
|
+
@"klarnaSignInAlreadyInProgress": @"KlarnaSignInAlreadyInProgress",
|
|
15
|
+
@"klarnaSignInAuthorizationFailed": @"KlarnaSignInAuthorizationFailed",
|
|
16
|
+
@"klarnaSignInInvalidClientID": @"KlarnaSignInInvalidClientID",
|
|
17
|
+
@"klarnaSignInInvalidMarket": @"KlarnaSignInInvalidMarket",
|
|
18
|
+
@"klarnaSignInInvalidPresentationContext": @"KlarnaSignInInvalidPresentationContext",
|
|
19
|
+
@"klarnaSignInInvalidScope": @"KlarnaSignInInvalidScope",
|
|
20
|
+
@"klarnaSignInMissingTokenizationDelegate": @"KlarnaSignInMissingTokenizationId",
|
|
21
|
+
};
|
|
22
|
+
NSString *mappedError = signInErrorsMap[errorName];
|
|
23
|
+
if (mappedError) {
|
|
24
|
+
return mappedError;
|
|
25
|
+
} else {
|
|
26
|
+
return errorName;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
+(NSString *)mapSignInEventName:(NSString *)eventName {
|
|
31
|
+
NSDictionary *signInEventsMap = @{
|
|
32
|
+
@"klarnaToken": @"KlarnaSignInToken",
|
|
33
|
+
@"klarnaSignInUserCancelled": @"KlarnaSignInUserCancelled"
|
|
34
|
+
};
|
|
35
|
+
NSString *mappedEvent = signInEventsMap[eventName];
|
|
36
|
+
if (mappedEvent) {
|
|
37
|
+
return mappedEvent;
|
|
38
|
+
} else {
|
|
39
|
+
return eventName;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
+(NSString *)mapSignInParamName:(NSString *)paramName {
|
|
44
|
+
NSDictionary *signInParamsMap = @{
|
|
45
|
+
@"klarnaToken": @"KlarnaSignInToken"
|
|
46
|
+
};
|
|
47
|
+
NSString *mappedParam = signInParamsMap[paramName];
|
|
48
|
+
if (mappedParam) {
|
|
49
|
+
return mappedParam;
|
|
50
|
+
} else {
|
|
51
|
+
return paramName;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
@end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//
|
|
2
|
+
// KlarnaSignInSDK.h
|
|
3
|
+
// RNKlarnaMobileSDK
|
|
4
|
+
//
|
|
5
|
+
// Created by Jorge Palacio on 2025-02-20.
|
|
6
|
+
// Copyright © 2025 Facebook. All rights reserved.
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
#import <Foundation/Foundation.h>
|
|
10
|
+
#import <React/RCTBridgeModule.h>
|
|
11
|
+
#import <RNKlarnaMobileSDK/RNKlarnaMobileSDK.h>
|
|
12
|
+
|
|
13
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
14
|
+
|
|
15
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
16
|
+
@interface KlarnaSignInModule: NSObject<NativeKlarnaSignInSpec>
|
|
17
|
+
|
|
18
|
+
#else
|
|
19
|
+
|
|
20
|
+
@interface KlarnaSignInModule: NSObject<RCTBridgeModule>
|
|
21
|
+
|
|
22
|
+
#endif
|
|
23
|
+
|
|
24
|
+
@end
|
|
25
|
+
|
|
26
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
//
|
|
2
|
+
// KlarnaSignInEventsHandler.h
|
|
3
|
+
// react-native-klarna-inapp-sdk
|
|
4
|
+
//
|
|
5
|
+
// Created by Jorge Palacio on 2025-02-26.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#import <Foundation/Foundation.h>
|
|
9
|
+
#import <React/RCTBridgeModule.h>
|
|
10
|
+
|
|
11
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
12
|
+
|
|
13
|
+
@interface KlarnaSignInModuleImp: NSObject
|
|
14
|
+
|
|
15
|
+
- (void)dispose:(NSString *)instanceId
|
|
16
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
17
|
+
rejecter:(RCTPromiseRejectBlock)reject;
|
|
18
|
+
|
|
19
|
+
-(void)initWith:(NSString *)instanceId
|
|
20
|
+
environment: (NSString *)environment
|
|
21
|
+
region: (NSString *)region
|
|
22
|
+
returnUrl: (NSString *) returnUrl
|
|
23
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
24
|
+
rejecter:(RCTPromiseRejectBlock)reject;
|
|
25
|
+
|
|
26
|
+
-(void)signInWith:(NSString *)instanceId
|
|
27
|
+
clientId:(NSString *)clientId
|
|
28
|
+
scope:(NSString *)scope
|
|
29
|
+
market:(NSString *)market
|
|
30
|
+
locale:(NSString *)locale
|
|
31
|
+
tokenizationId:(NSString *)tokenizationId
|
|
32
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
33
|
+
rejecter:(RCTPromiseRejectBlock)reject;
|
|
34
|
+
|
|
35
|
+
@end
|
|
36
|
+
|
|
37
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
//
|
|
2
|
+
// KlarnaSignInEventsHandler.m
|
|
3
|
+
// react-native-klarna-inapp-sdk
|
|
4
|
+
//
|
|
5
|
+
// Created by Jorge Palacio on 2025-02-26.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#import "KlarnaSignInModuleImpl.h"
|
|
9
|
+
#import "../common/RNMobileSDKUtils.h"
|
|
10
|
+
#import <AuthenticationServices/AuthenticationServices.h>
|
|
11
|
+
#import "KlarnaMobileSDK/KlarnaMobileSDK-Swift.h"
|
|
12
|
+
#import <React/RCTLog.h>
|
|
13
|
+
#import "KlarnaSignInData.h"
|
|
14
|
+
#import "KlarnaSignInEventsMapper.h"
|
|
15
|
+
|
|
16
|
+
@interface KlarnaSignInModuleImp()<KlarnaEventHandler, ASWebAuthenticationPresentationContextProviding>
|
|
17
|
+
|
|
18
|
+
@property (nonatomic, strong) NSMutableDictionary<NSString *, KlarnaSignInData *> *signInSDKs;
|
|
19
|
+
|
|
20
|
+
- (KlarnaEnvironment *)environmentFrom: (NSString *)value;
|
|
21
|
+
- (KlarnaRegion *)regionFrom: (NSString *)value;
|
|
22
|
+
- (void)rejectWithInvalidiOSVersionSupported:(RCTPromiseRejectBlock) rejectBlock;
|
|
23
|
+
- (KlarnaSignInData *)getInstanceFromComponent: (id <KlarnaComponent> _Nonnull)component;
|
|
24
|
+
|
|
25
|
+
@end
|
|
26
|
+
|
|
27
|
+
@implementation KlarnaSignInModuleImp
|
|
28
|
+
|
|
29
|
+
- (id)init {
|
|
30
|
+
self = [super init];
|
|
31
|
+
_signInSDKs = [NSMutableDictionary new];
|
|
32
|
+
return self;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
- (KlarnaEnvironment *)environmentFrom: (NSString *)value {
|
|
36
|
+
KlarnaEnvironment *env = KlarnaEnvironment.production;
|
|
37
|
+
if ([value isEqualToString:@"playground"]) {
|
|
38
|
+
env = KlarnaEnvironment.playground;
|
|
39
|
+
}
|
|
40
|
+
if ([value isEqualToString:@"staging"]) {
|
|
41
|
+
env = KlarnaEnvironment.staging;
|
|
42
|
+
}
|
|
43
|
+
if ([value isEqualToString:@"production"]) {
|
|
44
|
+
env = KlarnaEnvironment.production;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return env;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
- (KlarnaRegion *)regionFrom: (NSString *)value {
|
|
51
|
+
KlarnaRegion *reg = KlarnaRegion.eu;
|
|
52
|
+
if ([value isEqualToString:@"eu"]) {
|
|
53
|
+
reg = KlarnaRegion.eu;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if ([value isEqualToString:@"na"]) {
|
|
57
|
+
reg = KlarnaRegion.na;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if ([value isEqualToString:@"oc"]) {
|
|
61
|
+
reg = KlarnaRegion.oc;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return reg;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
- (KlarnaSignInData *)getInstanceFromComponent:(id<KlarnaComponent>)component {
|
|
68
|
+
for (NSString *key in _signInSDKs) {
|
|
69
|
+
KlarnaSignInData *data = _signInSDKs[key];
|
|
70
|
+
if (data.sdkInstance == component) {
|
|
71
|
+
return data;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return nil;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// MARK: - Module public Methods
|
|
78
|
+
|
|
79
|
+
- (void)dispose:(NSString *)instanceId
|
|
80
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
81
|
+
rejecter:(RCTPromiseRejectBlock)reject {
|
|
82
|
+
KlarnaSignInData *signInData = _signInSDKs[instanceId];
|
|
83
|
+
if (signInData != nil) {
|
|
84
|
+
[_signInSDKs removeObjectForKey:instanceId];
|
|
85
|
+
resolve(nil);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
- (void)initWith:(NSString *)instanceId
|
|
90
|
+
environment: (NSString *)environment
|
|
91
|
+
region: (NSString *)region
|
|
92
|
+
returnUrl: (NSString *)returnUrl
|
|
93
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
94
|
+
rejecter:(RCTPromiseRejectBlock)reject {
|
|
95
|
+
KlarnaEnvironment * env = [self environmentFrom: environment];
|
|
96
|
+
KlarnaRegion * reg = [self regionFrom: region];
|
|
97
|
+
NSURL *url = [NSURL URLWithString: returnUrl];
|
|
98
|
+
if (url != nil && url.scheme != nil) {
|
|
99
|
+
if (@available(iOS 13.0, *)) {
|
|
100
|
+
KlarnaSignInSDK *signInInstance = [[KlarnaSignInSDK alloc] initWithEnvironment: env
|
|
101
|
+
region: reg
|
|
102
|
+
returnUrl: url
|
|
103
|
+
eventHandler: self];
|
|
104
|
+
KlarnaSignInData *data = [[KlarnaSignInData alloc] initWith: instanceId sdkInstance: signInInstance];
|
|
105
|
+
[_signInSDKs setObject: data forKey: instanceId];
|
|
106
|
+
resolve(nil);
|
|
107
|
+
} else {
|
|
108
|
+
[self rejectWithInvalidiOSVersionSupported: reject];
|
|
109
|
+
}
|
|
110
|
+
} else {
|
|
111
|
+
[self rejectWithInvalidURL: reject];
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
- (void)signInWith:(NSString *)instanceId
|
|
116
|
+
clientId:(NSString *)clientId
|
|
117
|
+
scope:(NSString *)scope
|
|
118
|
+
market:(NSString *)market
|
|
119
|
+
locale:(NSString *)locale
|
|
120
|
+
tokenizationId:(NSString *)tokenizationId
|
|
121
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
122
|
+
rejecter:(RCTPromiseRejectBlock)reject {
|
|
123
|
+
if (@available(iOS 13.0, *)) {
|
|
124
|
+
KlarnaSignInData *signInData = [_signInSDKs objectForKey: instanceId];
|
|
125
|
+
if (signInData == nil) {
|
|
126
|
+
RCTLog(@"No instance found for the given instanceId");
|
|
127
|
+
reject(@"RNKlarnaSignIn", @"No instance found to initiate signIn, Init function must be called prior to this one.", nil);
|
|
128
|
+
} else {
|
|
129
|
+
signInData.resolver = resolve;
|
|
130
|
+
signInData.rejecter = reject;
|
|
131
|
+
[signInData.sdkInstance signInClientId: clientId
|
|
132
|
+
scope: scope
|
|
133
|
+
market: market
|
|
134
|
+
locale: locale
|
|
135
|
+
tokenizationId: tokenizationId
|
|
136
|
+
presentationContext: self];
|
|
137
|
+
}
|
|
138
|
+
} else {
|
|
139
|
+
[self rejectWithInvalidiOSVersionSupported: reject];
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
- (void)rejectWithInvalidiOSVersionSupported:(RCTPromiseRejectBlock) rejectBlock {
|
|
144
|
+
NSString *msg = @"KlarnaSignIn is supported from iOS version 13.0";
|
|
145
|
+
rejectBlock(@"RNKlarnaSignIn", msg, nil);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
- (void)rejectWithInvalidURL:(RCTPromiseRejectBlock) rejectBlock {
|
|
149
|
+
NSString *msg = @"Invalid or null return URL.";
|
|
150
|
+
NSError *errorEvent = [NSError errorWithDomain:@"com.klarnamobilesdk" code: 0001 userInfo: @{
|
|
151
|
+
@"name": @"KlarnaSignInInvalidReturnUrl",
|
|
152
|
+
@"message": msg,
|
|
153
|
+
@"isFatal": @"true"
|
|
154
|
+
}];
|
|
155
|
+
rejectBlock(@"", msg, errorEvent);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// MARK: - KlarnaEventHandler Methods
|
|
159
|
+
|
|
160
|
+
- (void)klarnaComponent:(id <KlarnaComponent> _Nonnull)klarnaComponent dispatchedEvent:(KlarnaProductEvent * _Nonnull)event {
|
|
161
|
+
KlarnaSignInData *signInData = [self getInstanceFromComponent: klarnaComponent];
|
|
162
|
+
if (signInData == nil) {
|
|
163
|
+
RCTLog(@"No instance found for the given component");
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
if (signInData.resolver == nil) {
|
|
167
|
+
RCTLog(@"Missing 'resolver' callback prop.");
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
NSMutableDictionary<NSString *, id> *resolvedEvent = [NSMutableDictionary dictionaryWithDictionary: @{
|
|
171
|
+
@"action": [KlarnaSignInEventsMapper mapSignInEventName: event.action],
|
|
172
|
+
@"sessionId": event.sessionId,
|
|
173
|
+
}];
|
|
174
|
+
NSMutableDictionary *updatedParams = [NSMutableDictionary new];
|
|
175
|
+
[[event getParams] enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull obj, BOOL * _Nonnull stop) {
|
|
176
|
+
NSString *updatedKey = [KlarnaSignInEventsMapper mapSignInParamName: key];
|
|
177
|
+
[updatedParams setValue: obj forKey: updatedKey];
|
|
178
|
+
}];
|
|
179
|
+
if ([updatedParams count] > 0) {
|
|
180
|
+
[resolvedEvent setValue: updatedParams forKey: @"params"];
|
|
181
|
+
}
|
|
182
|
+
signInData.resolver(resolvedEvent);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
- (void)klarnaComponent:(id <KlarnaComponent> _Nonnull)klarnaComponent encounteredError:(KlarnaError * _Nonnull)error {
|
|
186
|
+
if (!error.isFatal) {
|
|
187
|
+
NSArray *allowedNonFatalErrors = @[@"KlarnaSignInAlreadyInProgress", @"KlarnaSignInAuthorizationFailed"];
|
|
188
|
+
if (![allowedNonFatalErrors containsObject: error.name]) {
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
KlarnaSignInData *signInData = [self getInstanceFromComponent: klarnaComponent];
|
|
193
|
+
if (signInData == nil) {
|
|
194
|
+
RCTLog(@"No instance found for the given component");
|
|
195
|
+
} else {
|
|
196
|
+
if (signInData.rejecter == nil) {
|
|
197
|
+
RCTLog(@"Missing 'rejecter' callback prop.");
|
|
198
|
+
} else {
|
|
199
|
+
NSMutableDictionary<NSString *, id> *infoDict = [NSMutableDictionary dictionaryWithDictionary: @{
|
|
200
|
+
@"name": [KlarnaSignInEventsMapper mapSignInErrorName: error.name],
|
|
201
|
+
@"message": error.message,
|
|
202
|
+
@"isFatal": error.isFatal ? @"true" : @"false",
|
|
203
|
+
@"sessionId": error.sessionId,
|
|
204
|
+
}];
|
|
205
|
+
NSDictionary *params = [error getParams];
|
|
206
|
+
if ([params count] > 0) {
|
|
207
|
+
[infoDict setValue: params forKey: @"params"];
|
|
208
|
+
}
|
|
209
|
+
NSError *errorEvent = [NSError errorWithDomain:@"com.klarnamobilesdk" code: 0001 userInfo: infoDict];
|
|
210
|
+
signInData.rejecter(@"", error.message, errorEvent);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// MARK: - ASWebAuthenticationPresentationContextProviding
|
|
216
|
+
|
|
217
|
+
- (ASPresentationAnchor)presentationAnchorForWebAuthenticationSession:(ASWebAuthenticationSession *)session {
|
|
218
|
+
UIWindowScene *windowScene = (UIWindowScene *)[[[UIApplication sharedApplication].connectedScenes objectsPassingTest:^BOOL(UIScene * _Nonnull obj, BOOL * _Nonnull stop) {
|
|
219
|
+
if(obj.activationState == UISceneActivationStateForegroundActive) {
|
|
220
|
+
*stop = YES; // Stop after finding the first match
|
|
221
|
+
return YES;
|
|
222
|
+
}
|
|
223
|
+
return NO;
|
|
224
|
+
}] allObjects].firstObject;
|
|
225
|
+
|
|
226
|
+
if (windowScene != nil) {
|
|
227
|
+
if (@available(iOS 15.0, *)) {
|
|
228
|
+
return windowScene.keyWindow;
|
|
229
|
+
} else {
|
|
230
|
+
UIWindow *currentTopWindow = windowScene.windows.firstObject;
|
|
231
|
+
if (currentTopWindow != nil) {
|
|
232
|
+
return currentTopWindow;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return [[UIWindow alloc] initWithWindowScene: windowScene];
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// This Shouldn't execute app crashes!!!
|
|
240
|
+
// Windows can't be created in a bg thread. Hence the crash.
|
|
241
|
+
return nil;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
@end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
//
|
|
2
|
+
// KlarnaSignInSDK.m
|
|
3
|
+
// RNKlarnaMobileSDK
|
|
4
|
+
//
|
|
5
|
+
// Created by Jorge Palacio on 2025-02-20.
|
|
6
|
+
// Copyright © 2025 Facebook. All rights reserved.
|
|
7
|
+
//
|
|
8
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
9
|
+
|
|
10
|
+
#import "KlarnaSignInModule.h"
|
|
11
|
+
#import "KlarnaSignInModuleImpl.h"
|
|
12
|
+
|
|
13
|
+
@interface KlarnaSignInModule()
|
|
14
|
+
|
|
15
|
+
@property (strong, nonatomic) KlarnaSignInModuleImp *signInModule;
|
|
16
|
+
|
|
17
|
+
@end
|
|
18
|
+
|
|
19
|
+
@implementation KlarnaSignInModule
|
|
20
|
+
|
|
21
|
+
RCT_EXPORT_MODULE(RNKlarnaSignIn);
|
|
22
|
+
|
|
23
|
+
- (id)init {
|
|
24
|
+
self = [super init];
|
|
25
|
+
_signInModule = [KlarnaSignInModuleImp new];
|
|
26
|
+
return self;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const facebook::react::ObjCTurboModule::InitParams &)params {
|
|
30
|
+
return std::make_shared<facebook::react::NativeKlarnaSignInSpecJSI>(params);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
- (void)dispose:(NSString *)instanceId
|
|
34
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
35
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
36
|
+
[self.signInModule dispose:instanceId
|
|
37
|
+
resolver:resolve
|
|
38
|
+
rejecter:reject];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
- (void)init:(NSString *)instanceId
|
|
42
|
+
environment:(NSString *)environment
|
|
43
|
+
region:(NSString *)region
|
|
44
|
+
returnUrl:(NSString *)returnUrl
|
|
45
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
46
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
47
|
+
[self.signInModule initWith: instanceId
|
|
48
|
+
environment: environment
|
|
49
|
+
region: region
|
|
50
|
+
returnUrl: returnUrl
|
|
51
|
+
resolver: resolve
|
|
52
|
+
rejecter: reject];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
- (void)signIn:(NSString *)instanceId
|
|
56
|
+
clientId:(NSString *)clientId
|
|
57
|
+
scope:(NSString *)scope
|
|
58
|
+
market:(NSString *)market
|
|
59
|
+
locale:(NSString *)locale
|
|
60
|
+
tokenizationId:(NSString *)tokenizationId
|
|
61
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
62
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
63
|
+
[self.signInModule signInWith: instanceId
|
|
64
|
+
clientId: clientId
|
|
65
|
+
scope: scope
|
|
66
|
+
market: market
|
|
67
|
+
locale: locale
|
|
68
|
+
tokenizationId: tokenizationId
|
|
69
|
+
resolver: resolve
|
|
70
|
+
rejecter: reject];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@end
|
|
74
|
+
|
|
75
|
+
#endif
|