react-native-klarna-inapp-sdk 2.1.13 → 2.2.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 (104) hide show
  1. package/README.md +100 -270
  2. package/android/build.gradle +84 -106
  3. package/android/gradle.properties +7 -0
  4. package/android/src/main/AndroidManifest.xml +2 -1
  5. package/android/src/main/AndroidManifestNew.xml +4 -0
  6. package/android/src/main/java/com/klarna/mobile/sdk/reactnative/KlarnaMobileSDKPackage.java +33 -0
  7. package/android/src/main/java/com/klarna/mobile/sdk/reactnative/common/ArgumentsUtil.java +62 -0
  8. package/android/src/main/java/com/klarna/mobile/sdk/reactnative/common/WebViewResizeObserver.java +100 -0
  9. package/android/src/main/java/com/klarna/{inapp/sdk → mobile/sdk/reactnative/payments}/KlarnaPaymentEvent.java +9 -19
  10. package/android/src/main/java/com/klarna/mobile/sdk/reactnative/payments/KlarnaPaymentViewManager.java +343 -0
  11. package/android/src/main/java/com/klarna/mobile/sdk/reactnative/payments/PaymentViewWrapper.java +78 -0
  12. package/android/src/main/java/com/klarna/mobile/sdk/reactnative/standalonewebview/KlarnaStandaloneWebViewEvent.java +67 -0
  13. package/android/src/main/java/com/klarna/mobile/sdk/reactnative/standalonewebview/KlarnaStandaloneWebViewEventSender.java +139 -0
  14. package/android/src/main/java/com/klarna/mobile/sdk/reactnative/standalonewebview/KlarnaStandaloneWebViewManager.java +205 -0
  15. package/android/src/newarch/java/com/klarna/mobile/sdk/reactnative/spec/RNKlarnaPaymentViewSpec.java +32 -0
  16. package/android/src/newarch/java/com/klarna/mobile/sdk/reactnative/spec/RNKlarnaStandaloneWebViewSpec.java +33 -0
  17. package/android/src/oldarch/java/com/klarna/mobile/sdk/reactnative/spec/RNKlarnaPaymentViewSpec.java +25 -0
  18. package/android/src/oldarch/java/com/klarna/mobile/sdk/reactnative/spec/RNKlarnaStandaloneWebViewSpec.java +19 -0
  19. package/android/src/test/java/com/klarna/{inapp/sdk/KlarnaPaymentViewPackageTest.java → mobile/sdk/reactnative/KlarnaMobileSDKPackageTest.java} +9 -4
  20. package/android/src/test/java/com/klarna/{inapp/sdk → mobile/sdk/reactnative/payments}/KlarnaPaymentEventTest.java +17 -20
  21. package/android/src/test/java/com/klarna/{inapp/sdk → mobile/sdk/reactnative/payments}/KlarnaPaymentViewManagerTest.java +62 -36
  22. package/ios/{KlarnaInAppSDK.xcodeproj → RNKlarnaMobileSDK.xcodeproj}/project.pbxproj +147 -87
  23. package/ios/{KlarnaInAppSDK.xcodeproj/xcshareddata/xcschemes/KlarnaInAppSDK.xcscheme → RNKlarnaMobileSDK.xcodeproj/xcshareddata/xcschemes/RNKlarnaMobileSDK.xcscheme} +9 -9
  24. package/ios/{KlarnaInAppSDK.xcodeproj/xcshareddata/xcschemes/KlarnaInAppSDKTests.xcscheme → RNKlarnaMobileSDK.xcodeproj/xcshareddata/xcschemes/RNKlarnaMobileSDKTests.xcscheme} +3 -3
  25. package/ios/Sources/KlarnaPaymentViewManager.h +5 -0
  26. package/ios/Sources/{KlarnaPaymentView.m → KlarnaPaymentViewManager.mm} +10 -15
  27. package/ios/Sources/KlarnaStandaloneWebViewManager.h +5 -0
  28. package/ios/Sources/KlarnaStandaloneWebViewManager.mm +77 -0
  29. package/ios/Sources/view/newarch/KlarnaStandaloneWebViewWrapper.h +29 -0
  30. package/ios/Sources/view/newarch/KlarnaStandaloneWebViewWrapper.mm +265 -0
  31. package/ios/Sources/view/newarch/PaymentViewWrapper.h +33 -0
  32. package/ios/Sources/view/newarch/PaymentViewWrapper.mm +240 -0
  33. package/ios/Sources/view/oldarch/KlarnaStandaloneWebViewWrapper.h +42 -0
  34. package/ios/Sources/view/oldarch/KlarnaStandaloneWebViewWrapper.mm +195 -0
  35. package/ios/Sources/view/{PaymentViewWrapper.h → oldarch/PaymentViewWrapper.h} +9 -7
  36. package/ios/Sources/view/{PaymentViewWrapper.m → oldarch/PaymentViewWrapper.mm} +40 -27
  37. package/ios/Tests/PaymentViewWrapperTests.m +8 -10
  38. package/lib/commonjs/KlarnaPaymentView.js +192 -0
  39. package/lib/commonjs/KlarnaPaymentView.js.map +1 -0
  40. package/lib/commonjs/KlarnaStandaloneWebView.js +81 -0
  41. package/lib/commonjs/KlarnaStandaloneWebView.js.map +1 -0
  42. package/lib/commonjs/index.js +28 -0
  43. package/lib/commonjs/index.js.map +1 -0
  44. package/lib/commonjs/specs/KlarnaPaymentViewNativeComponent.js +16 -0
  45. package/lib/commonjs/specs/KlarnaPaymentViewNativeComponent.js.map +1 -0
  46. package/lib/commonjs/specs/KlarnaStandaloneWebViewNativeComponent.js +16 -0
  47. package/lib/commonjs/specs/KlarnaStandaloneWebViewNativeComponent.js.map +1 -0
  48. package/lib/module/KlarnaPaymentView.js +182 -0
  49. package/lib/module/KlarnaPaymentView.js.map +1 -0
  50. package/lib/module/KlarnaStandaloneWebView.js +71 -0
  51. package/lib/module/KlarnaStandaloneWebView.js.map +1 -0
  52. package/lib/module/index.js +3 -0
  53. package/lib/module/index.js.map +1 -0
  54. package/lib/module/specs/KlarnaPaymentViewNativeComponent.js +7 -0
  55. package/lib/module/specs/KlarnaPaymentViewNativeComponent.js.map +1 -0
  56. package/lib/module/specs/KlarnaStandaloneWebViewNativeComponent.js +7 -0
  57. package/lib/module/specs/KlarnaStandaloneWebViewNativeComponent.js.map +1 -0
  58. package/lib/typescript/KlarnaPaymentView.d.ts +51 -0
  59. package/lib/typescript/KlarnaPaymentView.d.ts.map +1 -0
  60. package/lib/typescript/KlarnaStandaloneWebView.d.ts +46 -0
  61. package/lib/typescript/KlarnaStandaloneWebView.d.ts.map +1 -0
  62. package/lib/typescript/index.d.ts +3 -0
  63. package/lib/typescript/index.d.ts.map +1 -0
  64. package/lib/typescript/specs/KlarnaPaymentViewNativeComponent.d.ts +49 -0
  65. package/lib/typescript/specs/KlarnaPaymentViewNativeComponent.d.ts.map +1 -0
  66. package/lib/typescript/specs/KlarnaStandaloneWebViewNativeComponent.d.ts +65 -0
  67. package/lib/typescript/specs/KlarnaStandaloneWebViewNativeComponent.d.ts.map +1 -0
  68. package/package.json +86 -14
  69. package/react-native-klarna-inapp-sdk.podspec +32 -13
  70. package/src/KlarnaPaymentView.tsx +323 -0
  71. package/src/KlarnaStandaloneWebView.tsx +217 -0
  72. package/src/index.tsx +2 -0
  73. package/src/specs/KlarnaPaymentViewNativeComponent.ts +99 -0
  74. package/src/specs/KlarnaStandaloneWebViewNativeComponent.ts +96 -0
  75. package/.gitattributes +0 -3
  76. package/.watchmanconfig +0 -1
  77. package/.yarnrc +0 -5
  78. package/CHANGELOG.md +0 -116
  79. package/android/README.md +0 -14
  80. package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  81. package/android/gradle/wrapper/gradle-wrapper.properties +0 -6
  82. package/android/gradlew +0 -172
  83. package/android/gradlew.bat +0 -84
  84. package/android/src/main/java/com/klarna/inapp/sdk/HeightListener.java +0 -159
  85. package/android/src/main/java/com/klarna/inapp/sdk/KlarnaPaymentViewManager.java +0 -282
  86. package/android/src/main/java/com/klarna/inapp/sdk/KlarnaPaymentViewPackage.java +0 -25
  87. package/android/src/main/java/com/klarna/inapp/sdk/Mappable.java +0 -10
  88. package/android/src/main/java/com/klarna/inapp/sdk/MappableKlarnaPaymentsSDKError.java +0 -31
  89. package/android/src/main/java/com/klarna/inapp/sdk/PaymentViewWrapper.java +0 -131
  90. package/android/src/test/java/com/klarna/inapp/sdk/MappableKlarnaPaymentsSDKErrorTest.java +0 -45
  91. package/babel.config.js +0 -3
  92. package/integration-tests/build.gradle +0 -59
  93. package/integration-tests/gradle/wrapper/gradle-wrapper.jar +0 -0
  94. package/integration-tests/gradle/wrapper/gradle-wrapper.properties +0 -6
  95. package/integration-tests/gradlew +0 -172
  96. package/integration-tests/gradlew.bat +0 -84
  97. package/integration-tests/settings.gradle +0 -2
  98. package/integration-tests/src/test/resources/junit-platform.properties +0 -4
  99. package/ios/KlarnaInAppSDK.xcworkspace/contents.xcworkspacedata +0 -10
  100. package/ios/KlarnaInAppSDK.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
  101. package/ios/Podfile +0 -73
  102. package/ios/Sources/KlarnaPaymentView.h +0 -5
  103. package/scripts/bootstrap.js +0 -29
  104. package/src/index.js +0 -72
@@ -0,0 +1,343 @@
1
+ package com.klarna.mobile.sdk.reactnative.payments;
2
+
3
+ import androidx.annotation.NonNull;
4
+ import androidx.annotation.Nullable;
5
+
6
+ import com.facebook.react.bridge.ReactApplicationContext;
7
+ import com.facebook.react.bridge.ReactContext;
8
+ import com.facebook.react.bridge.ReadableArray;
9
+ import com.facebook.react.bridge.ReadableMap;
10
+ import com.facebook.react.bridge.WritableMap;
11
+ import com.facebook.react.common.MapBuilder;
12
+ import com.facebook.react.uimanager.ThemedReactContext;
13
+ import com.facebook.react.uimanager.UIManagerHelper;
14
+ import com.facebook.react.uimanager.annotations.ReactProp;
15
+ import com.facebook.react.uimanager.events.EventDispatcher;
16
+ import com.klarna.mobile.sdk.api.payments.KlarnaPaymentView;
17
+ import com.klarna.mobile.sdk.api.payments.KlarnaPaymentViewCallback;
18
+ import com.klarna.mobile.sdk.api.payments.KlarnaPaymentsSDKError;
19
+ import com.klarna.mobile.sdk.reactnative.common.ArgumentsUtil;
20
+ import com.klarna.mobile.sdk.reactnative.spec.RNKlarnaPaymentViewSpec;
21
+
22
+ import org.jetbrains.annotations.NotNull;
23
+
24
+ import java.lang.ref.WeakReference;
25
+ import java.util.HashMap;
26
+ import java.util.Map;
27
+ import java.util.Objects;
28
+
29
+ /**
30
+ * Wraps the Payment Views being exposed to JS.
31
+ */
32
+ public class KlarnaPaymentViewManager extends RNKlarnaPaymentViewSpec<PaymentViewWrapper> implements KlarnaPaymentViewCallback, PaymentViewWrapper.OnResizedListener {
33
+
34
+ // Commands that can be triggered from RN
35
+ public static final String COMMAND_INITIALIZE = "initialize";
36
+ public static final String COMMAND_LOAD = "load";
37
+ public static final String COMMAND_LOAD_PAYMENT_REVIEW = "loadPaymentReview";
38
+ public static final String COMMAND_AUTHORIZE = "authorize";
39
+ public static final String COMMAND_REAUTHORIZE = "reauthorize";
40
+ public static final String COMMAND_FINALIZE = "finalize";
41
+
42
+ public static final String REACT_CLASS = "RNKlarnaPaymentView";
43
+
44
+ private final ReactApplicationContext reactAppContext;
45
+
46
+ // Store a list of views to event dispatchers so we send up events via the right views.
47
+ private final Map<WeakReference<PaymentViewWrapper>, EventDispatcher> viewToDispatcher;
48
+
49
+ public KlarnaPaymentViewManager(ReactApplicationContext reactApplicationContext) {
50
+ super();
51
+ this.viewToDispatcher = new HashMap<>();
52
+ this.reactAppContext = reactApplicationContext;
53
+ }
54
+
55
+ @NonNull
56
+ @Override
57
+ public String getName() {
58
+ return REACT_CLASS;
59
+ }
60
+
61
+ @NonNull
62
+ @Override
63
+ public PaymentViewWrapper createViewInstance(@NonNull ThemedReactContext context) {
64
+ PaymentViewWrapper view = new PaymentViewWrapper(reactAppContext, null, this, this);
65
+
66
+ // Each view has its own event dispatcher.
67
+ EventDispatcher dispatcher = UIManagerHelper.getEventDispatcherForReactTag((ReactContext) view.getContext(), view.getId());
68
+ viewToDispatcher.put(new WeakReference<>(view), dispatcher);
69
+
70
+ return view;
71
+ }
72
+
73
+ /**
74
+ * Handles commands received from RN to a specific view.
75
+ *
76
+ * @param root view receiving the command
77
+ * @param commandId identifier of the command
78
+ * @param args array of command arguments
79
+ */
80
+ @Override
81
+ public void receiveCommand(@NonNull PaymentViewWrapper root, String commandId, @Nullable ReadableArray args) {
82
+ String sessionData = null;
83
+
84
+ switch (commandId) {
85
+ case COMMAND_INITIALIZE:
86
+ if (args != null && args.size() > 0) {
87
+ final String token = args.getString(0);
88
+ String returnUrl = null;
89
+ if (args.size() > 1) {
90
+ returnUrl = args.getString(1);
91
+ }
92
+ initialize(root, token, returnUrl);
93
+ }
94
+ break;
95
+
96
+ case COMMAND_LOAD:
97
+ if (args != null && args.size() > 0) {
98
+ sessionData = args.getString(0);
99
+ }
100
+ load(root, sessionData);
101
+ break;
102
+
103
+ case COMMAND_LOAD_PAYMENT_REVIEW:
104
+ loadPaymentReview(root);
105
+ break;
106
+
107
+ case COMMAND_AUTHORIZE:
108
+ boolean autoFinalize = true;
109
+ if (args != null && args.size() > 0) {
110
+ autoFinalize = args.getBoolean(0);
111
+ if (args.size() > 1) {
112
+ sessionData = args.getString(1);
113
+ }
114
+ }
115
+ authorize(root, autoFinalize, sessionData);
116
+ break;
117
+
118
+ case COMMAND_REAUTHORIZE:
119
+ if (args != null && args.size() > 0) {
120
+ sessionData = args.getString(0);
121
+ }
122
+ reauthorize(root, sessionData);
123
+ break;
124
+
125
+ case COMMAND_FINALIZE:
126
+ if (args != null && args.size() > 0) {
127
+ sessionData = args.getString(0);
128
+ }
129
+ finalize(root, sessionData);
130
+ break;
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Exposes direct event types that will be accessible as prop "callbacks" from RN.
136
+ * <p>
137
+ * Structure must follow:
138
+ * { "<eventName>": {"registrationName": "<eventName>"} }
139
+ */
140
+ @Nullable
141
+ @Override
142
+ public Map<String, Object> getExportedCustomDirectEventTypeConstants() {
143
+ MapBuilder.Builder<String, Object> builder = MapBuilder.builder();
144
+ builder.put(KlarnaPaymentEvent.EVENT_NAME_ON_INITIALIZE, MapBuilder.of("registrationName", KlarnaPaymentEvent.EVENT_NAME_ON_INITIALIZE));
145
+ builder.put(KlarnaPaymentEvent.EVENT_NAME_ON_LOAD, MapBuilder.of("registrationName", KlarnaPaymentEvent.EVENT_NAME_ON_LOAD));
146
+ builder.put(KlarnaPaymentEvent.EVENT_NAME_ON_LOAD_PAYMENT_REVIEW, MapBuilder.of("registrationName", KlarnaPaymentEvent.EVENT_NAME_ON_LOAD_PAYMENT_REVIEW));
147
+ builder.put(KlarnaPaymentEvent.EVENT_NAME_ON_AUTHORIZE, MapBuilder.of("registrationName", KlarnaPaymentEvent.EVENT_NAME_ON_AUTHORIZE));
148
+ builder.put(KlarnaPaymentEvent.EVENT_NAME_ON_REAUTHORIZE, MapBuilder.of("registrationName", KlarnaPaymentEvent.EVENT_NAME_ON_REAUTHORIZE));
149
+ builder.put(KlarnaPaymentEvent.EVENT_NAME_ON_FINALIZE, MapBuilder.of("registrationName", KlarnaPaymentEvent.EVENT_NAME_ON_FINALIZE));
150
+ builder.put(KlarnaPaymentEvent.EVENT_NAME_ON_ERROR, MapBuilder.of("registrationName", KlarnaPaymentEvent.EVENT_NAME_ON_ERROR));
151
+ builder.put(KlarnaPaymentEvent.EVENT_NAME_ON_RESIZED, MapBuilder.of("registrationName", KlarnaPaymentEvent.EVENT_NAME_ON_RESIZED));
152
+ return builder.build();
153
+ }
154
+
155
+ @ReactProp(name = "category")
156
+ @Override
157
+ public void setCategory(PaymentViewWrapper view, String category) {
158
+ if (!Objects.equals(category, view.paymentView.getCategory())) {
159
+ view.paymentView.setCategory(category);
160
+ }
161
+ }
162
+
163
+ @ReactProp(name = "returnUrl")
164
+ @Override
165
+ public void setReturnUrl(PaymentViewWrapper view, @Nullable String value) {
166
+ if (!Objects.equals(value, view.paymentView.getReturnURL())) {
167
+ view.paymentView.setReturnURL(value);
168
+ }
169
+ }
170
+
171
+ @Override
172
+ public void initialize(PaymentViewWrapper view, String clientToken, String returnUrl) {
173
+ view.paymentView.initialize(clientToken, returnUrl != null && returnUrl.length() > 0 ? returnUrl : null);
174
+ }
175
+
176
+ @Override
177
+ public void load(PaymentViewWrapper view, String sessionData) {
178
+ view.load(sessionData != null && sessionData.length() > 0 ? sessionData : null);
179
+ }
180
+
181
+ @Override
182
+ public void loadPaymentReview(PaymentViewWrapper view) {
183
+ view.paymentView.loadPaymentReview();
184
+ }
185
+
186
+ @Override
187
+ public void authorize(PaymentViewWrapper view, boolean autoFinalize, String sessionData) {
188
+ view.paymentView.authorize(autoFinalize, sessionData != null && sessionData.length() > 0 ? sessionData : null);
189
+ }
190
+
191
+ @Override
192
+ public void reauthorize(PaymentViewWrapper view, String sessionData) {
193
+ view.paymentView.reauthorize(sessionData != null && sessionData.length() > 0 ? sessionData : null);
194
+ }
195
+
196
+ @Override
197
+ public void finalize(PaymentViewWrapper view, String sessionData) {
198
+ view.paymentView.finalize(sessionData != null && sessionData.length() > 0 ? sessionData : null);
199
+ }
200
+
201
+ /**
202
+ * Creates an event from event name and a map of params. Sends it via the right dispatcher.
203
+ *
204
+ * @param eventName name of the event should match getExportedCustomDirectEventTypeConstants
205
+ * @param additionalParams payload of the event
206
+ * @param view source native view
207
+ */
208
+ private void postEventForView(String eventName, WritableMap additionalParams, KlarnaPaymentView view) {
209
+ PaymentViewWrapper wrapper = wrapperForPaymentView(view);
210
+ if (wrapper != null) {
211
+ postEventForView(eventName, additionalParams, wrapper);
212
+ }
213
+ }
214
+
215
+ private void postEventForView(String eventName, WritableMap additionalParams, PaymentViewWrapper wrapper) {
216
+ if (wrapper != null) {
217
+ KlarnaPaymentEvent event = new KlarnaPaymentEvent(wrapper.getId(), eventName, additionalParams);
218
+ EventDispatcher eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag((ReactContext) wrapper.getContext(), wrapper.getId());
219
+ if (eventDispatcher != null) {
220
+ eventDispatcher.dispatchEvent(event);
221
+ }
222
+ }
223
+ }
224
+
225
+ /**
226
+ * Calls requestLayout on the wrapper to fetch height of the contents.
227
+ *
228
+ * @param view native view
229
+ */
230
+ private void requestLayout(KlarnaPaymentView view) {
231
+ if (view != null) {
232
+ PaymentViewWrapper wrapper = wrapperForPaymentView(view);
233
+ if (wrapper != null) {
234
+ wrapper.requestLayout();
235
+ }
236
+ }
237
+ }
238
+
239
+
240
+ /* -- KlarnaPaymentView callback methods -- */
241
+
242
+ @Override
243
+ public void onInitialized(@NotNull KlarnaPaymentView paymentView) {
244
+ requestLayout(paymentView);
245
+ postEventForView(KlarnaPaymentEvent.EVENT_NAME_ON_INITIALIZE, null, paymentView);
246
+ }
247
+
248
+ @Override
249
+ public void onLoaded(@NotNull KlarnaPaymentView paymentView) {
250
+ requestLayout(paymentView);
251
+ postEventForView(KlarnaPaymentEvent.EVENT_NAME_ON_LOAD, null, paymentView);
252
+ }
253
+
254
+ @Override
255
+ public void onLoadPaymentReview(@NotNull KlarnaPaymentView paymentView, boolean b) {
256
+ requestLayout(paymentView);
257
+ postEventForView(KlarnaPaymentEvent.EVENT_NAME_ON_LOAD_PAYMENT_REVIEW, null, paymentView);
258
+ }
259
+
260
+ @Override
261
+ public void onAuthorized(@NotNull KlarnaPaymentView paymentView, boolean approved, @org.jetbrains.annotations.Nullable String authToken, @org.jetbrains.annotations.Nullable Boolean finalizeRequired) {
262
+ requestLayout(paymentView);
263
+ WritableMap params = ArgumentsUtil.createMap(
264
+ new HashMap<String, Object>() {{
265
+ put("approved", approved);
266
+ put("authToken", authToken);
267
+ put("finalizeRequired", finalizeRequired);
268
+ }}
269
+ );
270
+ postEventForView(KlarnaPaymentEvent.EVENT_NAME_ON_AUTHORIZE, params, paymentView);
271
+ }
272
+
273
+ @Override
274
+ public void onReauthorized(@NotNull KlarnaPaymentView paymentView, boolean approved, @org.jetbrains.annotations.Nullable String authToken) {
275
+ requestLayout(paymentView);
276
+ WritableMap params = ArgumentsUtil.createMap(
277
+ new HashMap<String, Object>() {{
278
+ put("approved", approved);
279
+ put("authToken", authToken);
280
+ }}
281
+ );
282
+ postEventForView(KlarnaPaymentEvent.EVENT_NAME_ON_REAUTHORIZE, params, paymentView);
283
+ }
284
+
285
+ @Override
286
+ public void onFinalized(@NotNull KlarnaPaymentView paymentView, boolean approved, @org.jetbrains.annotations.Nullable String authToken) {
287
+ requestLayout(paymentView);
288
+ WritableMap params = ArgumentsUtil.createMap(
289
+ new HashMap<String, Object>() {{
290
+ put("approved", approved);
291
+ put("authToken", authToken);
292
+ }}
293
+ );
294
+ postEventForView(KlarnaPaymentEvent.EVENT_NAME_ON_FINALIZE, params, paymentView);
295
+ }
296
+
297
+ @Override
298
+ public void onErrorOccurred(@NotNull KlarnaPaymentView klarnaPaymentView, @NotNull KlarnaPaymentsSDKError klarnaPaymentsSDKError) {
299
+ requestLayout(klarnaPaymentView);
300
+ ReadableMap sdkError = buildErrorMap(klarnaPaymentsSDKError);
301
+ WritableMap params = ArgumentsUtil.createMap(
302
+ new HashMap<String, Object>() {{
303
+ put("error", sdkError);
304
+ }}
305
+ );
306
+ postEventForView(KlarnaPaymentEvent.EVENT_NAME_ON_ERROR, params, klarnaPaymentView);
307
+ }
308
+
309
+ @Override
310
+ public void onResized(PaymentViewWrapper paymentViewWrapper, int value) {
311
+ WritableMap params = ArgumentsUtil.createMap(
312
+ new HashMap<String, Object>() {{
313
+ put("height", String.valueOf(value));
314
+ }}
315
+ );
316
+ postEventForView(KlarnaPaymentEvent.EVENT_NAME_ON_RESIZED, params, paymentViewWrapper);
317
+ }
318
+
319
+ ReadableMap buildErrorMap(KlarnaPaymentsSDKError klarnaPaymentsSDKError) {
320
+ return ArgumentsUtil.createMap(
321
+ new HashMap<String, Object>() {{
322
+ put("action", klarnaPaymentsSDKError.getAction());
323
+ put("isFatal", klarnaPaymentsSDKError.isFatal());
324
+ put("message", klarnaPaymentsSDKError.getMessage());
325
+ put("name", klarnaPaymentsSDKError.getName());
326
+ put("sessionId", klarnaPaymentsSDKError.getSessionId());
327
+ put("invalidFields", ArgumentsUtil.createArray(klarnaPaymentsSDKError.getInvalidFields()));
328
+ }}
329
+ );
330
+ }
331
+
332
+ private PaymentViewWrapper wrapperForPaymentView(KlarnaPaymentView paymentView) {
333
+ for (WeakReference<PaymentViewWrapper> reference : viewToDispatcher.keySet()) {
334
+ PaymentViewWrapper wrapper = reference.get();
335
+
336
+ if (wrapper != null && wrapper.paymentView == paymentView) {
337
+ return wrapper;
338
+ }
339
+ }
340
+ return null;
341
+ }
342
+
343
+ }
@@ -0,0 +1,78 @@
1
+ package com.klarna.mobile.sdk.reactnative.payments;
2
+
3
+ import android.util.AttributeSet;
4
+ import android.view.View;
5
+ import android.view.ViewGroup;
6
+ import android.webkit.WebView;
7
+ import android.widget.LinearLayout;
8
+
9
+ import com.facebook.react.bridge.ReactApplicationContext;
10
+ import com.klarna.mobile.sdk.api.payments.KlarnaPaymentView;
11
+ import com.klarna.mobile.sdk.api.payments.KlarnaPaymentViewCallback;
12
+ import com.klarna.mobile.sdk.reactnative.common.WebViewResizeObserver;
13
+
14
+ /***
15
+ * Wraps the KlarnaPaymentView so we can see when a requestLayout() has been triggered.
16
+ */
17
+ public class PaymentViewWrapper extends LinearLayout implements WebViewResizeObserver.WebViewResizeObserverCallback {
18
+
19
+ public interface OnResizedListener {
20
+ void onResized(PaymentViewWrapper paymentViewWrapper, int value);
21
+ }
22
+
23
+ public KlarnaPaymentView paymentView;
24
+ private final WebViewResizeObserver resizeObserver;
25
+
26
+ private final OnResizedListener onResizedListener;
27
+
28
+ public PaymentViewWrapper(ReactApplicationContext context, AttributeSet attrs, KlarnaPaymentViewCallback paymentViewCallback, OnResizedListener onResizedListener) {
29
+ super(context, attrs);
30
+ this.onResizedListener = onResizedListener;
31
+ // Add KlarnaPaymentView
32
+ ViewGroup.LayoutParams webViewParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
33
+ paymentView = new KlarnaPaymentView(getReactAppContext().getCurrentActivity(), attrs); // Insure we use activity and not application context for dialogs.
34
+ paymentView.registerPaymentViewCallback(paymentViewCallback);
35
+ addView(paymentView, webViewParams);
36
+ resizeObserver = new WebViewResizeObserver(this);
37
+ WebView webView = getPaymentViewWebView();
38
+ if (webView != null) {
39
+ resizeObserver.addInterface(webView);
40
+ }
41
+ }
42
+
43
+ public void load(String sessionData) {
44
+ paymentView.load(sessionData);
45
+ WebView webView = getPaymentViewWebView();
46
+ if (webView != null) {
47
+ resizeObserver.injectListener(webView);
48
+ }
49
+ }
50
+
51
+ /**
52
+ * Attempts to retrieve the web view from within the KlarnaPaymentView. This is really fragile.
53
+ */
54
+ private WebView getPaymentViewWebView() {
55
+ for (int i = 0; i < paymentView.getChildCount(); i++) {
56
+ View child = paymentView.getChildAt(i);
57
+
58
+ if (child instanceof WebView) {
59
+ return (WebView) child;
60
+ }
61
+ }
62
+ return null;
63
+ }
64
+
65
+ /**
66
+ * Returns the app context the wrapper was initialized with.
67
+ */
68
+ private ReactApplicationContext getReactAppContext() {
69
+ return (ReactApplicationContext) getContext();
70
+ }
71
+
72
+ @Override
73
+ public void onResized(int value) {
74
+ if (onResizedListener != null) {
75
+ onResizedListener.onResized(this, value);
76
+ }
77
+ }
78
+ }
@@ -0,0 +1,67 @@
1
+ package com.klarna.mobile.sdk.reactnative.standalonewebview;
2
+
3
+ import androidx.annotation.IdRes;
4
+ import androidx.annotation.NonNull;
5
+ import androidx.annotation.Nullable;
6
+
7
+ import com.facebook.react.bridge.Arguments;
8
+ import com.facebook.react.bridge.WritableMap;
9
+ import com.facebook.react.uimanager.events.Event;
10
+
11
+ /**
12
+ * A `KlarnaStandaloneWebViewEvent` builds the event that will be eventually sent to the React Native side.
13
+ * <p>
14
+ * It consists of a flat JSON object with a single `name` parameter for the event name as well as
15
+ * other, optional parameters depending on the function that was called.
16
+ */
17
+ public class KlarnaStandaloneWebViewEvent extends Event<KlarnaStandaloneWebViewEvent> {
18
+
19
+ // List of possible events that can be sent to the React Native side.
20
+ public enum Event {
21
+ // This event is sent just before loading a URL
22
+ ON_LOAD_START("onLoadStart"),
23
+ // This event is sent when loading a URL is done
24
+ ON_LOAD_END("onLoadEnd"),
25
+ // This event is sent when loading a URL encounters an error
26
+ ON_ERROR("onError"),
27
+ // This event is sent when the progress of loading a page changes
28
+ ON_LOAD_PROGRESS("onLoadProgress"),
29
+ // This event is sent when the Mobile SDK wants to send an event to the Web View
30
+ ON_KLARNA_MESSAGE("onKlarnaMessage"),
31
+ // This event is sent when the WebView's render process has exited
32
+ ON_RENDER_PROCESS_GONE("onRenderProcessGone");
33
+
34
+ public final String name;
35
+
36
+ Event(String name) {
37
+ this.name = name;
38
+ }
39
+ }
40
+
41
+ @NonNull
42
+ private final String eventName;
43
+
44
+ @Nullable
45
+ private final WritableMap additionalParams;
46
+
47
+ public KlarnaStandaloneWebViewEvent(@IdRes int viewId, @NonNull String eventName, @Nullable WritableMap additionalParams) {
48
+ super(viewId);
49
+ this.eventName = eventName;
50
+ this.additionalParams = additionalParams;
51
+ }
52
+
53
+ @Override
54
+ public String getEventName() {
55
+ return eventName;
56
+ }
57
+
58
+ @Nullable
59
+ @Override
60
+ protected WritableMap getEventData() {
61
+ if (additionalParams != null) {
62
+ return additionalParams;
63
+ }
64
+ return Arguments.createMap();
65
+ }
66
+
67
+ }
@@ -0,0 +1,139 @@
1
+ package com.klarna.mobile.sdk.reactnative.standalonewebview;
2
+
3
+ import androidx.annotation.NonNull;
4
+ import androidx.annotation.Nullable;
5
+
6
+ import com.facebook.react.bridge.ReactContext;
7
+ import com.facebook.react.bridge.ReadableMap;
8
+ import com.facebook.react.bridge.WritableMap;
9
+ import com.facebook.react.uimanager.UIManagerHelper;
10
+ import com.facebook.react.uimanager.events.EventDispatcher;
11
+ import com.klarna.mobile.sdk.api.KlarnaProductEvent;
12
+ import com.klarna.mobile.sdk.api.standalonewebview.KlarnaStandaloneWebView;
13
+ import com.klarna.mobile.sdk.reactnative.common.ArgumentsUtil;
14
+
15
+ import java.lang.ref.WeakReference;
16
+ import java.util.HashMap;
17
+ import java.util.Map;
18
+
19
+ /**
20
+ * This class is responsible for sending some KlarnaStandaloneWebView-related events to the React Native side.
21
+ */
22
+ public class KlarnaStandaloneWebViewEventSender {
23
+
24
+ private static final String PARAM_NAME_NAVIGATION_EVENT = "navigationEvent";
25
+ private static final String PARAM_NAME_NAVIGATION_ERROR = "navigationError";
26
+ private static final String PARAM_NAME_PROGRESS_EVENT = "progressEvent";
27
+ private static final String PARAM_NAME_KLARNA_MESSAGE_EVENT = "klarnaMessageEvent";
28
+ private static final String PARAM_NAME_RENDER_PROCESS_GONE_EVENT = "renderProcessGoneEvent";
29
+ private static final String PARAM_NAME_CODE = "code";
30
+ private static final String PARAM_NAME_DESCRIPTION = "description";
31
+ private static final String PARAM_NAME_TITLE = "title";
32
+ private static final String PARAM_NAME_URL = "url";
33
+ private static final String PARAM_NAME_CAN_GO_BACK = "canGoBack";
34
+ private static final String PARAM_NAME_CAN_GO_FORWARD = "canGoForward";
35
+ private static final String PARAM_NAME_PROGRESS = "progress";
36
+ private static final String PARAM_NAME_LOADING = "loading";
37
+ private static final String PARAM_NAME_ACTION = "action";
38
+ private static final String PARAM_NAME_DID_CRASH = "didCrash";
39
+
40
+ private final Map<WeakReference<KlarnaStandaloneWebView>, EventDispatcher> viewToDispatcher;
41
+
42
+ KlarnaStandaloneWebViewEventSender(@NonNull final Map<WeakReference<KlarnaStandaloneWebView>, EventDispatcher> viewToDispatcher) {
43
+ this.viewToDispatcher = viewToDispatcher;
44
+ }
45
+
46
+ public void sendLoadProgressEvent(@Nullable KlarnaStandaloneWebView view, int progress) {
47
+ WritableMap webViewMap = buildWebViewMap(view, null);
48
+ webViewMap.putDouble(PARAM_NAME_PROGRESS, progress);
49
+ WritableMap params = ArgumentsUtil.createMap(new HashMap<String, Object>() {{
50
+ put(PARAM_NAME_PROGRESS_EVENT, webViewMap);
51
+ }});
52
+ postEventForView(KlarnaStandaloneWebViewEvent.Event.ON_LOAD_PROGRESS, params, view);
53
+ }
54
+
55
+ public void sendErrorEvent(@Nullable KlarnaStandaloneWebView view, int code, String description) {
56
+ WritableMap webViewMap = buildWebViewMap(view, null);
57
+ webViewMap.putDouble(PARAM_NAME_CODE, code);
58
+ webViewMap.putString(PARAM_NAME_DESCRIPTION, description);
59
+ WritableMap params = ArgumentsUtil.createMap(new HashMap<String, Object>() {{
60
+ put(PARAM_NAME_NAVIGATION_ERROR, webViewMap);
61
+ }});
62
+ postEventForView(KlarnaStandaloneWebViewEvent.Event.ON_ERROR, params, view);
63
+ }
64
+
65
+ public void sendNavigationEvent(@Nullable KlarnaStandaloneWebView view, KlarnaStandaloneWebViewEvent.Event event, String url) {
66
+ WritableMap webViewMap = buildWebViewMap(view, url);
67
+ WritableMap params = ArgumentsUtil.createMap(new HashMap<String, Object>() {{
68
+ put(PARAM_NAME_NAVIGATION_EVENT, webViewMap);
69
+ }});
70
+ postEventForView(event, params, view);
71
+ }
72
+
73
+ public void sendKlarnaMessageEvent(@Nullable KlarnaStandaloneWebView view, @NonNull KlarnaProductEvent klarnaProductEvent) {
74
+ ReadableMap eventMap = ArgumentsUtil.createMap(new HashMap<String, Object>() {{
75
+ put(PARAM_NAME_ACTION, klarnaProductEvent.getAction());
76
+ }});
77
+ WritableMap params = ArgumentsUtil.createMap(new HashMap<String, Object>() {{
78
+ put(PARAM_NAME_KLARNA_MESSAGE_EVENT, eventMap);
79
+ }});
80
+ postEventForView(KlarnaStandaloneWebViewEvent.Event.ON_KLARNA_MESSAGE, params, view);
81
+ }
82
+
83
+ public void sendRenderProcessGoneEvent(@Nullable KlarnaStandaloneWebView view, boolean didCrash) {
84
+ ReadableMap eventMap = ArgumentsUtil.createMap(new HashMap<String, Object>() {{
85
+ put(PARAM_NAME_DID_CRASH, didCrash);
86
+ }});
87
+ WritableMap params = ArgumentsUtil.createMap(new HashMap<String, Object>() {{
88
+ put(PARAM_NAME_RENDER_PROCESS_GONE_EVENT, eventMap);
89
+ }});
90
+ postEventForView(KlarnaStandaloneWebViewEvent.Event.ON_RENDER_PROCESS_GONE, params, view);
91
+ }
92
+
93
+ /**
94
+ * Creates an event from event name and a map of params. Sends it via the right dispatcher.
95
+ *
96
+ * @param event name of the event should match getExportedCustomDirectEventTypeConstants
97
+ * @param additionalParams payload of the event
98
+ * @param view source native view
99
+ */
100
+ private void postEventForView(KlarnaStandaloneWebViewEvent.Event event, WritableMap additionalParams, @Nullable KlarnaStandaloneWebView view) {
101
+ KlarnaStandaloneWebView klarnaStandaloneWebView = getKlarnaStandaloneWebView(view);
102
+ if (klarnaStandaloneWebView != null) {
103
+ EventDispatcher eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag((ReactContext) klarnaStandaloneWebView.getContext(), klarnaStandaloneWebView.getId());
104
+ if (eventDispatcher != null) {
105
+ KlarnaStandaloneWebViewEvent e = new KlarnaStandaloneWebViewEvent(klarnaStandaloneWebView.getId(), event.name, additionalParams);
106
+ eventDispatcher.dispatchEvent(e);
107
+ }
108
+ }
109
+ }
110
+
111
+ @Nullable
112
+ private KlarnaStandaloneWebView getKlarnaStandaloneWebView(@Nullable KlarnaStandaloneWebView klarnaStandaloneWebView) {
113
+ if (klarnaStandaloneWebView == null) {
114
+ return null;
115
+ }
116
+ for (WeakReference<KlarnaStandaloneWebView> reference : viewToDispatcher.keySet()) {
117
+ KlarnaStandaloneWebView webView = reference.get();
118
+ if (webView != null && webView == klarnaStandaloneWebView) {
119
+ return webView;
120
+ }
121
+ }
122
+ return null;
123
+ }
124
+
125
+ private WritableMap buildWebViewMap(KlarnaStandaloneWebView webView, String url) {
126
+ return ArgumentsUtil.createMap(new HashMap<String, Object>() {{
127
+ if (webView != null) {
128
+ put(PARAM_NAME_URL, url != null ? url : webView.getUrl());
129
+ put(PARAM_NAME_TITLE, webView.getTitle());
130
+ put(PARAM_NAME_LOADING, webView.getProgress() < 100);
131
+ put(PARAM_NAME_CAN_GO_BACK, webView.canGoBack());
132
+ put(PARAM_NAME_CAN_GO_FORWARD, webView.canGoForward());
133
+ } else {
134
+ put(PARAM_NAME_URL, url);
135
+ }
136
+ }});
137
+ }
138
+
139
+ }