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.
Files changed (83) hide show
  1. package/README.md +1 -0
  2. package/android/src/main/java/com/klarna/mobile/sdk/reactnative/KlarnaMobileSDKPackage.java +2 -4
  3. package/android/src/main/java/com/klarna/mobile/sdk/reactnative/checkout/KlarnaCheckoutViewEventSender.java +7 -2
  4. package/android/src/main/java/com/klarna/mobile/sdk/reactnative/checkout/KlarnaCheckoutViewManager.java +51 -18
  5. package/android/src/main/java/com/klarna/mobile/sdk/reactnative/common/WebViewResizeObserver.java +9 -4
  6. package/android/src/main/java/com/klarna/mobile/sdk/reactnative/common/event/KlarnaEventHandlerEventsUtil.java +62 -3
  7. package/android/src/main/java/com/klarna/mobile/sdk/reactnative/common/ui/ResizeObserverWrapperView.java +3 -2
  8. package/android/src/main/java/com/klarna/mobile/sdk/reactnative/common/util/ArgumentsUtil.java +40 -0
  9. package/android/src/main/java/com/klarna/mobile/sdk/reactnative/payments/PaymentViewWrapper.java +1 -1
  10. package/android/src/main/java/com/klarna/mobile/sdk/reactnative/signin/KlarnaSignInData.java +15 -0
  11. package/android/src/main/java/com/klarna/mobile/sdk/reactnative/signin/KlarnaSignInEventsMapper.java +40 -0
  12. package/android/src/main/java/com/klarna/mobile/sdk/reactnative/signin/KlarnaSignInModuleImpl.java +124 -0
  13. package/android/src/newarch/java/com/klarna/mobile/sdk/reactnative/spec/RNKlarnaSignInModuleSpec.java +65 -0
  14. package/android/src/oldarch/java/com/klarna/mobile/sdk/reactnative/spec/RNKlarnaSignInModuleSpec.java +39 -0
  15. package/android/src/test/java/com/klarna/mobile/sdk/reactnative/KlarnaMobileSDKPackageTest.java +5 -4
  16. package/ios/Sources/KlarnaCheckoutViewManager.mm +32 -24
  17. package/ios/Sources/signIn/KlarnaSignInData.h +25 -0
  18. package/ios/Sources/signIn/KlarnaSignInData.mm +21 -0
  19. package/ios/Sources/signIn/KlarnaSignInEventsMapper.h +18 -0
  20. package/ios/Sources/signIn/KlarnaSignInEventsMapper.m +54 -0
  21. package/ios/Sources/signIn/KlarnaSignInModule.h +26 -0
  22. package/ios/Sources/signIn/KlarnaSignInModuleImpl.h +37 -0
  23. package/ios/Sources/signIn/KlarnaSignInModuleImpl.mm +244 -0
  24. package/ios/Sources/signIn/newarch/KlarnaSignInModule.mm +75 -0
  25. package/ios/Sources/signIn/oldarch/KlarnaSignInModule.mm +72 -0
  26. package/ios/Sources/view/KlarnaCheckoutViewWrapper.h +1 -3
  27. package/ios/Sources/view/newarch/KlarnaCheckoutViewWrapper.mm +53 -29
  28. package/ios/Sources/view/oldarch/KlarnaCheckoutViewWrapper.mm +58 -20
  29. package/lib/commonjs/KlarnaCheckoutView.js +16 -3
  30. package/lib/commonjs/KlarnaCheckoutView.js.map +1 -1
  31. package/lib/commonjs/KlarnaSignInSDK.js +80 -0
  32. package/lib/commonjs/KlarnaSignInSDK.js.map +1 -0
  33. package/lib/commonjs/index.js +11 -0
  34. package/lib/commonjs/index.js.map +1 -1
  35. package/lib/commonjs/specs/KlarnaCheckoutViewNativeComponent.js.map +1 -1
  36. package/lib/commonjs/specs/NativeKlarnaSignIn.js +10 -0
  37. package/lib/commonjs/specs/NativeKlarnaSignIn.js.map +1 -0
  38. package/lib/commonjs/types/common/KlarnaEnvironment.js +13 -0
  39. package/lib/commonjs/types/common/KlarnaEnvironment.js.map +1 -0
  40. package/lib/commonjs/types/common/KlarnaRegion.js +14 -0
  41. package/lib/commonjs/types/common/KlarnaRegion.js.map +1 -0
  42. package/lib/module/KlarnaCheckoutView.js +16 -3
  43. package/lib/module/KlarnaCheckoutView.js.map +1 -1
  44. package/lib/module/KlarnaSignInSDK.js +72 -0
  45. package/lib/module/KlarnaSignInSDK.js.map +1 -0
  46. package/lib/module/index.js +1 -0
  47. package/lib/module/index.js.map +1 -1
  48. package/lib/module/specs/KlarnaCheckoutViewNativeComponent.js.map +1 -1
  49. package/lib/module/specs/NativeKlarnaSignIn.js +3 -0
  50. package/lib/module/specs/NativeKlarnaSignIn.js.map +1 -0
  51. package/lib/module/types/common/KlarnaEnvironment.js +6 -0
  52. package/lib/module/types/common/KlarnaEnvironment.js.map +1 -0
  53. package/lib/module/types/common/KlarnaRegion.js +7 -0
  54. package/lib/module/types/common/KlarnaRegion.js.map +1 -0
  55. package/lib/typescript/KlarnaCheckoutView.d.ts +2 -0
  56. package/lib/typescript/KlarnaCheckoutView.d.ts.map +1 -1
  57. package/lib/typescript/KlarnaSignInSDK.d.ts +19 -0
  58. package/lib/typescript/KlarnaSignInSDK.d.ts.map +1 -0
  59. package/lib/typescript/index.d.ts +1 -0
  60. package/lib/typescript/index.d.ts.map +1 -1
  61. package/lib/typescript/specs/KlarnaCheckoutViewNativeComponent.d.ts +1 -0
  62. package/lib/typescript/specs/KlarnaCheckoutViewNativeComponent.d.ts.map +1 -1
  63. package/lib/typescript/specs/NativeKlarnaSignIn.d.ts +10 -0
  64. package/lib/typescript/specs/NativeKlarnaSignIn.d.ts.map +1 -0
  65. package/lib/typescript/types/common/KlarnaEnvironment.d.ts +5 -0
  66. package/lib/typescript/types/common/KlarnaEnvironment.d.ts.map +1 -0
  67. package/lib/typescript/types/common/KlarnaMobileSDKError.d.ts +4 -0
  68. package/lib/typescript/types/common/KlarnaMobileSDKError.d.ts.map +1 -1
  69. package/lib/typescript/types/common/KlarnaProductEvent.d.ts +1 -0
  70. package/lib/typescript/types/common/KlarnaProductEvent.d.ts.map +1 -1
  71. package/lib/typescript/types/common/KlarnaRegion.d.ts +6 -0
  72. package/lib/typescript/types/common/KlarnaRegion.d.ts.map +1 -0
  73. package/package.json +1 -1
  74. package/react-native-klarna-inapp-sdk.podspec +1 -1
  75. package/src/KlarnaCheckoutView.tsx +16 -3
  76. package/src/KlarnaSignInSDK.tsx +122 -0
  77. package/src/index.tsx +1 -0
  78. package/src/specs/KlarnaCheckoutViewNativeComponent.ts +1 -0
  79. package/src/specs/NativeKlarnaSignIn.ts +25 -0
  80. package/src/types/common/KlarnaEnvironment.ts +4 -0
  81. package/src/types/common/KlarnaMobileSDKError.ts +2 -0
  82. package/src/types/common/KlarnaProductEvent.ts +1 -0
  83. package/src/types/common/KlarnaRegion.ts +5 -0
package/README.md CHANGED
@@ -11,6 +11,7 @@ currently has the following components:
11
11
  - `KlarnaPaymentView` to integrate Klarna Payments
12
12
  - `KlarnaStandaloneWebView` to integrate Klarna Standalone WebView
13
13
  - `KlarnaCheckoutView` to integrate Klarna Checkout
14
+ - `KlarnaSignInSDK` to integrate Klarna Sign In
14
15
 
15
16
  This repository also includes a test application that you can use to see how it works.
16
17
 
@@ -1,7 +1,5 @@
1
1
  package com.klarna.mobile.sdk.reactnative;
2
2
 
3
- import android.app.Application;
4
-
5
3
  import androidx.annotation.NonNull;
6
4
 
7
5
  import com.facebook.react.ReactPackage;
@@ -10,9 +8,9 @@ import com.facebook.react.bridge.ReactApplicationContext;
10
8
  import com.facebook.react.uimanager.ViewManager;
11
9
  import com.klarna.mobile.sdk.reactnative.checkout.KlarnaCheckoutViewManager;
12
10
  import com.klarna.mobile.sdk.reactnative.payments.KlarnaPaymentViewManager;
11
+ import com.klarna.mobile.sdk.reactnative.spec.RNKlarnaSignInModuleSpec;
13
12
  import com.klarna.mobile.sdk.reactnative.standalonewebview.KlarnaStandaloneWebViewManager;
14
13
 
15
- import java.util.Collections;
16
14
  import java.util.List;
17
15
 
18
16
  public class KlarnaMobileSDKPackage implements ReactPackage {
@@ -20,7 +18,7 @@ public class KlarnaMobileSDKPackage implements ReactPackage {
20
18
  @NonNull
21
19
  @Override
22
20
  public List<NativeModule> createNativeModules(@NonNull ReactApplicationContext reactContext) {
23
- return Collections.emptyList();
21
+ return List.of(new RNKlarnaSignInModuleSpec(reactContext));
24
22
  }
25
23
 
26
24
  @NonNull
@@ -8,7 +8,6 @@ import com.facebook.react.uimanager.events.EventDispatcher;
8
8
  import com.klarna.mobile.sdk.KlarnaMobileSDKError;
9
9
  import com.klarna.mobile.sdk.api.KlarnaProductEvent;
10
10
  import com.klarna.mobile.sdk.api.checkout.KlarnaCheckoutView;
11
- import com.klarna.mobile.sdk.reactnative.common.event.ComponentEvent;
12
11
  import com.klarna.mobile.sdk.reactnative.common.event.ComponentEventSender;
13
12
  import com.klarna.mobile.sdk.reactnative.common.event.KlarnaEventHandlerEventsUtil;
14
13
  import com.klarna.mobile.sdk.reactnative.common.ui.ResizeObserverWrapperView;
@@ -23,6 +22,7 @@ import java.util.Map;
23
22
  public class KlarnaCheckoutViewEventSender extends ComponentEventSender<ResizeObserverWrapperView<KlarnaCheckoutView>> {
24
23
 
25
24
  private static final String EVENT_NAME_ON_RESIZED = "onResized";
25
+ private static final String EVENT_NAME_ON_CHECKOUT_VIEW_READY = "onCheckoutViewReady";
26
26
 
27
27
  KlarnaCheckoutViewEventSender(@NonNull final Map<WeakReference<ResizeObserverWrapperView<KlarnaCheckoutView>>, EventDispatcher> viewToDispatcher) {
28
28
  super(viewToDispatcher);
@@ -33,7 +33,8 @@ public class KlarnaCheckoutViewEventSender extends ComponentEventSender<ResizeOb
33
33
  return Arrays.asList(
34
34
  KlarnaEventHandlerEventsUtil.EVENT_NAME_ON_EVENT,
35
35
  KlarnaEventHandlerEventsUtil.EVENT_NAME_ON_ERROR,
36
- EVENT_NAME_ON_RESIZED
36
+ EVENT_NAME_ON_RESIZED,
37
+ EVENT_NAME_ON_CHECKOUT_VIEW_READY
37
38
  );
38
39
  }
39
40
 
@@ -53,4 +54,8 @@ public class KlarnaCheckoutViewEventSender extends ComponentEventSender<ResizeOb
53
54
  );
54
55
  postEventForView(view, EVENT_NAME_ON_RESIZED, params);
55
56
  }
57
+
58
+ public void sendOnKlarnaCheckoutViewReadyEvent(@Nullable KlarnaCheckoutView view) {
59
+ postEventForView(view, EVENT_NAME_ON_CHECKOUT_VIEW_READY, null);
60
+ }
56
61
  }
@@ -1,6 +1,8 @@
1
1
  package com.klarna.mobile.sdk.reactnative.checkout;
2
2
 
3
3
  import android.os.Handler;
4
+ import android.os.Looper;
5
+ import android.view.View;
4
6
 
5
7
  import androidx.annotation.NonNull;
6
8
  import androidx.annotation.Nullable;
@@ -12,7 +14,6 @@ import com.facebook.react.uimanager.ThemedReactContext;
12
14
  import com.facebook.react.uimanager.UIManagerHelper;
13
15
  import com.facebook.react.uimanager.annotations.ReactProp;
14
16
  import com.facebook.react.uimanager.events.EventDispatcher;
15
- import com.klarna.mobile.sdk.api.KlarnaLoggingLevel;
16
17
  import com.klarna.mobile.sdk.api.checkout.KlarnaCheckoutView;
17
18
  import com.klarna.mobile.sdk.reactnative.common.WebViewResizeObserver;
18
19
  import com.klarna.mobile.sdk.reactnative.common.ui.ResizeObserverWrapperView;
@@ -41,13 +42,15 @@ public class KlarnaCheckoutViewManager extends RNKlarnaCheckoutViewSpec<ResizeOb
41
42
 
42
43
  private final KlarnaCheckoutViewEventSender eventSender;
43
44
  private final KlarnaCheckoutViewEventHandler eventHandler;
45
+ private Runnable javascriptInterfaceInjectionRunnable;
46
+ private final Handler handler = new Handler(Looper.getMainLooper());
44
47
 
45
48
  public KlarnaCheckoutViewManager(ReactApplicationContext reactApplicationContext) {
46
49
  super();
47
- this.viewToDispatcher = new HashMap<>();
48
- this.reactAppContext = reactApplicationContext;
49
- this.eventSender = new KlarnaCheckoutViewEventSender(viewToDispatcher);
50
- this.eventHandler = new KlarnaCheckoutViewEventHandler(eventSender);
50
+ viewToDispatcher = new HashMap<>();
51
+ reactAppContext = reactApplicationContext;
52
+ eventSender = new KlarnaCheckoutViewEventSender(viewToDispatcher);
53
+ eventHandler = new KlarnaCheckoutViewEventHandler(eventSender);
51
54
  }
52
55
 
53
56
  @NonNull
@@ -60,7 +63,6 @@ public class KlarnaCheckoutViewManager extends RNKlarnaCheckoutViewSpec<ResizeOb
60
63
  @Override
61
64
  protected ResizeObserverWrapperView<KlarnaCheckoutView> createViewInstance(@NonNull ThemedReactContext themedReactContext) {
62
65
  KlarnaCheckoutView klarnaCheckoutView = new KlarnaCheckoutView(reactAppContext.getCurrentActivity(), null, 0, eventHandler);
63
- klarnaCheckoutView.setLoggingLevel(KlarnaLoggingLevel.Verbose);
64
66
  ResizeObserverWrapperView<KlarnaCheckoutView> view = new ResizeObserverWrapperView<>(reactAppContext, null, klarnaCheckoutView);
65
67
 
66
68
  // Each view has its own event dispatcher.
@@ -68,15 +70,24 @@ public class KlarnaCheckoutViewManager extends RNKlarnaCheckoutViewSpec<ResizeOb
68
70
  viewToDispatcher.put(new WeakReference<>(view), eventDispatcher);
69
71
 
70
72
  view.initiateWebViewResizeObserver(WebViewResizeObserver.TargetElement.CHECKOUT_CONTAINER, (resizeObserverWrapperView, newHeight) -> {
71
- if (resizeObserverWrapperView == null) {
72
- return;
73
- }
74
- if (eventDispatcher == null) {
73
+ if (resizeObserverWrapperView == null || eventDispatcher == null) {
75
74
  return;
76
75
  }
77
76
  eventSender.sendOnResizedEvent(resizeObserverWrapperView.getView(), newHeight);
78
77
  });
79
- view.addInterfaceToWebView();
78
+ view.addJavascriptInterfaceToWebView();
79
+
80
+ view.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
81
+ @Override
82
+ public void onViewAttachedToWindow(@NonNull View v) {
83
+ eventSender.sendOnKlarnaCheckoutViewReadyEvent(view.getView());
84
+ v.removeOnAttachStateChangeListener(this);
85
+ }
86
+
87
+ @Override
88
+ public void onViewDetachedFromWindow(@NonNull View v) {
89
+ }
90
+ });
80
91
 
81
92
  return view;
82
93
  }
@@ -128,20 +139,42 @@ public class KlarnaCheckoutViewManager extends RNKlarnaCheckoutViewSpec<ResizeOb
128
139
 
129
140
  @Override
130
141
  public void setSnippet(ResizeObserverWrapperView<KlarnaCheckoutView> view, String snippet) {
131
- view.getView().setSnippet(snippet);
132
- view.addInterfaceToWebView();
133
- // Delay the injection of the resize observer to ensure the web view is ready
134
- final Handler handler = new Handler();
135
- handler.postDelayed(view::injectListenerToWebView, 500);
142
+ if (view == null) {
143
+ return;
144
+ }
145
+
146
+ KlarnaCheckoutView klarnaCheckoutView = view.getView();
147
+ if (klarnaCheckoutView == null) {
148
+ return;
149
+ }
150
+
151
+ if (snippet == null || snippet.isEmpty()) {
152
+ return;
153
+ }
154
+
155
+ klarnaCheckoutView.setSnippet(snippet);
156
+ view.addJavascriptInterfaceToWebView();
157
+
158
+ if (javascriptInterfaceInjectionRunnable != null) {
159
+ handler.removeCallbacks(javascriptInterfaceInjectionRunnable);
160
+ }
161
+ javascriptInterfaceInjectionRunnable = view::injectListenerToWebView;
162
+ handler.postDelayed(javascriptInterfaceInjectionRunnable, 500);
136
163
  }
137
164
 
138
165
  @Override
139
166
  public void suspend(ResizeObserverWrapperView<KlarnaCheckoutView> view) {
140
- view.getView().suspend();
167
+ KlarnaCheckoutView klarnaCheckoutView = view.getView();
168
+ if (klarnaCheckoutView != null) {
169
+ klarnaCheckoutView.suspend();
170
+ }
141
171
  }
142
172
 
143
173
  @Override
144
174
  public void resume(ResizeObserverWrapperView<KlarnaCheckoutView> view) {
145
- view.getView().resume();
175
+ KlarnaCheckoutView klarnaCheckoutView = view.getView();
176
+ if (klarnaCheckoutView != null) {
177
+ klarnaCheckoutView.resume();
178
+ }
146
179
  }
147
180
  }
@@ -29,8 +29,10 @@ public class WebViewResizeObserver {
29
29
  this.targetElement = targetElement;
30
30
  }
31
31
 
32
- public void addInterface(WebView webView) {
33
- webView.addJavascriptInterface(this, JS_INTERFACE_NAME);
32
+ public void addJavascriptInterface(WebView webView) {
33
+ if (webView != null) {
34
+ webView.addJavascriptInterface(this, JS_INTERFACE_NAME);
35
+ }
34
36
  }
35
37
 
36
38
  public void injectListener(WebView webView) {
@@ -62,12 +64,12 @@ public class WebViewResizeObserver {
62
64
  }
63
65
 
64
66
  private void injectScript(WebView webView, String script) {
65
- String tryCatchScript = "try {\n" +
67
+ String scriptWrappedInTryCatch = "try {\n" +
66
68
  " " + script + "\n" +
67
69
  "} catch (error) {\n" +
68
70
  " console.error(\"inject failed\")\n" +
69
71
  "}";
70
- evaluateJSCompat(webView, tryCatchScript);
72
+ evaluateJSCompat(webView, scriptWrappedInTryCatch);
71
73
  }
72
74
 
73
75
  /**
@@ -77,6 +79,9 @@ public class WebViewResizeObserver {
77
79
  * @param script The script to be evaluated
78
80
  */
79
81
  private void evaluateJSCompat(WebView webView, String script) {
82
+ if (webView == null) {
83
+ return;
84
+ }
80
85
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
81
86
  webView.evaluateJavascript(script, null);
82
87
  } else {
@@ -5,25 +5,33 @@ import android.view.View;
5
5
  import androidx.annotation.NonNull;
6
6
  import androidx.annotation.Nullable;
7
7
 
8
+ import com.facebook.react.bridge.Promise;
8
9
  import com.facebook.react.bridge.ReadableMap;
9
10
  import com.facebook.react.bridge.WritableMap;
11
+ import com.google.gson.reflect.TypeToken;
10
12
  import com.klarna.mobile.sdk.KlarnaMobileSDKError;
11
13
  import com.klarna.mobile.sdk.api.KlarnaProductEvent;
14
+ import com.klarna.mobile.sdk.api.signin.model.KlarnaSignInToken;
12
15
  import com.klarna.mobile.sdk.reactnative.common.util.ArgumentsUtil;
13
16
  import com.klarna.mobile.sdk.reactnative.common.util.ParserUtil;
17
+ import com.klarna.mobile.sdk.reactnative.signin.KlarnaSignInData;
18
+ import com.klarna.mobile.sdk.reactnative.signin.KlarnaSignInEventsMapper;
14
19
 
20
+ import java.lang.reflect.Type;
15
21
  import java.util.HashMap;
22
+ import java.util.Map;
16
23
 
17
24
  public class KlarnaEventHandlerEventsUtil {
18
25
 
19
26
  public static final String EVENT_NAME_ON_EVENT = "onEvent";
20
27
  public static final String EVENT_NAME_ON_ERROR = "onError";
28
+ public static final String PARAM_NAME_IS_FATAL = "isFatal";
29
+ public static final String PARAM_NAME_MESSAGE = "message";
30
+ public static final String PARAM_NAME_NAME = "name";
31
+ public static final String PARAM_NAME_SESSION_ID = "sessionId";
21
32
 
22
33
  private static final String PARAM_NAME_ACTION = "action";
23
34
  private static final String PARAM_NAME_PARAMS = "params";
24
- private static final String PARAM_NAME_IS_FATAL = "isFatal";
25
- private static final String PARAM_NAME_MESSAGE = "message";
26
- private static final String PARAM_NAME_NAME = "name";
27
35
  private static final String PARAM_NAME_PRODUCT_EVENT = "productEvent";
28
36
 
29
37
  public static <T extends View> void sendKlarnaProductEvent(@NonNull ComponentEventSender<T> componentEventSender, @Nullable View view, @NonNull KlarnaProductEvent klarnaProductEvent) {
@@ -50,4 +58,55 @@ public class KlarnaEventHandlerEventsUtil {
50
58
  }});
51
59
  componentEventSender.postEventForView(view, EVENT_NAME_ON_EVENT, params);
52
60
  }
61
+
62
+ public static void sendKlarnaProductEvent(@NonNull KlarnaSignInData signInData, @NonNull KlarnaProductEvent klarnaProductEvent) {
63
+ if (klarnaProductEvent.getAction().equals("KlarnaSignInUserAuth")) {
64
+ return;
65
+ }
66
+ Map<String, Object> updatedParams = new HashMap<>();
67
+ for(Map.Entry<String, Object> entry : klarnaProductEvent.getParams().entrySet()) {
68
+ String updatedKey = KlarnaSignInEventsMapper.mapSignInParamName(entry.getKey());
69
+ updatedParams.put(updatedKey, entry.getValue());
70
+ }
71
+ String eventName = KlarnaSignInEventsMapper.mapSignInEventName(klarnaProductEvent.getAction());
72
+ ReadableMap eventMap = ArgumentsUtil.createMap(new HashMap<String, Object>() {{
73
+ put(PARAM_NAME_ACTION, eventName);
74
+ put(PARAM_NAME_SESSION_ID, klarnaProductEvent.getSessionId());
75
+ if (!updatedParams.isEmpty()) {
76
+ put(PARAM_NAME_PARAMS, ArgumentsUtil.createMapUsingJSONString(updatedParams));
77
+ }
78
+ }});
79
+
80
+ if (signInData.promise != null) {
81
+ signInData.promise.resolve(eventMap);
82
+ }
83
+ }
84
+
85
+ public static void sendKlarnaMobileSDKError(@NonNull KlarnaSignInData signInData, @NonNull KlarnaMobileSDKError klarnaMobileSDKError) {
86
+ String errorName = KlarnaSignInEventsMapper.mapSignInErrorName(klarnaMobileSDKError.getName());
87
+ WritableMap eventMap = ArgumentsUtil.createMap(new HashMap<String, Object>() {{
88
+ put(PARAM_NAME_NAME, errorName);
89
+ put(PARAM_NAME_MESSAGE, klarnaMobileSDKError.getMessage());
90
+ put(PARAM_NAME_IS_FATAL, klarnaMobileSDKError.isFatal());
91
+ put(PARAM_NAME_SESSION_ID, klarnaMobileSDKError.getSessionId());
92
+ if (!klarnaMobileSDKError.getParams().isEmpty()) {
93
+ put(PARAM_NAME_PARAMS, ArgumentsUtil.createMapUsingJSONString(klarnaMobileSDKError.getParams()));
94
+ }
95
+ }});
96
+ if (signInData.promise != null) {
97
+ signInData.promise.reject(EVENT_NAME_ON_ERROR, eventMap);
98
+ }
99
+ }
100
+
101
+ public static ReadableMap createMapFrom(HashMap<String, Object> map) {
102
+ WritableMap writableMap = ArgumentsUtil.createMap(new HashMap<String, Object>());
103
+ for (Map.Entry<String, Object> entry : map.entrySet()) {
104
+ if (entry.getValue() instanceof String) {
105
+ writableMap.putString(entry.getKey(), (String) entry.getValue());
106
+ } else if (entry.getValue() instanceof Object) {
107
+
108
+ }
109
+ }
110
+ return ArgumentsUtil.createMap(map);
111
+ }
53
112
  }
@@ -49,10 +49,10 @@ public class ResizeObserverWrapperView<T extends ViewGroup> extends WrapperView<
49
49
  this.webViewResizeObserver = new WebViewResizeObserver(webViewResizeObserverCallback, targetElement);
50
50
  }
51
51
 
52
- public void addInterfaceToWebView() {
52
+ public void addJavascriptInterfaceToWebView() {
53
53
  WebView webView = findWebView(getView());
54
54
  if (webView != null && webViewResizeObserver != null) {
55
- webViewResizeObserver.addInterface(webView);
55
+ webViewResizeObserver.addJavascriptInterface(webView);
56
56
  }
57
57
  }
58
58
 
@@ -63,6 +63,7 @@ public class ResizeObserverWrapperView<T extends ViewGroup> extends WrapperView<
63
63
  }
64
64
  }
65
65
 
66
+ @Nullable
66
67
  private WebView findWebView(T view) {
67
68
  if (view == null) {
68
69
  return null;
@@ -6,9 +6,15 @@ import com.facebook.react.bridge.ReadableMap;
6
6
  import com.facebook.react.bridge.WritableArray;
7
7
  import com.facebook.react.bridge.WritableMap;
8
8
 
9
+ import org.json.JSONException;
10
+ import org.json.JSONObject;
11
+
12
+ import java.util.Iterator;
9
13
  import java.util.List;
10
14
  import java.util.Map;
11
15
 
16
+ import okhttp3.internal.Util;
17
+
12
18
  public class ArgumentsUtil {
13
19
 
14
20
  public static WritableMap createMap(Map<String, Object> sourceMap) {
@@ -59,4 +65,38 @@ public class ArgumentsUtil {
59
65
  }
60
66
  return array;
61
67
  }
68
+
69
+ public static WritableMap createMapUsingJSONString(Map<String, Object> sourceMap) {
70
+ String jsonString = ParserUtil.toJson(sourceMap);
71
+ WritableMap map = Arguments.createMap();
72
+ try {
73
+ JSONObject jsonObject = new JSONObject(jsonString);
74
+ map = jsonToWritableMap(jsonObject);
75
+ } catch (JSONException e) {
76
+ System.out.println("JSONException occurred: " + e.getMessage());
77
+ }
78
+ return map;
79
+ }
80
+
81
+ private static WritableMap jsonToWritableMap(JSONObject jsonObject) throws JSONException {
82
+ WritableMap map = Arguments.createMap();
83
+ for (Iterator<String> it = jsonObject.keys(); it.hasNext(); ) {
84
+ String key = it.next();
85
+ Object value = jsonObject.get(key);
86
+ if (value instanceof JSONObject) {
87
+ map.putMap(key, jsonToWritableMap((JSONObject) value));
88
+ } else if (value instanceof Boolean) {
89
+ map.putBoolean(key, (Boolean) value);
90
+ } else if (value instanceof Integer) {
91
+ map.putInt(key, (Integer) value);
92
+ } else if (value instanceof Double) {
93
+ map.putDouble(key, (Double) value);
94
+ } else if (value instanceof String) {
95
+ map.putString(key, (String) value);
96
+ } else {
97
+ map.putNull(key);
98
+ }
99
+ }
100
+ return map;
101
+ }
62
102
  }
@@ -36,7 +36,7 @@ public class PaymentViewWrapper extends LinearLayout implements WebViewResizeObs
36
36
  resizeObserver = new WebViewResizeObserver(this, WebViewResizeObserver.TargetElement.PAYMENT_CONTAINER);
37
37
  WebView webView = getPaymentViewWebView();
38
38
  if (webView != null) {
39
- resizeObserver.addInterface(webView);
39
+ resizeObserver.addJavascriptInterface(webView);
40
40
  }
41
41
  }
42
42
 
@@ -0,0 +1,15 @@
1
+ package com.klarna.mobile.sdk.reactnative.signin;
2
+
3
+ import com.facebook.react.bridge.Promise;
4
+ import com.klarna.mobile.sdk.api.signin.KlarnaSignInSDK;
5
+
6
+ public class KlarnaSignInData {
7
+ String instanceId;
8
+ public Promise promise;
9
+ KlarnaSignInSDK sdkInstance;
10
+
11
+ public KlarnaSignInData(String instanceId, KlarnaSignInSDK sdkInstance) {
12
+ this.instanceId = instanceId;
13
+ this.sdkInstance = sdkInstance;
14
+ }
15
+ }
@@ -0,0 +1,40 @@
1
+ package com.klarna.mobile.sdk.reactnative.signin;
2
+
3
+ import java.util.Collections;
4
+ import java.util.HashMap;
5
+ import java.util.Map;
6
+
7
+ public class KlarnaSignInEventsMapper {
8
+ public static String mapSignInErrorName(String key) {
9
+ Map<String, String> errorsMap = new HashMap<>();
10
+ errorsMap.put("InvalidReturnUrlError", "KlarnaSignInInvalidReturnURL");
11
+ errorsMap.put("KlarnaSignInErrorInvalidCustomTabsReturnUrl", "KlarnaSignInInvalidReturnURL");
12
+ errorsMap.put("KlarnaSignInErrorAlreadyInProgress", "KlarnaSignInAlreadyInProgress");
13
+ errorsMap.put("KlarnaSignInErrorSignInFailed", "KlarnaSignInAuthorizationFailed");
14
+ errorsMap.put("KlarnaSignInErrorInvalidClientID", "KlarnaSignInInvalidClientID");
15
+ errorsMap.put("KlarnaSignInErrorInvalidMarket", "KlarnaSignInInvalidMarket");
16
+ errorsMap.put("klarnaSignInInvalidPresentationContext", "KlarnaSignInInvalidPresentationContext");
17
+ errorsMap.put("KlarnaSignInErrorInvalidScope", "KlarnaSignInInvalidScope");
18
+ errorsMap.put("KlarnaSignInErrorMissingTokenizationCallback", "KlarnaSignInMissingTokenizationId");
19
+ if (errorsMap.get(key) == null) {
20
+ return key;
21
+ }
22
+ return errorsMap.get(key);
23
+ }
24
+
25
+ public static String mapSignInEventName(String key) {
26
+ Map<String, String> eventsMap = new HashMap<>();
27
+ eventsMap.put("KlarnaSignInToken", "KlarnaSignInToken");
28
+ eventsMap.put("KlarnaSignInUserCancelled", "KlarnaSignInUserCancelled");
29
+ if (eventsMap.get(key) == null) {
30
+ return key;
31
+ }
32
+ return eventsMap.get(key);
33
+ }
34
+
35
+ public static String mapSignInParamName(String key) {
36
+ Map<String, String> paramsMap = new HashMap<>();
37
+ paramsMap.put("KlarnaSignInToken", "KlarnaSignInToken");
38
+ return paramsMap.get(key);
39
+ }
40
+ }
@@ -0,0 +1,124 @@
1
+ package com.klarna.mobile.sdk.reactnative.signin;
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.ReadableMap;
8
+ import com.klarna.mobile.sdk.KlarnaMobileSDKError;
9
+ import com.klarna.mobile.sdk.api.KlarnaEnvironment;
10
+ import com.klarna.mobile.sdk.api.KlarnaEventHandler;
11
+ import com.klarna.mobile.sdk.api.KlarnaProductEvent;
12
+ import com.klarna.mobile.sdk.api.KlarnaRegion;
13
+ import com.klarna.mobile.sdk.api.component.KlarnaComponent;
14
+ import com.klarna.mobile.sdk.api.signin.KlarnaSignInError;
15
+ import com.klarna.mobile.sdk.api.signin.KlarnaSignInEvent;
16
+ import com.klarna.mobile.sdk.api.signin.KlarnaSignInSDK;
17
+ import com.klarna.mobile.sdk.reactnative.common.event.KlarnaEventHandlerEventsUtil;
18
+ import com.klarna.mobile.sdk.reactnative.common.util.ArgumentsUtil;
19
+
20
+ import java.util.ArrayList;
21
+ import java.util.HashMap;
22
+ import java.util.Map;
23
+
24
+ public class KlarnaSignInModuleImpl implements KlarnaEventHandler {
25
+
26
+ public static final String NAME = "RNKlarnaSignIn";
27
+
28
+ public static final String SIGN_IN_SDK_NOT_INITIALIZED = "SIGN_IN_SDK_NOT_INITIALIZED";
29
+
30
+ private final ReactApplicationContext reactAppContext;
31
+ private final HashMap<String, KlarnaSignInData> signInSDKMap;
32
+
33
+ public KlarnaSignInModuleImpl(ReactApplicationContext reactAppContext) {
34
+ this.reactAppContext = reactAppContext;
35
+ this.signInSDKMap = new HashMap<String, KlarnaSignInData>();
36
+ }
37
+
38
+ /* Module private methods */
39
+
40
+ private KlarnaEnvironment environmentFrom(@NonNull String value) {
41
+ return switch (value) {
42
+ case "playground" -> KlarnaEnvironment.PLAYGROUND;
43
+ case "staging" -> KlarnaEnvironment.STAGING;
44
+ default -> KlarnaEnvironment.PRODUCTION;
45
+ };
46
+
47
+ }
48
+
49
+ private KlarnaRegion regionFrom(@NonNull String value) {
50
+ return switch (value) {
51
+ case "na" -> KlarnaRegion.NA;
52
+ case "oc" -> KlarnaRegion.OC;
53
+ default -> KlarnaRegion.EU;
54
+ };
55
+
56
+ }
57
+
58
+ private KlarnaSignInData getInstanceData(KlarnaComponent component) {
59
+ for (Map.Entry<String, KlarnaSignInData> entry : signInSDKMap.entrySet()) {
60
+ KlarnaSignInData data = entry.getValue();
61
+ if (data.sdkInstance == component) {
62
+ return data;
63
+ }
64
+ }
65
+ return null;
66
+ }
67
+
68
+ /* Module public methods */
69
+ public void init(String instanceId, String environment, String region, String returnUrl, Promise promise) {
70
+ KlarnaEnvironment env = environmentFrom(environment);
71
+ KlarnaRegion reg = regionFrom(region);
72
+ reactAppContext.runOnUiQueueThread(() -> {
73
+ KlarnaSignInSDK signInInstance = new KlarnaSignInSDK(reactAppContext.getCurrentActivity(), returnUrl, this, env, reg);
74
+ KlarnaSignInData signInData = new KlarnaSignInData(instanceId, signInInstance);
75
+ signInSDKMap.put(instanceId, signInData);
76
+ promise.resolve(null);
77
+ });
78
+ }
79
+
80
+ public void signIn(String instanceId, String clientId, String scope, String market, String locale, String tokenizationId, Promise promise) {
81
+ KlarnaSignInData signInData = signInSDKMap.get(instanceId);
82
+ if (signInData != null) {
83
+ signInData.promise = promise;
84
+ signInData.sdkInstance.signIn(clientId, scope, market, locale, tokenizationId);
85
+ } else {
86
+ promise.reject(SIGN_IN_SDK_NOT_INITIALIZED, "Sign in SDK not initialized");
87
+ }
88
+ }
89
+
90
+ public void dispose(String instanceId, Promise promise) {
91
+ KlarnaSignInData signInData = signInSDKMap.get(instanceId);
92
+ if (signInData != null) {
93
+ signInSDKMap.remove(instanceId);
94
+ promise.resolve(null);
95
+ }
96
+ }
97
+
98
+ /* KlarnaEventHandler methods */
99
+
100
+ @Override
101
+ public void onError(@NonNull KlarnaComponent klarnaComponent, @NonNull KlarnaMobileSDKError klarnaMobileSDKError) {
102
+ ArrayList<String> allowedNonFatalErrors = new ArrayList<>();
103
+ allowedNonFatalErrors.add(KlarnaSignInError.SignInFailed);
104
+ allowedNonFatalErrors.add(KlarnaSignInError.AlreadyInProgress);
105
+ if (klarnaMobileSDKError.isFatal() || !allowedNonFatalErrors.contains(klarnaMobileSDKError.getName())) {
106
+ KlarnaSignInData data = getInstanceData(klarnaComponent);
107
+ if (data != null) {
108
+ if (data.promise != null) {
109
+ KlarnaEventHandlerEventsUtil.sendKlarnaMobileSDKError(data, klarnaMobileSDKError);
110
+ }
111
+ }
112
+ }
113
+ }
114
+
115
+ @Override
116
+ public void onEvent(@NonNull KlarnaComponent klarnaComponent, @NonNull KlarnaProductEvent klarnaProductEvent) {
117
+ KlarnaSignInData data = getInstanceData(klarnaComponent);
118
+ if (data != null) {
119
+ if (data.promise != null) {
120
+ KlarnaEventHandlerEventsUtil.sendKlarnaProductEvent(data, klarnaProductEvent);
121
+ }
122
+ }
123
+ }
124
+ }
@@ -0,0 +1,65 @@
1
+ package com.klarna.mobile.sdk.reactnative.spec;
2
+
3
+ import androidx.annotation.Nullable;
4
+
5
+ import com.facebook.react.bridge.NativeModule;
6
+ import com.facebook.react.bridge.Promise;
7
+ import com.facebook.react.bridge.ReactApplicationContext;
8
+ import com.facebook.react.module.model.ReactModuleInfo;
9
+ import com.facebook.react.module.model.ReactModuleInfoProvider;
10
+ import com.klarna.mobile.sdk.reactnative.NativeKlarnaSignInSpec;
11
+ import com.klarna.mobile.sdk.reactnative.signin.KlarnaSignInModuleImpl;
12
+
13
+ import java.util.HashMap;
14
+ import java.util.Map;
15
+
16
+ public class RNKlarnaSignInModuleSpec extends NativeKlarnaSignInSpec {
17
+
18
+ private final KlarnaSignInModuleImpl module;
19
+
20
+ public RNKlarnaSignInModuleSpec(ReactApplicationContext reactContext) {
21
+ super(reactContext);
22
+ this.module = new KlarnaSignInModuleImpl(reactContext);
23
+ }
24
+
25
+ @Nullable
26
+ public NativeModule getModule(String name, ReactApplicationContext reactContext) {
27
+ if (name.equals(RNKlarnaSignInModuleSpec.NAME)) {
28
+ return new RNKlarnaSignInModuleSpec(reactContext);
29
+ } else {
30
+ return null;
31
+ }
32
+ }
33
+
34
+ public ReactModuleInfoProvider getReactModuleInfoProvider() {
35
+ return () -> {
36
+ final Map<String, ReactModuleInfo> moduleInfos = new HashMap<>();
37
+ moduleInfos.put(
38
+ RNKlarnaSignInModuleSpec.NAME,
39
+ new ReactModuleInfo(
40
+ RNKlarnaSignInModuleSpec.NAME,
41
+ RNKlarnaSignInModuleSpec.NAME,
42
+ false, // canOverrideExistingModule
43
+ false, // needsEagerInit
44
+ false, // isCxxModule
45
+ true // isTurboModule
46
+ ));
47
+ return moduleInfos;
48
+ };
49
+ }
50
+
51
+ @Override
52
+ public void init(String instanceId, String environment, String region, String returnUrl, Promise promise) {
53
+ module.init(instanceId, environment, region, returnUrl, promise);
54
+ }
55
+
56
+ @Override
57
+ public void dispose(String instanceId, Promise promise) {
58
+ module.dispose(instanceId, promise);
59
+ }
60
+
61
+ @Override
62
+ public void signIn(String instanceId, String clientId, String scope, String market, String locale, String tokenizationId, Promise promise) {
63
+ module.signIn(instanceId, clientId, scope, market, locale, tokenizationId, promise);
64
+ }
65
+ }