react-native-iap 10.1.0 → 10.1.2
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 +0 -1
- package/ios/RNIapIos.swift +3 -3
- package/lib/commonjs/iap.js +344 -30
- package/lib/commonjs/iap.js.map +1 -1
- package/lib/commonjs/index.js +13 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/types/index.js.map +1 -1
- package/lib/module/iap.js +344 -30
- package/lib/module/iap.js.map +1 -1
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/types/index.js.map +1 -1
- package/lib/typescript/iap.d.ts +345 -55
- package/lib/typescript/index.d.ts +1 -0
- package/lib/typescript/types/index.d.ts +33 -1
- package/package.json +5 -2
- package/src/iap.ts +348 -55
- package/src/index.ts +1 -0
- package/src/types/index.ts +43 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["ProrationModesAndroid","PurchaseStateAndroid","PROMOTED_PRODUCT","InstallSourceAndroid","ProductType"],"sources":["index.ts"],"sourcesContent":["import type {\n AmazonModuleProps,\n AndroidModuleProps,\n IosModuleProps,\n} from '../modules';\n\nexport type Sku = string;\n\nexport enum ProrationModesAndroid {\n IMMEDIATE_WITH_TIME_PRORATION = 1,\n IMMEDIATE_AND_CHARGE_PRORATED_PRICE = 2,\n IMMEDIATE_WITHOUT_PRORATION = 3,\n DEFERRED = 4,\n IMMEDIATE_AND_CHARGE_FULL_PRICE = 5,\n UNKNOWN_SUBSCRIPTION_UPGRADE_DOWNGRADE_POLICY = 0,\n}\n\nexport enum PurchaseStateAndroid {\n UNSPECIFIED_STATE = 0,\n PURCHASED = 1,\n PENDING = 2,\n}\n\nexport const PROMOTED_PRODUCT = 'iap-promoted-product';\n\nexport enum InstallSourceAndroid {\n NOT_SET = 0,\n GOOGLE_PLAY = 1,\n AMAZON = 2,\n}\n\nexport enum ProductType {\n /** Subscription */\n subs = 'subs',\n\n /** Subscription */\n sub = 'sub',\n\n /** Consumable */\n inapp = 'inapp',\n\n /** Consumable */\n iap = 'iap',\n}\n\nexport interface ProductCommon {\n type: 'subs' | 'sub' | 'inapp' | 'iap';\n productId: string
|
|
1
|
+
{"version":3,"names":["ProrationModesAndroid","PurchaseStateAndroid","PROMOTED_PRODUCT","InstallSourceAndroid","ProductType"],"sources":["index.ts"],"sourcesContent":["import type {\n AmazonModuleProps,\n AndroidModuleProps,\n IosModuleProps,\n} from '../modules';\n\nimport type * as Apple from './apple';\n\nexport type Sku = string;\n\nexport enum ProrationModesAndroid {\n IMMEDIATE_WITH_TIME_PRORATION = 1,\n IMMEDIATE_AND_CHARGE_PRORATED_PRICE = 2,\n IMMEDIATE_WITHOUT_PRORATION = 3,\n DEFERRED = 4,\n IMMEDIATE_AND_CHARGE_FULL_PRICE = 5,\n UNKNOWN_SUBSCRIPTION_UPGRADE_DOWNGRADE_POLICY = 0,\n}\n\nexport enum PurchaseStateAndroid {\n UNSPECIFIED_STATE = 0,\n PURCHASED = 1,\n PENDING = 2,\n}\n\nexport const PROMOTED_PRODUCT = 'iap-promoted-product';\n\nexport enum InstallSourceAndroid {\n NOT_SET = 0,\n GOOGLE_PLAY = 1,\n AMAZON = 2,\n}\n\nexport enum ProductType {\n /** Subscription */\n subs = 'subs',\n\n /** Subscription */\n sub = 'sub',\n\n /** Consumable */\n inapp = 'inapp',\n\n /** Consumable */\n iap = 'iap',\n}\n\nexport interface ProductCommon {\n type: 'subs' | 'sub' | 'inapp' | 'iap';\n productId: string; //iOS\n productIds?: string[];\n title: string;\n description: string;\n price: string;\n currency: string;\n localizedPrice: string;\n countryCode?: string;\n}\n\nexport interface ProductPurchase {\n productId: string;\n transactionId?: string;\n transactionDate: number;\n transactionReceipt: string;\n purchaseToken?: string;\n //iOS\n quantityIOS?: number;\n originalTransactionDateIOS?: string;\n originalTransactionIdentifierIOS?: string;\n //Android\n productIds?: string[];\n dataAndroid?: string;\n signatureAndroid?: string;\n autoRenewingAndroid?: boolean;\n purchaseStateAndroid?: PurchaseStateAndroid;\n isAcknowledgedAndroid?: boolean;\n packageNameAndroid?: string;\n developerPayloadAndroid?: string;\n obfuscatedAccountIdAndroid?: string;\n obfuscatedProfileIdAndroid?: string;\n //Amazon\n userIdAmazon?: string;\n userMarketplaceAmazon?: string;\n userJsonAmazon?: string;\n isCanceledAmazon?: boolean;\n}\n\nexport interface PurchaseResult {\n responseCode?: number;\n debugMessage?: string;\n code?: string;\n message?: string;\n purchaseToken?: string;\n}\n\nexport interface SubscriptionPurchase extends ProductPurchase {\n autoRenewingAndroid?: boolean;\n originalTransactionDateIOS?: string;\n originalTransactionIdentifierIOS?: string;\n}\n\nexport type Purchase = ProductPurchase | SubscriptionPurchase;\n\nexport interface Discount {\n identifier: string;\n type: string;\n numberOfPeriods: string;\n price: string;\n localizedPrice: string;\n paymentMode: '' | 'FREETRIAL' | 'PAYASYOUGO' | 'PAYUPFRONT';\n subscriptionPeriod: string;\n}\n\nexport interface ProductAndroid extends ProductCommon {\n type: 'inapp' | 'iap';\n oneTimePurchaseOfferDetails?: {\n priceCurrencyCode: string;\n formattedPrice: string;\n priceAmountMicros: string;\n };\n}\nexport interface ProductIOS extends ProductCommon {\n type: 'inapp' | 'iap';\n}\n\nexport type Product = ProductAndroid & ProductIOS;\n\n// Android V5\nexport interface SubscriptionAndroid extends ProductCommon {\n type: 'subs';\n\n productType?: string;\n name?: string;\n subscriptionOfferDetails?: {\n offerToken: string;\n pricingPhases: {\n pricingPhaseList: {\n formattedPrice: string;\n priceCurrencyCode: string;\n /**\n * P1W, P1M, P1Y\n */\n billingPeriod: string;\n billingCycleCount: number;\n priceAmountMicros: string;\n recurrenceMode: number;\n }[];\n };\n offerTags: string[];\n }[];\n}\n\nexport interface SubscriptionIOS extends ProductCommon {\n type: 'subs';\n discounts?: Discount[];\n introductoryPrice?: string;\n introductoryPriceAsAmountIOS?: string;\n introductoryPricePaymentModeIOS?:\n | ''\n | 'FREETRIAL'\n | 'PAYASYOUGO'\n | 'PAYUPFRONT';\n introductoryPriceNumberOfPeriodsIOS?: string;\n introductoryPriceSubscriptionPeriodIOS?:\n | 'DAY'\n | 'WEEK'\n | 'MONTH'\n | 'YEAR'\n | '';\n\n subscriptionPeriodNumberIOS?: string;\n subscriptionPeriodUnitIOS?: '' | 'YEAR' | 'MONTH' | 'WEEK' | 'DAY';\n}\n\nexport type Subscription = SubscriptionAndroid & SubscriptionIOS;\nexport interface RequestPurchaseBaseAndroid {\n obfuscatedAccountIdAndroid?: string;\n obfuscatedProfileIdAndroid?: string;\n isOfferPersonalized?: boolean; // For AndroidBilling V5 https://developer.android.com/google/play/billing/integrate#personalized-price\n}\n\nexport interface RequestPurchaseAndroid extends RequestPurchaseBaseAndroid {\n skus?: Sku[];\n}\n\nexport interface RequestPurchaseIOS {\n sku?: Sku;\n andDangerouslyFinishTransactionAutomaticallyIOS?: boolean;\n /**\n * UUID representing user account\n */\n applicationUsername?: string;\n quantity?: number;\n withOffer?: Apple.PaymentDiscount;\n}\n\nexport type RequestPurchase = RequestPurchaseAndroid & RequestPurchaseIOS;\n\n/**\n * In order to purchase a new subscription, every sku must have a selected offerToken\n * @see SubscriptionAndroid.subscriptionOfferDetails.offerToken\n */\nexport interface SubscriptionOffer {\n sku: Sku;\n offerToken: string;\n}\n\nexport interface RequestSubscriptionAndroid extends RequestPurchaseBaseAndroid {\n purchaseTokenAndroid?: string;\n prorationModeAndroid?: ProrationModesAndroid;\n subscriptionOffers?: SubscriptionOffer[]; // For AndroidBilling V5\n}\n\nexport type RequestSubscriptionIOS = RequestPurchaseIOS;\n\nexport type RequestSubscription = RequestSubscriptionAndroid &\n RequestSubscriptionIOS;\n\ndeclare module 'react-native' {\n interface NativeModulesStatic {\n RNIapIos: IosModuleProps;\n RNIapModule: AndroidModuleProps;\n RNIapAmazonModule: AmazonModuleProps;\n }\n}\n"],"mappings":"AAUA,WAAYA,qBAAZ;;WAAYA,qB;EAAAA,qB,CAAAA,qB;EAAAA,qB,CAAAA,qB;EAAAA,qB,CAAAA,qB;EAAAA,qB,CAAAA,qB;EAAAA,qB,CAAAA,qB;EAAAA,qB,CAAAA,qB;GAAAA,qB,KAAAA,qB;;AASZ,WAAYC,oBAAZ;;WAAYA,oB;EAAAA,oB,CAAAA,oB;EAAAA,oB,CAAAA,oB;EAAAA,oB,CAAAA,oB;GAAAA,oB,KAAAA,oB;;AAMZ,OAAO,MAAMC,gBAAgB,GAAG,sBAAzB;AAEP,WAAYC,oBAAZ;;WAAYA,oB;EAAAA,oB,CAAAA,oB;EAAAA,oB,CAAAA,oB;EAAAA,oB,CAAAA,oB;GAAAA,oB,KAAAA,oB;;AAMZ,WAAYC,WAAZ;;WAAYA,W;EAAAA,W;EAAAA,W;EAAAA,W;EAAAA,W;GAAAA,W,KAAAA,W"}
|
package/lib/typescript/iap.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { ResponseBody as ReceiptValidationResponse } from '@jeremybarbet/ap
|
|
|
2
2
|
import type * as Amazon from './types/amazon';
|
|
3
3
|
import type * as Android from './types/android';
|
|
4
4
|
import type * as Apple from './types/apple';
|
|
5
|
-
import { Product, ProductPurchase,
|
|
5
|
+
import { Product, ProductPurchase, Purchase, PurchaseResult, RequestPurchase, RequestSubscription, Sku, Subscription, SubscriptionPurchase } from './types';
|
|
6
6
|
import { InstallSourceAndroid } from './types';
|
|
7
7
|
export declare const getInstallSourceAndroid: () => InstallSourceAndroid;
|
|
8
8
|
export declare const setAndroidNativeModule: (nativeModule: import("./modules").AndroidModuleProps) => void;
|
|
@@ -11,11 +11,41 @@ export declare const getIosModule: () => import("./modules").IosModuleProps;
|
|
|
11
11
|
export declare const getNativeModule: () => import("./modules").AmazonModuleProps | import("./modules").AndroidModuleProps | import("./modules").IosModuleProps;
|
|
12
12
|
/**
|
|
13
13
|
* Init module for purchase flow. Required on Android. In ios it will check whether user canMakePayment.
|
|
14
|
-
*
|
|
14
|
+
* ## Usage
|
|
15
|
+
|
|
16
|
+
```tsx
|
|
17
|
+
import React, {useEffect} from 'react';
|
|
18
|
+
import {View} from 'react-native';
|
|
19
|
+
import {initConnection} from 'react-native-iap';
|
|
20
|
+
|
|
21
|
+
const App = () => {
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
void initConnection();
|
|
24
|
+
}, []);
|
|
25
|
+
|
|
26
|
+
return <View />;
|
|
27
|
+
};
|
|
28
|
+
```
|
|
15
29
|
*/
|
|
16
30
|
export declare const initConnection: () => Promise<boolean>;
|
|
17
31
|
/**
|
|
18
|
-
*
|
|
32
|
+
* Disconnects from native SDK
|
|
33
|
+
* Usage
|
|
34
|
+
* ```tsx
|
|
35
|
+
import React, {useEffect} from 'react';
|
|
36
|
+
import {View} from 'react-native';
|
|
37
|
+
import {endConnection} from 'react-native-iap';
|
|
38
|
+
|
|
39
|
+
const App = () => {
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
return () => {
|
|
42
|
+
void endConnection();
|
|
43
|
+
};
|
|
44
|
+
}, []);
|
|
45
|
+
|
|
46
|
+
return <View />;
|
|
47
|
+
};
|
|
48
|
+
```
|
|
19
49
|
* @returns {Promise<void>}
|
|
20
50
|
*/
|
|
21
51
|
export declare const endConnection: () => Promise<boolean>;
|
|
@@ -26,76 +56,324 @@ export declare const endConnection: () => Promise<boolean>;
|
|
|
26
56
|
export declare const flushFailedPurchasesCachedAsPendingAndroid: () => Promise<boolean>;
|
|
27
57
|
/**
|
|
28
58
|
* Get a list of products (consumable and non-consumable items, but not subscriptions)
|
|
29
|
-
|
|
30
|
-
|
|
59
|
+
## Usage
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
import React, {useState} from 'react';
|
|
63
|
+
import {Platform} from 'react-native';
|
|
64
|
+
import {getProducts, Product} from 'react-native-iap';
|
|
65
|
+
|
|
66
|
+
const skus = Platform.select({
|
|
67
|
+
ios: ['com.example.consumableIos'],
|
|
68
|
+
android: ['com.example.consumableAndroid'],
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const App = () => {
|
|
72
|
+
const [products, setProducts] = useState<Product[]>([]);
|
|
73
|
+
|
|
74
|
+
const handleProducts = async () => {
|
|
75
|
+
const items = await getProducts({skus});
|
|
76
|
+
|
|
77
|
+
setProducts(items);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
void handleProducts();
|
|
82
|
+
}, []);
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<>
|
|
86
|
+
{products.map((product) => (
|
|
87
|
+
<Text key={product.productId}>{product.productId}</Text>
|
|
88
|
+
))}
|
|
89
|
+
</>
|
|
90
|
+
);
|
|
91
|
+
};
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Just a few things to keep in mind:
|
|
95
|
+
|
|
96
|
+
- You can get your products in `componentDidMount`, `useEffect` or another appropriate area of your app.
|
|
97
|
+
- Since a user may start your app with a bad or no internet connection, preparing/getting the items more than once may be a good idea.
|
|
98
|
+
- If the user has no IAPs available when the app starts first, you may want to check again when the user enters your IAP store.
|
|
99
|
+
|
|
31
100
|
*/
|
|
32
101
|
export declare const getProducts: ({ skus, }: {
|
|
33
102
|
skus: string[];
|
|
34
103
|
}) => Promise<Array<Product>>;
|
|
35
104
|
/**
|
|
36
105
|
* Get a list of subscriptions
|
|
37
|
-
*
|
|
38
|
-
|
|
106
|
+
* ## Usage
|
|
107
|
+
|
|
108
|
+
```tsx
|
|
109
|
+
import React, {useCallback} from 'react';
|
|
110
|
+
import {View} from 'react-native';
|
|
111
|
+
import {getSubscriptions} from 'react-native-iap';
|
|
112
|
+
|
|
113
|
+
const App = () => {
|
|
114
|
+
const subscriptions = useCallback(
|
|
115
|
+
async () =>
|
|
116
|
+
await getSubscriptions(['com.example.product1', 'com.example.product2']),
|
|
117
|
+
[],
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
return <View />;
|
|
121
|
+
};
|
|
122
|
+
```
|
|
123
|
+
|
|
39
124
|
*/
|
|
40
125
|
export declare const getSubscriptions: ({ skus, }: {
|
|
41
126
|
skus: string[];
|
|
42
127
|
}) => Promise<Subscription[]>;
|
|
43
128
|
/**
|
|
44
129
|
* Gets an inventory of purchases made by the user regardless of consumption status
|
|
45
|
-
*
|
|
130
|
+
* ## Usage
|
|
131
|
+
|
|
132
|
+
```tsx
|
|
133
|
+
import React, {useCallback} from 'react';
|
|
134
|
+
import {View} from 'react-native';
|
|
135
|
+
import {getPurchaseHistory} from 'react-native-iap';
|
|
136
|
+
|
|
137
|
+
const App = () => {
|
|
138
|
+
const history = useCallback(
|
|
139
|
+
async () =>
|
|
140
|
+
await getPurchaseHistory([
|
|
141
|
+
'com.example.product1',
|
|
142
|
+
'com.example.product2',
|
|
143
|
+
]),
|
|
144
|
+
[],
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
return <View />;
|
|
148
|
+
};
|
|
149
|
+
```
|
|
46
150
|
*/
|
|
47
151
|
export declare const getPurchaseHistory: () => Promise<(ProductPurchase | SubscriptionPurchase)[]>;
|
|
48
152
|
/**
|
|
49
153
|
* Get all purchases made by the user (either non-consumable, or haven't been consumed yet)
|
|
50
|
-
*
|
|
154
|
+
* ## Usage
|
|
155
|
+
|
|
156
|
+
```tsx
|
|
157
|
+
import React, {useCallback} from 'react';
|
|
158
|
+
import {View} from 'react-native';
|
|
159
|
+
import {getAvailablePurchases} from 'react-native-iap';
|
|
160
|
+
|
|
161
|
+
const App = () => {
|
|
162
|
+
const availablePurchases = useCallback(
|
|
163
|
+
async () => await getAvailablePurchases(),
|
|
164
|
+
[],
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
return <View />;
|
|
168
|
+
};
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Restoring purchases
|
|
172
|
+
|
|
173
|
+
You can use `getAvailablePurchases()` to do what's commonly understood as "restoring" purchases.
|
|
174
|
+
|
|
175
|
+
:::note
|
|
176
|
+
For debugging you may want to consume all items, you have then to iterate over the purchases returned by `getAvailablePurchases()`.
|
|
177
|
+
:::
|
|
178
|
+
|
|
179
|
+
:::warning
|
|
180
|
+
Beware that if you consume an item without having recorded the purchase in your database the user may have paid for something without getting it delivered and you will have no way to recover the receipt to validate and restore their purchase.
|
|
181
|
+
:::
|
|
182
|
+
|
|
183
|
+
```tsx
|
|
184
|
+
import React from 'react';
|
|
185
|
+
import {Button} from 'react-native';
|
|
186
|
+
import {getAvailablePurchases,finishTransaction} from 'react-native-iap';
|
|
187
|
+
|
|
188
|
+
const App = () => {
|
|
189
|
+
handleRestore = async () => {
|
|
190
|
+
try {
|
|
191
|
+
const purchases = await getAvailablePurchases();
|
|
192
|
+
const newState = {premium: false, ads: true};
|
|
193
|
+
let titles = [];
|
|
194
|
+
|
|
195
|
+
await Promise.all(purchases.map(async purchase => {
|
|
196
|
+
switch (purchase.productId) {
|
|
197
|
+
case 'com.example.premium':
|
|
198
|
+
newState.premium = true;
|
|
199
|
+
titles.push('Premium Version');
|
|
200
|
+
break;
|
|
201
|
+
|
|
202
|
+
case 'com.example.no_ads':
|
|
203
|
+
newState.ads = false;
|
|
204
|
+
titles.push('No Ads');
|
|
205
|
+
break;
|
|
206
|
+
|
|
207
|
+
case 'com.example.coins100':
|
|
208
|
+
await finishTransaction(purchase.purchaseToken);
|
|
209
|
+
CoinStore.addCoins(100);
|
|
210
|
+
}
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
Alert.alert(
|
|
214
|
+
'Restore Successful',
|
|
215
|
+
`You successfully restored the following purchases: ${titles.join(', ')}`,
|
|
216
|
+
);
|
|
217
|
+
} catch (error) {
|
|
218
|
+
console.warn(error);
|
|
219
|
+
Alert.alert(error.message);
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
return (
|
|
224
|
+
<Button title="Restore purchases" onPress={handleRestore} />
|
|
225
|
+
)
|
|
226
|
+
};
|
|
227
|
+
```
|
|
228
|
+
*
|
|
51
229
|
*/
|
|
52
230
|
export declare const getAvailablePurchases: () => Promise<(ProductPurchase | SubscriptionPurchase)[]>;
|
|
53
231
|
/**
|
|
54
232
|
* Request a purchase for product. This will be received in `PurchaseUpdatedListener`.
|
|
55
|
-
*
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
233
|
+
* Request a purchase for a product (consumables or non-consumables).
|
|
234
|
+
|
|
235
|
+
The response will be received through the `PurchaseUpdatedListener`.
|
|
236
|
+
|
|
237
|
+
:::note
|
|
238
|
+
`andDangerouslyFinishTransactionAutomatically` defaults to false. We recommend
|
|
239
|
+
always keeping at false, and verifying the transaction receipts on the server-side.
|
|
240
|
+
:::
|
|
241
|
+
|
|
242
|
+
## Signature
|
|
243
|
+
|
|
244
|
+
```ts
|
|
245
|
+
requestPurchase(
|
|
246
|
+
The product's sku/ID
|
|
247
|
+
sku,
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
* You should set this to false and call finishTransaction manually when you have delivered the purchased goods to the user.
|
|
251
|
+
* @default false
|
|
252
|
+
|
|
253
|
+
andDangerouslyFinishTransactionAutomaticallyIOS = false,
|
|
254
|
+
|
|
255
|
+
/** Specifies an optional obfuscated string that is uniquely associated with the user's account in your app.
|
|
256
|
+
obfuscatedAccountIdAndroid,
|
|
257
|
+
|
|
258
|
+
Specifies an optional obfuscated string that is uniquely associated with the user's profile in your app.
|
|
259
|
+
obfuscatedProfileIdAndroid,
|
|
260
|
+
|
|
261
|
+
The purchaser's user ID
|
|
262
|
+
applicationUsername,
|
|
263
|
+
): Promise<ProductPurchase>;
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Usage
|
|
267
|
+
|
|
268
|
+
```tsx
|
|
269
|
+
import React, {useCallback} from 'react';
|
|
270
|
+
import {Button} from 'react-native';
|
|
271
|
+
import {requestPurchase, Product, Sku, getProducts} from 'react-native-iap';
|
|
272
|
+
|
|
273
|
+
const App = () => {
|
|
274
|
+
const products = useCallback(
|
|
275
|
+
async () => getProducts(['com.example.product']),
|
|
276
|
+
[],
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
const handlePurchase = async (sku: Sku) => {
|
|
280
|
+
await requestPurchase({sku});
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
return (
|
|
284
|
+
<>
|
|
285
|
+
{products.map((product) => (
|
|
286
|
+
<Button
|
|
287
|
+
key={product.productId}
|
|
288
|
+
title="Buy product"
|
|
289
|
+
onPress={() => handlePurchase(product.productId)}
|
|
290
|
+
/>
|
|
291
|
+
))}
|
|
292
|
+
</>
|
|
293
|
+
);
|
|
294
|
+
};
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
*/
|
|
298
|
+
export declare const requestPurchase: ({ sku, andDangerouslyFinishTransactionAutomaticallyIOS, applicationUsername, obfuscatedAccountIdAndroid, obfuscatedProfileIdAndroid, skus, isOfferPersonalized, }: RequestPurchase) => Promise<ProductPurchase | void>;
|
|
74
299
|
/**
|
|
75
300
|
* Request a purchase for product. This will be received in `PurchaseUpdatedListener`.
|
|
76
|
-
*
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
301
|
+
* Request a purchase for a subscription.
|
|
302
|
+
|
|
303
|
+
The response will be received through the `PurchaseUpdatedListener`.
|
|
304
|
+
|
|
305
|
+
:::note
|
|
306
|
+
`andDangerouslyFinishTransactionAutomatically` defaults to false. We recommend
|
|
307
|
+
always keeping at false, and verifying the transaction receipts on the server-side.
|
|
308
|
+
:::
|
|
309
|
+
|
|
310
|
+
## Signature
|
|
311
|
+
|
|
312
|
+
```ts
|
|
313
|
+
requestSubscription(
|
|
314
|
+
The product's sku/ID
|
|
315
|
+
sku,
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
* You should set this to false and call finishTransaction manually when you have delivered the purchased goods to the user.
|
|
319
|
+
* @default false
|
|
320
|
+
|
|
321
|
+
andDangerouslyFinishTransactionAutomaticallyIOS = false,
|
|
322
|
+
|
|
323
|
+
purchaseToken that the user is upgrading or downgrading from (Android).
|
|
324
|
+
purchaseTokenAndroid,
|
|
325
|
+
|
|
326
|
+
UNKNOWN_SUBSCRIPTION_UPGRADE_DOWNGRADE_POLICY, IMMEDIATE_WITH_TIME_PRORATION, IMMEDIATE_AND_CHARGE_PRORATED_PRICE, IMMEDIATE_WITHOUT_PRORATION, DEFERRED
|
|
327
|
+
prorationModeAndroid = -1,
|
|
328
|
+
|
|
329
|
+
/** Specifies an optional obfuscated string that is uniquely associated with the user's account in your app.
|
|
330
|
+
obfuscatedAccountIdAndroid,
|
|
331
|
+
|
|
332
|
+
Specifies an optional obfuscated string that is uniquely associated with the user's profile in your app.
|
|
333
|
+
obfuscatedProfileIdAndroid,
|
|
334
|
+
|
|
335
|
+
The purchaser's user ID
|
|
336
|
+
applicationUsername,
|
|
337
|
+
): Promise<SubscriptionPurchase>
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
## Usage
|
|
341
|
+
|
|
342
|
+
```tsx
|
|
343
|
+
import React, {useCallback} from 'react';
|
|
344
|
+
import {Button} from 'react-native';
|
|
345
|
+
import {
|
|
346
|
+
requestSubscription,
|
|
347
|
+
Product,
|
|
348
|
+
Sku,
|
|
349
|
+
getSubscriptions,
|
|
350
|
+
} from 'react-native-iap';
|
|
351
|
+
|
|
352
|
+
const App = () => {
|
|
353
|
+
const subscriptions = useCallback(
|
|
354
|
+
async () => getSubscriptions(['com.example.subscription']),
|
|
355
|
+
[],
|
|
356
|
+
);
|
|
357
|
+
|
|
358
|
+
const handlePurchase = async (sku: Sku) => {
|
|
359
|
+
await requestSubscription({sku});
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
return (
|
|
363
|
+
<>
|
|
364
|
+
{subscriptions.map((subscription) => (
|
|
365
|
+
<Button
|
|
366
|
+
key={subscription.productId}
|
|
367
|
+
title="Buy subscription"
|
|
368
|
+
onPress={() => handlePurchase(subscription.productId)}
|
|
369
|
+
/>
|
|
370
|
+
))}
|
|
371
|
+
</>
|
|
372
|
+
);
|
|
373
|
+
};
|
|
374
|
+
```
|
|
375
|
+
*/
|
|
376
|
+
export declare const requestSubscription: ({ sku, andDangerouslyFinishTransactionAutomaticallyIOS, applicationUsername, purchaseTokenAndroid, prorationModeAndroid, subscriptionOffers, obfuscatedAccountIdAndroid, obfuscatedProfileIdAndroid, isOfferPersonalized, }: RequestSubscription) => Promise<SubscriptionPurchase | null | void>;
|
|
99
377
|
/**
|
|
100
378
|
* Request a purchase for product. This will be received in `PurchaseUpdatedListener`.
|
|
101
379
|
* @param {string} sku The product's sku/ID
|
|
@@ -112,10 +390,22 @@ export declare const requestPurchaseWithQuantityIOS: ({ sku, quantity, }: {
|
|
|
112
390
|
* Call this after you have persisted the purchased state to your server or local data in your app.
|
|
113
391
|
* `react-native-iap` will continue to deliver the purchase updated events with the successful purchase until you finish the transaction. **Even after the app has relaunched.**
|
|
114
392
|
* Android: it will consume purchase for consumables and acknowledge purchase for non-consumables.
|
|
115
|
-
*
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
393
|
+
*
|
|
394
|
+
```tsx
|
|
395
|
+
import React from 'react';
|
|
396
|
+
import {Button} from 'react-native';
|
|
397
|
+
import {finishTransaction} from 'react-native-iap';
|
|
398
|
+
|
|
399
|
+
const App = () => {
|
|
400
|
+
const handlePurchase = async () => {
|
|
401
|
+
// ... handle the purchase request
|
|
402
|
+
|
|
403
|
+
const result = finishTransaction(purchase);
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
return <Button title="Buy product" onPress={handlePurchase} />;
|
|
407
|
+
};
|
|
408
|
+
```
|
|
119
409
|
*/
|
|
120
410
|
export declare const finishTransaction: ({ purchase, isConsumable, developerPayloadAndroid, }: {
|
|
121
411
|
purchase: ProductPurchase | ProductPurchase;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AmazonModuleProps, AndroidModuleProps, IosModuleProps } from '../modules';
|
|
2
|
+
import type * as Apple from './apple';
|
|
2
3
|
export declare type Sku = string;
|
|
3
4
|
export declare enum ProrationModesAndroid {
|
|
4
5
|
IMMEDIATE_WITH_TIME_PRORATION = 1,
|
|
@@ -86,7 +87,7 @@ export interface Discount {
|
|
|
86
87
|
paymentMode: '' | 'FREETRIAL' | 'PAYASYOUGO' | 'PAYUPFRONT';
|
|
87
88
|
subscriptionPeriod: string;
|
|
88
89
|
}
|
|
89
|
-
export interface
|
|
90
|
+
export interface ProductAndroid extends ProductCommon {
|
|
90
91
|
type: 'inapp' | 'iap';
|
|
91
92
|
oneTimePurchaseOfferDetails?: {
|
|
92
93
|
priceCurrencyCode: string;
|
|
@@ -94,6 +95,10 @@ export interface Product extends ProductCommon {
|
|
|
94
95
|
priceAmountMicros: string;
|
|
95
96
|
};
|
|
96
97
|
}
|
|
98
|
+
export interface ProductIOS extends ProductCommon {
|
|
99
|
+
type: 'inapp' | 'iap';
|
|
100
|
+
}
|
|
101
|
+
export declare type Product = ProductAndroid & ProductIOS;
|
|
97
102
|
export interface SubscriptionAndroid extends ProductCommon {
|
|
98
103
|
type: 'subs';
|
|
99
104
|
productType?: string;
|
|
@@ -113,6 +118,7 @@ export interface SubscriptionAndroid extends ProductCommon {
|
|
|
113
118
|
recurrenceMode: number;
|
|
114
119
|
}[];
|
|
115
120
|
};
|
|
121
|
+
offerTags: string[];
|
|
116
122
|
}[];
|
|
117
123
|
}
|
|
118
124
|
export interface SubscriptionIOS extends ProductCommon {
|
|
@@ -127,6 +133,25 @@ export interface SubscriptionIOS extends ProductCommon {
|
|
|
127
133
|
subscriptionPeriodUnitIOS?: '' | 'YEAR' | 'MONTH' | 'WEEK' | 'DAY';
|
|
128
134
|
}
|
|
129
135
|
export declare type Subscription = SubscriptionAndroid & SubscriptionIOS;
|
|
136
|
+
export interface RequestPurchaseBaseAndroid {
|
|
137
|
+
obfuscatedAccountIdAndroid?: string;
|
|
138
|
+
obfuscatedProfileIdAndroid?: string;
|
|
139
|
+
isOfferPersonalized?: boolean;
|
|
140
|
+
}
|
|
141
|
+
export interface RequestPurchaseAndroid extends RequestPurchaseBaseAndroid {
|
|
142
|
+
skus?: Sku[];
|
|
143
|
+
}
|
|
144
|
+
export interface RequestPurchaseIOS {
|
|
145
|
+
sku?: Sku;
|
|
146
|
+
andDangerouslyFinishTransactionAutomaticallyIOS?: boolean;
|
|
147
|
+
/**
|
|
148
|
+
* UUID representing user account
|
|
149
|
+
*/
|
|
150
|
+
applicationUsername?: string;
|
|
151
|
+
quantity?: number;
|
|
152
|
+
withOffer?: Apple.PaymentDiscount;
|
|
153
|
+
}
|
|
154
|
+
export declare type RequestPurchase = RequestPurchaseAndroid & RequestPurchaseIOS;
|
|
130
155
|
/**
|
|
131
156
|
* In order to purchase a new subscription, every sku must have a selected offerToken
|
|
132
157
|
* @see SubscriptionAndroid.subscriptionOfferDetails.offerToken
|
|
@@ -135,6 +160,13 @@ export interface SubscriptionOffer {
|
|
|
135
160
|
sku: Sku;
|
|
136
161
|
offerToken: string;
|
|
137
162
|
}
|
|
163
|
+
export interface RequestSubscriptionAndroid extends RequestPurchaseBaseAndroid {
|
|
164
|
+
purchaseTokenAndroid?: string;
|
|
165
|
+
prorationModeAndroid?: ProrationModesAndroid;
|
|
166
|
+
subscriptionOffers?: SubscriptionOffer[];
|
|
167
|
+
}
|
|
168
|
+
export declare type RequestSubscriptionIOS = RequestPurchaseIOS;
|
|
169
|
+
export declare type RequestSubscription = RequestSubscriptionAndroid & RequestSubscriptionIOS;
|
|
138
170
|
declare module 'react-native' {
|
|
139
171
|
interface NativeModulesStatic {
|
|
140
172
|
RNIapIos: IosModuleProps;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-iap",
|
|
3
|
-
"version": "10.1.
|
|
3
|
+
"version": "10.1.2",
|
|
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)",
|
|
@@ -65,7 +65,8 @@
|
|
|
65
65
|
"lint:ci": "yarn lint:tsc && yarn lint:eslint -f ./node_modules/@firmnav/eslint-github-actions-formatter/dist/formatter.js && yarn lint:prettier",
|
|
66
66
|
"lint:prettier": "prettier --write \"**/*.{md,js,jsx,ts,tsx}\"",
|
|
67
67
|
"format": "git ls-files -m | xargs yarn prettier --write --ignore-unknown --no-error-on-unmatched-pattern",
|
|
68
|
-
"bootstrap": "yarn example && yarn && yarn example pods"
|
|
68
|
+
"bootstrap": "yarn example && yarn && yarn example pods",
|
|
69
|
+
"gen:doc": "typedoc"
|
|
69
70
|
},
|
|
70
71
|
"devDependencies": {
|
|
71
72
|
"@babel/eslint-parser": "7.18.9",
|
|
@@ -96,6 +97,8 @@
|
|
|
96
97
|
"react-native-builder-bob": "0.18.3",
|
|
97
98
|
"release-it": "15.2.0",
|
|
98
99
|
"ts-jest": "28.0.7",
|
|
100
|
+
"typedoc": "^0.23.14",
|
|
101
|
+
"typedoc-plugin-markdown": "^3.13.6",
|
|
99
102
|
"typescript": "4.7.4"
|
|
100
103
|
},
|
|
101
104
|
"resolutions": {
|