react-native-iap 7.2.1 → 7.5.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/CHANGELOG.md +22 -0
- package/README.md +8 -4
- package/android/build.gradle +1 -1
- package/android/src/amazon/java/com/dooboolab/RNIap/RNIapAmazonListener.java +17 -16
- package/android/src/play/java/com/dooboolab/RNIap/RNIapModule.java +1 -3
- package/ios/RNIap.xcodeproj/project.pbxproj +2 -2
- package/ios/RNIapIos.m +5 -5
- package/ios/RNIapIos.swift +11 -0
- package/package.json +17 -17
- package/src/hooks/useIAP.d.ts +3 -0
- package/src/hooks/useIAP.js +31 -90
- package/src/hooks/withIAPContext.d.ts +21 -0
- package/src/hooks/withIAPContext.js +140 -0
- package/src/hooks/withIAPContext.tsx +150 -0
- package/src/iap.d.ts +5 -5
- package/src/iap.js +32 -41
- package/src/index.d.ts +1 -0
- package/src/index.js +1 -0
- package/src/types/index.d.ts +6 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
## Changelogs
|
|
2
2
|
|
|
3
|
+
# 7.5.0
|
|
4
|
+
|
|
5
|
+
### Bugfix
|
|
6
|
+
- Fix canceled purchase dangling [#1504](https://github.com/dooboolab/react-native-iap/pull/1504)
|
|
7
|
+
|
|
8
|
+
### Dependencies
|
|
9
|
+
- Set default `androidX` version [#1505](https://github.com/dooboolab/react-native-iap/pull/1505)
|
|
10
|
+
- Update packages [#1506](https://github.com/dooboolab/react-native-iap/pull/1506)
|
|
11
|
+
|
|
12
|
+
# 7.4.1
|
|
13
|
+
|
|
14
|
+
- [iOS] Add `quantityIOS` in purchase data [#1476](https://github.com/dooboolab/react-native-iap/pull/1476)
|
|
15
|
+
|
|
16
|
+
# 7.4.0
|
|
17
|
+
|
|
18
|
+
- Now using React's Context to manage IAP state
|
|
19
|
+
- Introduce `withIAPContext` HOC ([how to use](docs/docs/usage_instructions/using_hooks.md))
|
|
20
|
+
|
|
21
|
+
# 7.3.0
|
|
22
|
+
|
|
23
|
+
_Breaking Change_:Amazon's receipt was incorrectly being put in `originalJson` it now matches the other platforms: `transactionReceipt` [#1461](https://github.com/dooboolab/react-native-iap/pull/1461)
|
|
24
|
+
|
|
3
25
|
# 7.2.1
|
|
4
26
|
|
|
5
27
|
Fix android crash by delaying ios check [#1456](https://github.com/dooboolab/react-native-iap/pull/1456)
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
[](https://github.com/dooboolab/react-native-iap/actions/workflows/ci.yml)
|
|
7
7
|
[](https://github.com/dooboolab/react-native-iap/actions/workflows/deploy-document.yml)
|
|
8
8
|
[](https://npmjs.org/package/react-native-iap)
|
|
9
|
-
[](https://github.com/dooboolab/react-native-iap)
|
|
10
10
|
[](https://opencollective.com/react-native-iap#backers)
|
|
11
11
|
[](https://github.com/dooboolab/react-native-iap/issues)
|
|
12
12
|
[](https://github.com/dooboolab/react-native-iap/issues?q=is%3Aissue+is%3Aclosed)
|
|
@@ -90,17 +90,21 @@ Quick News
|
|
|
90
90
|
- We had hard time supporting `react-native-iap` issues that did not provide working codes or any other examples. Therefore, we've decided to make an `example` app called [DoobooIAP](https://github.com/hyochan/DoobooIAP), which will contain all the features of `IAP`'s and willing to continuously improve to support real-life examples. [@Bang9](http://github.com/bang9) who had been helping many others for `react-native-iap`, is willing to support this repo so he will grant $300 of our income in `opencollective` as described in [#855](https://github.com/dooboolab/react-native-iap/issues/855) :tada:.
|
|
91
91
|
- `react-native-iap@4.0.8` ~ `react-native-iap@4.1.0` is incompatible with `react-native <0.61`. This is fixed in `react-native-iap@4.1.1` and above.
|
|
92
92
|
- `react-native-iap@4.0.0` has been released. You can see [#716](https://github.com/dooboolab/react-native-iap/pull/716) for updates.
|
|
93
|
-
- In the past, `react-native-iap@^3.*` has been updated very
|
|
94
|
-
Don't get
|
|
93
|
+
- In the past, `react-native-iap@^3.*` has been updated very promptly for migration issues.
|
|
94
|
+
Don't get surprised too much on why it is bumping up version so quickly these days.
|
|
95
95
|
1. Migrated to new `AndroidX` APIs.
|
|
96
96
|
2. Migrated to new `Android` billing client which is `> 2.0.0`.
|
|
97
97
|
- [`acknowledgePurchase()`][android-acknowledge-purchase] has been added since `3.2.0` which is very important.
|
|
98
98
|
3. New [Purchase Flow][a-purchase-flow]
|
|
99
|
-
4. More is
|
|
99
|
+
4. More is coming in `iOS 13`.
|
|
100
100
|
|
|
101
101
|
Breaking Changes
|
|
102
102
|
----------------
|
|
103
103
|
|
|
104
|
+
[7.4.0]
|
|
105
|
+
- Now using React's Context to manage IAP state
|
|
106
|
+
- Introduce `withIAPContext` HOC ([how to use](docs/docs/usage_instructions/using_hooks.md))
|
|
107
|
+
|
|
104
108
|
[7.1.0]
|
|
105
109
|
- `androidOldSku` is no longer required [#1438](https://github.com/dooboolab/react-native-iap/pull/1438).
|
|
106
110
|
|
package/android/build.gradle
CHANGED
|
@@ -71,7 +71,7 @@ dependencies {
|
|
|
71
71
|
implementation "com.android.support:support-annotations:$supportLibVersion"
|
|
72
72
|
implementation "com.android.support:customtabs:$supportLibVersion"
|
|
73
73
|
} else {
|
|
74
|
-
def defaultAndroidXVersion = "1
|
|
74
|
+
def defaultAndroidXVersion = "1.2.0"
|
|
75
75
|
if (androidXVersion == null) {
|
|
76
76
|
androidXVersion = defaultAndroidXVersion
|
|
77
77
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
package com.dooboolab.RNIap;
|
|
2
2
|
|
|
3
3
|
import android.util.Log;
|
|
4
|
+
import androidx.annotation.NonNull;
|
|
4
5
|
import androidx.annotation.Nullable;
|
|
5
6
|
import com.amazon.device.iap.PurchasingListener;
|
|
6
7
|
import com.amazon.device.iap.PurchasingService;
|
|
@@ -154,14 +155,7 @@ public class RNIapAmazonListener implements PurchasingListener {
|
|
|
154
155
|
WritableMap promiseItem = null;
|
|
155
156
|
final List<Receipt> purchases = response.getReceipts();
|
|
156
157
|
for (Receipt receipt : purchases) {
|
|
157
|
-
WritableMap item =
|
|
158
|
-
item.putString("productId", receipt.getSku());
|
|
159
|
-
item.putDouble("transactionDate", receipt.getPurchaseDate().getTime());
|
|
160
|
-
item.putString("purchaseToken", receipt.getReceiptId());
|
|
161
|
-
item.putString("originalJson", receipt.toJSON().toString());
|
|
162
|
-
item.putString("userIdAmazon", userData.getUserId());
|
|
163
|
-
item.putString("userMarketplaceAmazon", userData.getMarketplace());
|
|
164
|
-
item.putString("userJsonAmazon", userData.toJSON().toString());
|
|
158
|
+
WritableMap item = receiptToMap(userData, receipt);
|
|
165
159
|
|
|
166
160
|
promiseItem = new WritableNativeMap();
|
|
167
161
|
promiseItem.merge(item);
|
|
@@ -234,6 +228,20 @@ public class RNIapAmazonListener implements PurchasingListener {
|
|
|
234
228
|
}
|
|
235
229
|
}
|
|
236
230
|
|
|
231
|
+
@NonNull
|
|
232
|
+
private WritableMap receiptToMap(UserData userData, Receipt receipt) {
|
|
233
|
+
WritableMap item = Arguments.createMap();
|
|
234
|
+
item.putString("productId", receipt.getSku());
|
|
235
|
+
item.putDouble("transactionDate", receipt.getPurchaseDate().getTime());
|
|
236
|
+
item.putString("purchaseToken", receipt.getReceiptId());
|
|
237
|
+
item.putString("transactionReceipt", receipt.toJSON().toString());
|
|
238
|
+
item.putString("userIdAmazon", userData.getUserId());
|
|
239
|
+
item.putString("userMarketplaceAmazon", userData.getMarketplace());
|
|
240
|
+
item.putString("userJsonAmazon", userData.toJSON().toString());
|
|
241
|
+
item.putBoolean("isCanceledAmazon", receipt.isCanceled());
|
|
242
|
+
return item;
|
|
243
|
+
}
|
|
244
|
+
|
|
237
245
|
@Override
|
|
238
246
|
public void onPurchaseResponse(final PurchaseResponse response) {
|
|
239
247
|
final String requestId = response.getRequestId().toString();
|
|
@@ -249,14 +257,7 @@ public class RNIapAmazonListener implements PurchasingListener {
|
|
|
249
257
|
case SUCCESSFUL:
|
|
250
258
|
final Receipt receipt = response.getReceipt();
|
|
251
259
|
final UserData userData = response.getUserData();
|
|
252
|
-
WritableMap item =
|
|
253
|
-
item.putString("productId", receipt.getSku());
|
|
254
|
-
item.putDouble("transactionDate", receipt.getPurchaseDate().getTime());
|
|
255
|
-
item.putString("purchaseToken", receipt.getReceiptId());
|
|
256
|
-
item.putString("originalJson", receipt.toJSON().toString());
|
|
257
|
-
item.putString("userIdAmazon", userData.getUserId());
|
|
258
|
-
item.putString("userMarketplaceAmazon", userData.getMarketplace());
|
|
259
|
-
item.putString("userJsonAmazon", userData.toJSON().toString());
|
|
260
|
+
WritableMap item = receiptToMap(userData, receipt);
|
|
260
261
|
|
|
261
262
|
WritableMap promiseItem = new WritableNativeMap();
|
|
262
263
|
promiseItem.merge(item);
|
|
@@ -583,9 +583,7 @@ public class RNIapModule extends ReactContextBaseJavaModule implements Purchases
|
|
|
583
583
|
error.putString("message", errorData[1]);
|
|
584
584
|
sendEvent(reactContext, "purchase-error", error);
|
|
585
585
|
|
|
586
|
-
|
|
587
|
-
PlayUtils.getInstance().rejectPromisesWithBillingError(PROMISE_BUY_ITEM, responseCode);
|
|
588
|
-
}
|
|
586
|
+
PlayUtils.getInstance().rejectPromisesWithBillingError(PROMISE_BUY_ITEM, responseCode);
|
|
589
587
|
return;
|
|
590
588
|
}
|
|
591
589
|
|
|
@@ -247,7 +247,7 @@
|
|
|
247
247
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
|
248
248
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
|
249
249
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
|
250
|
-
IPHONEOS_DEPLOYMENT_TARGET =
|
|
250
|
+
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
|
251
251
|
MTL_ENABLE_DEBUG_INFO = YES;
|
|
252
252
|
ONLY_ACTIVE_ARCH = YES;
|
|
253
253
|
SDKROOT = iphoneos;
|
|
@@ -293,7 +293,7 @@
|
|
|
293
293
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
|
294
294
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
|
295
295
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
|
296
|
-
IPHONEOS_DEPLOYMENT_TARGET =
|
|
296
|
+
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
|
297
297
|
MTL_ENABLE_DEBUG_INFO = NO;
|
|
298
298
|
SDKROOT = iphoneos;
|
|
299
299
|
VALIDATE_PRODUCT = YES;
|
package/ios/RNIapIos.m
CHANGED
|
@@ -327,6 +327,7 @@ RCT_EXPORT_METHOD(getPendingTransactions:(RCTPromiseResolveBlock)resolve
|
|
|
327
327
|
@(item.transactionDate.timeIntervalSince1970 * 1000), @"transactionDate",
|
|
328
328
|
item.transactionIdentifier, @"transactionId",
|
|
329
329
|
item.payment.productIdentifier, @"productId",
|
|
330
|
+
@(item.payment.quantity), @"quantityIOS",
|
|
330
331
|
[receiptData base64EncodedStringWithOptions:0], @"transactionReceipt",
|
|
331
332
|
nil
|
|
332
333
|
];
|
|
@@ -462,11 +463,9 @@ RCT_EXPORT_METHOD(presentCodeRedemptionSheet:(RCTPromiseResolveBlock)resolve
|
|
|
462
463
|
[self sendEventWithName:@"purchase-error" body:err];
|
|
463
464
|
}
|
|
464
465
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
error:transaction.error];
|
|
469
|
-
}
|
|
466
|
+
[self rejectPromisesForKey:transaction.payment.productIdentifier code:[self standardErrorCode:(int)transaction.error.code]
|
|
467
|
+
message:transaction.error.localizedDescription
|
|
468
|
+
error:transaction.error];
|
|
470
469
|
});
|
|
471
470
|
break;
|
|
472
471
|
}
|
|
@@ -768,6 +767,7 @@ RCT_EXPORT_METHOD(presentCodeRedemptionSheet:(RCTPromiseResolveBlock)resolve
|
|
|
768
767
|
@(transaction.transactionDate.timeIntervalSince1970 * 1000), @"transactionDate",
|
|
769
768
|
transaction.transactionIdentifier, @"transactionId",
|
|
770
769
|
transaction.payment.productIdentifier, @"productId",
|
|
770
|
+
@(transaction.payment.quantity), @"quantityIOS",
|
|
771
771
|
[receiptData base64EncodedStringWithOptions:0], @"transactionReceipt",
|
|
772
772
|
nil
|
|
773
773
|
];
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// WIP Migrating from Objective C to swift
|
|
2
|
+
func paymentQueue(_ queue: SKPaymentQueue, removedTransactions transactions: [SKPaymentTransaction]) {
|
|
3
|
+
print("removedTransactions")
|
|
4
|
+
if countPendingTransaction != nil && countPendingTransaction > 0 {
|
|
5
|
+
countPendingTransaction -= transactions.count
|
|
6
|
+
if countPendingTransaction == 0 {
|
|
7
|
+
resolvePromises(forKey: "cleaningTransactions", value: nil)
|
|
8
|
+
countPendingTransaction = nil
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-iap",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.5.0",
|
|
4
4
|
"description": "React Native In App Purchase Module.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -43,31 +43,31 @@
|
|
|
43
43
|
"dooboolab-welcome": "1.3.2"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@babel/core": "7.
|
|
46
|
+
"@babel/core": "7.15.5",
|
|
47
47
|
"@babel/plugin-proposal-class-properties": "7.14.5",
|
|
48
48
|
"@babel/plugin-proposal-private-methods": "7.14.5",
|
|
49
|
-
"@babel/preset-env": "7.
|
|
49
|
+
"@babel/preset-env": "7.15.6",
|
|
50
50
|
"@babel/preset-react": "7.14.5",
|
|
51
|
-
"@babel/preset-typescript": "7.
|
|
52
|
-
"@dooboo/eslint-config": "0.8.
|
|
53
|
-
"@testing-library/jest-native": "4.0.
|
|
51
|
+
"@babel/preset-typescript": "7.15.0",
|
|
52
|
+
"@dooboo/eslint-config": "0.8.5",
|
|
53
|
+
"@testing-library/jest-native": "4.0.2",
|
|
54
54
|
"@testing-library/react-native": "7.2.0",
|
|
55
55
|
"@types/eslint": "7.28.0",
|
|
56
|
-
"@types/jest": "
|
|
57
|
-
"@types/react": "17.0.
|
|
58
|
-
"@types/react-native": "0.
|
|
56
|
+
"@types/jest": "27.0.1",
|
|
57
|
+
"@types/react": "17.0.21",
|
|
58
|
+
"@types/react-native": "0.65.0",
|
|
59
59
|
"babel-core": "7.0.0-bridge.0",
|
|
60
60
|
"babel-eslint": "10.1.0",
|
|
61
|
-
"babel-jest": "27.0
|
|
62
|
-
"eslint": "7.
|
|
63
|
-
"flow-bin": "0.
|
|
61
|
+
"babel-jest": "27.2.0",
|
|
62
|
+
"eslint": "7.32.0",
|
|
63
|
+
"flow-bin": "0.160.0",
|
|
64
64
|
"flowgen": "1.14.1",
|
|
65
|
-
"jest": "27.0
|
|
65
|
+
"jest": "27.2.0",
|
|
66
66
|
"metro-react-native-babel-preset": "0.66.2",
|
|
67
|
-
"monolinter": "1.0.
|
|
68
|
-
"prettier": "2.
|
|
67
|
+
"monolinter": "1.0.4",
|
|
68
|
+
"prettier": "2.4.1",
|
|
69
69
|
"react-native": "0.64.2",
|
|
70
|
-
"ts-jest": "27.0.
|
|
71
|
-
"typescript": "4.3
|
|
70
|
+
"ts-jest": "27.0.5",
|
|
71
|
+
"typescript": "4.4.3"
|
|
72
72
|
}
|
|
73
73
|
}
|
package/src/hooks/useIAP.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Product, Purchase, PurchaseError, Subscription } from '../types';
|
|
2
|
+
import { requestPurchase as iapRequestPurchase, requestSubscription as iapRequestSubscription } from '../iap';
|
|
2
3
|
declare type IAP_STATUS = {
|
|
3
4
|
connected: boolean;
|
|
4
5
|
products: Product[];
|
|
@@ -13,6 +14,8 @@ declare type IAP_STATUS = {
|
|
|
13
14
|
getPurchaseHistories: () => Promise<void>;
|
|
14
15
|
getProducts: (skus: string[]) => Promise<void>;
|
|
15
16
|
getSubscriptions: (skus: string[]) => Promise<void>;
|
|
17
|
+
requestPurchase: typeof iapRequestPurchase;
|
|
18
|
+
requesSubscription: typeof iapRequestSubscription;
|
|
16
19
|
};
|
|
17
20
|
export declare function useIAP(): IAP_STATUS;
|
|
18
21
|
export {};
|
package/src/hooks/useIAP.js
CHANGED
|
@@ -34,53 +34,38 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
34
34
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
35
35
|
}
|
|
36
36
|
};
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return to;
|
|
41
|
-
};
|
|
42
|
-
import { NativeEventEmitter, NativeModules, } from 'react-native';
|
|
43
|
-
import { endConnection, getPromotedProductIOS, getPurchaseHistory, finishTransaction as iapFinishTransaction, getAvailablePurchases as iapGetAvailablePurchases, getProducts as iapGetProducts, getSubscriptions as iapGetSubscriptions, initConnection, purchaseErrorListener, purchaseUpdatedListener, } from '../iap';
|
|
44
|
-
import { useCallback, useEffect, useState } from 'react';
|
|
45
|
-
var RNIapIos = NativeModules.RNIapIos;
|
|
46
|
-
var IAPEmitter = new NativeEventEmitter(RNIapIos);
|
|
47
|
-
var purchaseUpdateSubscription;
|
|
48
|
-
var purchaseErrorSubscription;
|
|
49
|
-
var promotedProductsSubscription;
|
|
37
|
+
import { getPurchaseHistory, finishTransaction as iapFinishTransaction, getAvailablePurchases as iapGetAvailablePurchases, getProducts as iapGetProducts, getSubscriptions as iapGetSubscriptions, requestPurchase as iapRequestPurchase, requestSubscription as iapRequestSubscription, } from '../iap';
|
|
38
|
+
import { useCallback } from 'react';
|
|
39
|
+
import { useIAPContext } from './withIAPContext';
|
|
50
40
|
export function useIAP() {
|
|
51
41
|
var _this = this;
|
|
52
|
-
var _a =
|
|
53
|
-
var _b = useState([]), products = _b[0], setProducts = _b[1];
|
|
54
|
-
var _c = useState([]), promotedProductsIOS = _c[0], setPromotedProductsIOS = _c[1];
|
|
55
|
-
var _d = useState([]), subscriptions = _d[0], setSubscriptions = _d[1];
|
|
56
|
-
var _e = useState([]), purchaseHistories = _e[0], setPurchaseHistories = _e[1];
|
|
57
|
-
var _f = useState([]), availablePurchases = _f[0], setAvailablePurchases = _f[1];
|
|
58
|
-
var _g = useState(), currentPurchase = _g[0], setCurrentPurchase = _g[1];
|
|
59
|
-
var _h = useState(), currentPurchaseError = _h[0], setCurrentPurchaseError = _h[1];
|
|
42
|
+
var _a = useIAPContext(), connected = _a.connected, products = _a.products, promotedProductsIOS = _a.promotedProductsIOS, subscriptions = _a.subscriptions, purchaseHistories = _a.purchaseHistories, availablePurchases = _a.availablePurchases, currentPurchase = _a.currentPurchase, currentPurchaseError = _a.currentPurchaseError, setProducts = _a.setProducts, setSubscriptions = _a.setSubscriptions, setAvailablePurchases = _a.setAvailablePurchases, setPurchaseHistories = _a.setPurchaseHistories, setCurrentPurchase = _a.setCurrentPurchase, setCurrentPurchaseError = _a.setCurrentPurchaseError;
|
|
60
43
|
var getProducts = useCallback(function (skus) { return __awaiter(_this, void 0, void 0, function () {
|
|
61
|
-
var
|
|
62
|
-
return __generator(this, function (
|
|
63
|
-
switch (
|
|
64
|
-
case 0:
|
|
44
|
+
var _a;
|
|
45
|
+
return __generator(this, function (_b) {
|
|
46
|
+
switch (_b.label) {
|
|
47
|
+
case 0:
|
|
48
|
+
_a = setProducts;
|
|
49
|
+
return [4 /*yield*/, iapGetProducts(skus)];
|
|
65
50
|
case 1:
|
|
66
|
-
|
|
67
|
-
setProducts(iaps);
|
|
51
|
+
_a.apply(void 0, [_b.sent()]);
|
|
68
52
|
return [2 /*return*/];
|
|
69
53
|
}
|
|
70
54
|
});
|
|
71
|
-
}); }, []);
|
|
55
|
+
}); }, [setProducts]);
|
|
72
56
|
var getSubscriptions = useCallback(function (skus) { return __awaiter(_this, void 0, void 0, function () {
|
|
73
|
-
var
|
|
74
|
-
return __generator(this, function (
|
|
75
|
-
switch (
|
|
76
|
-
case 0:
|
|
57
|
+
var _a;
|
|
58
|
+
return __generator(this, function (_b) {
|
|
59
|
+
switch (_b.label) {
|
|
60
|
+
case 0:
|
|
61
|
+
_a = setSubscriptions;
|
|
62
|
+
return [4 /*yield*/, iapGetSubscriptions(skus)];
|
|
77
63
|
case 1:
|
|
78
|
-
|
|
79
|
-
setSubscriptions(subs);
|
|
64
|
+
_a.apply(void 0, [_b.sent()]);
|
|
80
65
|
return [2 /*return*/];
|
|
81
66
|
}
|
|
82
67
|
});
|
|
83
|
-
}); }, []);
|
|
68
|
+
}); }, [setSubscriptions]);
|
|
84
69
|
var getAvailablePurchases = useCallback(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
85
70
|
var _a;
|
|
86
71
|
return __generator(this, function (_b) {
|
|
@@ -93,7 +78,7 @@ export function useIAP() {
|
|
|
93
78
|
return [2 /*return*/];
|
|
94
79
|
}
|
|
95
80
|
});
|
|
96
|
-
}); }, []);
|
|
81
|
+
}); }, [setAvailablePurchases]);
|
|
97
82
|
var getPurchaseHistories = useCallback(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
98
83
|
var _a;
|
|
99
84
|
return __generator(this, function (_b) {
|
|
@@ -106,7 +91,7 @@ export function useIAP() {
|
|
|
106
91
|
return [2 /*return*/];
|
|
107
92
|
}
|
|
108
93
|
});
|
|
109
|
-
}); }, []);
|
|
94
|
+
}); }, [setPurchaseHistories]);
|
|
110
95
|
var finishTransaction = useCallback(function (purchase, isConsumable, developerPayloadAndroid) { return __awaiter(_this, void 0, void 0, function () {
|
|
111
96
|
var err_1;
|
|
112
97
|
return __generator(this, function (_a) {
|
|
@@ -117,7 +102,7 @@ export function useIAP() {
|
|
|
117
102
|
case 1: return [2 /*return*/, _a.sent()];
|
|
118
103
|
case 2:
|
|
119
104
|
err_1 = _a.sent();
|
|
120
|
-
throw
|
|
105
|
+
throw err_1;
|
|
121
106
|
case 3:
|
|
122
107
|
if (purchase.productId === (currentPurchase === null || currentPurchase === void 0 ? void 0 : currentPurchase.productId))
|
|
123
108
|
setCurrentPurchase(undefined);
|
|
@@ -127,58 +112,12 @@ export function useIAP() {
|
|
|
127
112
|
case 4: return [2 /*return*/];
|
|
128
113
|
}
|
|
129
114
|
});
|
|
130
|
-
}); }, [
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
case 0: return [4 /*yield*/, initConnection()];
|
|
137
|
-
case 1:
|
|
138
|
-
result = _a.sent();
|
|
139
|
-
setConnected(result);
|
|
140
|
-
if (result) {
|
|
141
|
-
purchaseUpdateSubscription = purchaseUpdatedListener(function (purchase) { return __awaiter(_this, void 0, void 0, function () {
|
|
142
|
-
return __generator(this, function (_a) {
|
|
143
|
-
setCurrentPurchaseError(undefined);
|
|
144
|
-
setCurrentPurchase(purchase);
|
|
145
|
-
return [2 /*return*/];
|
|
146
|
-
});
|
|
147
|
-
}); });
|
|
148
|
-
purchaseErrorSubscription = purchaseErrorListener(function (error) {
|
|
149
|
-
setCurrentPurchase(undefined);
|
|
150
|
-
setCurrentPurchaseError(error);
|
|
151
|
-
});
|
|
152
|
-
promotedProductsSubscription = IAPEmitter.addListener('iap-promoted-product', function () { return __awaiter(_this, void 0, void 0, function () {
|
|
153
|
-
var product;
|
|
154
|
-
return __generator(this, function (_a) {
|
|
155
|
-
switch (_a.label) {
|
|
156
|
-
case 0: return [4 /*yield*/, getPromotedProductIOS()];
|
|
157
|
-
case 1:
|
|
158
|
-
product = _a.sent();
|
|
159
|
-
setPromotedProductsIOS(function (prevProducts) { return __spreadArray(__spreadArray([], prevProducts), (product ? [product] : [])); });
|
|
160
|
-
return [2 /*return*/];
|
|
161
|
-
}
|
|
162
|
-
});
|
|
163
|
-
}); });
|
|
164
|
-
}
|
|
165
|
-
return [2 /*return*/];
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
|
-
}); }, []);
|
|
169
|
-
useEffect(function () {
|
|
170
|
-
initIapWithSubscriptions();
|
|
171
|
-
return function () {
|
|
172
|
-
if (purchaseUpdateSubscription)
|
|
173
|
-
purchaseUpdateSubscription.remove();
|
|
174
|
-
if (purchaseErrorSubscription)
|
|
175
|
-
purchaseErrorSubscription.remove();
|
|
176
|
-
if (promotedProductsSubscription)
|
|
177
|
-
promotedProductsSubscription.remove();
|
|
178
|
-
endConnection();
|
|
179
|
-
setConnected(false);
|
|
180
|
-
};
|
|
181
|
-
}, [initIapWithSubscriptions]);
|
|
115
|
+
}); }, [
|
|
116
|
+
currentPurchase === null || currentPurchase === void 0 ? void 0 : currentPurchase.productId,
|
|
117
|
+
currentPurchaseError === null || currentPurchaseError === void 0 ? void 0 : currentPurchaseError.productId,
|
|
118
|
+
setCurrentPurchase,
|
|
119
|
+
setCurrentPurchaseError,
|
|
120
|
+
]);
|
|
182
121
|
return {
|
|
183
122
|
connected: connected,
|
|
184
123
|
products: products,
|
|
@@ -193,5 +132,7 @@ export function useIAP() {
|
|
|
193
132
|
getSubscriptions: getSubscriptions,
|
|
194
133
|
getAvailablePurchases: getAvailablePurchases,
|
|
195
134
|
getPurchaseHistories: getPurchaseHistories,
|
|
135
|
+
requestPurchase: iapRequestPurchase,
|
|
136
|
+
requesSubscription: iapRequestSubscription,
|
|
196
137
|
};
|
|
197
138
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Product, Purchase, PurchaseError, Subscription } from '../types';
|
|
3
|
+
declare type IAPContextType = {
|
|
4
|
+
connected: boolean;
|
|
5
|
+
products: Product[];
|
|
6
|
+
promotedProductsIOS: Product[];
|
|
7
|
+
subscriptions: Subscription[];
|
|
8
|
+
purchaseHistories: Purchase[];
|
|
9
|
+
availablePurchases: Purchase[];
|
|
10
|
+
currentPurchase?: Purchase;
|
|
11
|
+
currentPurchaseError?: PurchaseError;
|
|
12
|
+
setProducts: (products: Product[]) => void;
|
|
13
|
+
setSubscriptions: (subscriptions: Subscription[]) => void;
|
|
14
|
+
setPurchaseHistories: (purchaseHistories: Purchase[]) => void;
|
|
15
|
+
setAvailablePurchases: (availablePurchases: Purchase[]) => void;
|
|
16
|
+
setCurrentPurchase: (currentPurchase: Purchase | undefined) => void;
|
|
17
|
+
setCurrentPurchaseError: (currentPurchaseError: PurchaseError | undefined) => void;
|
|
18
|
+
};
|
|
19
|
+
export declare function useIAPContext(): IAPContextType;
|
|
20
|
+
export declare function withIAPContext<T>(Component: React.ComponentType<T>): (props: T) => JSX.Element;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
11
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
12
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
13
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
14
|
+
function step(op) {
|
|
15
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
16
|
+
while (_) try {
|
|
17
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
18
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
19
|
+
switch (op[0]) {
|
|
20
|
+
case 0: case 1: t = op; break;
|
|
21
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
22
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
23
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
24
|
+
default:
|
|
25
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
26
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
27
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
28
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
29
|
+
if (t[2]) _.ops.pop();
|
|
30
|
+
_.trys.pop(); continue;
|
|
31
|
+
}
|
|
32
|
+
op = body.call(thisArg, _);
|
|
33
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
34
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
38
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
39
|
+
if (ar || !(i in from)) {
|
|
40
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
41
|
+
ar[i] = from[i];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
45
|
+
};
|
|
46
|
+
import React, { useContext, useEffect, useMemo, useState } from 'react';
|
|
47
|
+
import { NativeEventEmitter, NativeModules } from 'react-native';
|
|
48
|
+
import { getPromotedProductIOS, initConnection, purchaseErrorListener, purchaseUpdatedListener, } from '../iap';
|
|
49
|
+
var RNIapIos = NativeModules.RNIapIos;
|
|
50
|
+
var IAPEmitter = new NativeEventEmitter(RNIapIos);
|
|
51
|
+
// @ts-ignore
|
|
52
|
+
var IAPContext = React.createContext(null);
|
|
53
|
+
export function useIAPContext() {
|
|
54
|
+
var ctx = useContext(IAPContext);
|
|
55
|
+
if (!ctx)
|
|
56
|
+
throw new Error('You need wrap your app with withIAPContext HOC');
|
|
57
|
+
return ctx;
|
|
58
|
+
}
|
|
59
|
+
export function withIAPContext(Component) {
|
|
60
|
+
return function WrapperComponent(props) {
|
|
61
|
+
var _this = this;
|
|
62
|
+
var _a = useState(false), connected = _a[0], setConnected = _a[1];
|
|
63
|
+
var _b = useState([]), products = _b[0], setProducts = _b[1];
|
|
64
|
+
var _c = useState([]), promotedProductsIOS = _c[0], setPromotedProductsIOS = _c[1];
|
|
65
|
+
var _d = useState([]), subscriptions = _d[0], setSubscriptions = _d[1];
|
|
66
|
+
var _e = useState([]), purchaseHistories = _e[0], setPurchaseHistories = _e[1];
|
|
67
|
+
var _f = useState([]), availablePurchases = _f[0], setAvailablePurchases = _f[1];
|
|
68
|
+
var _g = useState(), currentPurchase = _g[0], setCurrentPurchase = _g[1];
|
|
69
|
+
var _h = useState(), currentPurchaseError = _h[0], setCurrentPurchaseError = _h[1];
|
|
70
|
+
var context = useMemo(function () { return ({
|
|
71
|
+
connected: connected,
|
|
72
|
+
products: products,
|
|
73
|
+
subscriptions: subscriptions,
|
|
74
|
+
promotedProductsIOS: promotedProductsIOS,
|
|
75
|
+
purchaseHistories: purchaseHistories,
|
|
76
|
+
availablePurchases: availablePurchases,
|
|
77
|
+
currentPurchase: currentPurchase,
|
|
78
|
+
currentPurchaseError: currentPurchaseError,
|
|
79
|
+
setProducts: setProducts,
|
|
80
|
+
setSubscriptions: setSubscriptions,
|
|
81
|
+
setPurchaseHistories: setPurchaseHistories,
|
|
82
|
+
setAvailablePurchases: setAvailablePurchases,
|
|
83
|
+
setCurrentPurchase: setCurrentPurchase,
|
|
84
|
+
setCurrentPurchaseError: setCurrentPurchaseError,
|
|
85
|
+
}); }, [
|
|
86
|
+
connected,
|
|
87
|
+
products,
|
|
88
|
+
subscriptions,
|
|
89
|
+
promotedProductsIOS,
|
|
90
|
+
purchaseHistories,
|
|
91
|
+
availablePurchases,
|
|
92
|
+
currentPurchase,
|
|
93
|
+
currentPurchaseError,
|
|
94
|
+
setProducts,
|
|
95
|
+
setSubscriptions,
|
|
96
|
+
setPurchaseHistories,
|
|
97
|
+
setAvailablePurchases,
|
|
98
|
+
setCurrentPurchase,
|
|
99
|
+
setCurrentPurchaseError,
|
|
100
|
+
]);
|
|
101
|
+
useEffect(function () {
|
|
102
|
+
initConnection().then(setConnected);
|
|
103
|
+
}, []);
|
|
104
|
+
useEffect(function () {
|
|
105
|
+
if (!connected)
|
|
106
|
+
return;
|
|
107
|
+
var purchaseUpdateSubscription = purchaseUpdatedListener(function (purchase) { return __awaiter(_this, void 0, void 0, function () {
|
|
108
|
+
return __generator(this, function (_a) {
|
|
109
|
+
setCurrentPurchaseError(undefined);
|
|
110
|
+
setCurrentPurchase(purchase);
|
|
111
|
+
return [2 /*return*/];
|
|
112
|
+
});
|
|
113
|
+
}); });
|
|
114
|
+
var purchaseErrorSubscription = purchaseErrorListener(function (error) {
|
|
115
|
+
setCurrentPurchase(undefined);
|
|
116
|
+
setCurrentPurchaseError(error);
|
|
117
|
+
});
|
|
118
|
+
var promotedProductsSubscription = IAPEmitter.addListener('iap-promoted-product', function () { return __awaiter(_this, void 0, void 0, function () {
|
|
119
|
+
var product;
|
|
120
|
+
return __generator(this, function (_a) {
|
|
121
|
+
switch (_a.label) {
|
|
122
|
+
case 0: return [4 /*yield*/, getPromotedProductIOS()];
|
|
123
|
+
case 1:
|
|
124
|
+
product = _a.sent();
|
|
125
|
+
setPromotedProductsIOS(function (prevProducts) { return __spreadArray(__spreadArray([], prevProducts, true), (product ? [product] : []), true); });
|
|
126
|
+
return [2 /*return*/];
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
}); });
|
|
130
|
+
return function () {
|
|
131
|
+
purchaseUpdateSubscription.remove();
|
|
132
|
+
purchaseErrorSubscription.remove();
|
|
133
|
+
promotedProductsSubscription.remove();
|
|
134
|
+
};
|
|
135
|
+
}, [connected]);
|
|
136
|
+
return (<IAPContext.Provider value={context}>
|
|
137
|
+
<Component {...props}/>
|
|
138
|
+
</IAPContext.Provider>);
|
|
139
|
+
};
|
|
140
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import React, {useContext, useEffect, useMemo, useState} from 'react';
|
|
2
|
+
import {NativeEventEmitter, NativeModules} from 'react-native';
|
|
3
|
+
import {
|
|
4
|
+
InAppPurchase,
|
|
5
|
+
Product,
|
|
6
|
+
Purchase,
|
|
7
|
+
PurchaseError,
|
|
8
|
+
Subscription,
|
|
9
|
+
SubscriptionPurchase,
|
|
10
|
+
} from '../types';
|
|
11
|
+
import {
|
|
12
|
+
getPromotedProductIOS,
|
|
13
|
+
initConnection,
|
|
14
|
+
purchaseErrorListener,
|
|
15
|
+
purchaseUpdatedListener,
|
|
16
|
+
} from '../iap';
|
|
17
|
+
|
|
18
|
+
type IAPContextType = {
|
|
19
|
+
connected: boolean;
|
|
20
|
+
products: Product[];
|
|
21
|
+
promotedProductsIOS: Product[];
|
|
22
|
+
subscriptions: Subscription[];
|
|
23
|
+
purchaseHistories: Purchase[];
|
|
24
|
+
availablePurchases: Purchase[];
|
|
25
|
+
currentPurchase?: Purchase;
|
|
26
|
+
currentPurchaseError?: PurchaseError;
|
|
27
|
+
setProducts: (products: Product[]) => void;
|
|
28
|
+
setSubscriptions: (subscriptions: Subscription[]) => void;
|
|
29
|
+
setPurchaseHistories: (purchaseHistories: Purchase[]) => void;
|
|
30
|
+
setAvailablePurchases: (availablePurchases: Purchase[]) => void;
|
|
31
|
+
setCurrentPurchase: (currentPurchase: Purchase | undefined) => void;
|
|
32
|
+
setCurrentPurchaseError: (
|
|
33
|
+
currentPurchaseError: PurchaseError | undefined,
|
|
34
|
+
) => void;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const {RNIapIos} = NativeModules;
|
|
38
|
+
const IAPEmitter = new NativeEventEmitter(RNIapIos);
|
|
39
|
+
|
|
40
|
+
// @ts-ignore
|
|
41
|
+
const IAPContext = React.createContext<IAPContextType>(null);
|
|
42
|
+
|
|
43
|
+
export function useIAPContext(): IAPContextType {
|
|
44
|
+
const ctx = useContext(IAPContext);
|
|
45
|
+
if (!ctx) throw new Error('You need wrap your app with withIAPContext HOC');
|
|
46
|
+
|
|
47
|
+
return ctx;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function withIAPContext<T>(Component: React.ComponentType<T>) {
|
|
51
|
+
return function WrapperComponent(props: T) {
|
|
52
|
+
const [connected, setConnected] = useState<boolean>(false);
|
|
53
|
+
const [products, setProducts] = useState<Product[]>([]);
|
|
54
|
+
|
|
55
|
+
const [promotedProductsIOS, setPromotedProductsIOS] = useState<Product[]>(
|
|
56
|
+
[],
|
|
57
|
+
);
|
|
58
|
+
const [subscriptions, setSubscriptions] = useState<Subscription[]>([]);
|
|
59
|
+
const [purchaseHistories, setPurchaseHistories] = useState<Purchase[]>([]);
|
|
60
|
+
|
|
61
|
+
const [availablePurchases, setAvailablePurchases] = useState<Purchase[]>(
|
|
62
|
+
[],
|
|
63
|
+
);
|
|
64
|
+
const [currentPurchase, setCurrentPurchase] = useState<Purchase>();
|
|
65
|
+
|
|
66
|
+
const [currentPurchaseError, setCurrentPurchaseError] =
|
|
67
|
+
useState<PurchaseError>();
|
|
68
|
+
|
|
69
|
+
const context = useMemo(
|
|
70
|
+
() => ({
|
|
71
|
+
connected,
|
|
72
|
+
products,
|
|
73
|
+
subscriptions,
|
|
74
|
+
promotedProductsIOS,
|
|
75
|
+
purchaseHistories,
|
|
76
|
+
availablePurchases,
|
|
77
|
+
currentPurchase,
|
|
78
|
+
currentPurchaseError,
|
|
79
|
+
setProducts,
|
|
80
|
+
setSubscriptions,
|
|
81
|
+
setPurchaseHistories,
|
|
82
|
+
setAvailablePurchases,
|
|
83
|
+
setCurrentPurchase,
|
|
84
|
+
setCurrentPurchaseError,
|
|
85
|
+
}),
|
|
86
|
+
[
|
|
87
|
+
connected,
|
|
88
|
+
products,
|
|
89
|
+
subscriptions,
|
|
90
|
+
promotedProductsIOS,
|
|
91
|
+
purchaseHistories,
|
|
92
|
+
availablePurchases,
|
|
93
|
+
currentPurchase,
|
|
94
|
+
currentPurchaseError,
|
|
95
|
+
setProducts,
|
|
96
|
+
setSubscriptions,
|
|
97
|
+
setPurchaseHistories,
|
|
98
|
+
setAvailablePurchases,
|
|
99
|
+
setCurrentPurchase,
|
|
100
|
+
setCurrentPurchaseError,
|
|
101
|
+
],
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
useEffect(() => {
|
|
105
|
+
initConnection().then(setConnected);
|
|
106
|
+
}, []);
|
|
107
|
+
|
|
108
|
+
useEffect(() => {
|
|
109
|
+
if (!connected) return;
|
|
110
|
+
|
|
111
|
+
const purchaseUpdateSubscription = purchaseUpdatedListener(
|
|
112
|
+
async (purchase: InAppPurchase | SubscriptionPurchase) => {
|
|
113
|
+
setCurrentPurchaseError(undefined);
|
|
114
|
+
setCurrentPurchase(purchase);
|
|
115
|
+
},
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
const purchaseErrorSubscription = purchaseErrorListener(
|
|
119
|
+
(error: PurchaseError) => {
|
|
120
|
+
setCurrentPurchase(undefined);
|
|
121
|
+
setCurrentPurchaseError(error);
|
|
122
|
+
},
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
const promotedProductsSubscription = IAPEmitter.addListener(
|
|
126
|
+
'iap-promoted-product',
|
|
127
|
+
async () => {
|
|
128
|
+
const product = await getPromotedProductIOS();
|
|
129
|
+
|
|
130
|
+
setPromotedProductsIOS((prevProducts) => [
|
|
131
|
+
...prevProducts,
|
|
132
|
+
...(product ? [product] : []),
|
|
133
|
+
]);
|
|
134
|
+
},
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
return () => {
|
|
138
|
+
purchaseUpdateSubscription.remove();
|
|
139
|
+
purchaseErrorSubscription.remove();
|
|
140
|
+
promotedProductsSubscription.remove();
|
|
141
|
+
};
|
|
142
|
+
}, [connected]);
|
|
143
|
+
|
|
144
|
+
return (
|
|
145
|
+
<IAPContext.Provider value={context}>
|
|
146
|
+
<Component {...props} />
|
|
147
|
+
</IAPContext.Provider>
|
|
148
|
+
);
|
|
149
|
+
};
|
|
150
|
+
}
|
package/src/iap.d.ts
CHANGED
|
@@ -24,7 +24,7 @@ export declare const flushFailedPurchasesCachedAsPendingAndroid: () => Promise<s
|
|
|
24
24
|
* @param {string[]} skus The item skus
|
|
25
25
|
* @returns {Promise<Product[]>}
|
|
26
26
|
*/
|
|
27
|
-
export declare const getProducts:
|
|
27
|
+
export declare const getProducts: (skus: string[]) => Promise<Array<Product>>;
|
|
28
28
|
/**
|
|
29
29
|
* Get a list of subscriptions
|
|
30
30
|
* @param {string[]} skus The item skus
|
|
@@ -49,7 +49,7 @@ export declare const getAvailablePurchases: () => Promise<(InAppPurchase | Subsc
|
|
|
49
49
|
* @param {string} [obfuscatedProfileIdAndroid] Specifies an optional obfuscated string that is uniquely associated with the user's profile in your app.
|
|
50
50
|
* @returns {Promise<InAppPurchase>}
|
|
51
51
|
*/
|
|
52
|
-
export declare const requestPurchase: (sku: string, andDangerouslyFinishTransactionAutomaticallyIOS?: boolean
|
|
52
|
+
export declare const requestPurchase: (sku: string, andDangerouslyFinishTransactionAutomaticallyIOS?: boolean, obfuscatedAccountIdAndroid?: string | undefined, obfuscatedProfileIdAndroid?: string | undefined) => Promise<InAppPurchase>;
|
|
53
53
|
/**
|
|
54
54
|
* Request a purchase for product. This will be received in `PurchaseUpdatedListener`.
|
|
55
55
|
* @param {string} [sku] The product's sku/ID
|
|
@@ -60,7 +60,7 @@ export declare const requestPurchase: (sku: string, andDangerouslyFinishTransact
|
|
|
60
60
|
* @param {string} [obfuscatedProfileIdAndroid] Specifies an optional obfuscated string that is uniquely associated with the user's profile in your app.
|
|
61
61
|
* @returns {Promise<SubscriptionPurchase | null>} Promise resolves to null when using proratioModesAndroid=DEFERRED, and to a SubscriptionPurchase otherwise
|
|
62
62
|
*/
|
|
63
|
-
export declare const requestSubscription: (sku: string, andDangerouslyFinishTransactionAutomaticallyIOS?: boolean
|
|
63
|
+
export declare const requestSubscription: (sku: string, andDangerouslyFinishTransactionAutomaticallyIOS?: boolean, purchaseTokenAndroid?: string | undefined, prorationModeAndroid?: ProrationModesAndroid, obfuscatedAccountIdAndroid?: string | undefined, obfuscatedProfileIdAndroid?: string | undefined) => Promise<SubscriptionPurchase | null>;
|
|
64
64
|
/**
|
|
65
65
|
* Request a purchase for product. This will be received in `PurchaseUpdatedListener`.
|
|
66
66
|
* @param {string} sku The product's sku/ID
|
|
@@ -165,12 +165,12 @@ export declare const validateReceiptAndroid: (packageName: string, productId: st
|
|
|
165
165
|
*/
|
|
166
166
|
export declare const validateReceiptAmazon: (developerSecret: string, userId: string, receiptId: string, useSandbox?: boolean) => Promise<Amazon.ReceiptType>;
|
|
167
167
|
/**
|
|
168
|
-
* Add IAP purchase event
|
|
168
|
+
* Add IAP purchase event
|
|
169
169
|
* @returns {callback(e: InAppPurchase | ProductPurchase)}
|
|
170
170
|
*/
|
|
171
171
|
export declare const purchaseUpdatedListener: (listener: (event: InAppPurchase | SubscriptionPurchase) => void) => EmitterSubscription;
|
|
172
172
|
/**
|
|
173
|
-
* Add IAP purchase error event
|
|
173
|
+
* Add IAP purchase error event
|
|
174
174
|
* @returns {callback(e: PurchaseError)}
|
|
175
175
|
*/
|
|
176
176
|
export declare const purchaseErrorListener: (listener: (errorEvent: PurchaseError) => void) => EmitterSubscription;
|
package/src/iap.js
CHANGED
|
@@ -132,14 +132,14 @@ var fillProductsAdditionalData = function (products) { return __awaiter(void 0,
|
|
|
132
132
|
export var getProducts = function (skus) {
|
|
133
133
|
return (Platform.select({
|
|
134
134
|
ios: function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
135
|
+
var items;
|
|
135
136
|
return __generator(this, function (_a) {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
})];
|
|
137
|
+
switch (_a.label) {
|
|
138
|
+
case 0: return [4 /*yield*/, getIosModule().getItems(skus)];
|
|
139
|
+
case 1:
|
|
140
|
+
items = _a.sent();
|
|
141
|
+
return [2 /*return*/, items.filter(function (item) { return skus.includes(item.productId); })];
|
|
142
|
+
}
|
|
143
143
|
});
|
|
144
144
|
}); },
|
|
145
145
|
android: function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
@@ -163,12 +163,16 @@ export var getProducts = function (skus) {
|
|
|
163
163
|
export var getSubscriptions = function (skus) {
|
|
164
164
|
return (Platform.select({
|
|
165
165
|
ios: function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
166
|
+
var items;
|
|
166
167
|
return __generator(this, function (_a) {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
168
|
+
switch (_a.label) {
|
|
169
|
+
case 0: return [4 /*yield*/, getIosModule().getItems(skus)];
|
|
170
|
+
case 1:
|
|
171
|
+
items = _a.sent();
|
|
172
|
+
return [2 /*return*/, items.filter(function (item) {
|
|
173
|
+
return skus.includes(item.productId);
|
|
174
|
+
})];
|
|
175
|
+
}
|
|
172
176
|
});
|
|
173
177
|
}); },
|
|
174
178
|
android: function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
@@ -247,13 +251,12 @@ export var getAvailablePurchases = function () {
|
|
|
247
251
|
* @returns {Promise<InAppPurchase>}
|
|
248
252
|
*/
|
|
249
253
|
export var requestPurchase = function (sku, andDangerouslyFinishTransactionAutomaticallyIOS, obfuscatedAccountIdAndroid, obfuscatedProfileIdAndroid) {
|
|
254
|
+
if (andDangerouslyFinishTransactionAutomaticallyIOS === void 0) { andDangerouslyFinishTransactionAutomaticallyIOS = false; }
|
|
255
|
+
if (obfuscatedAccountIdAndroid === void 0) { obfuscatedAccountIdAndroid = undefined; }
|
|
256
|
+
if (obfuscatedProfileIdAndroid === void 0) { obfuscatedProfileIdAndroid = undefined; }
|
|
250
257
|
return (Platform.select({
|
|
251
258
|
ios: function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
252
259
|
return __generator(this, function (_a) {
|
|
253
|
-
andDangerouslyFinishTransactionAutomaticallyIOS =
|
|
254
|
-
andDangerouslyFinishTransactionAutomaticallyIOS === undefined
|
|
255
|
-
? false
|
|
256
|
-
: andDangerouslyFinishTransactionAutomaticallyIOS;
|
|
257
260
|
if (andDangerouslyFinishTransactionAutomaticallyIOS)
|
|
258
261
|
// eslint-disable-next-line no-console
|
|
259
262
|
console.warn(
|
|
@@ -280,13 +283,14 @@ export var requestPurchase = function (sku, andDangerouslyFinishTransactionAutom
|
|
|
280
283
|
* @returns {Promise<SubscriptionPurchase | null>} Promise resolves to null when using proratioModesAndroid=DEFERRED, and to a SubscriptionPurchase otherwise
|
|
281
284
|
*/
|
|
282
285
|
export var requestSubscription = function (sku, andDangerouslyFinishTransactionAutomaticallyIOS, purchaseTokenAndroid, prorationModeAndroid, obfuscatedAccountIdAndroid, obfuscatedProfileIdAndroid) {
|
|
286
|
+
if (andDangerouslyFinishTransactionAutomaticallyIOS === void 0) { andDangerouslyFinishTransactionAutomaticallyIOS = false; }
|
|
287
|
+
if (purchaseTokenAndroid === void 0) { purchaseTokenAndroid = undefined; }
|
|
288
|
+
if (prorationModeAndroid === void 0) { prorationModeAndroid = -1; }
|
|
289
|
+
if (obfuscatedAccountIdAndroid === void 0) { obfuscatedAccountIdAndroid = undefined; }
|
|
290
|
+
if (obfuscatedProfileIdAndroid === void 0) { obfuscatedProfileIdAndroid = undefined; }
|
|
283
291
|
return (Platform.select({
|
|
284
292
|
ios: function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
285
293
|
return __generator(this, function (_a) {
|
|
286
|
-
andDangerouslyFinishTransactionAutomaticallyIOS =
|
|
287
|
-
andDangerouslyFinishTransactionAutomaticallyIOS === undefined
|
|
288
|
-
? false
|
|
289
|
-
: andDangerouslyFinishTransactionAutomaticallyIOS;
|
|
290
294
|
if (andDangerouslyFinishTransactionAutomaticallyIOS)
|
|
291
295
|
// eslint-disable-next-line no-console
|
|
292
296
|
console.warn(
|
|
@@ -297,8 +301,6 @@ export var requestSubscription = function (sku, andDangerouslyFinishTransactionA
|
|
|
297
301
|
}); },
|
|
298
302
|
android: function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
299
303
|
return __generator(this, function (_a) {
|
|
300
|
-
if (!prorationModeAndroid)
|
|
301
|
-
prorationModeAndroid = -1;
|
|
302
304
|
return [2 /*return*/, getAndroidModule().buyItemByType(ANDROID_ITEM_TYPE_SUBSCRIPTION, sku, purchaseTokenAndroid, prorationModeAndroid, obfuscatedAccountIdAndroid, obfuscatedProfileIdAndroid)];
|
|
303
305
|
});
|
|
304
306
|
}); },
|
|
@@ -553,33 +555,22 @@ export var validateReceiptAmazon = function (developerSecret, userId, receiptId,
|
|
|
553
555
|
});
|
|
554
556
|
};
|
|
555
557
|
/**
|
|
556
|
-
* Add IAP purchase event
|
|
558
|
+
* Add IAP purchase event
|
|
557
559
|
* @returns {callback(e: InAppPurchase | ProductPurchase)}
|
|
558
560
|
*/
|
|
559
561
|
export var purchaseUpdatedListener = function (listener) {
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
var myRNIapModule = getAndroidModule();
|
|
566
|
-
var myModuleEvt = new NativeEventEmitter(myRNIapModule);
|
|
567
|
-
var emitterSubscription = myModuleEvt.addListener('purchase-updated', listener);
|
|
568
|
-
myRNIapModule.startListening();
|
|
569
|
-
return emitterSubscription;
|
|
570
|
-
}
|
|
562
|
+
var myModuleEvt = new NativeEventEmitter(getNativeModule());
|
|
563
|
+
var emitterSubscription = myModuleEvt.addListener('purchase-updated', listener);
|
|
564
|
+
if (Platform.OS === 'android')
|
|
565
|
+
getAndroidModule().startListening();
|
|
566
|
+
return emitterSubscription;
|
|
571
567
|
};
|
|
572
568
|
/**
|
|
573
|
-
* Add IAP purchase error event
|
|
569
|
+
* Add IAP purchase error event
|
|
574
570
|
* @returns {callback(e: PurchaseError)}
|
|
575
571
|
*/
|
|
576
572
|
export var purchaseErrorListener = function (listener) {
|
|
577
|
-
|
|
578
|
-
var myModuleEvt = new NativeEventEmitter(getIosModule());
|
|
579
|
-
return myModuleEvt.addListener('purchase-error', listener);
|
|
580
|
-
}
|
|
581
|
-
else
|
|
582
|
-
return new NativeEventEmitter(getAndroidModule()).addListener('purchase-error', listener);
|
|
573
|
+
return new NativeEventEmitter(getNativeModule()).addListener('purchase-error', listener);
|
|
583
574
|
};
|
|
584
575
|
/**
|
|
585
576
|
* Get the current receipt base64 encoded in IOS.
|
package/src/index.d.ts
CHANGED
package/src/index.js
CHANGED
package/src/types/index.d.ts
CHANGED
|
@@ -48,12 +48,13 @@ export interface ProductPurchase {
|
|
|
48
48
|
transactionDate: number;
|
|
49
49
|
transactionReceipt: string;
|
|
50
50
|
purchaseToken?: string;
|
|
51
|
+
quantityIOS?: number;
|
|
52
|
+
originalTransactionDateIOS?: string;
|
|
53
|
+
originalTransactionIdentifierIOS?: string;
|
|
51
54
|
dataAndroid?: string;
|
|
52
55
|
signatureAndroid?: string;
|
|
53
56
|
autoRenewingAndroid?: boolean;
|
|
54
57
|
purchaseStateAndroid?: PurchaseStateAndroid;
|
|
55
|
-
originalTransactionDateIOS?: string;
|
|
56
|
-
originalTransactionIdentifierIOS?: string;
|
|
57
58
|
isAcknowledgedAndroid?: boolean;
|
|
58
59
|
packageNameAndroid?: string;
|
|
59
60
|
developerPayloadAndroid?: string;
|
|
@@ -62,6 +63,7 @@ export interface ProductPurchase {
|
|
|
62
63
|
userIdAmazon?: string;
|
|
63
64
|
userMarketplaceAmazon?: string;
|
|
64
65
|
userJsonAmazon?: string;
|
|
66
|
+
isCanceledAmazon?: boolean;
|
|
65
67
|
}
|
|
66
68
|
export interface PurchaseResult {
|
|
67
69
|
responseCode?: number;
|
|
@@ -92,9 +94,9 @@ export interface Discount {
|
|
|
92
94
|
paymentMode: '' | 'FREETRIAL' | 'PAYASYOUGO' | 'PAYUPFRONT';
|
|
93
95
|
subscriptionPeriod: string;
|
|
94
96
|
}
|
|
95
|
-
export interface Product
|
|
97
|
+
export interface Product extends ProductCommon {
|
|
96
98
|
type: 'inapp' | 'iap';
|
|
97
|
-
productId:
|
|
99
|
+
productId: string;
|
|
98
100
|
}
|
|
99
101
|
export interface Subscription extends ProductCommon {
|
|
100
102
|
type: 'subs' | 'sub';
|