react-native-iap 10.1.0 → 10.1.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.
- package/README.md +0 -1
- 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 +32 -1
- package/package.json +5 -2
- package/src/iap.ts +348 -55
- package/src/index.ts +1 -0
- package/src/types/index.ts +42 -4
package/src/iap.ts
CHANGED
|
@@ -14,12 +14,12 @@ import {
|
|
|
14
14
|
Product,
|
|
15
15
|
ProductPurchase,
|
|
16
16
|
ProductType,
|
|
17
|
-
ProrationModesAndroid,
|
|
18
17
|
Purchase,
|
|
19
18
|
PurchaseResult,
|
|
19
|
+
RequestPurchase,
|
|
20
|
+
RequestSubscription,
|
|
20
21
|
Sku,
|
|
21
22
|
Subscription,
|
|
22
|
-
SubscriptionOffer,
|
|
23
23
|
SubscriptionPurchase,
|
|
24
24
|
} from './types';
|
|
25
25
|
import {InstallSourceAndroid, PurchaseStateAndroid} from './types';
|
|
@@ -81,13 +81,43 @@ export const getNativeModule = ():
|
|
|
81
81
|
|
|
82
82
|
/**
|
|
83
83
|
* Init module for purchase flow. Required on Android. In ios it will check whether user canMakePayment.
|
|
84
|
-
*
|
|
84
|
+
* ## Usage
|
|
85
|
+
|
|
86
|
+
```tsx
|
|
87
|
+
import React, {useEffect} from 'react';
|
|
88
|
+
import {View} from 'react-native';
|
|
89
|
+
import {initConnection} from 'react-native-iap';
|
|
90
|
+
|
|
91
|
+
const App = () => {
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
void initConnection();
|
|
94
|
+
}, []);
|
|
95
|
+
|
|
96
|
+
return <View />;
|
|
97
|
+
};
|
|
98
|
+
```
|
|
85
99
|
*/
|
|
86
100
|
export const initConnection = (): Promise<boolean> =>
|
|
87
101
|
getNativeModule().initConnection();
|
|
88
102
|
|
|
89
103
|
/**
|
|
90
|
-
*
|
|
104
|
+
* Disconnects from native SDK
|
|
105
|
+
* Usage
|
|
106
|
+
* ```tsx
|
|
107
|
+
import React, {useEffect} from 'react';
|
|
108
|
+
import {View} from 'react-native';
|
|
109
|
+
import {endConnection} from 'react-native-iap';
|
|
110
|
+
|
|
111
|
+
const App = () => {
|
|
112
|
+
useEffect(() => {
|
|
113
|
+
return () => {
|
|
114
|
+
void endConnection();
|
|
115
|
+
};
|
|
116
|
+
}, []);
|
|
117
|
+
|
|
118
|
+
return <View />;
|
|
119
|
+
};
|
|
120
|
+
```
|
|
91
121
|
* @returns {Promise<void>}
|
|
92
122
|
*/
|
|
93
123
|
export const endConnection = (): Promise<boolean> =>
|
|
@@ -103,8 +133,47 @@ export const flushFailedPurchasesCachedAsPendingAndroid =
|
|
|
103
133
|
|
|
104
134
|
/**
|
|
105
135
|
* Get a list of products (consumable and non-consumable items, but not subscriptions)
|
|
106
|
-
|
|
107
|
-
|
|
136
|
+
## Usage
|
|
137
|
+
|
|
138
|
+
```ts
|
|
139
|
+
import React, {useState} from 'react';
|
|
140
|
+
import {Platform} from 'react-native';
|
|
141
|
+
import {getProducts, Product} from 'react-native-iap';
|
|
142
|
+
|
|
143
|
+
const skus = Platform.select({
|
|
144
|
+
ios: ['com.example.consumableIos'],
|
|
145
|
+
android: ['com.example.consumableAndroid'],
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
const App = () => {
|
|
149
|
+
const [products, setProducts] = useState<Product[]>([]);
|
|
150
|
+
|
|
151
|
+
const handleProducts = async () => {
|
|
152
|
+
const items = await getProducts({skus});
|
|
153
|
+
|
|
154
|
+
setProducts(items);
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
useEffect(() => {
|
|
158
|
+
void handleProducts();
|
|
159
|
+
}, []);
|
|
160
|
+
|
|
161
|
+
return (
|
|
162
|
+
<>
|
|
163
|
+
{products.map((product) => (
|
|
164
|
+
<Text key={product.productId}>{product.productId}</Text>
|
|
165
|
+
))}
|
|
166
|
+
</>
|
|
167
|
+
);
|
|
168
|
+
};
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Just a few things to keep in mind:
|
|
172
|
+
|
|
173
|
+
- You can get your products in `componentDidMount`, `useEffect` or another appropriate area of your app.
|
|
174
|
+
- 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.
|
|
175
|
+
- 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.
|
|
176
|
+
|
|
108
177
|
*/
|
|
109
178
|
export const getProducts = ({
|
|
110
179
|
skus,
|
|
@@ -134,8 +203,24 @@ export const getProducts = ({
|
|
|
134
203
|
|
|
135
204
|
/**
|
|
136
205
|
* Get a list of subscriptions
|
|
137
|
-
*
|
|
138
|
-
|
|
206
|
+
* ## Usage
|
|
207
|
+
|
|
208
|
+
```tsx
|
|
209
|
+
import React, {useCallback} from 'react';
|
|
210
|
+
import {View} from 'react-native';
|
|
211
|
+
import {getSubscriptions} from 'react-native-iap';
|
|
212
|
+
|
|
213
|
+
const App = () => {
|
|
214
|
+
const subscriptions = useCallback(
|
|
215
|
+
async () =>
|
|
216
|
+
await getSubscriptions(['com.example.product1', 'com.example.product2']),
|
|
217
|
+
[],
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
return <View />;
|
|
221
|
+
};
|
|
222
|
+
```
|
|
223
|
+
|
|
139
224
|
*/
|
|
140
225
|
export const getSubscriptions = ({
|
|
141
226
|
skus,
|
|
@@ -165,7 +250,26 @@ export const getSubscriptions = ({
|
|
|
165
250
|
|
|
166
251
|
/**
|
|
167
252
|
* Gets an inventory of purchases made by the user regardless of consumption status
|
|
168
|
-
*
|
|
253
|
+
* ## Usage
|
|
254
|
+
|
|
255
|
+
```tsx
|
|
256
|
+
import React, {useCallback} from 'react';
|
|
257
|
+
import {View} from 'react-native';
|
|
258
|
+
import {getPurchaseHistory} from 'react-native-iap';
|
|
259
|
+
|
|
260
|
+
const App = () => {
|
|
261
|
+
const history = useCallback(
|
|
262
|
+
async () =>
|
|
263
|
+
await getPurchaseHistory([
|
|
264
|
+
'com.example.product1',
|
|
265
|
+
'com.example.product2',
|
|
266
|
+
]),
|
|
267
|
+
[],
|
|
268
|
+
);
|
|
269
|
+
|
|
270
|
+
return <View />;
|
|
271
|
+
};
|
|
272
|
+
```
|
|
169
273
|
*/
|
|
170
274
|
export const getPurchaseHistory = (): Promise<
|
|
171
275
|
(ProductPurchase | SubscriptionPurchase)[]
|
|
@@ -195,7 +299,81 @@ export const getPurchaseHistory = (): Promise<
|
|
|
195
299
|
|
|
196
300
|
/**
|
|
197
301
|
* Get all purchases made by the user (either non-consumable, or haven't been consumed yet)
|
|
198
|
-
*
|
|
302
|
+
* ## Usage
|
|
303
|
+
|
|
304
|
+
```tsx
|
|
305
|
+
import React, {useCallback} from 'react';
|
|
306
|
+
import {View} from 'react-native';
|
|
307
|
+
import {getAvailablePurchases} from 'react-native-iap';
|
|
308
|
+
|
|
309
|
+
const App = () => {
|
|
310
|
+
const availablePurchases = useCallback(
|
|
311
|
+
async () => await getAvailablePurchases(),
|
|
312
|
+
[],
|
|
313
|
+
);
|
|
314
|
+
|
|
315
|
+
return <View />;
|
|
316
|
+
};
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
## Restoring purchases
|
|
320
|
+
|
|
321
|
+
You can use `getAvailablePurchases()` to do what's commonly understood as "restoring" purchases.
|
|
322
|
+
|
|
323
|
+
:::note
|
|
324
|
+
For debugging you may want to consume all items, you have then to iterate over the purchases returned by `getAvailablePurchases()`.
|
|
325
|
+
:::
|
|
326
|
+
|
|
327
|
+
:::warning
|
|
328
|
+
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.
|
|
329
|
+
:::
|
|
330
|
+
|
|
331
|
+
```tsx
|
|
332
|
+
import React from 'react';
|
|
333
|
+
import {Button} from 'react-native';
|
|
334
|
+
import {getAvailablePurchases,finishTransaction} from 'react-native-iap';
|
|
335
|
+
|
|
336
|
+
const App = () => {
|
|
337
|
+
handleRestore = async () => {
|
|
338
|
+
try {
|
|
339
|
+
const purchases = await getAvailablePurchases();
|
|
340
|
+
const newState = {premium: false, ads: true};
|
|
341
|
+
let titles = [];
|
|
342
|
+
|
|
343
|
+
await Promise.all(purchases.map(async purchase => {
|
|
344
|
+
switch (purchase.productId) {
|
|
345
|
+
case 'com.example.premium':
|
|
346
|
+
newState.premium = true;
|
|
347
|
+
titles.push('Premium Version');
|
|
348
|
+
break;
|
|
349
|
+
|
|
350
|
+
case 'com.example.no_ads':
|
|
351
|
+
newState.ads = false;
|
|
352
|
+
titles.push('No Ads');
|
|
353
|
+
break;
|
|
354
|
+
|
|
355
|
+
case 'com.example.coins100':
|
|
356
|
+
await finishTransaction(purchase.purchaseToken);
|
|
357
|
+
CoinStore.addCoins(100);
|
|
358
|
+
}
|
|
359
|
+
})
|
|
360
|
+
|
|
361
|
+
Alert.alert(
|
|
362
|
+
'Restore Successful',
|
|
363
|
+
`You successfully restored the following purchases: ${titles.join(', ')}`,
|
|
364
|
+
);
|
|
365
|
+
} catch (error) {
|
|
366
|
+
console.warn(error);
|
|
367
|
+
Alert.alert(error.message);
|
|
368
|
+
}
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
return (
|
|
372
|
+
<Button title="Restore purchases" onPress={handleRestore} />
|
|
373
|
+
)
|
|
374
|
+
};
|
|
375
|
+
```
|
|
376
|
+
*
|
|
199
377
|
*/
|
|
200
378
|
export const getAvailablePurchases = (): Promise<
|
|
201
379
|
(ProductPurchase | SubscriptionPurchase)[]
|
|
@@ -225,14 +403,70 @@ export const getAvailablePurchases = (): Promise<
|
|
|
225
403
|
|
|
226
404
|
/**
|
|
227
405
|
* Request a purchase for product. This will be received in `PurchaseUpdatedListener`.
|
|
228
|
-
*
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
406
|
+
* Request a purchase for a product (consumables or non-consumables).
|
|
407
|
+
|
|
408
|
+
The response will be received through the `PurchaseUpdatedListener`.
|
|
409
|
+
|
|
410
|
+
:::note
|
|
411
|
+
`andDangerouslyFinishTransactionAutomatically` defaults to false. We recommend
|
|
412
|
+
always keeping at false, and verifying the transaction receipts on the server-side.
|
|
413
|
+
:::
|
|
414
|
+
|
|
415
|
+
## Signature
|
|
416
|
+
|
|
417
|
+
```ts
|
|
418
|
+
requestPurchase(
|
|
419
|
+
The product's sku/ID
|
|
420
|
+
sku,
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
* You should set this to false and call finishTransaction manually when you have delivered the purchased goods to the user.
|
|
424
|
+
* @default false
|
|
425
|
+
|
|
426
|
+
andDangerouslyFinishTransactionAutomaticallyIOS = false,
|
|
427
|
+
|
|
428
|
+
/** Specifies an optional obfuscated string that is uniquely associated with the user's account in your app.
|
|
429
|
+
obfuscatedAccountIdAndroid,
|
|
430
|
+
|
|
431
|
+
Specifies an optional obfuscated string that is uniquely associated with the user's profile in your app.
|
|
432
|
+
obfuscatedProfileIdAndroid,
|
|
433
|
+
|
|
434
|
+
The purchaser's user ID
|
|
435
|
+
applicationUsername,
|
|
436
|
+
): Promise<ProductPurchase>;
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
## Usage
|
|
440
|
+
|
|
441
|
+
```tsx
|
|
442
|
+
import React, {useCallback} from 'react';
|
|
443
|
+
import {Button} from 'react-native';
|
|
444
|
+
import {requestPurchase, Product, Sku, getProducts} from 'react-native-iap';
|
|
445
|
+
|
|
446
|
+
const App = () => {
|
|
447
|
+
const products = useCallback(
|
|
448
|
+
async () => getProducts(['com.example.product']),
|
|
449
|
+
[],
|
|
450
|
+
);
|
|
451
|
+
|
|
452
|
+
const handlePurchase = async (sku: Sku) => {
|
|
453
|
+
await requestPurchase({sku});
|
|
454
|
+
};
|
|
455
|
+
|
|
456
|
+
return (
|
|
457
|
+
<>
|
|
458
|
+
{products.map((product) => (
|
|
459
|
+
<Button
|
|
460
|
+
key={product.productId}
|
|
461
|
+
title="Buy product"
|
|
462
|
+
onPress={() => handlePurchase(product.productId)}
|
|
463
|
+
/>
|
|
464
|
+
))}
|
|
465
|
+
</>
|
|
466
|
+
);
|
|
467
|
+
};
|
|
468
|
+
```
|
|
469
|
+
|
|
236
470
|
*/
|
|
237
471
|
|
|
238
472
|
export const requestPurchase = ({
|
|
@@ -243,16 +477,7 @@ export const requestPurchase = ({
|
|
|
243
477
|
obfuscatedProfileIdAndroid,
|
|
244
478
|
skus,
|
|
245
479
|
isOfferPersonalized,
|
|
246
|
-
}:
|
|
247
|
-
sku?: Sku;
|
|
248
|
-
andDangerouslyFinishTransactionAutomaticallyIOS?: boolean;
|
|
249
|
-
applicationUsername?: string;
|
|
250
|
-
obfuscatedAccountIdAndroid?: string;
|
|
251
|
-
obfuscatedProfileIdAndroid?: string;
|
|
252
|
-
/** For Google Play Billing Library 5 https://developer.android.com/google/play/billing/integrate#personalized-price */
|
|
253
|
-
skus?: Sku[];
|
|
254
|
-
isOfferPersonalized?: boolean;
|
|
255
|
-
}): Promise<ProductPurchase | void> =>
|
|
480
|
+
}: RequestPurchase): Promise<ProductPurchase | void> =>
|
|
256
481
|
(
|
|
257
482
|
Platform.select({
|
|
258
483
|
ios: async () => {
|
|
@@ -302,15 +527,80 @@ export const requestPurchase = ({
|
|
|
302
527
|
|
|
303
528
|
/**
|
|
304
529
|
* Request a purchase for product. This will be received in `PurchaseUpdatedListener`.
|
|
305
|
-
*
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
530
|
+
* Request a purchase for a subscription.
|
|
531
|
+
|
|
532
|
+
The response will be received through the `PurchaseUpdatedListener`.
|
|
533
|
+
|
|
534
|
+
:::note
|
|
535
|
+
`andDangerouslyFinishTransactionAutomatically` defaults to false. We recommend
|
|
536
|
+
always keeping at false, and verifying the transaction receipts on the server-side.
|
|
537
|
+
:::
|
|
538
|
+
|
|
539
|
+
## Signature
|
|
540
|
+
|
|
541
|
+
```ts
|
|
542
|
+
requestSubscription(
|
|
543
|
+
The product's sku/ID
|
|
544
|
+
sku,
|
|
545
|
+
|
|
546
|
+
|
|
547
|
+
* You should set this to false and call finishTransaction manually when you have delivered the purchased goods to the user.
|
|
548
|
+
* @default false
|
|
549
|
+
|
|
550
|
+
andDangerouslyFinishTransactionAutomaticallyIOS = false,
|
|
551
|
+
|
|
552
|
+
purchaseToken that the user is upgrading or downgrading from (Android).
|
|
553
|
+
purchaseTokenAndroid,
|
|
554
|
+
|
|
555
|
+
UNKNOWN_SUBSCRIPTION_UPGRADE_DOWNGRADE_POLICY, IMMEDIATE_WITH_TIME_PRORATION, IMMEDIATE_AND_CHARGE_PRORATED_PRICE, IMMEDIATE_WITHOUT_PRORATION, DEFERRED
|
|
556
|
+
prorationModeAndroid = -1,
|
|
557
|
+
|
|
558
|
+
/** Specifies an optional obfuscated string that is uniquely associated with the user's account in your app.
|
|
559
|
+
obfuscatedAccountIdAndroid,
|
|
560
|
+
|
|
561
|
+
Specifies an optional obfuscated string that is uniquely associated with the user's profile in your app.
|
|
562
|
+
obfuscatedProfileIdAndroid,
|
|
563
|
+
|
|
564
|
+
The purchaser's user ID
|
|
565
|
+
applicationUsername,
|
|
566
|
+
): Promise<SubscriptionPurchase>
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
## Usage
|
|
570
|
+
|
|
571
|
+
```tsx
|
|
572
|
+
import React, {useCallback} from 'react';
|
|
573
|
+
import {Button} from 'react-native';
|
|
574
|
+
import {
|
|
575
|
+
requestSubscription,
|
|
576
|
+
Product,
|
|
577
|
+
Sku,
|
|
578
|
+
getSubscriptions,
|
|
579
|
+
} from 'react-native-iap';
|
|
580
|
+
|
|
581
|
+
const App = () => {
|
|
582
|
+
const subscriptions = useCallback(
|
|
583
|
+
async () => getSubscriptions(['com.example.subscription']),
|
|
584
|
+
[],
|
|
585
|
+
);
|
|
586
|
+
|
|
587
|
+
const handlePurchase = async (sku: Sku) => {
|
|
588
|
+
await requestSubscription({sku});
|
|
589
|
+
};
|
|
590
|
+
|
|
591
|
+
return (
|
|
592
|
+
<>
|
|
593
|
+
{subscriptions.map((subscription) => (
|
|
594
|
+
<Button
|
|
595
|
+
key={subscription.productId}
|
|
596
|
+
title="Buy subscription"
|
|
597
|
+
onPress={() => handlePurchase(subscription.productId)}
|
|
598
|
+
/>
|
|
599
|
+
))}
|
|
600
|
+
</>
|
|
601
|
+
);
|
|
602
|
+
};
|
|
603
|
+
```
|
|
314
604
|
*/
|
|
315
605
|
export const requestSubscription = ({
|
|
316
606
|
sku,
|
|
@@ -322,19 +612,7 @@ export const requestSubscription = ({
|
|
|
322
612
|
obfuscatedAccountIdAndroid,
|
|
323
613
|
obfuscatedProfileIdAndroid,
|
|
324
614
|
isOfferPersonalized = undefined,
|
|
325
|
-
}:
|
|
326
|
-
sku?: Sku;
|
|
327
|
-
andDangerouslyFinishTransactionAutomaticallyIOS?: boolean;
|
|
328
|
-
applicationUsername?: string;
|
|
329
|
-
purchaseTokenAndroid?: string;
|
|
330
|
-
prorationModeAndroid?: ProrationModesAndroid;
|
|
331
|
-
/** For Google Play Billing Library 5 */
|
|
332
|
-
subscriptionOffers?: SubscriptionOffer[];
|
|
333
|
-
obfuscatedAccountIdAndroid?: string;
|
|
334
|
-
obfuscatedProfileIdAndroid?: string;
|
|
335
|
-
/** For Google Play Billing Library 5 https://developer.android.com/google/play/billing/integrate#personalized-price */
|
|
336
|
-
isOfferPersonalized?: boolean;
|
|
337
|
-
}): Promise<SubscriptionPurchase | null | void> =>
|
|
615
|
+
}: RequestSubscription): Promise<SubscriptionPurchase | null | void> =>
|
|
338
616
|
(
|
|
339
617
|
Platform.select({
|
|
340
618
|
ios: async () => {
|
|
@@ -405,10 +683,22 @@ export const requestPurchaseWithQuantityIOS = ({
|
|
|
405
683
|
* Call this after you have persisted the purchased state to your server or local data in your app.
|
|
406
684
|
* `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.**
|
|
407
685
|
* Android: it will consume purchase for consumables and acknowledge purchase for non-consumables.
|
|
408
|
-
*
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
686
|
+
*
|
|
687
|
+
```tsx
|
|
688
|
+
import React from 'react';
|
|
689
|
+
import {Button} from 'react-native';
|
|
690
|
+
import {finishTransaction} from 'react-native-iap';
|
|
691
|
+
|
|
692
|
+
const App = () => {
|
|
693
|
+
const handlePurchase = async () => {
|
|
694
|
+
// ... handle the purchase request
|
|
695
|
+
|
|
696
|
+
const result = finishTransaction(purchase);
|
|
697
|
+
};
|
|
698
|
+
|
|
699
|
+
return <Button title="Buy product" onPress={handlePurchase} />;
|
|
700
|
+
};
|
|
701
|
+
```
|
|
412
702
|
*/
|
|
413
703
|
export const finishTransaction = ({
|
|
414
704
|
purchase,
|
|
@@ -603,7 +893,10 @@ export const validateReceiptIos = async ({
|
|
|
603
893
|
? 'https://sandbox.itunes.apple.com/verifyReceipt'
|
|
604
894
|
: 'https://buy.itunes.apple.com/verifyReceipt';
|
|
605
895
|
|
|
606
|
-
return await enhancedFetch<ReceiptValidationResponse>(url
|
|
896
|
+
return await enhancedFetch<ReceiptValidationResponse>(url, {
|
|
897
|
+
method: 'POST',
|
|
898
|
+
body: receiptBody,
|
|
899
|
+
});
|
|
607
900
|
};
|
|
608
901
|
|
|
609
902
|
/**
|
package/src/index.ts
CHANGED
package/src/types/index.ts
CHANGED
|
@@ -4,6 +4,8 @@ import type {
|
|
|
4
4
|
IosModuleProps,
|
|
5
5
|
} from '../modules';
|
|
6
6
|
|
|
7
|
+
import type * as Apple from './apple';
|
|
8
|
+
|
|
7
9
|
export type Sku = string;
|
|
8
10
|
|
|
9
11
|
export enum ProrationModesAndroid {
|
|
@@ -45,7 +47,7 @@ export enum ProductType {
|
|
|
45
47
|
|
|
46
48
|
export interface ProductCommon {
|
|
47
49
|
type: 'subs' | 'sub' | 'inapp' | 'iap';
|
|
48
|
-
productId: string;
|
|
50
|
+
productId: string; //iOS
|
|
49
51
|
productIds?: string[];
|
|
50
52
|
title: string;
|
|
51
53
|
description: string;
|
|
@@ -109,15 +111,19 @@ export interface Discount {
|
|
|
109
111
|
subscriptionPeriod: string;
|
|
110
112
|
}
|
|
111
113
|
|
|
112
|
-
export interface
|
|
114
|
+
export interface ProductAndroid extends ProductCommon {
|
|
113
115
|
type: 'inapp' | 'iap';
|
|
114
|
-
// Android V5
|
|
115
116
|
oneTimePurchaseOfferDetails?: {
|
|
116
117
|
priceCurrencyCode: string;
|
|
117
118
|
formattedPrice: string;
|
|
118
119
|
priceAmountMicros: string;
|
|
119
120
|
};
|
|
120
121
|
}
|
|
122
|
+
export interface ProductIOS extends ProductCommon {
|
|
123
|
+
type: 'inapp' | 'iap';
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export type Product = ProductAndroid & ProductIOS;
|
|
121
127
|
|
|
122
128
|
// Android V5
|
|
123
129
|
export interface SubscriptionAndroid extends ProductCommon {
|
|
@@ -145,7 +151,6 @@ export interface SubscriptionAndroid extends ProductCommon {
|
|
|
145
151
|
|
|
146
152
|
export interface SubscriptionIOS extends ProductCommon {
|
|
147
153
|
type: 'subs';
|
|
148
|
-
|
|
149
154
|
discounts?: Discount[];
|
|
150
155
|
introductoryPrice?: string;
|
|
151
156
|
introductoryPriceAsAmountIOS?: string;
|
|
@@ -167,6 +172,28 @@ export interface SubscriptionIOS extends ProductCommon {
|
|
|
167
172
|
}
|
|
168
173
|
|
|
169
174
|
export type Subscription = SubscriptionAndroid & SubscriptionIOS;
|
|
175
|
+
export interface RequestPurchaseBaseAndroid {
|
|
176
|
+
obfuscatedAccountIdAndroid?: string;
|
|
177
|
+
obfuscatedProfileIdAndroid?: string;
|
|
178
|
+
isOfferPersonalized?: boolean; // For AndroidBilling V5 https://developer.android.com/google/play/billing/integrate#personalized-price
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export interface RequestPurchaseAndroid extends RequestPurchaseBaseAndroid {
|
|
182
|
+
skus?: Sku[];
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export interface RequestPurchaseIOS {
|
|
186
|
+
sku?: Sku;
|
|
187
|
+
andDangerouslyFinishTransactionAutomaticallyIOS?: boolean;
|
|
188
|
+
/**
|
|
189
|
+
* UUID representing user account
|
|
190
|
+
*/
|
|
191
|
+
applicationUsername?: string;
|
|
192
|
+
quantity?: number;
|
|
193
|
+
withOffer?: Apple.PaymentDiscount;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export type RequestPurchase = RequestPurchaseAndroid & RequestPurchaseIOS;
|
|
170
197
|
|
|
171
198
|
/**
|
|
172
199
|
* In order to purchase a new subscription, every sku must have a selected offerToken
|
|
@@ -177,6 +204,17 @@ export interface SubscriptionOffer {
|
|
|
177
204
|
offerToken: string;
|
|
178
205
|
}
|
|
179
206
|
|
|
207
|
+
export interface RequestSubscriptionAndroid extends RequestPurchaseBaseAndroid {
|
|
208
|
+
purchaseTokenAndroid?: string;
|
|
209
|
+
prorationModeAndroid?: ProrationModesAndroid;
|
|
210
|
+
subscriptionOffers?: SubscriptionOffer[]; // For AndroidBilling V5
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export type RequestSubscriptionIOS = RequestPurchaseIOS;
|
|
214
|
+
|
|
215
|
+
export type RequestSubscription = RequestSubscriptionAndroid &
|
|
216
|
+
RequestSubscriptionIOS;
|
|
217
|
+
|
|
180
218
|
declare module 'react-native' {
|
|
181
219
|
interface NativeModulesStatic {
|
|
182
220
|
RNIapIos: IosModuleProps;
|