@juspay-tech/react-native-hyperswitch 1.3.4 → 1.3.6

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 (46) hide show
  1. package/android/build.gradle +22 -1
  2. package/android/src/main/assets/hyperswitch.bundle +590 -590
  3. package/android/src/main/java/com/hyperswitchsdkreactnative/modules/NativeLog.kt +107 -0
  4. package/android/src/main/java/com/hyperswitchsdkreactnative/modules/ReactNativeHyperswitchModule.kt +318 -117
  5. package/android/src/main/java/io/hyperswitch/paymentsession/ExitHeadlessCallBackManager.kt +4 -2
  6. package/android/src/main/java/io/hyperswitch/paymentsession/PaymentSessionHandlerImpl.kt +20 -4
  7. package/android/src/main/java/io/hyperswitch/paymentsession/PaymentSessionReactLauncher.kt +104 -9
  8. package/android/src/main/java/io/hyperswitch/paymentsheet/PaymentResult.kt +7 -1
  9. package/android/src/main/java/io/hyperswitch/react/HyperModule.kt +13 -0
  10. package/android/src/main/java/io/hyperswitch/view/PaymentWidgetView.kt +27 -4
  11. package/android/src/rn79/assets/hyperswitch.bundle +590 -590
  12. package/android/src/rn79/java/io/hyperswitch/react/HyperFragment.kt +20 -0
  13. package/android/src/rn81/java/io/hyperswitch/react/HyperFragment.kt +20 -0
  14. package/ios/Modules/ReactNative/NativeHyperswitchModuleImpl.swift +3 -1
  15. package/ios/hyperswitchSDK/Core/ApplePay/ApplePayHandler.swift +49 -38
  16. package/ios/hyperswitchSDK/Core/HyperPaymentSheet/PaymentSheetView+UIKit.swift +1 -5
  17. package/ios/hyperswitchSDK/Core/NativeModule/HyperModuleImpl.swift +49 -34
  18. package/ios/hyperswitchSDK/Core/NativeModule/RNHeadlessManager.swift +2 -12
  19. package/ios/hyperswitchSDK/Core/Resources/hyperswitch-rn82plus.bundle +590 -590
  20. package/ios/hyperswitchSDK/Core/Resources/hyperswitch.bundle +590 -590
  21. package/ios/hyperswitchSDK/Shared/Environment.swift +49 -3
  22. package/ios/hyperswitchSDK/Shared/HyperswitchEnvironment.swift +1 -0
  23. package/ios/hyperswitchSDK/Shared/NativeLogger/LogBuilder.swift +15 -0
  24. package/ios/hyperswitchSDK/Shared/NativeLogger/LogManager.swift +10 -2
  25. package/ios/hyperswitchSDK/Shared/NativeLogger/LogPayload.swift +1 -0
  26. package/ios/hyperswitchSDK/Shared/NativeLogger/NativeLog.swift +101 -0
  27. package/ios/hyperswitchSDK/Shared/PaymentSession.swift +8 -1
  28. package/lib/commonjs/index.bundle.js +2 -2
  29. package/lib/commonjs/index.bundle.js.map +1 -1
  30. package/lib/module/index.bundle.js +2 -2
  31. package/lib/module/index.bundle.js.map +1 -1
  32. package/lib/typescript/src/context/HyperElements.d.ts.map +1 -1
  33. package/lib/typescript/src/index.d.ts.map +1 -1
  34. package/lib/typescript/src/native/NativeResponseMapper.d.ts +2 -1
  35. package/lib/typescript/src/native/NativeResponseMapper.d.ts.map +1 -1
  36. package/lib/typescript/src/session/SavedPaymentMethods.d.ts.map +1 -1
  37. package/lib/typescript/src/session/presentPaymentSheet.d.ts +0 -12
  38. package/lib/typescript/src/session/presentPaymentSheet.d.ts.map +1 -1
  39. package/lib/typescript/src/views/PaymentElement.d.ts.map +1 -1
  40. package/package.json +1 -1
  41. package/src/context/HyperElements.tsx +7 -6
  42. package/src/index.ts +9 -1
  43. package/src/native/NativeResponseMapper.ts +20 -4
  44. package/src/session/SavedPaymentMethods.ts +10 -2
  45. package/src/session/presentPaymentSheet.ts +7 -1
  46. package/src/views/PaymentElement.tsx +17 -8
@@ -1 +1 @@
1
- {"version":3,"file":"PaymentElement.d.ts","sourceRoot":"","sources":["../../../../src/views/PaymentElement.tsx"],"names":[],"mappings":"AACA,OAAO,EAA6B,KAAK,SAAS,EAAY,MAAM,cAAc,CAAC;AAGnF,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,oCAAoC,CAAC;AAMpF,OAAO,KAAK,EAGV,kBAAkB,EACnB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAK5D,KAAK,mBAAmB,GAAG;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,yBAAyB,CAAC;IACpC,eAAe,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;IACjD,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAC/C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB,CAAC;AAEF,eAAO,MAAM,cAAc,sHAoHzB,CAAC"}
1
+ {"version":3,"file":"PaymentElement.d.ts","sourceRoot":"","sources":["../../../../src/views/PaymentElement.tsx"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,SAAS,EAEf,MAAM,cAAc,CAAC;AAGtB,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,oCAAoC,CAAC;AAMpF,OAAO,KAAK,EAGV,kBAAkB,EACnB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAK5D,KAAK,mBAAmB,GAAG;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,yBAAyB,CAAC;IACpC,eAAe,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;IACjD,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAC/C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB,CAAC;AAEF,eAAO,MAAM,cAAc,sHAwHzB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay-tech/react-native-hyperswitch",
3
- "version": "1.3.4",
3
+ "version": "1.3.6",
4
4
  "description": "Hyperswitch SDK for React Native",
5
5
  "main": "lib/commonjs/index.bundle.js",
6
6
  "module": "lib/module/index.bundle.js",
@@ -64,13 +64,14 @@ export function HyperElements({
64
64
  const [sdkAuthorization, setSdkAuthorization] = useState<string | null>(null);
65
65
  const [loading, setLoading] = useState(true);
66
66
  const [error, setError] = useState<Error | null>(null);
67
- const [walletSession, setWalletSession] = useState<WalletSessionHandle | null>(
68
- null
67
+ const [walletSession, setWalletSession] =
68
+ useState<WalletSessionHandle | null>(null);
69
+ const [walletEligibility, setWalletEligibility] = useState<WalletEligibility>(
70
+ {
71
+ googlePay: false,
72
+ applePay: false,
73
+ }
69
74
  );
70
- const [walletEligibility, setWalletEligibility] = useState<WalletEligibility>({
71
- googlePay: false,
72
- applePay: false,
73
- });
74
75
  const [walletLoading, setWalletLoading] = useState(false);
75
76
 
76
77
  const loadWalletSession = useCallback(async () => {
package/src/index.ts CHANGED
@@ -15,12 +15,20 @@ import NativeHyperswitchModule from './codegen/modules/NativeHyperswitchModule';
15
15
  import { createPaymentSession } from './session/PaymentSession';
16
16
  import { Elements } from './types/elements';
17
17
  import { createElements } from './session/Elements';
18
- import { setInitializing } from './native/InitializationState';
18
+ import {
19
+ setInitializing,
20
+ setSheetPresented,
21
+ } from './native/InitializationState';
19
22
 
20
23
  export function loadHyper(
21
24
  config: HyperswitchConfiguration
22
25
  ): Promise<HyperswitchSession> {
23
26
  setInitializing(true);
27
+ /*
28
+ * A presentPaymentSheet that never settled would otherwise block every later call with
29
+ * sheet_already_presented; native resolves that stale call when the next sheet is presented.
30
+ */
31
+ setSheetPresented(false);
24
32
  return NativeHyperswitchModule.initialise(
25
33
  config.publishableKey,
26
34
  config.platformPublishableKey ?? '',
@@ -2,7 +2,9 @@ import type { PaymentResult } from '../types/paymentresult';
2
2
 
3
3
  interface NativeResponse {
4
4
  status: string;
5
- message: string;
5
+ message?: string;
6
+ // Android's PaymentResult.Failed historically wrote the text under `error`.
7
+ error?: string;
6
8
  code?: string;
7
9
  type?: string;
8
10
  data?: any;
@@ -38,13 +40,27 @@ export function mapStatus(status: string): PaymentResult['status'] {
38
40
  }
39
41
  }
40
42
 
43
+ function firstNonEmpty(...values: unknown[]): string | undefined {
44
+ for (const value of values) {
45
+ if (typeof value === 'string' && value.trim() !== '') return value;
46
+ }
47
+ return undefined;
48
+ }
49
+
41
50
  export function mapNativeResponseToPaymentResult(
42
51
  raw: string | NativeResponse
43
52
  ): PaymentResult {
44
53
  const parsed = parseNativeResponse(raw);
54
+ const status = mapStatus(parsed.status);
55
+ const detail = firstNonEmpty(parsed.message, parsed.error, parsed.code);
45
56
  return {
46
- status: mapStatus(parsed.status),
47
- type: parsed.type ?? parsed.code ?? mapStatus(parsed.status) ?? '',
48
- message: parsed.message ?? parsed.code ?? '',
57
+ status,
58
+ type: firstNonEmpty(parsed.type, parsed.code, status) ?? '',
59
+ // Never hand back an empty message for a failure; callers show it to users.
60
+ message:
61
+ detail ??
62
+ (status === 'failed'
63
+ ? 'The payment failed but no error detail was returned.'
64
+ : ''),
49
65
  };
50
66
  }
@@ -9,7 +9,10 @@ import {
9
9
  SavedPaymentMethodsConfiguration,
10
10
  } from '../types/savedPaymentMethods';
11
11
  import type { PaymentResult } from '../types/paymentresult';
12
- import { mapNativeResponseToPaymentResult } from '../native/NativeResponseMapper';
12
+ import {
13
+ mapNativeResponseToPaymentResult,
14
+ parseNativeResponse,
15
+ } from '../native/NativeResponseMapper';
13
16
  import { getWidget } from '../widget/WidgetRegistry';
14
17
 
15
18
  function getReactTag(widgetId?: string): number {
@@ -116,6 +119,11 @@ export async function getCustomerSavedPaymentMethods(
116
119
  }
117
120
  },
118
121
  };
119
- await NativeHyperswitchModule.getCustomerSavedPaymentMethods(payload);
122
+ const raw = await NativeHyperswitchModule.getCustomerSavedPaymentMethods(payload);
123
+ const { status, code, message } = parseNativeResponse(raw);
124
+ // Android reports failures as status "failed", iOS as code "error".
125
+ if (status === 'failed' || code === 'error') {
126
+ throw new Error(message ?? 'Failed to load saved payment methods');
127
+ }
120
128
  return createCustomerSavedPaymentMethodsSession();
121
129
  }
@@ -20,6 +20,9 @@ import {
20
20
  * developer mistake) short-circuits to "sheet_already_presented"
21
21
  * instead of stacking a duplicate.
22
22
  */
23
+ // Identifies the latest call, so an older call settling late cannot clear the guard for it.
24
+ let presentCallId = 0;
25
+
23
26
  export async function presentPaymentSheetWithPayload(
24
27
  payload: NativePaymentSheetPayload
25
28
  ): Promise<PaymentResult> {
@@ -41,6 +44,7 @@ export async function presentPaymentSheetWithPayload(
41
44
  message: 'A payment sheet is already presented.',
42
45
  };
43
46
  }
47
+ const callId = ++presentCallId;
44
48
  setSheetPresented(true);
45
49
  try {
46
50
  const raw = await NativeHyperswitchModule.presentPaymentSheet({
@@ -50,6 +54,8 @@ export async function presentPaymentSheetWithPayload(
50
54
  });
51
55
  return mapNativeResponseToPaymentResult(raw);
52
56
  } finally {
53
- setSheetPresented(false);
57
+ if (callId === presentCallId) {
58
+ setSheetPresented(false);
59
+ }
54
60
  }
55
61
  }
@@ -1,5 +1,10 @@
1
1
  import { forwardRef, useEffect, useImperativeHandle, useRef } from 'react';
2
- import { UIManager, findNodeHandle, type ViewStyle, Platform } from 'react-native';
2
+ import {
3
+ UIManager,
4
+ findNodeHandle,
5
+ type ViewStyle,
6
+ Platform,
7
+ } from 'react-native';
3
8
  import NativePaymentWidgetImpl from './PaymentWidgetBridge';
4
9
  import { registerWidget, unregisterWidget } from '../widget/WidgetRegistry';
5
10
  import type { PaymentSheetConfiguration } from '../types/PaymentSheetConfiguration';
@@ -111,16 +116,20 @@ export const PaymentElement = forwardRef<
111
116
  }
112
117
  }, [options, onChange]);
113
118
 
114
- const onPaymentResultInternal = (event: NativeEventEnvelope & { nativeEvent: {
115
- eventName: string;
116
- payload: string;
117
- target: number;
118
- }}) => {
119
+ const onPaymentResultInternal = (
120
+ event: NativeEventEnvelope & {
121
+ nativeEvent: {
122
+ eventName: string;
123
+ payload: string;
124
+ target: number;
125
+ };
126
+ }
127
+ ) => {
119
128
  onPaymentResult(
120
129
  mapNativeResponseToPaymentResult(
121
130
  Platform.OS === 'ios'
122
- ? event.nativeEvent.result ?? ""
123
- : event.nativeEvent.payload ?? ""
131
+ ? (event.nativeEvent.result ?? '')
132
+ : (event.nativeEvent.payload ?? '')
124
133
  )
125
134
  );
126
135
  };