react-native-purchases
Version:
React Native in-app purchases and subscriptions made easy. Supports iOS and Android.
819 lines • 107 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
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;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.STOREKIT_VERSION = exports.LOG_LEVEL = exports.REFUND_REQUEST_STATUS = exports.BILLING_FEATURE = exports.PURCHASES_ARE_COMPLETED_BY_TYPE = exports.PURCHASE_TYPE = void 0;
var react_native_1 = require("react-native");
var purchases_typescript_internal_1 = require("@revenuecat/purchases-typescript-internal");
var environment_1 = require("./utils/environment");
var nativeModule_1 = require("./preview/nativeModule");
// This export is kept to keep backwards compatibility to any possible users using this file directly
var purchases_typescript_internal_2 = require("@revenuecat/purchases-typescript-internal");
Object.defineProperty(exports, "PURCHASE_TYPE", { enumerable: true, get: function () { return purchases_typescript_internal_2.PURCHASE_TYPE; } });
Object.defineProperty(exports, "PURCHASES_ARE_COMPLETED_BY_TYPE", { enumerable: true, get: function () { return purchases_typescript_internal_2.PURCHASES_ARE_COMPLETED_BY_TYPE; } });
Object.defineProperty(exports, "BILLING_FEATURE", { enumerable: true, get: function () { return purchases_typescript_internal_2.BILLING_FEATURE; } });
Object.defineProperty(exports, "REFUND_REQUEST_STATUS", { enumerable: true, get: function () { return purchases_typescript_internal_2.REFUND_REQUEST_STATUS; } });
Object.defineProperty(exports, "LOG_LEVEL", { enumerable: true, get: function () { return purchases_typescript_internal_2.LOG_LEVEL; } });
Object.defineProperty(exports, "STOREKIT_VERSION", { enumerable: true, get: function () { return purchases_typescript_internal_2.STOREKIT_VERSION; } });
var react_native_2 = require("react-native");
// Get the native module or use the preview implementation
var usingPreviewAPIMode = (0, environment_1.shouldUsePreviewAPIMode)();
var RNPurchases = usingPreviewAPIMode ? nativeModule_1.previewNativeModuleRNPurchases : react_native_1.NativeModules.RNPurchases;
var eventEmitter = usingPreviewAPIMode ? null : new react_native_1.NativeEventEmitter(RNPurchases);
var customerInfoUpdateListeners = [];
var shouldPurchasePromoProductListeners = [];
var customLogHandler;
eventEmitter === null || eventEmitter === void 0 ? void 0 : eventEmitter.addListener("Purchases-CustomerInfoUpdated", function (customerInfo) {
customerInfoUpdateListeners.forEach(function (listener) { return listener(customerInfo); });
});
eventEmitter === null || eventEmitter === void 0 ? void 0 : eventEmitter.addListener("Purchases-ShouldPurchasePromoProduct", function (_a) {
var callbackID = _a.callbackID;
shouldPurchasePromoProductListeners.forEach(function (listener) {
return listener(function () { return RNPurchases.makeDeferredPurchase(callbackID); });
});
});
eventEmitter === null || eventEmitter === void 0 ? void 0 : eventEmitter.addListener("Purchases-LogHandlerEvent", function (_a) {
var logLevel = _a.logLevel, message = _a.message;
var logLevelEnum = purchases_typescript_internal_1.LOG_LEVEL[logLevel];
customLogHandler(logLevelEnum, message);
});
var Purchases = /** @class */ (function () {
function Purchases() {
}
/**
* Sets up Purchases with your API key and an app user id.
* @param {String} apiKey RevenueCat API Key. Needs to be a String
* @param {String?} appUserID An optional unique id for identifying the user. Needs to be a string.
* @param {PurchasesAreCompletedBy} [purchasesAreCompletedBy=PURCHASES_ARE_COMPLETED_BY_TYPE.REVENUECAT] Set this to an instance of PurchasesAreCompletedByMyApp if you have your own IAP implementation and want to use only RevenueCat's backend. Default is PURCHASES_ARE_COMPLETED_BY_TYPE.REVENUECAT.
* @param {STOREKIT_VERSION} [storeKitVersion=DEFAULT] iOS-only. Defaults to STOREKIT_2. StoreKit 2 is only available on iOS 16+. StoreKit 1 will be used for previous iOS versions regardless of this setting.
* @param {ENTITLEMENT_VERIFICATION_MODE} [entitlementVerificationMode=ENTITLEMENT_VERIFICATION_MODE.DISABLED] Sets the entitlement verifciation mode to use. For more details, check https://rev.cat/trusted-entitlements
* @param {boolean} [useAmazon=false] An optional boolean. Android-only. Set this to true to enable Amazon on compatible devices.
* @param {String?} userDefaultsSuiteName An optional string. iOS-only, will be ignored for Android.
* Set this if you would like the RevenueCat SDK to store its preferences in a different NSUserDefaults suite, otherwise it will use standardUserDefaults.
* Default is null, which will make the SDK use standardUserDefaults.
* @param {boolean} [pendingTransactionsForPrepaidPlansEnabled=false] An optional boolean. Android-only. Set this to true to enable pending transactions for prepaid subscriptions in Google Play.
* @param {boolean} [diagnosticsEnabled=false] An optional boolean. Set this to true to enable SDK diagnostics.
*
* @warning If you use purchasesAreCompletedBy=PurchasesAreCompletedByMyApp, you must also provide a value for storeKitVersion.
*/
Purchases.configure = function (_a) {
var apiKey = _a.apiKey, _b = _a.appUserID, appUserID = _b === void 0 ? null : _b, _c = _a.purchasesAreCompletedBy, purchasesAreCompletedBy = _c === void 0 ? purchases_typescript_internal_1.PURCHASES_ARE_COMPLETED_BY_TYPE.REVENUECAT : _c, userDefaultsSuiteName = _a.userDefaultsSuiteName, _d = _a.storeKitVersion, storeKitVersion = _d === void 0 ? purchases_typescript_internal_1.STOREKIT_VERSION.DEFAULT : _d, _e = _a.useAmazon, useAmazon = _e === void 0 ? false : _e, _f = _a.shouldShowInAppMessagesAutomatically, shouldShowInAppMessagesAutomatically = _f === void 0 ? true : _f, _g = _a.entitlementVerificationMode, entitlementVerificationMode = _g === void 0 ? purchases_typescript_internal_1.ENTITLEMENT_VERIFICATION_MODE.DISABLED : _g, _h = _a.pendingTransactionsForPrepaidPlansEnabled, pendingTransactionsForPrepaidPlansEnabled = _h === void 0 ? false : _h, _j = _a.diagnosticsEnabled, diagnosticsEnabled = _j === void 0 ? false : _j;
if (!customLogHandler) {
this.setLogHandler(function (logLevel, message) {
switch (logLevel) {
case purchases_typescript_internal_1.LOG_LEVEL.DEBUG:
// tslint:disable-next-line:no-console
console.debug("[RevenueCat] ".concat(message));
break;
case purchases_typescript_internal_1.LOG_LEVEL.INFO:
// tslint:disable-next-line:no-console
console.info("[RevenueCat] ".concat(message));
break;
case purchases_typescript_internal_1.LOG_LEVEL.WARN:
// tslint:disable-next-line:no-console
console.warn("[RevenueCat] ".concat(message));
break;
case purchases_typescript_internal_1.LOG_LEVEL.ERROR:
// tslint:disable-next-line:no-console
console.error("[RevenueCat] ".concat(message));
break;
default:
// tslint:disable-next-line:no-console
console.log("[RevenueCat] ".concat(message));
}
});
}
if (apiKey === undefined || typeof apiKey !== "string") {
throw new Error('Invalid API key. It must be called with an Object: configure({apiKey: "key"})');
}
if (appUserID !== null &&
typeof appUserID !== "undefined" &&
typeof appUserID !== "string") {
throw new Error("appUserID needs to be a string");
}
var purchasesCompletedByToUse = purchases_typescript_internal_1.PURCHASES_ARE_COMPLETED_BY_TYPE.REVENUECAT;
var storeKitVersionToUse = storeKitVersion;
if (Purchases.isPurchasesAreCompletedByMyApp(purchasesAreCompletedBy)) {
purchasesCompletedByToUse = purchases_typescript_internal_1.PURCHASES_ARE_COMPLETED_BY_TYPE.MY_APP;
storeKitVersionToUse = purchasesAreCompletedBy.storeKitVersion;
if (storeKitVersion !== purchases_typescript_internal_1.STOREKIT_VERSION.DEFAULT &&
storeKitVersionToUse !== storeKitVersion) {
// Typically, console messages aren't used in TS libraries, but in this case it's worth calling out the difference in
// StoreKit versions, and since the difference isn't possible farther down the call chain, we should go ahead
// and log it here.
// tslint:disable-next-line:no-console
console.warn("Warning: The storeKitVersion in purchasesAreCompletedBy does not match the function's storeKitVersion parameter. We will use the value found in purchasesAreCompletedBy.");
}
if (storeKitVersionToUse === purchases_typescript_internal_1.STOREKIT_VERSION.DEFAULT) {
// tslint:disable-next-line:no-console
console.warn("Warning: You should provide the specific StoreKit version you're using in your implementation when configuring PURCHASES_ARE_COMPLETED_BY_TYPE.MY_APP, and not rely on the DEFAULT.");
}
}
if (usingPreviewAPIMode) {
// tslint:disable-next-line:no-console
console.warn("[RevenueCat] [configure], You successfully installed the RevenueCat SDK. However, it's currently running in Preview API mode because it requires some native modules that are not available in Expo Go. All the APIs are available but have no effect. Please, use a development build to test the real behavior of the RevenueCat SDK.");
}
RNPurchases.setupPurchases(apiKey, appUserID, purchasesCompletedByToUse, userDefaultsSuiteName, storeKitVersionToUse, useAmazon, shouldShowInAppMessagesAutomatically, entitlementVerificationMode, pendingTransactionsForPrepaidPlansEnabled, diagnosticsEnabled);
};
/**
* @deprecated, configure behavior through the RevenueCat dashboard (app.revenuecat.com) instead.
* If an user tries to purchase a product that is active on the current app store account,
* we will treat it as a restore and alias the new ID with the previous id.
* If you have configured the Legacy restore behavior in the RevenueCat dashboard
* and are currently setting this to true, keep this setting active.
* @param {boolean} allowSharing Set this to true if you are passing in an appUserID but it is anonymous,
* this is true by default if you didn't pass an appUserID
* @returns {Promise<void>} The promise will be rejected if configure has not been called yet.
*/
Purchases.setAllowSharingStoreAccount = function (allowSharing) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, Purchases.throwIfNotConfigured()];
case 1:
_a.sent();
Purchases.logWarningIfPreviewAPIMode('setAllowSharingStoreAccount');
RNPurchases.setAllowSharingStoreAccount(allowSharing);
return [2 /*return*/];
}
});
});
};
/**
* iOS only.
* @param {boolean} simulatesAskToBuyInSandbox Set this property to true *only* when testing the ask-to-buy / SCA
* purchases flow. More information: http://errors.rev.cat/ask-to-buy
* @returns {Promise<void>} The promise will be rejected if configure has not been called yet.
*/
Purchases.setSimulatesAskToBuyInSandbox = function (simulatesAskToBuyInSandbox) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
if (react_native_2.Platform.OS === "ios") {
RNPurchases.setSimulatesAskToBuyInSandbox(simulatesAskToBuyInSandbox);
}
return [2 /*return*/];
});
});
};
/**
* Sets a function to be called on updated customer info
* @param {CustomerInfoUpdateListener} customerInfoUpdateListener CustomerInfo update listener
*/
Purchases.addCustomerInfoUpdateListener = function (customerInfoUpdateListener) {
if (typeof customerInfoUpdateListener !== "function") {
throw new Error("addCustomerInfoUpdateListener needs a function");
}
customerInfoUpdateListeners.push(customerInfoUpdateListener);
};
/**
* Removes a given CustomerInfoUpdateListener
* @param {CustomerInfoUpdateListener} listenerToRemove CustomerInfoUpdateListener reference of the listener to remove
* @returns {boolean} True if listener was removed, false otherwise
*/
Purchases.removeCustomerInfoUpdateListener = function (listenerToRemove) {
if (customerInfoUpdateListeners.includes(listenerToRemove)) {
customerInfoUpdateListeners = customerInfoUpdateListeners.filter(function (listener) { return listenerToRemove !== listener; });
return true;
}
return false;
};
/**
* Sets a function to be called on purchases initiated on the Apple App Store. This is only used in iOS.
* @param {ShouldPurchasePromoProductListener} shouldPurchasePromoProductListener Called when a user initiates a
* promotional in-app purchase from the App Store. If your app is able to handle a purchase at the current time, run
* the deferredPurchase function. If the app is not in a state to make a purchase: cache the deferredPurchase, then
* call the deferredPurchase when the app is ready to make the promotional purchase.
* If the purchase should never be made, you don't need to ever call the deferredPurchase and the app will not
* proceed with promotional purchases.
*/
Purchases.addShouldPurchasePromoProductListener = function (shouldPurchasePromoProductListener) {
if (typeof shouldPurchasePromoProductListener !== "function") {
throw new Error("addShouldPurchasePromoProductListener needs a function");
}
shouldPurchasePromoProductListeners.push(shouldPurchasePromoProductListener);
};
/**
* Removes a given ShouldPurchasePromoProductListener
* @param {ShouldPurchasePromoProductListener} listenerToRemove ShouldPurchasePromoProductListener reference of
* the listener to remove
* @returns {boolean} True if listener was removed, false otherwise
*/
Purchases.removeShouldPurchasePromoProductListener = function (listenerToRemove) {
if (shouldPurchasePromoProductListeners.includes(listenerToRemove)) {
shouldPurchasePromoProductListeners =
shouldPurchasePromoProductListeners.filter(function (listener) { return listenerToRemove !== listener; });
return true;
}
return false;
};
/**
* Gets the map of entitlements -> offerings -> products
* @returns {Promise<PurchasesOfferings>} Promise of entitlements structure. The promise will be rejected if configure
* has not been called yet.
*/
Purchases.getOfferings = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, Purchases.throwIfNotConfigured()];
case 1:
_a.sent();
Purchases.logWarningIfPreviewAPIMode('getOfferings');
return [2 /*return*/, RNPurchases.getOfferings()];
}
});
});
};
/**
* Retrieves a current offering for a placement identifier, use this to access offerings defined by targeting
* placements configured in the RevenueCat dashboard.
* @param {String} placementIdentifier The placement identifier to fetch a current offeringn for
* @returns {Promise<PurchasesOffering | null>} Promise of an optional offering. The promise will be rejected if configure
* has not been called yet.
*/
Purchases.getCurrentOfferingForPlacement = function (placementIdentifier) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, Purchases.throwIfNotConfigured()];
case 1:
_a.sent();
Purchases.logWarningIfPreviewAPIMode('getCurrentOfferingForPlacement');
return [2 /*return*/, RNPurchases.getCurrentOfferingForPlacement(placementIdentifier)];
}
});
});
};
/**
* Syncs subscriber attributes and then fetches the configured offerings for this user. This method is intended to
* be called when using Targeting Rules with Custom Attributes. Any subscriber attributes should be set before
* calling this method to ensure the returned offerings are applied with the latest subscriber attributes.
* @returns {Promise<PurchasesOfferings>} Promise of entitlements structure. The promise will be rejected if configure
* has not been called yet.
*/
Purchases.syncAttributesAndOfferingsIfNeeded = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, Purchases.throwIfNotConfigured()];
case 1:
_a.sent();
Purchases.logWarningIfPreviewAPIMode('syncAttributesAndOfferingsIfNeeded');
return [2 /*return*/, RNPurchases.syncAttributesAndOfferingsIfNeeded()];
}
});
});
};
/**
* Fetch the product info
* @param {String[]} productIdentifiers Array of product identifiers
* @param {String} type Optional type of products to fetch, can be SUBSCRIPTION or NON_SUBSCRIPTION. SUBSCRIPTION by default
* @returns {Promise<PurchasesStoreProduct[]>} A promise containing an array of products. The promise will be rejected
* if the products are not properly configured in RevenueCat or if there is another error retrieving them.
* Rejections return an error code, and a userInfo object with more information. The promise will also be rejected
* if configure has not been called yet.
*/
Purchases.getProducts = function (productIdentifiers_1) {
return __awaiter(this, arguments, void 0, function (productIdentifiers, type) {
if (type === void 0) { type = purchases_typescript_internal_1.PRODUCT_CATEGORY.SUBSCRIPTION; }
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, Purchases.throwIfNotConfigured()];
case 1:
_a.sent();
Purchases.logWarningIfPreviewAPIMode('getProducts');
return [2 /*return*/, RNPurchases.getProductInfo(productIdentifiers, type)];
}
});
});
};
/**
* Make a purchase
*
* @param {String} productIdentifier The product identifier of the product you want to purchase
* @param {UpgradeInfo} upgradeInfo Android only. Optional UpgradeInfo you wish to upgrade from containing the oldSKU
* and the optional prorationMode.
* @param {String} type Optional type of product, can be inapp or subs. Subs by default
* @deprecated, use purchaseStoreProduct instead
*/
Purchases.purchaseProduct = function (productIdentifier_1, upgradeInfo_1) {
return __awaiter(this, arguments, void 0, function (productIdentifier, upgradeInfo, type) {
if (type === void 0) { type = purchases_typescript_internal_1.PURCHASE_TYPE.SUBS; }
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, Purchases.throwIfNotConfigured()];
case 1:
_a.sent();
Purchases.logWarningIfPreviewAPIMode('purchaseProduct');
return [2 /*return*/, RNPurchases.purchaseProduct(productIdentifier, upgradeInfo, type, null, null, null).catch(function (error) {
error.userCancelled =
error.code === purchases_typescript_internal_1.PURCHASES_ERROR_CODE.PURCHASE_CANCELLED_ERROR;
throw error;
})];
}
});
});
};
/**
* Make a purchase
*
* @param {PurchasesStoreProduct} product The product you want to purchase
* @param {GoogleProductChangeInfo} googleProductChangeInfo Android only. Optional GoogleProductChangeInfo you
* wish to upgrade from containing the oldProductIdentifier and the optional prorationMode.
* @param {boolean} googleIsPersonalizedPrice Android and Google only. Optional boolean indicates personalized pricing on products available for purchase in the EU.
* For compliance with EU regulations. User will see "This price has been customize for you" in the purchase dialog when true.
* See https://developer.android.com/google/play/billing/integrate#personalized-price for more info.
* @returns {Promise<{ productIdentifier: string, customerInfo:CustomerInfo }>} A promise of an object containing
* a customer info object and a product identifier. Rejections return an error code,
* a boolean indicating if the user cancelled the purchase, and an object with more information. The promise will
* also be rejected if configure has not been called yet.
*/
Purchases.purchaseStoreProduct = function (product, googleProductChangeInfo, googleIsPersonalizedPrice) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, Purchases.throwIfNotConfigured()];
case 1:
_a.sent();
Purchases.logWarningIfPreviewAPIMode('purchaseStoreProduct');
return [2 /*return*/, RNPurchases.purchaseProduct(product.identifier, googleProductChangeInfo, product.productCategory, null, googleIsPersonalizedPrice == null
? null
: { isPersonalizedPrice: googleIsPersonalizedPrice }, product.presentedOfferingContext).catch(function (error) {
error.userCancelled =
error.code === purchases_typescript_internal_1.PURCHASES_ERROR_CODE.PURCHASE_CANCELLED_ERROR;
throw error;
})];
}
});
});
};
/**
* iOS only. Purchase a product applying a given discount.
*
* @param {PurchasesStoreProduct} product The product you want to purchase
* @param {PurchasesPromotionalOffer} discount Discount to apply to this package. Retrieve this discount using getPromotionalOffer.
* @param {boolean} googleIsPersonalizedPrice Android and Google only. Optional boolean indicates personalized pricing on products available for purchase in the EU.
* For compliance with EU regulations. User will see "This price has been customize for you" in the purchase dialog when true.
* See https://developer.android.com/google/play/billing/integrate#personalized-price for more info.
* @returns {Promise<{ productIdentifier: string, customerInfo:CustomerInfo }>} A promise of an object containing
* a customer info object and a product identifier. Rejections return an error code,
* a boolean indicating if the user cancelled the purchase, and an object with more information. The promise will be
* rejected if configure has not been called yet.
*/
Purchases.purchaseDiscountedProduct = function (product, discount) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, Purchases.throwIfNotConfigured()];
case 1:
_a.sent();
Purchases.logWarningIfPreviewAPIMode('purchaseDiscountedProduct');
if (typeof discount === "undefined" || discount == null) {
throw new Error("A discount is required");
}
return [2 /*return*/, RNPurchases.purchaseProduct(product.identifier, null, null, discount.timestamp.toString(), null, product.presentedOfferingContext).catch(function (error) {
error.userCancelled =
error.code === purchases_typescript_internal_1.PURCHASES_ERROR_CODE.PURCHASE_CANCELLED_ERROR;
throw error;
})];
}
});
});
};
/**
* Make a purchase
*
* @param {PurchasesPackage} aPackage The Package you wish to purchase. You can get the Packages by calling getOfferings
* @param {UpgradeInfo} upgradeInfo DEPRECATED. Use googleProductChangeInfo.
* @param {GoogleProductChangeInfo} googleProductChangeInfo Android only. Optional GoogleProductChangeInfo you
* wish to upgrade from containing the oldProductIdentifier and the optional prorationMode.
* @param {boolean} googleIsPersonalizedPrice Android and Google only. Optional boolean indicates personalized pricing on products available for purchase in the EU.
* For compliance with EU regulations. User will see "This price has been customize for you" in the purchase dialog when true.
* See https://developer.android.com/google/play/billing/integrate#personalized-price for more info.
* @returns {Promise<{ productIdentifier: string, customerInfo: CustomerInfo }>} A promise of an object containing
* a customer info object and a product identifier. Rejections return an error code, a boolean indicating if the
* user cancelled the purchase, and an object with more information. The promise will be also be rejected if configure
* has not been called yet.
*/
Purchases.purchasePackage = function (aPackage, upgradeInfo, googleProductChangeInfo, googleIsPersonalizedPrice) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, Purchases.throwIfNotConfigured()];
case 1:
_a.sent();
Purchases.logWarningIfPreviewAPIMode('purchasePackage');
return [2 /*return*/, RNPurchases.purchasePackage(aPackage.identifier, aPackage.presentedOfferingContext, googleProductChangeInfo || upgradeInfo, null, googleIsPersonalizedPrice == null
? null
: { isPersonalizedPrice: googleIsPersonalizedPrice }).catch(function (error) {
error.userCancelled =
error.code === purchases_typescript_internal_1.PURCHASES_ERROR_CODE.PURCHASE_CANCELLED_ERROR;
throw error;
})];
}
});
});
};
/**
* Google only. Make a purchase of a subscriptionOption
*
* @param {SubscriptionOption} subscriptionOption The SubscriptionOption you wish to purchase. You can get the SubscriptionOption from StoreProducts by calling getOfferings
* @param {GoogleProductChangeInfo} googleProductChangeInfo Android only. Optional GoogleProductChangeInfo you
* wish to upgrade from containing the oldProductIdentifier and the optional prorationMode.
* @param {boolean} googleIsPersonalizedPrice Android and Google only. Optional boolean indicates personalized pricing on products available for purchase in the EU.
* For compliance with EU regulations. User will see "This price has been customize for you" in the purchase dialog when true.
* See https://developer.android.com/google/play/billing/integrate#personalized-price for more info.
* @returns {Promise<{ productIdentifier: string, customerInfo: CustomerInfo }>} A promise of an object containing
* a customer info object and a product identifier. Rejections return an error code, a boolean indicating if the
* user cancelled the purchase, and an object with more information. The promise will be also be rejected if configure
* has not been called yet.
*/
Purchases.purchaseSubscriptionOption = function (subscriptionOption, googleProductChangeInfo, googleIsPersonalizedPrice) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, Purchases.throwIfNotConfigured()];
case 1:
_a.sent();
Purchases.logWarningIfPreviewAPIMode('purchaseSubscriptionOption');
return [4 /*yield*/, Purchases.throwIfIOSPlatform()];
case 2:
_a.sent();
return [2 /*return*/, RNPurchases.purchaseSubscriptionOption(subscriptionOption.productId, subscriptionOption.id, googleProductChangeInfo, null, googleIsPersonalizedPrice == null
? null
: { isPersonalizedPrice: googleIsPersonalizedPrice }, subscriptionOption.presentedOfferingContext).catch(function (error) {
error.userCancelled =
error.code === purchases_typescript_internal_1.PURCHASES_ERROR_CODE.PURCHASE_CANCELLED_ERROR;
throw error;
})];
}
});
});
};
/**
* iOS only. Purchase a package applying a given discount.
*
* @param {PurchasesPackage} aPackage The Package you wish to purchase. You can get the Packages by calling getOfferings
* @param {PurchasesPromotionalOffer} discount Discount to apply to this package. Retrieve this discount using getPromotionalOffer.
* @returns {Promise<{ productIdentifier: string, customerInfo: CustomerInfo }>} A promise of an object containing
* a customer info object and a product identifier. Rejections return an error code, a boolean indicating if the
* user cancelled the purchase, and an object with more information. The promise will be also be rejected if configure
* has not been called yet.
*/
Purchases.purchaseDiscountedPackage = function (aPackage, discount) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, Purchases.throwIfNotConfigured()];
case 1:
_a.sent();
Purchases.logWarningIfPreviewAPIMode('purchaseDiscountedPackage');
if (typeof discount === "undefined" || discount == null) {
throw new Error("A discount is required");
}
return [2 /*return*/, RNPurchases.purchasePackage(aPackage.identifier, aPackage.presentedOfferingContext, null, discount.timestamp.toString(), null).catch(function (error) {
error.userCancelled =
error.code === purchases_typescript_internal_1.PURCHASES_ERROR_CODE.PURCHASE_CANCELLED_ERROR;
throw error;
})];
}
});
});
};
/**
* Restores a user's previous purchases and links their appUserIDs to any user's also using those purchases.
* @returns {Promise<CustomerInfo>} A promise of a customer info object. Rejections return an error code, and an
* userInfo object with more information. The promise will be also be rejected if configure has not been called yet.
*/
Purchases.restorePurchases = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, Purchases.throwIfNotConfigured()];
case 1:
_a.sent();
Purchases.logWarningIfPreviewAPIMode('restorePurchases');
return [2 /*return*/, RNPurchases.restorePurchases()];
}
});
});
};
/**
* Get the appUserID
* @returns {Promise<string>} The app user id in a promise
*/
Purchases.getAppUserID = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, Purchases.throwIfNotConfigured()];
case 1:
_a.sent();
Purchases.logWarningIfPreviewAPIMode('getAppUserID');
return [2 /*return*/, RNPurchases.getAppUserID()];
}
});
});
};
/**
* Gets the storefront for the current store account.
* @returns {Promise<Storefront | null>} The storefront for the current store account, or null if the storefront is not available.
*/
Purchases.getStorefront = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, Purchases.throwIfNotConfigured()];
case 1:
_a.sent();
Purchases.logWarningIfPreviewAPIMode('getStorefront');
return [2 /*return*/, RNPurchases.getStorefront()];
}
});
});
};
/**
* This function will logIn the current user with an appUserID. Typically this would be used after a log in
* to identify a user without calling configure.
* @param {String} appUserID The appUserID that should be linked to the currently user
* @returns {Promise<LogInResult>} A promise of an object that contains the customerInfo after logging in, as well
* as a boolean indicating whether the user has just been created for the first time in the RevenueCat backend. The
* promise will be rejected if configure has not been called yet or if there's an issue logging in.
*/
Purchases.logIn = function (appUserID) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, Purchases.throwIfNotConfigured()];
case 1:
_a.sent();
Purchases.logWarningIfPreviewAPIMode('logIn');
// noinspection SuspiciousTypeOfGuard
if (typeof appUserID !== "string") {
throw new Error("appUserID needs to be a string");
}
return [2 /*return*/, RNPurchases.logIn(appUserID)];
}
});
});
};
/**
* Logs out the Purchases client clearing the saved appUserID. This will generate a random user id and save it in the cache.
* @returns {Promise<CustomerInfo>} A promise of a customer info object. Rejections return an error code,
* and a userInfo object with more information. The promise will be rejected if configure has not been called yet or if
* there's an issue logging out.
*/
Purchases.logOut = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, Purchases.throwIfNotConfigured()];
case 1:
_a.sent();
Purchases.logWarningIfPreviewAPIMode('logOut');
return [2 /*return*/, RNPurchases.logOut()];
}
});
});
};
/**
* Enables/Disables debugs logs
* @param {boolean} enabled Enable or not debug logs
* @deprecated, use setLogLevel instead
*/
Purchases.setDebugLogsEnabled = function (enabled) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
RNPurchases.setDebugLogsEnabled(enabled);
return [2 /*return*/];
});
});
};
/**
* Used to set the log level. Useful for debugging issues with the lovely team @RevenueCat.
* The default is {LOG_LEVEL.INFO} in release builds and {LOG_LEVEL.DEBUG} in debug builds.
* @param {LOG_LEVEL} level
*/
Purchases.setLogLevel = function (level) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
RNPurchases.setLogLevel(level);
return [2 /*return*/];
});
});
};
/**
* Set a custom log handler for redirecting logs to your own logging system.
* By default, this sends info, warning, and error messages.
* If you wish to receive Debug level messages, see [setLogLevel].
* @param {LogHandler} logHandler It will get called for each log event.
* Use this function to redirect the log to your own logging system
*/
Purchases.setLogHandler = function (logHandler) {
customLogHandler = logHandler;
RNPurchases.setLogHandler();
};
/**
* Gets current customer info
* @returns {Promise<CustomerInfo>} A promise of a customer info object. Rejections return an error code, and an
* userInfo object with more information. The promise will be rejected if configure has not been called yet or if
* there's an issue getting the customer information.
*/
Purchases.getCustomerInfo = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, Purchases.throwIfNotConfigured()];
case 1:
_a.sent();
Purchases.logWarningIfPreviewAPIMode('getCustomerInfo');
return [2 /*return*/, RNPurchases.getCustomerInfo()];
}
});
});
};
/**
* This method will send all the purchases to the RevenueCat backend. Call this when using your own implementation
* for subscriptions anytime a sync is needed, like after a successful purchase.
*
* @warning This function should only be called if you're not calling purchaseProduct/purchaseStoreProduct/purchasePackage/purchaseSubscriptionOption.
* @returns {Promise<void>} The promise will be rejected if configure has not been called yet or if there's an error
* syncing purchases.
*/
Purchases.syncPurchases = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, Purchases.throwIfNotConfigured()];
case 1:
_a.sent();
Purchases.logWarningIfPreviewAPIMode('syncPurchases');
RNPurchases.syncPurchases();
return [2 /*return*/];
}
});
});
};
/**
* This method will send a purchase to the RevenueCat backend. This function should only be called if you are
* in Amazon observer mode or performing a client side migration of your current users to RevenueCat.
*
* The receipt IDs are cached if successfully posted so they are not posted more than once.
*
* @param {string} productID Product ID associated to the purchase.
* @param {string} receiptID ReceiptId that represents the Amazon purchase.
* @param {string} amazonUserID Amazon's userID. This parameter will be ignored when syncing a Google purchase.
* @param {(string|null|undefined)} isoCurrencyCode Product's currency code in ISO 4217 format.
* @param {(number|null|undefined)} price Product's price.
* @returns {Promise<void>} The promise will be rejected if configure has not been called yet or if there's an error
* syncing purchases.
*/
Purchases.syncAmazonPurchase = function (productID, receiptID, amazonUserID, isoCurrencyCode, price) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, Purchases.throwIfIOSPlatform()];
case 1:
_a.sent();
return [4 /*yield*/, Purchases.throwIfNotConfigured()];
case 2:
_a.sent();
Purchases.logWarningIfPreviewAPIMode('syncAmazonPurchase');
RNPurchases.syncAmazonPurchase(productID, receiptID, amazonUserID, isoCurrencyCode, price);
return [2 /*return*/];
}
});
});
};
/**
* @deprecated, use syncAmazonPurchase instead.
*
* This method will send a purchase to the RevenueCat backend. This function should only be called if you are
* in Amazon observer mode or performing a client side migration of your current users to RevenueCat.
*
* The receipt IDs are cached if successfully posted so they are not posted more than once.
*
* @param {string} productID Product ID associated to the purchase.
* @param {string} receiptID ReceiptId that represents the Amazon purchase.
* @param {string} amazonUserID Amazon's userID. This parameter will be ignored when syncing a Google purchase.
* @param {(string|null|undefined)} isoCurrencyCode Product's currency code in ISO 4217 format.
* @param {(number|null|undefined)} price Product's price.
* @returns {Promise<void>} The promise will be rejected if configure has not been called yet or if there's an error
* syncing purchases.
*/
Purchases.syncObserverModeAmazonPurchase = function (productID, receiptID, amazonUserID, isoCurrencyCode, price) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, Purchases.throwIfIOSPlatform()];
case 1:
_a.sent();
return [4 /*yield*/, Purchases.throwIfNotConfigured()];
case 2:
_a.sent();
Purchases.logWarningIfPreviewAPIMode('syncObserverModeAmazonPurchase');
RNPurchases.syncObserverModeAmazonPurchase(productID, receiptID, amazonUserID, isoCurrencyCode, price);
return [2 /*return*/];
}
});
});
};
/**
* iOS only. Always returns an error on iOS < 15.
*
* Use this method only if you already have your own IAP implementation using StoreKit 2 and want to use
* RevenueCat's backend. If you are using StoreKit 1 for your implementation, you do not need this method.
*
* You only need to use this method with *new* purchases. Subscription updates are observed automatically.
*
* Important: This should only be used if you have set PurchasesAreCompletedBy to MY_APP during SDK configuration.
*
* @warning You need to finish the transaction yourself after calling this method.
*
* @param {string} productID Product ID that was just purchased
* @returns {Promise<PurchasesStoreTransaction>} If there was a transacton found and handled for the provided product ID.
*/
Purchases.recordPurchase = function (productID) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, Purchases.throwIfAndroidPlatform()];
case 1:
_a.sent();
return [4 /*yield*/, Purchases.throwIfNotConfigured()];
case 2:
_a.sent();
Purchases.logWarningIfPreviewAPIMode('recordPurchase');
return [2 /*return*/, RNPurchases.recordPurchaseForProductID(productID)];
}
});
});
};
/**
* Enable automatic collection of Apple Search Ad attribution on iOS. Disabled by default
* @returns {Promise<void>} The promise will be rejected if configure has not been called yet.
*/
Purchases.enableAdServicesAttributionTokenCollection = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!(react_native_2.Platform.OS === "ios")) return [3 /*break*/, 2];
return [4 /*yield*/, Purchases.throwIfNotConfigured()];
case 1:
_a.sent();
Purchases.logWarningIfPreviewAPIMode('enableAdServicesAttributionTokenCollection');
RNPurchases.enableAdServicesAttributionTokenCollection();
_a.label = 2;
case 2: return [2 /*return*/];
}
});
});
};
/**
* @returns { Promise<boolean> } If the `appUserID` has been generated by RevenueCat or not.
* @returns {Promise<void>} The promise will be rejected if configure has not been called yet.
*/
Purchases.isAnonymous = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, Purchases.throwIfNotConfigured()];
case 1:
_a.sent();
Purchases.logWarningIfPreviewAPIMode('isAnonymous');
return [2 /*return*/, RNPurchases.isAnonymous