react-native-iap 12.0.3 → 12.1.0
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/lib/commonjs/iap.js +143 -110
- package/lib/commonjs/iap.js.map +1 -1
- package/lib/commonjs/internal/fillProductsWithAdditionalData.js +2 -1
- package/lib/commonjs/internal/fillProductsWithAdditionalData.js.map +1 -1
- package/lib/commonjs/internal/platform.js +28 -1
- package/lib/commonjs/internal/platform.js.map +1 -1
- package/lib/commonjs/modules/android.js.map +1 -1
- package/lib/commonjs/modules/ios.js.map +1 -1
- package/lib/commonjs/types/appleSk2.js +3 -0
- package/lib/commonjs/types/appleSk2.js.map +1 -1
- package/lib/commonjs/types/index.js +15 -1
- package/lib/commonjs/types/index.js.map +1 -1
- package/lib/module/iap.js +143 -111
- package/lib/module/iap.js.map +1 -1
- package/lib/module/internal/fillProductsWithAdditionalData.js +2 -1
- package/lib/module/internal/fillProductsWithAdditionalData.js.map +1 -1
- package/lib/module/internal/platform.js +24 -0
- package/lib/module/internal/platform.js.map +1 -1
- package/lib/module/modules/android.js.map +1 -1
- package/lib/module/modules/ios.js.map +1 -1
- package/lib/module/types/appleSk2.js +2 -0
- package/lib/module/types/appleSk2.js.map +1 -1
- package/lib/module/types/index.js +12 -0
- package/lib/module/types/index.js.map +1 -1
- package/lib/typescript/iap.d.ts +4 -4
- package/lib/typescript/internal/fillProductsWithAdditionalData.d.ts +2 -1
- package/lib/typescript/internal/platform.d.ts +9 -0
- package/lib/typescript/modules/android.d.ts +1 -1
- package/lib/typescript/modules/ios.d.ts +4 -4
- package/lib/typescript/types/index.d.ts +54 -28
- package/package.json +1 -1
- package/src/iap.ts +130 -74
- package/src/internal/fillProductsWithAdditionalData.ts +3 -2
- package/src/internal/platform.ts +20 -0
- package/src/modules/android.ts +1 -1
- package/src/modules/ios.ts +5 -5
- package/src/types/appleSk2.ts +2 -0
- package/src/types/index.ts +70 -30
|
@@ -39,10 +39,7 @@ export interface ProductCommon {
|
|
|
39
39
|
description: string;
|
|
40
40
|
price: string;
|
|
41
41
|
currency: string;
|
|
42
|
-
|
|
43
|
-
* For Android use subscription.subscriptionOfferDetails[*].pricingPhases.pricingPhaseList[*].formattedPrice
|
|
44
|
-
*/
|
|
45
|
-
localizedPrice?: string;
|
|
42
|
+
localizedPrice: string;
|
|
46
43
|
countryCode?: string;
|
|
47
44
|
}
|
|
48
45
|
export interface ProductPurchase {
|
|
@@ -103,30 +100,55 @@ export interface ProductIOS extends ProductCommon {
|
|
|
103
100
|
type: 'inapp' | 'iap';
|
|
104
101
|
}
|
|
105
102
|
export declare type Product = ProductAndroid & ProductIOS;
|
|
106
|
-
|
|
103
|
+
/**
|
|
104
|
+
* Can be used to distinguish the different platforms' subscription information
|
|
105
|
+
*/
|
|
106
|
+
export declare enum SubscriptionPlatform {
|
|
107
|
+
android = "android",
|
|
108
|
+
amazon = "amazon",
|
|
109
|
+
ios = "ios"
|
|
110
|
+
}
|
|
111
|
+
/** Android Billing v5 type */
|
|
112
|
+
export interface SubscriptionAndroid {
|
|
113
|
+
platform: SubscriptionPlatform.android;
|
|
114
|
+
productType: 'subs';
|
|
115
|
+
name: string;
|
|
116
|
+
title: string;
|
|
117
|
+
description: string;
|
|
118
|
+
productId: string;
|
|
119
|
+
subscriptionOfferDetails: SubscriptionOfferAndroid[];
|
|
120
|
+
}
|
|
121
|
+
export interface SubscriptionOfferAndroid {
|
|
122
|
+
offerToken: string;
|
|
123
|
+
pricingPhases: {
|
|
124
|
+
pricingPhaseList: PricingPhaseAndroid[];
|
|
125
|
+
};
|
|
126
|
+
offerTags: string[];
|
|
127
|
+
}
|
|
128
|
+
export interface PricingPhaseAndroid {
|
|
129
|
+
formattedPrice: string;
|
|
130
|
+
priceCurrencyCode: string;
|
|
131
|
+
/**
|
|
132
|
+
* P1W, P1M, P1Y
|
|
133
|
+
*/
|
|
134
|
+
billingPeriod: string;
|
|
135
|
+
billingCycleCount: number;
|
|
136
|
+
priceAmountMicros: string;
|
|
137
|
+
recurrenceMode: number;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* TODO: As of 2022-10-10, this typing is not verified against the real
|
|
141
|
+
* Amazon API. Please update this if you have a more accurate type.
|
|
142
|
+
*/
|
|
143
|
+
export interface SubscriptionAmazon extends ProductCommon {
|
|
144
|
+
platform: SubscriptionPlatform.amazon;
|
|
107
145
|
type: 'subs';
|
|
108
146
|
productType?: string;
|
|
109
147
|
name?: string;
|
|
110
|
-
subscriptionOfferDetails?: {
|
|
111
|
-
offerToken: string;
|
|
112
|
-
pricingPhases: {
|
|
113
|
-
pricingPhaseList: {
|
|
114
|
-
formattedPrice: string;
|
|
115
|
-
priceCurrencyCode: string;
|
|
116
|
-
/**
|
|
117
|
-
* P1W, P1M, P1Y
|
|
118
|
-
*/
|
|
119
|
-
billingPeriod: string;
|
|
120
|
-
billingCycleCount: number;
|
|
121
|
-
priceAmountMicros: string;
|
|
122
|
-
recurrenceMode: number;
|
|
123
|
-
}[];
|
|
124
|
-
};
|
|
125
|
-
offerTags: string[];
|
|
126
|
-
}[];
|
|
127
148
|
}
|
|
128
149
|
export declare type SubscriptionIosPeriod = 'DAY' | 'WEEK' | 'MONTH' | 'YEAR' | '';
|
|
129
150
|
export interface SubscriptionIOS extends ProductCommon {
|
|
151
|
+
platform: SubscriptionPlatform.ios;
|
|
130
152
|
type: 'subs';
|
|
131
153
|
discounts?: Discount[];
|
|
132
154
|
introductoryPrice?: string;
|
|
@@ -137,17 +159,17 @@ export interface SubscriptionIOS extends ProductCommon {
|
|
|
137
159
|
subscriptionPeriodNumberIOS?: string;
|
|
138
160
|
subscriptionPeriodUnitIOS?: SubscriptionIosPeriod;
|
|
139
161
|
}
|
|
140
|
-
export declare type Subscription = SubscriptionAndroid
|
|
162
|
+
export declare type Subscription = SubscriptionAndroid | SubscriptionAmazon | SubscriptionIOS;
|
|
141
163
|
export interface RequestPurchaseBaseAndroid {
|
|
142
164
|
obfuscatedAccountIdAndroid?: string;
|
|
143
165
|
obfuscatedProfileIdAndroid?: string;
|
|
144
166
|
isOfferPersonalized?: boolean;
|
|
145
167
|
}
|
|
146
168
|
export interface RequestPurchaseAndroid extends RequestPurchaseBaseAndroid {
|
|
147
|
-
skus
|
|
169
|
+
skus: Sku[];
|
|
148
170
|
}
|
|
149
171
|
export interface RequestPurchaseIOS {
|
|
150
|
-
sku
|
|
172
|
+
sku: Sku;
|
|
151
173
|
andDangerouslyFinishTransactionAutomaticallyIOS?: boolean;
|
|
152
174
|
/**
|
|
153
175
|
* UUID representing user account
|
|
@@ -156,7 +178,9 @@ export interface RequestPurchaseIOS {
|
|
|
156
178
|
quantity?: number;
|
|
157
179
|
withOffer?: Apple.PaymentDiscount;
|
|
158
180
|
}
|
|
159
|
-
|
|
181
|
+
/** As of 2022-10-12, we only use the `sku` field for Amazon purchases */
|
|
182
|
+
export declare type RequestPurchaseAmazon = RequestPurchaseIOS;
|
|
183
|
+
export declare type RequestPurchase = RequestPurchaseAndroid | RequestPurchaseAmazon | RequestPurchaseIOS;
|
|
160
184
|
/**
|
|
161
185
|
* In order to purchase a new subscription, every sku must have a selected offerToken
|
|
162
186
|
* @see SubscriptionAndroid.subscriptionOfferDetails.offerToken
|
|
@@ -168,10 +192,12 @@ export interface SubscriptionOffer {
|
|
|
168
192
|
export interface RequestSubscriptionAndroid extends RequestPurchaseBaseAndroid {
|
|
169
193
|
purchaseTokenAndroid?: string;
|
|
170
194
|
prorationModeAndroid?: ProrationModesAndroid;
|
|
171
|
-
subscriptionOffers
|
|
195
|
+
subscriptionOffers: SubscriptionOffer[];
|
|
172
196
|
}
|
|
173
197
|
export declare type RequestSubscriptionIOS = RequestPurchaseIOS;
|
|
174
|
-
|
|
198
|
+
/** As of 2022-10-12, we only use the `sku` field for Amazon subscriptions */
|
|
199
|
+
export declare type RequestSubscriptionAmazon = RequestSubscriptionIOS;
|
|
200
|
+
export declare type RequestSubscription = RequestSubscriptionAndroid | RequestSubscriptionAmazon | RequestSubscriptionIOS;
|
|
175
201
|
declare module 'react-native' {
|
|
176
202
|
interface NativeModulesStatic {
|
|
177
203
|
RNIapIos: IosModuleProps;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-iap",
|
|
3
|
-
"version": "12.0
|
|
3
|
+
"version": "12.1.0",
|
|
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/iap.ts
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
import {
|
|
16
16
|
fillProductsWithAdditionalData,
|
|
17
17
|
getAndroidModule,
|
|
18
|
+
getAndroidModuleType,
|
|
18
19
|
getIosModule,
|
|
19
20
|
getNativeModule,
|
|
20
21
|
isAmazon,
|
|
@@ -28,12 +29,16 @@ import {
|
|
|
28
29
|
ProductPurchase,
|
|
29
30
|
ProductType,
|
|
30
31
|
PurchaseResult,
|
|
32
|
+
PurchaseStateAndroid,
|
|
31
33
|
RequestPurchase,
|
|
32
34
|
RequestSubscription,
|
|
33
35
|
Subscription,
|
|
36
|
+
SubscriptionAmazon,
|
|
37
|
+
SubscriptionAndroid,
|
|
38
|
+
SubscriptionIOS,
|
|
39
|
+
SubscriptionPlatform,
|
|
34
40
|
SubscriptionPurchase,
|
|
35
41
|
} from './types';
|
|
36
|
-
import {PurchaseStateAndroid} from './types';
|
|
37
42
|
|
|
38
43
|
export {IapAndroid, IapAmazon, IapIos, IapIosSk2, isIosStorekit2};
|
|
39
44
|
|
|
@@ -231,32 +236,69 @@ export const getSubscriptions = ({
|
|
|
231
236
|
}): Promise<Subscription[]> =>
|
|
232
237
|
(
|
|
233
238
|
Platform.select({
|
|
234
|
-
ios: async () => {
|
|
235
|
-
let items:
|
|
239
|
+
ios: async (): Promise<SubscriptionIOS[]> => {
|
|
240
|
+
let items: SubscriptionIOS[];
|
|
236
241
|
if (isIosStorekit2()) {
|
|
237
242
|
items = ((await RNIapIosSk2.getItems(skus)) as ProductSk2[]).map(
|
|
238
243
|
subscriptionSk2Map,
|
|
239
244
|
);
|
|
240
245
|
} else {
|
|
241
|
-
items = (await RNIapIos.getItems(skus)) as
|
|
246
|
+
items = (await RNIapIos.getItems(skus)) as SubscriptionIOS[];
|
|
242
247
|
}
|
|
243
248
|
|
|
244
|
-
|
|
245
|
-
(item:
|
|
249
|
+
items = items.filter(
|
|
250
|
+
(item: SubscriptionIOS) =>
|
|
246
251
|
skus.includes(item.productId) && item.type === 'subs',
|
|
247
252
|
);
|
|
253
|
+
|
|
254
|
+
return addSubscriptionPlatform(items, SubscriptionPlatform.ios);
|
|
248
255
|
},
|
|
249
|
-
android: async () => {
|
|
250
|
-
const
|
|
256
|
+
android: async (): Promise<Subscription[]> => {
|
|
257
|
+
const androidPlatform = getAndroidModuleType();
|
|
258
|
+
|
|
259
|
+
let subscriptions = (await getAndroidModule().getItemsByType(
|
|
251
260
|
ANDROID_ITEM_TYPE_SUBSCRIPTION,
|
|
252
261
|
skus,
|
|
253
|
-
)) as
|
|
254
|
-
|
|
255
|
-
|
|
262
|
+
)) as SubscriptionAndroid[] | SubscriptionAmazon[];
|
|
263
|
+
|
|
264
|
+
switch (androidPlatform) {
|
|
265
|
+
case 'android': {
|
|
266
|
+
const castSubscriptions = subscriptions as SubscriptionAndroid[];
|
|
267
|
+
return addSubscriptionPlatform(
|
|
268
|
+
castSubscriptions,
|
|
269
|
+
SubscriptionPlatform.android,
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
case 'amazon':
|
|
273
|
+
let castSubscriptions = subscriptions as SubscriptionAmazon[];
|
|
274
|
+
castSubscriptions = await fillProductsWithAdditionalData(
|
|
275
|
+
castSubscriptions,
|
|
276
|
+
);
|
|
277
|
+
return addSubscriptionPlatform(
|
|
278
|
+
castSubscriptions,
|
|
279
|
+
SubscriptionPlatform.amazon,
|
|
280
|
+
);
|
|
281
|
+
case null:
|
|
282
|
+
default:
|
|
283
|
+
throw new Error(
|
|
284
|
+
`getSubscriptions received unknown platform ${androidPlatform}. Verify the logic in getAndroidModuleType`,
|
|
285
|
+
);
|
|
286
|
+
}
|
|
256
287
|
},
|
|
257
288
|
}) || (() => Promise.reject(new Error('Unsupported Platform')))
|
|
258
289
|
)();
|
|
259
290
|
|
|
291
|
+
/**
|
|
292
|
+
* Adds an extra property to subscriptions so we can distinguish the platform
|
|
293
|
+
* we retrieved them on.
|
|
294
|
+
*/
|
|
295
|
+
const addSubscriptionPlatform = <T>(
|
|
296
|
+
subscriptions: T[],
|
|
297
|
+
platform: SubscriptionPlatform,
|
|
298
|
+
): T[] => {
|
|
299
|
+
return subscriptions.map((subscription) => ({...subscription, platform}));
|
|
300
|
+
};
|
|
301
|
+
|
|
260
302
|
/**
|
|
261
303
|
* Gets an inventory of purchases made by the user regardless of consumption status
|
|
262
304
|
* ## Usage
|
|
@@ -281,8 +323,8 @@ const App = () => {
|
|
|
281
323
|
```
|
|
282
324
|
@param {alsoPublishToEventListener}:boolean. (IOS Sk2 only) When `true`, every element will also be pushed to the purchaseUpdated listener.
|
|
283
325
|
Note that this is only for backaward compatiblity. It won't publish to transactionUpdated (Storekit2) Defaults to `false`
|
|
284
|
-
@param {automaticallyFinishRestoredTransactions}:boolean. (IOS Sk1 only) When `true`, all the transactions that are returned are automatically
|
|
285
|
-
finished. This means that if you call this method again you won't get the same result on the same device. On the other hand, if `false` you'd
|
|
326
|
+
@param {automaticallyFinishRestoredTransactions}:boolean. (IOS Sk1 only) When `true`, all the transactions that are returned are automatically
|
|
327
|
+
finished. This means that if you call this method again you won't get the same result on the same device. On the other hand, if `false` you'd
|
|
286
328
|
have to manually finish the returned transaction once you have delivered the content to your user.
|
|
287
329
|
*/
|
|
288
330
|
export const getPurchaseHistory = ({
|
|
@@ -403,7 +445,7 @@ const App = () => {
|
|
|
403
445
|
```
|
|
404
446
|
@param {alsoPublishToEventListener}:boolean When `true`, every element will also be pushed to the purchaseUpdated listener.
|
|
405
447
|
Note that this is only for backaward compatiblity. It won't publish to transactionUpdated (Storekit2) Defaults to `false`
|
|
406
|
-
*
|
|
448
|
+
*
|
|
407
449
|
*/
|
|
408
450
|
export const getAvailablePurchases = ({
|
|
409
451
|
alsoPublishToEventListener = false,
|
|
@@ -460,22 +502,22 @@ always keeping at false, and verifying the transaction receipts on the server-si
|
|
|
460
502
|
|
|
461
503
|
```ts
|
|
462
504
|
requestPurchase(
|
|
463
|
-
The product's sku/ID
|
|
505
|
+
The product's sku/ID
|
|
464
506
|
sku,
|
|
465
507
|
|
|
466
|
-
|
|
508
|
+
|
|
467
509
|
* You should set this to false and call finishTransaction manually when you have delivered the purchased goods to the user.
|
|
468
510
|
* @default false
|
|
469
|
-
|
|
511
|
+
|
|
470
512
|
andDangerouslyFinishTransactionAutomaticallyIOS = false,
|
|
471
513
|
|
|
472
|
-
/** Specifies an optional obfuscated string that is uniquely associated with the user's account in your app.
|
|
514
|
+
/** Specifies an optional obfuscated string that is uniquely associated with the user's account in your app.
|
|
473
515
|
obfuscatedAccountIdAndroid,
|
|
474
516
|
|
|
475
|
-
Specifies an optional obfuscated string that is uniquely associated with the user's profile in your app.
|
|
517
|
+
Specifies an optional obfuscated string that is uniquely associated with the user's profile in your app.
|
|
476
518
|
obfuscatedProfileIdAndroid,
|
|
477
519
|
|
|
478
|
-
The purchaser's user ID
|
|
520
|
+
The purchaser's user ID
|
|
479
521
|
applicationUsername,
|
|
480
522
|
): Promise<ProductPurchase>;
|
|
481
523
|
```
|
|
@@ -513,23 +555,24 @@ const App = () => {
|
|
|
513
555
|
|
|
514
556
|
*/
|
|
515
557
|
|
|
516
|
-
export const requestPurchase = (
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
obfuscatedAccountIdAndroid,
|
|
520
|
-
obfuscatedProfileIdAndroid,
|
|
521
|
-
appAccountToken,
|
|
522
|
-
skus, // Android Billing V5
|
|
523
|
-
isOfferPersonalized = undefined, // Android Billing V5
|
|
524
|
-
quantity,
|
|
525
|
-
withOffer,
|
|
526
|
-
}: RequestPurchase): Promise<ProductPurchase | void> =>
|
|
558
|
+
export const requestPurchase = (
|
|
559
|
+
request: RequestPurchase,
|
|
560
|
+
): Promise<ProductPurchase | void> =>
|
|
527
561
|
(
|
|
528
562
|
Platform.select({
|
|
529
563
|
ios: async () => {
|
|
530
|
-
if (!sku) {
|
|
531
|
-
|
|
564
|
+
if (!('sku' in request)) {
|
|
565
|
+
throw new Error('sku is required for iOS purchase');
|
|
532
566
|
}
|
|
567
|
+
|
|
568
|
+
const {
|
|
569
|
+
sku,
|
|
570
|
+
andDangerouslyFinishTransactionAutomaticallyIOS = false,
|
|
571
|
+
appAccountToken,
|
|
572
|
+
quantity,
|
|
573
|
+
withOffer,
|
|
574
|
+
} = request;
|
|
575
|
+
|
|
533
576
|
if (andDangerouslyFinishTransactionAutomaticallyIOS) {
|
|
534
577
|
console.warn(
|
|
535
578
|
'You are dangerously allowing react-native-iap to finish your transaction automatically. You should set andDangerouslyFinishTransactionAutomatically to false when calling requestPurchase and call finishTransaction manually when you have delivered the purchased goods to the user. It defaults to true to provide backwards compatibility. Will default to false in version 4.0.0.',
|
|
@@ -557,21 +600,25 @@ export const requestPurchase = ({
|
|
|
557
600
|
},
|
|
558
601
|
android: async () => {
|
|
559
602
|
if (isAmazon) {
|
|
560
|
-
if (!sku) {
|
|
561
|
-
|
|
562
|
-
new Error('sku is required for Amazon purchase'),
|
|
563
|
-
);
|
|
603
|
+
if (!('sku' in request)) {
|
|
604
|
+
throw new Error('sku is required for Amazon purchase');
|
|
564
605
|
}
|
|
606
|
+
const {sku} = request;
|
|
565
607
|
return RNIapAmazonModule.buyItemByType(sku);
|
|
566
608
|
} else {
|
|
567
|
-
if (!
|
|
568
|
-
|
|
569
|
-
new Error('skus is required for Android purchase'),
|
|
570
|
-
);
|
|
609
|
+
if (!('skus' in request) || !request.skus.length) {
|
|
610
|
+
throw new Error('skus is required for Android purchase');
|
|
571
611
|
}
|
|
612
|
+
|
|
613
|
+
const {
|
|
614
|
+
skus,
|
|
615
|
+
obfuscatedAccountIdAndroid,
|
|
616
|
+
obfuscatedProfileIdAndroid,
|
|
617
|
+
isOfferPersonalized,
|
|
618
|
+
} = request;
|
|
572
619
|
return getAndroidModule().buyItemByType(
|
|
573
620
|
ANDROID_ITEM_TYPE_IAP,
|
|
574
|
-
skus
|
|
621
|
+
skus,
|
|
575
622
|
undefined,
|
|
576
623
|
-1,
|
|
577
624
|
obfuscatedAccountIdAndroid,
|
|
@@ -599,7 +646,7 @@ always keeping at false, and verifying the transaction receipts on the server-si
|
|
|
599
646
|
|
|
600
647
|
```ts
|
|
601
648
|
requestSubscription(
|
|
602
|
-
The product's sku/ID
|
|
649
|
+
The product's sku/ID
|
|
603
650
|
sku,
|
|
604
651
|
|
|
605
652
|
|
|
@@ -608,19 +655,19 @@ requestSubscription(
|
|
|
608
655
|
|
|
609
656
|
andDangerouslyFinishTransactionAutomaticallyIOS = false,
|
|
610
657
|
|
|
611
|
-
purchaseToken that the user is upgrading or downgrading from (Android).
|
|
658
|
+
purchaseToken that the user is upgrading or downgrading from (Android).
|
|
612
659
|
purchaseTokenAndroid,
|
|
613
660
|
|
|
614
|
-
UNKNOWN_SUBSCRIPTION_UPGRADE_DOWNGRADE_POLICY, IMMEDIATE_WITH_TIME_PRORATION, IMMEDIATE_AND_CHARGE_PRORATED_PRICE, IMMEDIATE_WITHOUT_PRORATION, DEFERRED
|
|
661
|
+
UNKNOWN_SUBSCRIPTION_UPGRADE_DOWNGRADE_POLICY, IMMEDIATE_WITH_TIME_PRORATION, IMMEDIATE_AND_CHARGE_PRORATED_PRICE, IMMEDIATE_WITHOUT_PRORATION, DEFERRED
|
|
615
662
|
prorationModeAndroid = -1,
|
|
616
663
|
|
|
617
|
-
/** Specifies an optional obfuscated string that is uniquely associated with the user's account in your app.
|
|
664
|
+
/** Specifies an optional obfuscated string that is uniquely associated with the user's account in your app.
|
|
618
665
|
obfuscatedAccountIdAndroid,
|
|
619
666
|
|
|
620
|
-
Specifies an optional obfuscated string that is uniquely associated with the user's profile in your app.
|
|
667
|
+
Specifies an optional obfuscated string that is uniquely associated with the user's profile in your app.
|
|
621
668
|
obfuscatedProfileIdAndroid,
|
|
622
669
|
|
|
623
|
-
The purchaser's user ID
|
|
670
|
+
The purchaser's user ID
|
|
624
671
|
applicationUsername,
|
|
625
672
|
): Promise<SubscriptionPurchase>
|
|
626
673
|
```
|
|
@@ -661,27 +708,24 @@ const App = () => {
|
|
|
661
708
|
};
|
|
662
709
|
```
|
|
663
710
|
*/
|
|
664
|
-
export const requestSubscription = (
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
purchaseTokenAndroid,
|
|
668
|
-
prorationModeAndroid = -1,
|
|
669
|
-
obfuscatedAccountIdAndroid,
|
|
670
|
-
obfuscatedProfileIdAndroid,
|
|
671
|
-
subscriptionOffers = undefined, // Android Billing V5
|
|
672
|
-
isOfferPersonalized = undefined, // Android Billing V5
|
|
673
|
-
appAccountToken,
|
|
674
|
-
quantity,
|
|
675
|
-
withOffer,
|
|
676
|
-
}: RequestSubscription): Promise<SubscriptionPurchase | null | void> =>
|
|
711
|
+
export const requestSubscription = (
|
|
712
|
+
request: RequestSubscription,
|
|
713
|
+
): Promise<SubscriptionPurchase | null | void> =>
|
|
677
714
|
(
|
|
678
715
|
Platform.select({
|
|
679
716
|
ios: async () => {
|
|
680
|
-
if (!sku) {
|
|
681
|
-
|
|
682
|
-
new Error('sku is required for iOS subscription'),
|
|
683
|
-
);
|
|
717
|
+
if (!('sku' in request)) {
|
|
718
|
+
throw new Error('sku is required for iOS subscriptions');
|
|
684
719
|
}
|
|
720
|
+
|
|
721
|
+
const {
|
|
722
|
+
sku,
|
|
723
|
+
andDangerouslyFinishTransactionAutomaticallyIOS = false,
|
|
724
|
+
appAccountToken,
|
|
725
|
+
quantity,
|
|
726
|
+
withOffer,
|
|
727
|
+
} = request;
|
|
728
|
+
|
|
685
729
|
if (andDangerouslyFinishTransactionAutomaticallyIOS) {
|
|
686
730
|
console.warn(
|
|
687
731
|
'You are dangerously allowing react-native-iap to finish your transaction automatically. You should set andDangerouslyFinishTransactionAutomatically to false when calling requestPurchase and call finishTransaction manually when you have delivered the purchased goods to the user. It defaults to true to provide backwards compatibility. Will default to false in version 4.0.0.',
|
|
@@ -710,18 +754,30 @@ export const requestSubscription = ({
|
|
|
710
754
|
},
|
|
711
755
|
android: async () => {
|
|
712
756
|
if (isAmazon) {
|
|
713
|
-
if (!sku) {
|
|
714
|
-
|
|
715
|
-
new Error('sku is required for Amazon purchase'),
|
|
716
|
-
);
|
|
757
|
+
if (!('sku' in request)) {
|
|
758
|
+
throw new Error('sku is required for Amazon subscriptions');
|
|
717
759
|
}
|
|
760
|
+
const {sku} = request;
|
|
718
761
|
return RNIapAmazonModule.buyItemByType(sku);
|
|
719
762
|
} else {
|
|
720
|
-
if (
|
|
721
|
-
|
|
722
|
-
|
|
763
|
+
if (
|
|
764
|
+
!('subscriptionOffers' in request) ||
|
|
765
|
+
request.subscriptionOffers.length === 0
|
|
766
|
+
) {
|
|
767
|
+
throw new Error(
|
|
768
|
+
'subscriptionOffers are required for Google Play subscriptions',
|
|
723
769
|
);
|
|
724
770
|
}
|
|
771
|
+
|
|
772
|
+
const {
|
|
773
|
+
subscriptionOffers,
|
|
774
|
+
purchaseTokenAndroid,
|
|
775
|
+
prorationModeAndroid,
|
|
776
|
+
obfuscatedAccountIdAndroid,
|
|
777
|
+
obfuscatedProfileIdAndroid,
|
|
778
|
+
isOfferPersonalized,
|
|
779
|
+
} = request;
|
|
780
|
+
|
|
725
781
|
return RNIapModule.buyItemByType(
|
|
726
782
|
ANDROID_ITEM_TYPE_SUBSCRIPTION,
|
|
727
783
|
subscriptionOffers?.map((so) => so.sku),
|
|
@@ -744,7 +800,7 @@ export const requestSubscription = ({
|
|
|
744
800
|
* Call this after you have persisted the purchased state to your server or local data in your app.
|
|
745
801
|
* `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.**
|
|
746
802
|
* Android: it will consume purchase for consumables and acknowledge purchase for non-consumables.
|
|
747
|
-
*
|
|
803
|
+
*
|
|
748
804
|
```tsx
|
|
749
805
|
import React from 'react';
|
|
750
806
|
import {Button} from 'react-native';
|
|
@@ -759,7 +815,7 @@ const App = () => {
|
|
|
759
815
|
|
|
760
816
|
return <Button title="Buy product" onPress={handlePurchase} />;
|
|
761
817
|
};
|
|
762
|
-
```
|
|
818
|
+
```
|
|
763
819
|
*/
|
|
764
820
|
export const finishTransaction = ({
|
|
765
821
|
purchase,
|
|
@@ -5,11 +5,12 @@ import type {ProductCommon} from '../types';
|
|
|
5
5
|
const {RNIapAmazonModule} = NativeModules;
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
8
|
+
* For Amazon products, we add the currency code from the user's information
|
|
9
|
+
* since it isn't included in the product information.
|
|
9
10
|
*/
|
|
10
11
|
export const fillProductsWithAdditionalData = async <T extends ProductCommon>(
|
|
11
12
|
items: T[],
|
|
12
|
-
) => {
|
|
13
|
+
): Promise<T[]> => {
|
|
13
14
|
if (RNIapAmazonModule) {
|
|
14
15
|
// On amazon we must get the user marketplace to detect the currency
|
|
15
16
|
const user = await RNIapAmazonModule.getUser();
|
package/src/internal/platform.ts
CHANGED
|
@@ -25,6 +25,10 @@ export const checkNativeAndroidAvailable = (): void => {
|
|
|
25
25
|
}
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
+
/**
|
|
29
|
+
* If changing the typings of `getAndroidModule` to accommodate extra modules,
|
|
30
|
+
* make sure to update `getAndroidModuleType`.
|
|
31
|
+
*/
|
|
28
32
|
export const getAndroidModule = ():
|
|
29
33
|
| typeof RNIapModule
|
|
30
34
|
| typeof RNIapAmazonModule => {
|
|
@@ -37,6 +41,22 @@ export const getAndroidModule = ():
|
|
|
37
41
|
: RNIapAmazonModule;
|
|
38
42
|
};
|
|
39
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Returns whether the Android in-app-purchase code is using the Android,
|
|
46
|
+
* Amazon, or another store.
|
|
47
|
+
*/
|
|
48
|
+
export const getAndroidModuleType = (): 'android' | 'amazon' | null => {
|
|
49
|
+
const module = getAndroidModule();
|
|
50
|
+
switch (module) {
|
|
51
|
+
case RNIapModule:
|
|
52
|
+
return 'android';
|
|
53
|
+
case RNIapAmazonModule:
|
|
54
|
+
return 'amazon';
|
|
55
|
+
default:
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
40
60
|
export const getNativeModule = ():
|
|
41
61
|
| typeof RNIapModule
|
|
42
62
|
| typeof RNIapAmazonModule
|
package/src/modules/android.ts
CHANGED
|
@@ -35,7 +35,7 @@ export type BuyItemByType = (
|
|
|
35
35
|
type: string,
|
|
36
36
|
skus: Sku[],
|
|
37
37
|
purchaseToken: string | undefined,
|
|
38
|
-
prorationMode: ProrationModesAndroid,
|
|
38
|
+
prorationMode: ProrationModesAndroid | undefined,
|
|
39
39
|
obfuscatedAccountId: string | undefined,
|
|
40
40
|
obfuscatedProfileId: string | undefined,
|
|
41
41
|
subscriptionOffers: string[],
|
package/src/modules/ios.ts
CHANGED
|
@@ -2,17 +2,17 @@ import type {ResponseBody as ReceiptValidationResponse} from '@jeremybarbet/appl
|
|
|
2
2
|
|
|
3
3
|
import {getIosModule, isIosStorekit2} from '../internal';
|
|
4
4
|
import type {
|
|
5
|
-
|
|
5
|
+
ProductIOS,
|
|
6
6
|
ProductPurchase,
|
|
7
7
|
Purchase,
|
|
8
8
|
Sku,
|
|
9
|
-
|
|
9
|
+
SubscriptionIOS,
|
|
10
10
|
} from '../types';
|
|
11
11
|
import type {PaymentDiscount} from '../types/apple';
|
|
12
12
|
|
|
13
13
|
import type {NativeModuleProps} from './common';
|
|
14
14
|
|
|
15
|
-
type getItems = (skus: Sku[]) => Promise<
|
|
15
|
+
type getItems = (skus: Sku[]) => Promise<ProductIOS[] | SubscriptionIOS[]>;
|
|
16
16
|
|
|
17
17
|
type getAvailableItems = (
|
|
18
18
|
automaticallyFinishRestoredTransactions: boolean,
|
|
@@ -28,7 +28,7 @@ export type BuyProduct = (
|
|
|
28
28
|
|
|
29
29
|
type clearTransaction = () => Promise<void>;
|
|
30
30
|
type clearProducts = () => Promise<void>;
|
|
31
|
-
type promotedProduct = () => Promise<
|
|
31
|
+
type promotedProduct = () => Promise<ProductIOS | null>;
|
|
32
32
|
type buyPromotedProduct = () => Promise<void>;
|
|
33
33
|
type requestReceipt = (refresh: boolean) => Promise<string>;
|
|
34
34
|
|
|
@@ -83,7 +83,7 @@ export const presentCodeRedemptionSheetIOS = async (): Promise<null> =>
|
|
|
83
83
|
* Indicates the the App Store purchase should continue from the app instead of the App Store.
|
|
84
84
|
* @returns {Promise<Product | null>} promoted product
|
|
85
85
|
*/
|
|
86
|
-
export const getPromotedProductIOS = (): Promise<
|
|
86
|
+
export const getPromotedProductIOS = (): Promise<ProductIOS | null> => {
|
|
87
87
|
if (!isIosStorekit2()) {
|
|
88
88
|
return getIosModule().promotedProduct();
|
|
89
89
|
} else {
|
package/src/types/appleSk2.ts
CHANGED
|
@@ -7,6 +7,7 @@ import type {
|
|
|
7
7
|
SubscriptionIosPeriod,
|
|
8
8
|
} from '.';
|
|
9
9
|
import type * as Apple from './apple';
|
|
10
|
+
import {SubscriptionPlatform} from '.';
|
|
10
11
|
|
|
11
12
|
export type SubscriptionPeriod = {
|
|
12
13
|
unit: 'day' | 'week' | 'month' | 'year';
|
|
@@ -71,6 +72,7 @@ export const subscriptionSk2Map = ({
|
|
|
71
72
|
subscription,
|
|
72
73
|
}: ProductSk2): SubscriptionIOS => {
|
|
73
74
|
const prod: SubscriptionIOS = {
|
|
75
|
+
platform: SubscriptionPlatform.ios,
|
|
74
76
|
title: displayName,
|
|
75
77
|
productId: String(id),
|
|
76
78
|
description,
|