@idealyst/payments 1.2.108 → 1.2.109

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 CHANGED
@@ -1,100 +1,98 @@
1
1
  # @idealyst/payments
2
2
 
3
- Cross-platform payment provider abstractions for React and React Native. Wraps Stripe's Platform Pay API for Apple Pay and Google Pay on mobile.
3
+ Cross-platform In-App Purchase (IAP) wrapper for React Native. Supports StoreKit 2 (iOS) and Google Play Billing (Android) via `react-native-iap`.
4
4
 
5
5
  ## Installation
6
6
 
7
7
  ```bash
8
8
  yarn add @idealyst/payments
9
- ```
10
-
11
- ### Native (required for mobile payments)
12
9
 
13
- ```bash
14
- yarn add @stripe/stripe-react-native
10
+ # React Native — required for IAP:
11
+ yarn add react-native-iap
12
+ cd ios && pod install
15
13
  ```
16
14
 
17
- Follow the [Stripe React Native setup guide](https://github.com/stripe/stripe-react-native#installation) for iOS/Android configuration.
15
+ Follow the [react-native-iap setup guide](https://github.com/dooboolab-community/react-native-iap#installation) for iOS/Android configuration.
18
16
 
19
17
  ### Web
20
18
 
21
- No additional dependencies. Web provides a stub that reports all payment methods as unavailable use [Stripe Elements](https://stripe.com/docs/stripe-js/react) (`@stripe/react-stripe-js`) for web payments.
19
+ No additional dependencies. Web provides a stub `initializeIAP()` succeeds but product fetches return empty arrays and purchase actions throw descriptive errors.
22
20
 
23
21
  ## Quick Start
24
22
 
25
23
  ```tsx
26
- import { usePayments } from '@idealyst/payments';
24
+ import { useIAP } from '@idealyst/payments';
27
25
 
28
- function CheckoutScreen() {
26
+ function SubscriptionScreen() {
29
27
  const {
30
28
  isReady,
31
- isApplePayAvailable,
32
- isGooglePayAvailable,
29
+ subscriptions,
33
30
  isProcessing,
34
31
  error,
35
- confirmPayment,
36
- } = usePayments({
37
- config: {
38
- publishableKey: 'pk_test_xxx',
39
- merchantIdentifier: 'merchant.com.myapp',
40
- merchantName: 'My App',
41
- merchantCountryCode: 'US',
42
- },
32
+ purchaseSubscription,
33
+ finishTransaction,
34
+ } = useIAP({
35
+ subscriptionSkus: ['pro_monthly', 'pro_yearly'],
43
36
  });
44
37
 
45
- const handlePay = async () => {
46
- const result = await confirmPayment({
47
- clientSecret: 'pi_xxx_secret_xxx', // from your server
48
- amount: { amount: 1099, currencyCode: 'usd' },
49
- lineItems: [
50
- { label: 'Widget', amount: 999 },
51
- { label: 'Tax', amount: 100 },
52
- ],
53
- });
54
- console.log('Paid:', result.paymentIntentId);
38
+ const handleSubscribe = async (sku: string) => {
39
+ try {
40
+ const purchase = await purchaseSubscription(sku);
41
+
42
+ // Validate receipt on your server first, then finish
43
+ await validateReceiptOnServer(purchase.transactionReceipt);
44
+ await finishTransaction(purchase);
45
+ } catch (err) {
46
+ console.error('Purchase failed:', err);
47
+ }
55
48
  };
56
49
 
57
- if (!isReady) return null;
50
+ if (!isReady) return <Text>Loading...</Text>;
58
51
 
59
52
  return (
60
- <Button
61
- onPress={handlePay}
62
- disabled={isProcessing || (!isApplePayAvailable && !isGooglePayAvailable)}
63
- label={isApplePayAvailable ? 'Pay with Apple Pay' : 'Pay with Google Pay'}
64
- />
53
+ <View>
54
+ {subscriptions.map((sub) => (
55
+ <Button
56
+ key={sub.sku}
57
+ onPress={() => handleSubscribe(sub.sku)}
58
+ disabled={isProcessing}
59
+ >
60
+ {sub.title} — {sub.priceFormatted}
61
+ </Button>
62
+ ))}
63
+ </View>
65
64
  );
66
65
  }
67
66
  ```
68
67
 
69
68
  ## Flat Function API
70
69
 
71
- For more control, use the flat functions directly:
72
-
73
70
  ```typescript
74
71
  import {
75
- initializePayments,
76
- checkPaymentAvailability,
77
- confirmPayment,
78
- createPaymentMethod,
72
+ initializeIAP,
73
+ getProducts,
74
+ getSubscriptions,
75
+ purchaseProduct,
76
+ purchaseSubscription,
77
+ finishTransaction,
78
+ restorePurchases,
79
+ endConnection,
79
80
  } from '@idealyst/payments';
80
81
 
81
- await initializePayments({
82
- publishableKey: 'pk_test_xxx',
83
- merchantName: 'My App',
84
- merchantCountryCode: 'US',
85
- });
86
-
87
- const methods = await checkPaymentAvailability();
88
- const result = await confirmPayment({ clientSecret: '...', amount: { amount: 1099, currencyCode: 'usd' } });
82
+ await initializeIAP();
83
+ const products = await getProducts(['gem_pack_100', 'gem_pack_500']);
84
+ const purchase = await purchaseProduct('gem_pack_100');
85
+ await finishTransaction(purchase, true); // consumable
86
+ await endConnection(); // cleanup
89
87
  ```
90
88
 
91
89
  ## Platform Support
92
90
 
93
91
  | Feature | iOS | Android | Web |
94
92
  |---------|-----|---------|-----|
95
- | Apple Pay | Yes | | |
96
- | Google Pay | | Yes | |
97
- | Card (via sheet) | Yes | Yes | |
98
- | usePayments hook | Yes | Yes | Stub |
99
-
100
- Web returns all methods as unavailable. Use `@stripe/react-stripe-js` for web payments.
93
+ | Products (one-time) | Yes | Yes | Stub |
94
+ | Subscriptions | Yes | Yes | Stub |
95
+ | Restore Purchases | Yes | Yes | Stub |
96
+ | useIAP hook | Yes | Yes | Stub |
97
+ | purchaseProduct | Yes | Yes | Throws |
98
+ | purchaseSubscription | Yes | Yes | Throws |
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@idealyst/payments",
3
- "version": "1.2.108",
4
- "description": "Cross-platform payment provider abstractions for React and React Native (Apple Pay, Google Pay, Stripe)",
3
+ "version": "1.2.109",
4
+ "description": "Cross-platform In-App Purchase wrapper for React Native (StoreKit 2, Google Play Billing)",
5
5
  "documentation": "https://github.com/IdealystIO/idealyst-framework/tree/main/packages/payments#readme",
6
6
  "readme": "README.md",
7
7
  "main": "src/index.ts",
@@ -38,15 +38,15 @@
38
38
  "publish:npm": "npm publish"
39
39
  },
40
40
  "peerDependencies": {
41
- "@stripe/stripe-react-native": ">=0.38.0",
42
41
  "react": ">=16.8.0",
43
- "react-native": ">=0.60.0"
42
+ "react-native": ">=0.60.0",
43
+ "react-native-iap": ">=14.0.0"
44
44
  },
45
45
  "peerDependenciesMeta": {
46
- "@stripe/stripe-react-native": {
46
+ "react-native": {
47
47
  "optional": true
48
48
  },
49
- "react-native": {
49
+ "react-native-iap": {
50
50
  "optional": true
51
51
  }
52
52
  },
@@ -61,11 +61,11 @@
61
61
  "keywords": [
62
62
  "react",
63
63
  "react-native",
64
- "payments",
65
- "apple-pay",
66
- "google-pay",
67
- "stripe",
68
- "platform-pay",
64
+ "in-app-purchase",
65
+ "iap",
66
+ "storekit",
67
+ "google-play-billing",
68
+ "subscriptions",
69
69
  "cross-platform"
70
70
  ]
71
71
  }
package/src/constants.ts CHANGED
@@ -1,7 +1,6 @@
1
- import type { PaymentProviderStatus } from './types';
1
+ import type { IAPProviderStatus } from './types';
2
2
 
3
- export const INITIAL_PROVIDER_STATUS: PaymentProviderStatus = {
3
+ export const INITIAL_PROVIDER_STATUS: IAPProviderStatus = {
4
4
  state: 'uninitialized',
5
- availablePaymentMethods: [],
6
- isPaymentAvailable: false,
5
+ isStoreAvailable: false,
7
6
  };
package/src/errors.ts CHANGED
@@ -1,46 +1,78 @@
1
- import type { PaymentError, PaymentErrorCode } from './types';
1
+ import type { IAPError, IAPErrorCode } from './types';
2
2
 
3
- export function createPaymentError(
4
- code: PaymentErrorCode,
3
+ export function createIAPError(
4
+ code: IAPErrorCode,
5
5
  message: string,
6
6
  originalError?: unknown,
7
- ): PaymentError {
7
+ ): IAPError {
8
8
  return { code, message, originalError };
9
9
  }
10
10
 
11
11
  /**
12
- * Normalize a Stripe error (or any thrown value) into a PaymentError.
12
+ * Normalize a react-native-iap error (or any thrown value) into an IAPError.
13
+ *
14
+ * react-native-iap errors have a `code` property with values like
15
+ * "E_USER_CANCELLED", "E_ALREADY_OWNED", etc.
13
16
  */
14
- export function normalizeError(error: unknown): PaymentError {
17
+ export function normalizeError(error: unknown): IAPError {
15
18
  if (error && typeof error === 'object' && 'code' in error) {
16
- const stripeError = error as { code?: string; message?: string };
19
+ const iapError = error as { code?: string; message?: string };
17
20
 
18
- switch (stripeError.code) {
19
- case 'Canceled':
20
- case 'cancelled':
21
- return createPaymentError(
21
+ switch (iapError.code) {
22
+ case 'E_USER_CANCELLED':
23
+ return createIAPError(
22
24
  'user_cancelled',
23
- 'Payment was cancelled by user',
25
+ 'Purchase was cancelled by user',
24
26
  error,
25
27
  );
26
- case 'Failed':
27
- return createPaymentError(
28
- 'payment_failed',
29
- stripeError.message || 'Payment failed',
28
+ case 'E_ALREADY_OWNED':
29
+ return createIAPError(
30
+ 'already_owned',
31
+ 'This item has already been purchased',
32
+ error,
33
+ );
34
+ case 'E_NOT_PREPARED':
35
+ return createIAPError(
36
+ 'not_initialized',
37
+ 'IAP connection not initialized. Call initializeIAP() first.',
38
+ error,
39
+ );
40
+ case 'E_DEFERRED':
41
+ return createIAPError(
42
+ 'purchase_pending',
43
+ 'Purchase is pending approval (e.g., Ask to Buy)',
44
+ error,
45
+ );
46
+ case 'E_ITEM_UNAVAILABLE':
47
+ return createIAPError(
48
+ 'item_unavailable',
49
+ 'The requested product is not available in the store',
50
+ error,
51
+ );
52
+ case 'E_NETWORK_ERROR':
53
+ return createIAPError(
54
+ 'network_error',
55
+ iapError.message || 'A network error occurred',
56
+ error,
57
+ );
58
+ case 'E_SERVICE_ERROR':
59
+ return createIAPError(
60
+ 'store_error',
61
+ iapError.message || 'The store service encountered an error',
30
62
  error,
31
63
  );
32
64
  default:
33
- return createPaymentError(
34
- 'provider_error',
35
- stripeError.message || 'An error occurred with the payment provider',
65
+ return createIAPError(
66
+ 'unknown',
67
+ iapError.message || 'An unknown IAP error occurred',
36
68
  error,
37
69
  );
38
70
  }
39
71
  }
40
72
 
41
73
  if (error instanceof Error) {
42
- return createPaymentError('unknown', error.message, error);
74
+ return createIAPError('unknown', error.message, error);
43
75
  }
44
76
 
45
- return createPaymentError('unknown', String(error), error);
77
+ return createIAPError('unknown', String(error), error);
46
78
  }
@@ -1,27 +1,39 @@
1
1
  export * from './types';
2
2
  export { INITIAL_PROVIDER_STATUS } from './constants';
3
- export { createPaymentError, normalizeError } from './errors';
3
+ export { createIAPError, normalizeError } from './errors';
4
4
  export {
5
- initializePayments,
6
- checkPaymentAvailability,
7
- confirmPayment,
8
- createPaymentMethod,
9
- getPaymentStatus,
5
+ initializeIAP,
6
+ getProducts,
7
+ getSubscriptions,
8
+ purchaseProduct,
9
+ purchaseSubscription,
10
+ finishTransaction,
11
+ restorePurchases,
12
+ getIAPStatus,
13
+ endConnection,
10
14
  } from './payments.native';
11
15
 
12
- import { createUsePaymentsHook } from './usePayments';
16
+ import { createUseIAPHook } from './usePayments';
13
17
  import {
14
- initializePayments,
15
- checkPaymentAvailability,
16
- confirmPayment,
17
- createPaymentMethod,
18
- getPaymentStatus,
18
+ initializeIAP,
19
+ getProducts,
20
+ getSubscriptions,
21
+ purchaseProduct,
22
+ purchaseSubscription,
23
+ finishTransaction,
24
+ restorePurchases,
25
+ getIAPStatus,
26
+ endConnection,
19
27
  } from './payments.native';
20
28
 
21
- export const usePayments = createUsePaymentsHook({
22
- initializePayments,
23
- checkPaymentAvailability,
24
- confirmPayment,
25
- createPaymentMethod,
26
- getPaymentStatus,
29
+ export const useIAP = createUseIAPHook({
30
+ initializeIAP,
31
+ getProducts,
32
+ getSubscriptions,
33
+ purchaseProduct,
34
+ purchaseSubscription,
35
+ finishTransaction,
36
+ restorePurchases,
37
+ getIAPStatus,
38
+ endConnection,
27
39
  });
package/src/index.ts CHANGED
@@ -2,28 +2,40 @@
2
2
  // Platform-specific entry points (index.native.ts, index.web.ts) are resolved by bundlers.
3
3
  export * from './types';
4
4
  export { INITIAL_PROVIDER_STATUS } from './constants';
5
- export { createPaymentError, normalizeError } from './errors';
5
+ export { createIAPError, normalizeError } from './errors';
6
6
  export {
7
- initializePayments,
8
- checkPaymentAvailability,
9
- confirmPayment,
10
- createPaymentMethod,
11
- getPaymentStatus,
7
+ initializeIAP,
8
+ getProducts,
9
+ getSubscriptions,
10
+ purchaseProduct,
11
+ purchaseSubscription,
12
+ finishTransaction,
13
+ restorePurchases,
14
+ getIAPStatus,
15
+ endConnection,
12
16
  } from './payments.web';
13
17
 
14
- import { createUsePaymentsHook } from './usePayments';
18
+ import { createUseIAPHook } from './usePayments';
15
19
  import {
16
- initializePayments,
17
- checkPaymentAvailability,
18
- confirmPayment,
19
- createPaymentMethod,
20
- getPaymentStatus,
20
+ initializeIAP,
21
+ getProducts,
22
+ getSubscriptions,
23
+ purchaseProduct,
24
+ purchaseSubscription,
25
+ finishTransaction,
26
+ restorePurchases,
27
+ getIAPStatus,
28
+ endConnection,
21
29
  } from './payments.web';
22
30
 
23
- export const usePayments = createUsePaymentsHook({
24
- initializePayments,
25
- checkPaymentAvailability,
26
- confirmPayment,
27
- createPaymentMethod,
28
- getPaymentStatus,
31
+ export const useIAP = createUseIAPHook({
32
+ initializeIAP,
33
+ getProducts,
34
+ getSubscriptions,
35
+ purchaseProduct,
36
+ purchaseSubscription,
37
+ finishTransaction,
38
+ restorePurchases,
39
+ getIAPStatus,
40
+ endConnection,
29
41
  });
package/src/index.web.ts CHANGED
@@ -1,27 +1,39 @@
1
1
  export * from './types';
2
2
  export { INITIAL_PROVIDER_STATUS } from './constants';
3
- export { createPaymentError, normalizeError } from './errors';
3
+ export { createIAPError, normalizeError } from './errors';
4
4
  export {
5
- initializePayments,
6
- checkPaymentAvailability,
7
- confirmPayment,
8
- createPaymentMethod,
9
- getPaymentStatus,
5
+ initializeIAP,
6
+ getProducts,
7
+ getSubscriptions,
8
+ purchaseProduct,
9
+ purchaseSubscription,
10
+ finishTransaction,
11
+ restorePurchases,
12
+ getIAPStatus,
13
+ endConnection,
10
14
  } from './payments.web';
11
15
 
12
- import { createUsePaymentsHook } from './usePayments';
16
+ import { createUseIAPHook } from './usePayments';
13
17
  import {
14
- initializePayments,
15
- checkPaymentAvailability,
16
- confirmPayment,
17
- createPaymentMethod,
18
- getPaymentStatus,
18
+ initializeIAP,
19
+ getProducts,
20
+ getSubscriptions,
21
+ purchaseProduct,
22
+ purchaseSubscription,
23
+ finishTransaction,
24
+ restorePurchases,
25
+ getIAPStatus,
26
+ endConnection,
19
27
  } from './payments.web';
20
28
 
21
- export const usePayments = createUsePaymentsHook({
22
- initializePayments,
23
- checkPaymentAvailability,
24
- confirmPayment,
25
- createPaymentMethod,
26
- getPaymentStatus,
29
+ export const useIAP = createUseIAPHook({
30
+ initializeIAP,
31
+ getProducts,
32
+ getSubscriptions,
33
+ purchaseProduct,
34
+ purchaseSubscription,
35
+ finishTransaction,
36
+ restorePurchases,
37
+ getIAPStatus,
38
+ endConnection,
27
39
  });