react-native-iap 11.0.0-rc.2 → 11.0.0-rc.3
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/ios/IapSerializationUtils.swift +50 -11
- package/ios/IapTypes.swift +1 -6
- package/ios/RNIapIos.swift +2 -1
- package/ios/RNIapIosSk2.m +2 -1
- package/ios/RNIapIosSk2.swift +29 -16
- package/lib/commonjs/eventEmitter.js +145 -2
- package/lib/commonjs/eventEmitter.js.map +1 -1
- package/lib/commonjs/hooks/withIAPContext.js +8 -1
- package/lib/commonjs/hooks/withIAPContext.js.map +1 -1
- package/lib/commonjs/iap.js +40 -26
- package/lib/commonjs/iap.js.map +1 -1
- package/lib/commonjs/modules/ios.js +5 -2
- package/lib/commonjs/modules/ios.js.map +1 -1
- package/lib/commonjs/modules/iosSk2.js.map +1 -1
- package/lib/commonjs/types/appleSk2.js +2 -2
- package/lib/commonjs/types/appleSk2.js.map +1 -1
- package/lib/module/eventEmitter.js +141 -1
- package/lib/module/eventEmitter.js.map +1 -1
- package/lib/module/hooks/withIAPContext.js +9 -2
- package/lib/module/hooks/withIAPContext.js.map +1 -1
- package/lib/module/iap.js +40 -26
- package/lib/module/iap.js.map +1 -1
- package/lib/module/modules/ios.js +5 -2
- package/lib/module/modules/ios.js.map +1 -1
- package/lib/module/modules/iosSk2.js.map +1 -1
- package/lib/module/types/appleSk2.js +2 -2
- package/lib/module/types/appleSk2.js.map +1 -1
- package/lib/typescript/eventEmitter.d.ts +133 -0
- package/lib/typescript/hooks/withIAPContext.d.ts +2 -0
- package/lib/typescript/iap.d.ts +10 -2
- package/lib/typescript/modules/iosSk2.d.ts +1 -1
- package/lib/typescript/types/appleSk2.d.ts +30 -1
- package/package.json +1 -1
- package/src/eventEmitter.ts +144 -2
- package/src/hooks/withIAPContext.tsx +15 -0
- package/src/iap.ts +14 -6
- package/src/modules/ios.ts +5 -2
- package/src/modules/iosSk2.ts +3 -1
- package/src/types/appleSk2.ts +40 -3
|
@@ -1,17 +1,150 @@
|
|
|
1
1
|
import { EmitterSubscription } from 'react-native';
|
|
2
|
+
import { TransactionEvent } from './types/appleSk2';
|
|
2
3
|
import type { PurchaseError } from './purchaseError';
|
|
3
4
|
import type { Purchase } from './types';
|
|
4
5
|
/**
|
|
5
6
|
* Add IAP purchase event
|
|
7
|
+
* Register a callback that gets called when the store has any updates to purchases that have not yet been finished, consumed or acknowledged. Returns a React Native `EmitterSubscription` on which you can call `.remove()` to stop receiving updates. Register you listener as soon as possible and react to updates at all times.
|
|
8
|
+
|
|
9
|
+
## Signature
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
purchaseUpdatedListener((purchase: Purchase) => {});
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import React, {useEffect} from 'react';
|
|
19
|
+
import {View} from 'react-native';
|
|
20
|
+
import {purchaseUpdatedListener} from 'react-native-iap';
|
|
21
|
+
|
|
22
|
+
const App = () => {
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
const subscription = purchaseUpdatedListener((purchase: Purchase) => {
|
|
25
|
+
console.log(purchase);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
return () => {
|
|
29
|
+
subscription.remove();
|
|
30
|
+
};
|
|
31
|
+
}, []);
|
|
32
|
+
|
|
33
|
+
return <View />;
|
|
34
|
+
};
|
|
35
|
+
```
|
|
6
36
|
*/
|
|
7
37
|
export declare const purchaseUpdatedListener: (listener: (event: Purchase) => void) => EmitterSubscription;
|
|
8
38
|
/**
|
|
9
39
|
* Add IAP purchase error event
|
|
40
|
+
* Register a callback that gets called when there has been an error with a purchase. Returns a React Native `EmitterSubscription` on which you can call `.remove()` to stop receiving updates.
|
|
41
|
+
|
|
42
|
+
## Signature
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
purchaseErrorListener((error: PurchaseError) => {});
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Usage
|
|
49
|
+
|
|
50
|
+
```tsx
|
|
51
|
+
import React, {useEffect} from 'react';
|
|
52
|
+
import {View} from 'react-native';
|
|
53
|
+
import {purchaseErrorListener} from 'react-native-iap';
|
|
54
|
+
|
|
55
|
+
const App = () => {
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
const subscription = purchaseErrorListener((error: PurchaseError) => {
|
|
58
|
+
console.log(error);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
return () => {
|
|
62
|
+
subscription.remove();
|
|
63
|
+
};
|
|
64
|
+
}, []);
|
|
65
|
+
|
|
66
|
+
return <View />;
|
|
67
|
+
};
|
|
68
|
+
```
|
|
69
|
+
|
|
10
70
|
*/
|
|
11
71
|
export declare const purchaseErrorListener: (listener: (error: PurchaseError) => void) => EmitterSubscription;
|
|
12
72
|
/**
|
|
13
73
|
* Add IAP promoted subscription event
|
|
74
|
+
* Add IAP promoted subscription event.
|
|
75
|
+
|
|
76
|
+
## Signature
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
promotedProductListener((productId?: string) => {});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Usage
|
|
83
|
+
|
|
84
|
+
```tsx
|
|
85
|
+
import React, {useEffect} from 'react';
|
|
86
|
+
import {View} from 'react-native';
|
|
87
|
+
import {promotedProductListener} from 'react-native-iap';
|
|
88
|
+
|
|
89
|
+
const App = () => {
|
|
90
|
+
useEffect(() => {
|
|
91
|
+
const subscription = promotedProductListener((productId) => {
|
|
92
|
+
console.log(productId);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
return () => {
|
|
96
|
+
subscription.remove();
|
|
97
|
+
};
|
|
98
|
+
}, []);
|
|
99
|
+
|
|
100
|
+
return <View />;
|
|
101
|
+
};
|
|
102
|
+
```
|
|
103
|
+
|
|
14
104
|
*
|
|
15
105
|
* @platform iOS
|
|
16
106
|
*/
|
|
17
107
|
export declare const promotedProductListener: (listener: () => void) => EmitterSubscription | null;
|
|
108
|
+
/**
|
|
109
|
+
* Updated transactions for iOS Sk2
|
|
110
|
+
* Register a callback that gets called when the store has any updates to transactions related to purchases that have not yet been finished, consumed or acknowledged.
|
|
111
|
+
* Returns a React Native `EmitterSubscription` on which you can call `.remove()` to stop receiving updates. Register you listener as soon as possible and react to updates at all times.
|
|
112
|
+
|
|
113
|
+
**Warning**
|
|
114
|
+
This is only available for iOS 15 and higher and Storekit 2 is activated
|
|
115
|
+
|
|
116
|
+
## Signature
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
purchaseUpdatedListener((transactionOrError: TransactionOrError) => {});
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Usage
|
|
123
|
+
|
|
124
|
+
```tsx
|
|
125
|
+
import React, {useEffect} from 'react';
|
|
126
|
+
import {View} from 'react-native';
|
|
127
|
+
import {purchaseUpdatedListener} from 'react-native-iap';
|
|
128
|
+
|
|
129
|
+
const App = () => {
|
|
130
|
+
useEffect(() => {
|
|
131
|
+
const subscription = purchaseUpdatedListener((transactionOrError: TransactionOrError) => {
|
|
132
|
+
if(transactionOrError.transaction){
|
|
133
|
+
console.log("There's an update to a transaction", transactionOrError.transaction);
|
|
134
|
+
}else{
|
|
135
|
+
console.log("There's been an error with a received transaction")
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
return () => {
|
|
140
|
+
subscription.remove();
|
|
141
|
+
};
|
|
142
|
+
}, []);
|
|
143
|
+
|
|
144
|
+
return <View />;
|
|
145
|
+
};
|
|
146
|
+
```
|
|
147
|
+
*
|
|
148
|
+
* @platform iOS (Sk2)
|
|
149
|
+
*/
|
|
150
|
+
export declare const transactionListener: (listener: (event: TransactionEvent) => void) => EmitterSubscription | null;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { PurchaseError } from '../purchaseError';
|
|
3
3
|
import type { Product, Purchase, Subscription } from '../types';
|
|
4
|
+
import type { TransactionSk2 } from '../types/appleSk2';
|
|
4
5
|
declare type IAPContextType = {
|
|
5
6
|
connected: boolean;
|
|
6
7
|
products: Product[];
|
|
@@ -9,6 +10,7 @@ declare type IAPContextType = {
|
|
|
9
10
|
purchaseHistory: Purchase[];
|
|
10
11
|
availablePurchases: Purchase[];
|
|
11
12
|
currentPurchase?: Purchase;
|
|
13
|
+
currentTransaction?: TransactionSk2;
|
|
12
14
|
currentPurchaseError?: PurchaseError;
|
|
13
15
|
initConnectionError?: Error;
|
|
14
16
|
setProducts: (products: Product[]) => void;
|
package/lib/typescript/iap.d.ts
CHANGED
|
@@ -143,8 +143,12 @@ const App = () => {
|
|
|
143
143
|
return <View />;
|
|
144
144
|
};
|
|
145
145
|
```
|
|
146
|
+
@param {alsoPublishToEventListener}:boolean When `true`, every element will also be pushed to the purchaseUpdated listener.
|
|
147
|
+
Note that this is only for backaward compatiblity. It won't publish to transactionUpdated (Storekit2) Defaults to `false`
|
|
146
148
|
*/
|
|
147
|
-
export declare const getPurchaseHistory: (
|
|
149
|
+
export declare const getPurchaseHistory: ({ alsoPublishToEventListener, }?: {
|
|
150
|
+
alsoPublishToEventListener?: boolean | undefined;
|
|
151
|
+
}) => Promise<(ProductPurchase | SubscriptionPurchase)[]>;
|
|
148
152
|
/**
|
|
149
153
|
* Get all purchases made by the user (either non-consumable, or haven't been consumed yet)
|
|
150
154
|
* ## Usage
|
|
@@ -221,9 +225,13 @@ const App = () => {
|
|
|
221
225
|
)
|
|
222
226
|
};
|
|
223
227
|
```
|
|
228
|
+
@param {alsoPublishToEventListener}:boolean When `true`, every element will also be pushed to the purchaseUpdated listener.
|
|
229
|
+
Note that this is only for backaward compatiblity. It won't publish to transactionUpdated (Storekit2) Defaults to `false`
|
|
224
230
|
*
|
|
225
231
|
*/
|
|
226
|
-
export declare const getAvailablePurchases: (
|
|
232
|
+
export declare const getAvailablePurchases: ({ alsoPublishToEventListener, }?: {
|
|
233
|
+
alsoPublishToEventListener?: boolean | undefined;
|
|
234
|
+
}) => Promise<(ProductPurchase | SubscriptionPurchase)[]>;
|
|
227
235
|
/**
|
|
228
236
|
* Request a purchase for product. This will be received in `PurchaseUpdatedListener`.
|
|
229
237
|
* Request a purchase for a product (consumables or non-consumables).
|
|
@@ -2,7 +2,7 @@ import type { Product, ProductPurchase, Purchase, Sku } from '../types';
|
|
|
2
2
|
import type { PaymentDiscountSk2, ProductSk2, ProductStatus, TransactionSk2 } from '../types/appleSk2';
|
|
3
3
|
import type { NativeModuleProps } from './common';
|
|
4
4
|
declare type getItems = (skus: Sku[]) => Promise<ProductSk2[]>;
|
|
5
|
-
declare type getAvailableItems = () => Promise<Purchase[]>;
|
|
5
|
+
declare type getAvailableItems = (alsoPublishToEventListener?: boolean) => Promise<Purchase[]>;
|
|
6
6
|
export declare type BuyProduct = (sku: Sku, andDangerouslyFinishTransactionAutomaticallyIOS: boolean, applicationUsername: string | undefined, quantity: number, withOffer: PaymentDiscountSk2 | undefined) => Promise<Purchase>;
|
|
7
7
|
declare type clearTransaction = () => Promise<void>;
|
|
8
8
|
declare type clearProducts = () => Promise<void>;
|
|
@@ -1,5 +1,26 @@
|
|
|
1
|
+
import type { PurchaseError } from '../purchaseError';
|
|
1
2
|
import type { ProductIOS, Purchase, SubscriptionIOS } from '.';
|
|
2
3
|
import type * as Apple from './apple';
|
|
4
|
+
export declare type SubscriptionPeriod = {
|
|
5
|
+
unit: 'day' | 'week' | 'month' | 'year';
|
|
6
|
+
value: number;
|
|
7
|
+
};
|
|
8
|
+
export declare type PaymentMode = 'freeTrial' | 'payAsYouGo' | 'payUpFront';
|
|
9
|
+
export declare type SubscriptionOffer = {
|
|
10
|
+
displayPrice: string;
|
|
11
|
+
id: string;
|
|
12
|
+
paymentMode: PaymentMode;
|
|
13
|
+
period: SubscriptionPeriod;
|
|
14
|
+
periodCount: number;
|
|
15
|
+
price: number;
|
|
16
|
+
type: 'introductory' | 'promotional';
|
|
17
|
+
};
|
|
18
|
+
export declare type SubscriptionInfo = {
|
|
19
|
+
introductoryOffer?: SubscriptionOffer;
|
|
20
|
+
promotionalOffers?: SubscriptionOffer[];
|
|
21
|
+
subscriptionGroupID: string;
|
|
22
|
+
subscriptionPeriod: SubscriptionPeriod;
|
|
23
|
+
};
|
|
3
24
|
export declare type ProductSk2 = {
|
|
4
25
|
description: string;
|
|
5
26
|
displayName: string;
|
|
@@ -8,7 +29,7 @@ export declare type ProductSk2 = {
|
|
|
8
29
|
isFamilyShareable: boolean;
|
|
9
30
|
jsonRepresentation: string;
|
|
10
31
|
price: number;
|
|
11
|
-
subscription:
|
|
32
|
+
subscription: SubscriptionInfo;
|
|
12
33
|
type: 'autoRenewable' | 'consumable' | 'nonConsumable' | 'nonRenewable';
|
|
13
34
|
};
|
|
14
35
|
export declare const productSk2Map: ({ id, description, displayName, price, displayPrice, }: ProductSk2) => ProductIOS;
|
|
@@ -38,6 +59,14 @@ export declare type TransactionSk2 = {
|
|
|
38
59
|
subscriptionGroupID: number;
|
|
39
60
|
webOrderLineItemID: number;
|
|
40
61
|
};
|
|
62
|
+
export declare type TransactionError = PurchaseError;
|
|
63
|
+
/**
|
|
64
|
+
* Only one of `transaction` and `error` is not undefined at the time
|
|
65
|
+
*/
|
|
66
|
+
export declare type TransactionEvent = {
|
|
67
|
+
transaction?: TransactionSk2;
|
|
68
|
+
error?: TransactionError;
|
|
69
|
+
};
|
|
41
70
|
export declare type SubscriptionStatus = 'expired' | 'inBillingRetryPeriod' | 'inGracePeriod' | 'revoked' | 'subscribed';
|
|
42
71
|
export declare type ProductStatus = {
|
|
43
72
|
state: SubscriptionStatus;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-iap",
|
|
3
|
-
"version": "11.0.0-rc.
|
|
3
|
+
"version": "11.0.0-rc.3",
|
|
4
4
|
"description": "React Native In App Purchase Module.",
|
|
5
5
|
"repository": "https://github.com/dooboolab/react-native-iap",
|
|
6
6
|
"author": "dooboolab <support@dooboolab.com> (https://github.com/dooboolab)",
|
package/src/eventEmitter.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {EmitterSubscription, NativeEventEmitter} from 'react-native';
|
|
2
2
|
|
|
3
|
-
import {transactionSk2Map} from './types/appleSk2';
|
|
3
|
+
import {TransactionEvent, transactionSk2Map} from './types/appleSk2';
|
|
4
4
|
import {isIosStorekit2} from './iap';
|
|
5
5
|
import {
|
|
6
6
|
getAndroidModule,
|
|
@@ -14,6 +14,35 @@ import type {Purchase} from './types';
|
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Add IAP purchase event
|
|
17
|
+
* Register a callback that gets called when the store has any updates to purchases that have not yet been finished, consumed or acknowledged. Returns a React Native `EmitterSubscription` on which you can call `.remove()` to stop receiving updates. Register you listener as soon as possible and react to updates at all times.
|
|
18
|
+
|
|
19
|
+
## Signature
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
purchaseUpdatedListener((purchase: Purchase) => {});
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
import React, {useEffect} from 'react';
|
|
29
|
+
import {View} from 'react-native';
|
|
30
|
+
import {purchaseUpdatedListener} from 'react-native-iap';
|
|
31
|
+
|
|
32
|
+
const App = () => {
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
const subscription = purchaseUpdatedListener((purchase: Purchase) => {
|
|
35
|
+
console.log(purchase);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
return () => {
|
|
39
|
+
subscription.remove();
|
|
40
|
+
};
|
|
41
|
+
}, []);
|
|
42
|
+
|
|
43
|
+
return <View />;
|
|
44
|
+
};
|
|
45
|
+
```
|
|
17
46
|
*/
|
|
18
47
|
export const purchaseUpdatedListener = (
|
|
19
48
|
listener: (event: Purchase) => void,
|
|
@@ -38,6 +67,36 @@ export const purchaseUpdatedListener = (
|
|
|
38
67
|
|
|
39
68
|
/**
|
|
40
69
|
* Add IAP purchase error event
|
|
70
|
+
* Register a callback that gets called when there has been an error with a purchase. Returns a React Native `EmitterSubscription` on which you can call `.remove()` to stop receiving updates.
|
|
71
|
+
|
|
72
|
+
## Signature
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
purchaseErrorListener((error: PurchaseError) => {});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Usage
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
import React, {useEffect} from 'react';
|
|
82
|
+
import {View} from 'react-native';
|
|
83
|
+
import {purchaseErrorListener} from 'react-native-iap';
|
|
84
|
+
|
|
85
|
+
const App = () => {
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
const subscription = purchaseErrorListener((error: PurchaseError) => {
|
|
88
|
+
console.log(error);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
return () => {
|
|
92
|
+
subscription.remove();
|
|
93
|
+
};
|
|
94
|
+
}, []);
|
|
95
|
+
|
|
96
|
+
return <View />;
|
|
97
|
+
};
|
|
98
|
+
```
|
|
99
|
+
|
|
41
100
|
*/
|
|
42
101
|
export const purchaseErrorListener = (
|
|
43
102
|
listener: (error: PurchaseError) => void,
|
|
@@ -48,14 +107,97 @@ export const purchaseErrorListener = (
|
|
|
48
107
|
|
|
49
108
|
/**
|
|
50
109
|
* Add IAP promoted subscription event
|
|
110
|
+
* Add IAP promoted subscription event.
|
|
111
|
+
|
|
112
|
+
## Signature
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
promotedProductListener((productId?: string) => {});
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Usage
|
|
119
|
+
|
|
120
|
+
```tsx
|
|
121
|
+
import React, {useEffect} from 'react';
|
|
122
|
+
import {View} from 'react-native';
|
|
123
|
+
import {promotedProductListener} from 'react-native-iap';
|
|
124
|
+
|
|
125
|
+
const App = () => {
|
|
126
|
+
useEffect(() => {
|
|
127
|
+
const subscription = promotedProductListener((productId) => {
|
|
128
|
+
console.log(productId);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
return () => {
|
|
132
|
+
subscription.remove();
|
|
133
|
+
};
|
|
134
|
+
}, []);
|
|
135
|
+
|
|
136
|
+
return <View />;
|
|
137
|
+
};
|
|
138
|
+
```
|
|
139
|
+
|
|
51
140
|
*
|
|
52
141
|
* @platform iOS
|
|
53
142
|
*/
|
|
54
143
|
export const promotedProductListener = (listener: () => void) => {
|
|
55
|
-
if (isIos) {
|
|
144
|
+
if (isIos && !isIosStorekit2()) {
|
|
56
145
|
const eventEmitter = new NativeEventEmitter(getIosModule());
|
|
57
146
|
return eventEmitter.addListener('iap-promoted-product', listener);
|
|
58
147
|
}
|
|
59
148
|
|
|
60
149
|
return null;
|
|
61
150
|
};
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Updated transactions for iOS Sk2
|
|
154
|
+
* Register a callback that gets called when the store has any updates to transactions related to purchases that have not yet been finished, consumed or acknowledged.
|
|
155
|
+
* Returns a React Native `EmitterSubscription` on which you can call `.remove()` to stop receiving updates. Register you listener as soon as possible and react to updates at all times.
|
|
156
|
+
|
|
157
|
+
**Warning**
|
|
158
|
+
This is only available for iOS 15 and higher and Storekit 2 is activated
|
|
159
|
+
|
|
160
|
+
## Signature
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
purchaseUpdatedListener((transactionOrError: TransactionOrError) => {});
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Usage
|
|
167
|
+
|
|
168
|
+
```tsx
|
|
169
|
+
import React, {useEffect} from 'react';
|
|
170
|
+
import {View} from 'react-native';
|
|
171
|
+
import {purchaseUpdatedListener} from 'react-native-iap';
|
|
172
|
+
|
|
173
|
+
const App = () => {
|
|
174
|
+
useEffect(() => {
|
|
175
|
+
const subscription = purchaseUpdatedListener((transactionOrError: TransactionOrError) => {
|
|
176
|
+
if(transactionOrError.transaction){
|
|
177
|
+
console.log("There's an update to a transaction", transactionOrError.transaction);
|
|
178
|
+
}else{
|
|
179
|
+
console.log("There's been an error with a received transaction")
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
return () => {
|
|
184
|
+
subscription.remove();
|
|
185
|
+
};
|
|
186
|
+
}, []);
|
|
187
|
+
|
|
188
|
+
return <View />;
|
|
189
|
+
};
|
|
190
|
+
```
|
|
191
|
+
*
|
|
192
|
+
* @platform iOS (Sk2)
|
|
193
|
+
*/
|
|
194
|
+
export const transactionListener = (
|
|
195
|
+
listener: (event: TransactionEvent) => void,
|
|
196
|
+
) => {
|
|
197
|
+
if (isIos && isIosStorekit2()) {
|
|
198
|
+
const eventEmitter = new NativeEventEmitter(getIosModule());
|
|
199
|
+
return eventEmitter.addListener('iap-transaction-updated', listener);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return null;
|
|
203
|
+
};
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
promotedProductListener,
|
|
5
5
|
purchaseErrorListener,
|
|
6
6
|
purchaseUpdatedListener,
|
|
7
|
+
transactionListener,
|
|
7
8
|
} from '../eventEmitter';
|
|
8
9
|
import {IapIos, initConnection} from '../iap';
|
|
9
10
|
import type {PurchaseError} from '../purchaseError';
|
|
@@ -14,6 +15,7 @@ import type {
|
|
|
14
15
|
Subscription,
|
|
15
16
|
SubscriptionPurchase,
|
|
16
17
|
} from '../types';
|
|
18
|
+
import type {TransactionEvent, TransactionSk2} from '../types/appleSk2';
|
|
17
19
|
|
|
18
20
|
type IAPContextType = {
|
|
19
21
|
connected: boolean;
|
|
@@ -23,6 +25,7 @@ type IAPContextType = {
|
|
|
23
25
|
purchaseHistory: Purchase[];
|
|
24
26
|
availablePurchases: Purchase[];
|
|
25
27
|
currentPurchase?: Purchase;
|
|
28
|
+
currentTransaction?: TransactionSk2;
|
|
26
29
|
currentPurchaseError?: PurchaseError;
|
|
27
30
|
initConnectionError?: Error;
|
|
28
31
|
setProducts: (products: Product[]) => void;
|
|
@@ -63,6 +66,8 @@ export function withIAPContext<T>(Component: React.ComponentType<T>) {
|
|
|
63
66
|
[],
|
|
64
67
|
);
|
|
65
68
|
const [currentPurchase, setCurrentPurchase] = useState<Purchase>();
|
|
69
|
+
const [currentTransaction, setCurrentTransaction] =
|
|
70
|
+
useState<TransactionSk2>();
|
|
66
71
|
|
|
67
72
|
const [currentPurchaseError, setCurrentPurchaseError] =
|
|
68
73
|
useState<PurchaseError>();
|
|
@@ -78,6 +83,7 @@ export function withIAPContext<T>(Component: React.ComponentType<T>) {
|
|
|
78
83
|
purchaseHistory,
|
|
79
84
|
availablePurchases,
|
|
80
85
|
currentPurchase,
|
|
86
|
+
currentTransaction,
|
|
81
87
|
currentPurchaseError,
|
|
82
88
|
initConnectionError,
|
|
83
89
|
setProducts,
|
|
@@ -95,6 +101,7 @@ export function withIAPContext<T>(Component: React.ComponentType<T>) {
|
|
|
95
101
|
purchaseHistory,
|
|
96
102
|
availablePurchases,
|
|
97
103
|
currentPurchase,
|
|
104
|
+
currentTransaction,
|
|
98
105
|
currentPurchaseError,
|
|
99
106
|
initConnectionError,
|
|
100
107
|
setProducts,
|
|
@@ -127,6 +134,13 @@ export function withIAPContext<T>(Component: React.ComponentType<T>) {
|
|
|
127
134
|
},
|
|
128
135
|
);
|
|
129
136
|
|
|
137
|
+
const transactionUpdateSubscription = transactionListener(
|
|
138
|
+
async (transactionOrError: TransactionEvent) => {
|
|
139
|
+
setCurrentPurchaseError(transactionOrError?.error);
|
|
140
|
+
setCurrentTransaction(transactionOrError?.transaction);
|
|
141
|
+
},
|
|
142
|
+
);
|
|
143
|
+
|
|
130
144
|
const purchaseErrorSubscription = purchaseErrorListener(
|
|
131
145
|
(error: PurchaseError) => {
|
|
132
146
|
setCurrentPurchase(undefined);
|
|
@@ -147,6 +161,7 @@ export function withIAPContext<T>(Component: React.ComponentType<T>) {
|
|
|
147
161
|
purchaseUpdateSubscription.remove();
|
|
148
162
|
purchaseErrorSubscription.remove();
|
|
149
163
|
promotedProductSubscription?.remove();
|
|
164
|
+
transactionUpdateSubscription?.remove();
|
|
150
165
|
};
|
|
151
166
|
}, [connected]);
|
|
152
167
|
|
package/src/iap.ts
CHANGED
|
@@ -248,14 +248,18 @@ const App = () => {
|
|
|
248
248
|
return <View />;
|
|
249
249
|
};
|
|
250
250
|
```
|
|
251
|
+
@param {alsoPublishToEventListener}:boolean When `true`, every element will also be pushed to the purchaseUpdated listener.
|
|
252
|
+
Note that this is only for backaward compatiblity. It won't publish to transactionUpdated (Storekit2) Defaults to `false`
|
|
251
253
|
*/
|
|
252
|
-
export const getPurchaseHistory = (
|
|
253
|
-
|
|
254
|
-
|
|
254
|
+
export const getPurchaseHistory = ({
|
|
255
|
+
alsoPublishToEventListener = false,
|
|
256
|
+
}: {
|
|
257
|
+
alsoPublishToEventListener?: boolean;
|
|
258
|
+
} = {}): Promise<(ProductPurchase | SubscriptionPurchase)[]> =>
|
|
255
259
|
(
|
|
256
260
|
Platform.select({
|
|
257
261
|
ios: async () => {
|
|
258
|
-
return getIosModule().getAvailableItems();
|
|
262
|
+
return getIosModule().getAvailableItems(alsoPublishToEventListener);
|
|
259
263
|
},
|
|
260
264
|
android: async () => {
|
|
261
265
|
if (RNIapAmazonModule) {
|
|
@@ -351,15 +355,19 @@ const App = () => {
|
|
|
351
355
|
)
|
|
352
356
|
};
|
|
353
357
|
```
|
|
358
|
+
@param {alsoPublishToEventListener}:boolean When `true`, every element will also be pushed to the purchaseUpdated listener.
|
|
359
|
+
Note that this is only for backaward compatiblity. It won't publish to transactionUpdated (Storekit2) Defaults to `false`
|
|
354
360
|
*
|
|
355
361
|
*/
|
|
356
|
-
export const getAvailablePurchases = (
|
|
362
|
+
export const getAvailablePurchases = ({
|
|
363
|
+
alsoPublishToEventListener = false,
|
|
364
|
+
}: {alsoPublishToEventListener?: boolean} = {}): Promise<
|
|
357
365
|
(ProductPurchase | SubscriptionPurchase)[]
|
|
358
366
|
> =>
|
|
359
367
|
(
|
|
360
368
|
Platform.select({
|
|
361
369
|
ios: async () => {
|
|
362
|
-
return getIosModule().getAvailableItems();
|
|
370
|
+
return getIosModule().getAvailableItems(alsoPublishToEventListener);
|
|
363
371
|
},
|
|
364
372
|
android: async () => {
|
|
365
373
|
if (RNIapAmazonModule) {
|
package/src/modules/ios.ts
CHANGED
|
@@ -84,7 +84,7 @@ export const getPromotedProductIOS = (): Promise<Product | null> => {
|
|
|
84
84
|
if (!isIosStorekit2()) {
|
|
85
85
|
return getIosModule().promotedProduct();
|
|
86
86
|
} else {
|
|
87
|
-
return Promise.reject('Only available on
|
|
87
|
+
return Promise.reject('Only available on Sk1');
|
|
88
88
|
}
|
|
89
89
|
};
|
|
90
90
|
|
|
@@ -146,7 +146,10 @@ export const validateReceiptIos = async ({
|
|
|
146
146
|
? 'https://sandbox.itunes.apple.com/verifyReceipt'
|
|
147
147
|
: 'https://buy.itunes.apple.com/verifyReceipt';
|
|
148
148
|
|
|
149
|
-
return await enhancedFetch<ReceiptValidationResponse>(url
|
|
149
|
+
return await enhancedFetch<ReceiptValidationResponse>(url, {
|
|
150
|
+
method: 'POST',
|
|
151
|
+
body: receiptBody,
|
|
152
|
+
});
|
|
150
153
|
};
|
|
151
154
|
|
|
152
155
|
/**
|
package/src/modules/iosSk2.ts
CHANGED
|
@@ -13,7 +13,9 @@ const {RNIapIosSk2} = NativeModules;
|
|
|
13
13
|
|
|
14
14
|
type getItems = (skus: Sku[]) => Promise<ProductSk2[]>;
|
|
15
15
|
|
|
16
|
-
type getAvailableItems = (
|
|
16
|
+
type getAvailableItems = (
|
|
17
|
+
alsoPublishToEventListener?: boolean,
|
|
18
|
+
) => Promise<Purchase[]>;
|
|
17
19
|
|
|
18
20
|
export type BuyProduct = (
|
|
19
21
|
sku: Sku,
|
package/src/types/appleSk2.ts
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
|
+
import type {PurchaseError} from '../purchaseError';
|
|
2
|
+
|
|
1
3
|
import type {ProductIOS, Purchase, SubscriptionIOS} from '.';
|
|
2
4
|
import type * as Apple from './apple';
|
|
5
|
+
|
|
6
|
+
export type SubscriptionPeriod = {
|
|
7
|
+
unit: 'day' | 'week' | 'month' | 'year';
|
|
8
|
+
value: number;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export type PaymentMode = 'freeTrial' | 'payAsYouGo' | 'payUpFront';
|
|
12
|
+
|
|
13
|
+
export type SubscriptionOffer = {
|
|
14
|
+
displayPrice: string;
|
|
15
|
+
id: string;
|
|
16
|
+
paymentMode: PaymentMode;
|
|
17
|
+
period: SubscriptionPeriod;
|
|
18
|
+
periodCount: number;
|
|
19
|
+
price: number;
|
|
20
|
+
type: 'introductory' | 'promotional';
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type SubscriptionInfo = {
|
|
24
|
+
introductoryOffer?: SubscriptionOffer;
|
|
25
|
+
promotionalOffers?: SubscriptionOffer[];
|
|
26
|
+
subscriptionGroupID: string;
|
|
27
|
+
subscriptionPeriod: SubscriptionPeriod;
|
|
28
|
+
};
|
|
29
|
+
|
|
3
30
|
export type ProductSk2 = {
|
|
4
31
|
description: string;
|
|
5
32
|
displayName: string;
|
|
@@ -8,7 +35,7 @@ export type ProductSk2 = {
|
|
|
8
35
|
isFamilyShareable: boolean;
|
|
9
36
|
jsonRepresentation: string;
|
|
10
37
|
price: number;
|
|
11
|
-
subscription:
|
|
38
|
+
subscription: SubscriptionInfo;
|
|
12
39
|
type: 'autoRenewable' | 'consumable' | 'nonConsumable' | 'nonRenewable';
|
|
13
40
|
};
|
|
14
41
|
export const productSk2Map = ({
|
|
@@ -25,7 +52,7 @@ export const productSk2Map = ({
|
|
|
25
52
|
type: 'iap',
|
|
26
53
|
price: String(price),
|
|
27
54
|
localizedPrice: displayPrice,
|
|
28
|
-
currency: '', //
|
|
55
|
+
currency: '', // Not avaiable on new API, use localizedPrice instead
|
|
29
56
|
};
|
|
30
57
|
return prod;
|
|
31
58
|
};
|
|
@@ -44,7 +71,7 @@ export const subscriptionSk2Map = ({
|
|
|
44
71
|
type: 'subs',
|
|
45
72
|
price: String(price),
|
|
46
73
|
localizedPrice: displayPrice,
|
|
47
|
-
currency: '', //
|
|
74
|
+
currency: '', // Not avaiable on new API, use localizedPrice instead
|
|
48
75
|
};
|
|
49
76
|
return prod;
|
|
50
77
|
};
|
|
@@ -75,6 +102,16 @@ export type TransactionSk2 = {
|
|
|
75
102
|
webOrderLineItemID: number;
|
|
76
103
|
};
|
|
77
104
|
|
|
105
|
+
export type TransactionError = PurchaseError;
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Only one of `transaction` and `error` is not undefined at the time
|
|
109
|
+
*/
|
|
110
|
+
export type TransactionEvent = {
|
|
111
|
+
transaction?: TransactionSk2;
|
|
112
|
+
error?: TransactionError;
|
|
113
|
+
};
|
|
114
|
+
|
|
78
115
|
export type SubscriptionStatus =
|
|
79
116
|
| 'expired'
|
|
80
117
|
| 'inBillingRetryPeriod'
|