expo-iap 1.0.3 → 2.0.0-rc.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 (103) hide show
  1. package/.eslintrc.js +9 -0
  2. package/.prettierrc.js +9 -0
  3. package/.swiftlint.yml +10 -0
  4. package/README.md +28 -21
  5. package/android/build.gradle +34 -72
  6. package/android/src/main/AndroidManifest.xml +1 -4
  7. package/android/src/main/java/expo/modules/iap/ExpoIapModule.kt +535 -0
  8. package/android/src/main/java/expo/modules/iap/MissingCurrentActivityException.kt +6 -0
  9. package/android/src/main/java/expo/modules/iap/PlayUtils.kt +124 -0
  10. package/build/ExpoIap.types.d.ts +89 -0
  11. package/build/ExpoIap.types.d.ts.map +1 -0
  12. package/build/ExpoIap.types.js +59 -0
  13. package/build/ExpoIap.types.js.map +1 -0
  14. package/build/ExpoIapModule.d.ts +3 -0
  15. package/build/ExpoIapModule.d.ts.map +1 -0
  16. package/build/ExpoIapModule.js +5 -0
  17. package/build/ExpoIapModule.js.map +1 -0
  18. package/build/index.d.ts +38 -0
  19. package/build/index.d.ts.map +1 -0
  20. package/build/index.js +202 -0
  21. package/build/index.js.map +1 -0
  22. package/build/modules/android.d.ts +40 -0
  23. package/build/modules/android.d.ts.map +1 -0
  24. package/build/modules/android.js +54 -0
  25. package/build/modules/android.js.map +1 -0
  26. package/build/modules/ios.d.ts +41 -0
  27. package/build/modules/ios.d.ts.map +1 -0
  28. package/build/modules/ios.js +44 -0
  29. package/build/modules/ios.js.map +1 -0
  30. package/build/types/ExpoIapAndroid.types.d.ts +113 -0
  31. package/build/types/ExpoIapAndroid.types.d.ts.map +1 -0
  32. package/build/types/ExpoIapAndroid.types.js +23 -0
  33. package/build/types/ExpoIapAndroid.types.js.map +1 -0
  34. package/build/types/ExpoIapIos.types.d.ts +122 -0
  35. package/build/types/ExpoIapIos.types.d.ts.map +1 -0
  36. package/build/types/ExpoIapIos.types.js +2 -0
  37. package/build/types/ExpoIapIos.types.js.map +1 -0
  38. package/bun.lockb +0 -0
  39. package/expo-module.config.json +4 -8
  40. package/ios/ExpoIap.podspec +27 -0
  41. package/ios/ExpoIapModule.swift +498 -0
  42. package/ios/ProductStore.swift +27 -0
  43. package/ios/Types.swift +54 -0
  44. package/package.json +33 -62
  45. package/src/ExpoIap.types.ts +125 -0
  46. package/src/ExpoIapModule.ts +5 -0
  47. package/src/index.ts +397 -0
  48. package/src/modules/android.ts +89 -0
  49. package/src/modules/ios.ts +81 -0
  50. package/src/types/ExpoIapAndroid.types.ts +123 -0
  51. package/src/types/ExpoIapIos.types.ts +141 -0
  52. package/tsconfig.json +9 -0
  53. package/.editorconfig +0 -10
  54. package/.flowconfig +0 -11
  55. package/.monolinterrc +0 -3
  56. package/.yarn/install-state.gz +0 -0
  57. package/.yarn/releases/yarn-3.1.1.cjs +0 -768
  58. package/.yarnrc.yml +0 -3
  59. package/LICENSE +0 -21
  60. package/RNIap.podspec +0 -18
  61. package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  62. package/android/gradle/wrapper/gradle-wrapper.properties +0 -6
  63. package/android/gradle.properties +0 -2
  64. package/android/gradlew +0 -160
  65. package/android/gradlew.bat +0 -90
  66. package/android/libs/in-app-purchasing-2.0.76.jar +0 -0
  67. package/android/src/amazon/AndroidManifest.xml +0 -12
  68. package/android/src/amazon/java/com/dooboolab/RNIap/RNIapAmazonListener.kt +0 -356
  69. package/android/src/amazon/java/com/dooboolab/RNIap/RNIapAmazonModule.kt +0 -128
  70. package/android/src/amazon/java/com/dooboolab/RNIap/RNIapPackage.kt +0 -20
  71. package/android/src/main/java/com/dooboolab/RNIap/DoobooUtils.kt +0 -180
  72. package/android/src/play/java/com/dooboolab/RNIap/PlayUtils.kt +0 -77
  73. package/android/src/play/java/com/dooboolab/RNIap/RNIapModule.kt +0 -698
  74. package/android/src/play/java/com/dooboolab/RNIap/RNIapPackage.kt +0 -20
  75. package/babel.config.js +0 -10
  76. package/index.d.ts +0 -3
  77. package/index.js +0 -3
  78. package/index.js.flow +0 -9
  79. package/ios/RNIap.xcodeproj/project.pbxproj +0 -370
  80. package/ios/RNIap.xcodeproj/xcshareddata/xcschemes/RNIap.xcscheme +0 -80
  81. package/ios/RNIapIos.m +0 -60
  82. package/ios/RNIapIos.swift +0 -932
  83. package/ios/RNIapQueue.swift +0 -35
  84. package/jest.config.js +0 -194
  85. package/src/__test__/iap.test.d.ts +0 -1
  86. package/src/__test__/iap.test.js +0 -59
  87. package/src/hooks/useIAP.d.ts +0 -21
  88. package/src/hooks/useIAP.js +0 -140
  89. package/src/hooks/withIAPContext.d.ts +0 -21
  90. package/src/hooks/withIAPContext.js +0 -142
  91. package/src/iap.d.ts +0 -197
  92. package/src/iap.js +0 -625
  93. package/src/index.d.ts +0 -4
  94. package/src/index.js +0 -4
  95. package/src/types/amazon.d.ts +0 -23
  96. package/src/types/amazon.js +0 -1
  97. package/src/types/android.d.ts +0 -47
  98. package/src/types/android.js +0 -22
  99. package/src/types/apple.d.ts +0 -424
  100. package/src/types/apple.js +0 -165
  101. package/src/types/index.d.ts +0 -117
  102. package/src/types/index.js +0 -40
  103. package/test/mocks/react-native-modules.js +0 -14
@@ -0,0 +1,89 @@
1
+ import {Linking} from 'react-native';
2
+ import {Product, PurchaseResult, SubscriptionProduct} from '../ExpoIap.types';
3
+ import {ProductAndroid, ReceiptAndroid, SubscriptionProductAndroid} from '../types/ExpoIapAndroid.types';
4
+ import ExpoIapModule from '../ExpoIapModule';
5
+
6
+ export function isProductAndroid(product: Product): product is ProductAndroid {
7
+ return (product as ProductAndroid)?.title !== undefined;
8
+ }
9
+
10
+ export function isSubscriptionProductAndroid(product: SubscriptionProduct): product is SubscriptionProductAndroid {
11
+ return (product as SubscriptionProductAndroid)?.title !== undefined;
12
+ }
13
+
14
+ /**
15
+ * Deep link to subscriptions screen on Android.
16
+ * @param {string} sku The product's SKU (on Android)
17
+ * @returns {Promise<void>}
18
+ */
19
+ export const deepLinkToSubscriptionsAndroid = async ({
20
+ sku,
21
+ }: {
22
+ sku: string;
23
+ }): Promise<void> => {
24
+ return Linking.openURL(
25
+ `https://play.google.com/store/account/subscriptions?package=${await ExpoIapModule.getPackageName()}&sku=${sku}`,
26
+ );
27
+ };
28
+
29
+ /**
30
+ * Validate receipt for Android. NOTE: This method is here for debugging purposes only. Including
31
+ * your access token in the binary you ship to users is potentially dangerous.
32
+ * Use server side validation instead for your production builds
33
+ * @param {string} packageName package name of your app.
34
+ * @param {string} productId product id for your in app product.
35
+ * @param {string} productToken token for your purchase.
36
+ * @param {string} accessToken accessToken from googleApis.
37
+ * @param {boolean} isSub whether this is subscription or inapp. `true` for subscription.
38
+ * @returns {Promise<object>}
39
+ */
40
+ export const validateReceiptAndroid = async ({
41
+ packageName,
42
+ productId,
43
+ productToken,
44
+ accessToken,
45
+ isSub,
46
+ }: {
47
+ packageName: string;
48
+ productId: string;
49
+ productToken: string;
50
+ accessToken: string;
51
+ isSub?: boolean;
52
+ }): Promise<ReceiptAndroid> => {
53
+ const type = isSub ? 'subscriptions' : 'products';
54
+
55
+ const url =
56
+ 'https://androidpublisher.googleapis.com/androidpublisher/v3/applications' +
57
+ `/${packageName}/purchases/${type}/${productId}` +
58
+ `/tokens/${productToken}?access_token=${accessToken}`;
59
+
60
+ const response = await fetch(url, {
61
+ method: 'GET',
62
+ headers: {
63
+ 'Content-Type': 'application/json',
64
+ },
65
+ });
66
+
67
+ if (!response.ok) {
68
+ throw Object.assign(new Error(response.statusText), {
69
+ statusCode: response.status,
70
+ });
71
+ }
72
+
73
+ return response.json();
74
+ };
75
+
76
+ /**
77
+ * Acknowledge a product (on Android.) No-op on iOS.
78
+ * @param {string} token The product's token (on Android)
79
+ * @returns {Promise<PurchaseResult | void>}
80
+ */
81
+ export const acknowledgePurchaseAndroid = ({
82
+ token,
83
+ developerPayload,
84
+ }: {
85
+ token: string;
86
+ developerPayload?: string;
87
+ }): Promise<PurchaseResult | boolean | void> => {
88
+ return ExpoIapModule.acknowledgePurchase(token, developerPayload);
89
+ };
@@ -0,0 +1,81 @@
1
+ import {Platform} from 'react-native';
2
+ import {emitter, IapEvent} from '..';
3
+ import {Product, PurchaseError, SubscriptionProduct} from '../ExpoIap.types';
4
+ import type {
5
+ ProductIos,
6
+ ProductStatusIos,
7
+ SubscriptionProductIos,
8
+ TransactionSk2,
9
+ } from '../types/ExpoIapIos.types';
10
+ import ExpoIapModule from '../ExpoIapModule';
11
+
12
+ type TransactionEvent = {
13
+ transaction?: TransactionSk2;
14
+ error?: PurchaseError;
15
+ };
16
+
17
+ // Listeners
18
+ export const transactionUpdatedIos = (
19
+ listener: (event: TransactionEvent) => void,
20
+ ) => {
21
+ if (Platform.OS !== 'ios') {
22
+ throw new Error('This method is only available on iOS');
23
+ }
24
+
25
+ return emitter.addListener(IapEvent.TransactionIapUpdated, listener);
26
+ };
27
+
28
+ // Functions
29
+ export function isProductIos(product: Product): product is ProductIos {
30
+ return (product as ProductIos)?.displayName !== undefined;
31
+ }
32
+
33
+ export function isSubscriptionProductIos(
34
+ product: SubscriptionProduct,
35
+ ): product is SubscriptionProductIos {
36
+ return (product as SubscriptionProductIos)?.displayName !== undefined;
37
+ }
38
+
39
+ /**
40
+ * Sync state with Appstore (iOS only)
41
+ * https://developer.apple.com/documentation/storekit/appstore/3791906-sync
42
+ */
43
+ export const sync = (): Promise<null> => ExpoIapModule.sync();
44
+
45
+ /**
46
+ *
47
+ */
48
+ export const isEligibleForIntroOffer = (groupID: string): Promise<boolean> =>
49
+ ExpoIapModule.isEligibleForIntroOffer(groupID);
50
+
51
+ /**
52
+ *
53
+ */
54
+
55
+ export const subscriptionStatus = (sku: string): Promise<ProductStatusIos[]> =>
56
+ ExpoIapModule.subscriptionStatus(sku);
57
+
58
+ /**
59
+ *
60
+ */
61
+ export const currentEntitlement = (sku: string): Promise<TransactionSk2> =>
62
+ ExpoIapModule.currentEntitlement(sku);
63
+
64
+ /**
65
+ *
66
+ */
67
+ export const latestTransaction = (sku: string): Promise<TransactionSk2> =>
68
+ ExpoIapModule.latestTransaction(sku);
69
+
70
+ /**
71
+ *
72
+ */
73
+ type RefundRequestStatus = 'success' | 'userCancelled';
74
+ export const beginRefundRequest = (sku: string): Promise<RefundRequestStatus> =>
75
+ ExpoIapModule.beginRefundRequest(sku);
76
+
77
+ /**
78
+ *
79
+ */
80
+ export const showManageSubscriptions = (): Promise<null> =>
81
+ ExpoIapModule.showManageSubscriptions();
@@ -0,0 +1,123 @@
1
+ type OneTimePurchaseOfferDetails = {
2
+ priceCurrencyCode: string;
3
+ formattedPrice: string;
4
+ priceAmountMicros: string;
5
+ };
6
+
7
+ type SubscriptionOfferDetail = {
8
+ basePlanId: string;
9
+ offerId: string;
10
+ offerToken: string;
11
+ offerTags: string[];
12
+ pricingPhases: PricingPhases;
13
+ };
14
+
15
+ type PricingPhases = {
16
+ pricingPhaseList: PricingPhase[];
17
+ };
18
+
19
+ type PricingPhase = {
20
+ formattedPrice: string;
21
+ priceCurrencyCode: string;
22
+ billingPeriod: string;
23
+ billingCycleCount: number;
24
+ priceAmountMicros: string;
25
+ recurrenceMode: number;
26
+ };
27
+
28
+ export type ProductAndroid = {
29
+ productId: string;
30
+ title: string;
31
+ description: string;
32
+ productType: string;
33
+ name: string;
34
+ oneTimePurchaseOfferDetails?: OneTimePurchaseOfferDetails;
35
+ subscriptionOfferDetails?: SubscriptionOfferDetail[];
36
+ };
37
+
38
+ type PricingPhaseAndroid = {
39
+ formattedPrice: string;
40
+ priceCurrencyCode: string;
41
+ // P1W, P1M, P1Y
42
+ billingPeriod: string;
43
+ billingCycleCount: number;
44
+ priceAmountMicros: string;
45
+ recurrenceMode: number;
46
+ };
47
+
48
+ type SubscriptionOfferAndroid = {
49
+ basePlanId: string;
50
+ offerId: string | null;
51
+ offerToken: string;
52
+ pricingPhases: {pricingPhaseList: PricingPhaseAndroid[]};
53
+ offerTags: string[];
54
+ };
55
+
56
+ export type SubscriptionProductAndroid = ProductAndroid & {
57
+ name: string;
58
+ title: string;
59
+ description: string;
60
+ productId: string;
61
+ subscriptionOfferDetails: SubscriptionOfferAndroid[];
62
+ };
63
+
64
+ export type RequestPurchaseAndroidProps = {
65
+ skus: string[];
66
+ obfuscatedAccountIdAndroid?: string;
67
+ obfuscatedProfileIdAndroid?: string;
68
+ isOfferPersonalized?: boolean; // For AndroidBilling V5 https://developer.android.com/google/play/billing/integrate#personalized-price
69
+ };
70
+
71
+ enum ReplacementModesAndroid {
72
+ UNKNOWN_REPLACEMENT_MODE = 0,
73
+ WITH_TIME_PRORATION = 1,
74
+ CHARGE_PRORATED_PRICE = 2,
75
+ WITHOUT_PRORATION = 3,
76
+ CHARGE_FULL_PRICE = 5,
77
+ DEFERRED = 6,
78
+ }
79
+
80
+ type SubscriptionOffer = {
81
+ sku: string;
82
+ offerToken: string;
83
+ };
84
+
85
+ export type RequestSubscriptionAndroidProps = RequestPurchaseAndroidProps & {
86
+ purchaseTokenAndroid?: string;
87
+ replacementModeAndroid?: ReplacementModesAndroid;
88
+ subscriptionOffers: SubscriptionOffer[];
89
+ };
90
+
91
+ export type ReceiptAndroid = {
92
+ autoRenewing: boolean;
93
+ betaProduct: boolean;
94
+ cancelDate: number | null;
95
+ cancelReason: string;
96
+ deferredDate: number | null;
97
+ deferredSku: number | null;
98
+ freeTrialEndDate: number;
99
+ gracePeriodEndDate: number;
100
+ parentProductId: string;
101
+ productId: string;
102
+ productType: string;
103
+ purchaseDate: number;
104
+ quantity: number;
105
+ receiptId: string;
106
+ renewalDate: number;
107
+ term: string;
108
+ termSku: string;
109
+ testTransaction: boolean;
110
+ };
111
+
112
+ export enum FeatureTypeAndroid {
113
+ /** Show in-app messages. Included in documentation by the annotations: */
114
+ IN_APP_MESSAGING = 'IN_APP_MESSAGING',
115
+ /** Launch a price change confirmation flow. */
116
+ PRICE_CHANGE_CONFIRMATION = 'PRICE_CHANGE_CONFIRMATION',
117
+ /** Play billing library support for querying and purchasing with ProductDetails. */
118
+ PRODUCT_DETAILS = 'PRODUCT_DETAILS',
119
+ /** Purchase/query for subscriptions. */
120
+ SUBSCRIPTIONS = 'SUBSCRIPTIONS',
121
+ /** Subscriptions update/replace. */
122
+ SUBSCRIPTIONS_UPDATE = 'SUBSCRIPTIONS_UPDATE',
123
+ }
@@ -0,0 +1,141 @@
1
+ type SubscriptionIosPeriod = 'DAY' | 'WEEK' | 'MONTH' | 'YEAR' | '';
2
+ type PaymentMode = '' | 'FREETRIAL' | 'PAYASYOUGO' | 'PAYUPFRONT';
3
+
4
+ type SubscriptionOffer = {
5
+ displayPrice: string;
6
+ id: string;
7
+ paymentMode: PaymentMode;
8
+ period: SubscriptionIosPeriod;
9
+ periodCount: number;
10
+ price: number;
11
+ type: 'introductory' | 'promotional';
12
+ };
13
+
14
+ type SubscriptionInfo = {
15
+ introductoryOffer?: SubscriptionOffer;
16
+ promotionalOffers?: SubscriptionOffer[];
17
+ subscriptionGroupID: string;
18
+ subscriptionPeriod: SubscriptionIosPeriod;
19
+ };
20
+
21
+ export type ProductIos = {
22
+ currency: string;
23
+ description: string;
24
+ displayName: string;
25
+ displayPrice: string;
26
+ id: string;
27
+ type: 'autoRenewable' | 'consumable' | 'nonConsumable' | 'nonRenewable';
28
+ isFamilyShareable: boolean;
29
+ jsonRepresentation: string;
30
+ price: number;
31
+ subscription: SubscriptionInfo;
32
+ introductoryPriceNumberOfPeriodsIOS?: string;
33
+ introductoryPriceSubscriptionPeriodIOS?: SubscriptionIosPeriod;
34
+ };
35
+
36
+ type Discount = {
37
+ identifier: string;
38
+ type: string;
39
+ numberOfPeriods: string;
40
+ price: string;
41
+ localizedPrice: string;
42
+ paymentMode: PaymentMode;
43
+ subscriptionPeriod: string;
44
+ };
45
+
46
+ export type SubscriptionProductIos = ProductIos & {
47
+ discounts?: Discount[];
48
+ introductoryPrice?: string;
49
+ introductoryPriceAsAmountIOS?: string;
50
+ introductoryPricePaymentModeIOS?: PaymentMode;
51
+ introductoryPriceNumberOfPeriodsIOS?: string;
52
+ introductoryPriceSubscriptionPeriodIOS?: SubscriptionIosPeriod;
53
+ subscriptionPeriodNumberIOS?: string;
54
+ subscriptionPeriodUnitIOS?: SubscriptionIosPeriod;
55
+ };
56
+
57
+ export type PaymentDiscount = {
58
+ /**
59
+ * A string used to uniquely identify a discount offer for a product.
60
+ */
61
+ identifier: string;
62
+
63
+ /**
64
+ * A string that identifies the key used to generate the signature.
65
+ */
66
+ keyIdentifier: string;
67
+
68
+ /**
69
+ * A universally unique ID (UUID) value that you define.
70
+ */
71
+ nonce: string;
72
+
73
+ /**
74
+ * A UTF-8 string representing the properties of a specific discount offer, cryptographically signed.
75
+ */
76
+ signature: string;
77
+
78
+ /**
79
+ * The date and time of the signature's creation in milliseconds, formatted in Unix epoch time.
80
+ */
81
+ timestamp: number;
82
+ };
83
+
84
+ export type RequestPurchaseIosProps = {
85
+ sku: string;
86
+ andDangerouslyFinishTransactionAutomaticallyIOS?: boolean;
87
+ /**
88
+ * UUID representing user account
89
+ */
90
+ appAccountToken?: string;
91
+ quantity?: number;
92
+ withOffer?: PaymentDiscount;
93
+ };
94
+
95
+ export type RequestSubscriptionIosProps = RequestPurchaseIosProps;
96
+
97
+ export type TransactionSk2 = {
98
+ appAccountToken: string;
99
+ appBundleID: string;
100
+ debugDescription: string;
101
+ deviceVerification: string;
102
+ deviceVerificationNonce: string;
103
+ expirationDate: number;
104
+ environment?: 'Production' | 'Sandbox' | 'Xcode'; // Could be undefined in some cases on iOS 15, but it's stable since iOS 16
105
+ id: number;
106
+ isUpgraded: boolean;
107
+ jsonRepresentation: string;
108
+ offerID: string;
109
+ offerType: string;
110
+ originalID: string;
111
+ originalPurchaseDate: number;
112
+ ownershipType: string;
113
+ productID: string;
114
+ productType: string;
115
+ purchaseDate: number;
116
+ purchasedQuantity: number;
117
+ revocationDate: number;
118
+ revocationReason: string;
119
+ signedDate: number;
120
+ subscriptionGroupID: number;
121
+ webOrderLineItemID: number;
122
+ verificationResult?: string;
123
+ };
124
+
125
+ type SubscriptionStatus =
126
+ | 'expired'
127
+ | 'inBillingRetryPeriod'
128
+ | 'inGracePeriod'
129
+ | 'revoked'
130
+ | 'subscribed';
131
+
132
+ type RenewalInfo = {
133
+ jsonRepresentation?: string;
134
+ willAutoRenew: boolean;
135
+ autoRenewPreference?: string;
136
+ };
137
+
138
+ export type ProductStatusIos = {
139
+ state: SubscriptionStatus;
140
+ renewalInfo?: RenewalInfo;
141
+ };
package/tsconfig.json ADDED
@@ -0,0 +1,9 @@
1
+ // @generated by expo-module-scripts
2
+ {
3
+ "extends": "expo-module-scripts/tsconfig.base",
4
+ "compilerOptions": {
5
+ "outDir": "./build"
6
+ },
7
+ "include": ["./src"],
8
+ "exclude": ["**/__mocks__/*", "**/__tests__/*"]
9
+ }
package/.editorconfig DELETED
@@ -1,10 +0,0 @@
1
- root = true
2
-
3
- [*]
4
- end_of_line = lf
5
- insert_final_newline = true
6
-
7
- [*.{js,json,yml}]
8
- charset = utf-8
9
- indent_style = space
10
- indent_size = 2
package/.flowconfig DELETED
@@ -1,11 +0,0 @@
1
- [ignore]
2
- <PROJECT_ROOT>/node_modules/.*
3
- [include]
4
-
5
- [libs]
6
-
7
- [lints]
8
-
9
- [options]
10
-
11
- [strict]
package/.monolinterrc DELETED
@@ -1,3 +0,0 @@
1
- {
2
- "include":["package.json","docs/package.json","IapExample/package.json"]
3
- }
Binary file