UNPKG

@kirz/react-native-toolkit

Version:

Toolkit to speed up React Native development

163 lines (160 loc) 6.95 kB
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } import { Platform } from 'react-native'; import * as IAP from 'react-native-iap'; import { PurchaseStateAndroid } from 'react-native-iap'; import { transformProduct } from './utils/transformProduct'; import { transformPurchase } from './utils/transformPurchase'; import { transformSubscription } from './utils/transformSubscription'; import { ControlledPromise } from '../../utils/promise/control'; import { Plugin } from '../Plugin'; import { Subscription } from '../types'; export class InAppPurchasePlugin extends Plugin { // @ts-ignore // @ts-ignore // @ts-ignore constructor(options) { super(); this.options = options; _defineProperty(this, "name", 'InAppPurchasePlugin'); _defineProperty(this, "features", ['InAppPurchase']); _defineProperty(this, "initializationTimeout", 15000); _defineProperty(this, "products", void 0); _defineProperty(this, "subscriptions", void 0); _defineProperty(this, "receiptValidator", void 0); _defineProperty(this, "purchasePromise", null); } async initialize(bundle) { const iapReceiptValidator = bundle.getByFeature('IAPReceiptValidator'); if (!iapReceiptValidator) { throw new Error('No receipt validator found'); } await IAP.initConnection(); if (Platform.OS === 'android') { try { await IAP.flushFailedPurchasesCachedAsPendingAndroid(); } catch { // skip error } } if (Platform.OS === 'ios') { try { await IAP.clearTransactionIOS(); } catch { // skip error } } this.receiptValidator = iapReceiptValidator; await this.refetchProducts(); IAP.purchaseUpdatedListener(async purchase => { const productDef = this.options.products.find(x => x.productId === purchase.productId); try { var _this$purchasePromise; if (!productDef) { console.error('Unknown product: ' + purchase.productId); return; } const timestamp = new Date().valueOf(); const purchaseDate = purchase.transactionDate; if (Math.abs(purchaseDate - timestamp) > 1000 * 60 * 30) { return; } if (Platform.OS === 'android' && [PurchaseStateAndroid.PENDING, PurchaseStateAndroid.UNSPECIFIED_STATE].includes(purchase.purchaseStateAndroid)) { console.warn(`Skip purchase with status ${purchase.purchaseStateAndroid}`); return; } await IAP.finishTransaction({ purchase, isConsumable: productDef.type === 'consumable' }).catch(() => { // no-op }); await this.receiptValidator.handlePurchase(); (_this$purchasePromise = this.purchasePromise) === null || _this$purchasePromise === void 0 ? void 0 : _this$purchasePromise.resolve(purchase); } catch (err) { var _this$purchasePromise2; (_this$purchasePromise2 = this.purchasePromise) === null || _this$purchasePromise2 === void 0 ? void 0 : _this$purchasePromise2.reject({ isCancelled: false, message: err.message }); } }); IAP.purchaseErrorListener(async errorEvent => { var _this$purchasePromise3; (_this$purchasePromise3 = this.purchasePromise) === null || _this$purchasePromise3 === void 0 ? void 0 : _this$purchasePromise3.reject({ isCancelled: errorEvent.code === 'E_USER_CANCELLED', message: errorEvent.message }); }); } async refetchProducts() { const productSkus = this.options.products.filter(x => x.type !== 'subscription').map(x => x.productId); const subscriptionSkus = this.options.products.filter(x => x.type === 'subscription').map(x => x.productId); const [fetchedProducts, fetchedSubscriptions] = await Promise.all([productSkus.length ? IAP.getProducts({ skus: productSkus }) : Promise.resolve([]), subscriptionSkus.length ? IAP.getSubscriptions({ skus: subscriptionSkus }) : Promise.resolve([])]); const products = fetchedProducts.map(x => transformProduct(x, this.options.products.find(y => y.productId === x.productId).type === 'consumable')); const subscriptions = await Promise.all(fetchedSubscriptions.map(async x => { const { trial, ...subscription } = transformSubscription(x); const isTrialAvailable = !!trial && (Platform.OS === 'android' || (await this.receiptValidator.isTrialAvailable(subscription.productId))); return new Subscription({ ...subscription, ...(isTrialAvailable && { trial }) }); })); this.products = products.sort((a, b) => a.price - b.price); this.subscriptions = subscriptions.sort((a, b) => a.price - b.price); } async purchaseProduct(productId) { const productDef = this.options.products.find(x => x.productId === productId); if (!productDef) { throw new Error(`Unknown product "${productId}"`); } if (productDef.type === 'subscription') { // Handle android purchase request if (Platform.OS === 'android') { var _subscriptionOfferDet; const subscription = this.subscriptions.find(x => x.productId === productId); const offerToken = (_subscriptionOfferDet = subscription.originalData.subscriptionOfferDetails[0]) === null || _subscriptionOfferDet === void 0 ? void 0 : _subscriptionOfferDet.offerToken; const subscriptionRequest = { subscriptionOffers: [{ sku: productId, offerToken }] }; IAP.requestSubscription({ sku: productId, subscriptionOffers: subscriptionRequest.subscriptionOffers }).catch(() => { // no-op }); } else { IAP.requestSubscription({ sku: productId }).catch(() => { // no-op }); } } else { IAP.requestPurchase(Platform.OS === 'ios' ? { sku: productId } : { skus: [productId] }).catch(() => { // no-op }); } this.purchasePromise = new ControlledPromise(); const purchase = await this.purchasePromise.wait(); return transformPurchase(purchase); } } //# sourceMappingURL=InAppPurchasePlugin.js.map