document.addEventListener('deviceready', onDeviceReady);
function onDeviceReady() {
const store = CdvPurchase.store;
const { ProductType, Platform, LogLevel, Product, VerifiedReceipt } = CdvPurchase; // shortcuts
// We should first register all our products or we cannot use them in the app.
store.register([{
id: 'demo_monthly_basic',
type: ProductType.PAID_SUBSCRIPTION,
platform: Platform.GOOGLE_PLAY,
}, {
id: 'demo_weekly_basic',
type: ProductType.PAID_SUBSCRIPTION,
platform: Platform.GOOGLE_PLAY,
}]);
store.verbosity = LogLevel.DEBUG;
store.applicationUsername = () => "my_username_2"; // the plugin will hash this with md5 when needed
// For subscriptions and secured transactions, we setup a receipt validator.
store.validator = "https://staging.com/v1/validate?appName=XXX&apiKey=YYY";
store.validator_privacy_policy = ['analytics', 'support', 'tracking', 'fraud'];
// Show errors on the dedicated Div.
store.error(errorHandler);
// Define events handler for our subscription products
store.when()
.updated(object => {
// Re-render the interface on updates
log.info('Updated: ' + JSON.stringify(object));
renderUI();
})
.approved(transaction => {
// verify approved transactions
store.verify(transaction);
})
.verified(receipt => {
// finish transactions from verified receipts
store.finish(receipt);
renderUI();
});
// Load informations about products and purchases
store.initialize([
Platform.APPLE_APPSTORE,
Platform.GOOGLE_PLAY,
{
platform: Platform.BRAINTREE,
options: {
tokenizationKey: 'sandbox_xyz',
nonceProvider: (type, callback) => {
callback({ // only 3D secure supported.
type: CdvPurchase.Braintree.PaymentMethod.THREE_D_SECURE,
value: 'fake-valid-nonce',
});
}
}
}
]);
// Updates the user interface to reflect the initial state
renderUI();
}
// Perform a full render of the user interface
function renderUI() {
const store = CdvPurchase.store;
// When either of our susbscription products is owned, display "Subscribed".
// If one of them is being purchased or validated, display "Processing".
// In all other cases, display "Not Subscribed".
const subscriptions = store.products.filter(p => p.type === CdvPurchase.ProductType.PAID_SUBSCRIPTION);
const statusElement = document.getElementById('status');
const productsElement = document.getElementById('products');
if (!statusElement || !productsElement) return;
if (isOwned(subscriptions))
statusElement.textContent = 'Subscribed';
else if (isApproved(subscriptions) || isInitiated(subscriptions))
statusElement.textContent = 'Processing...';
else
statusElement.textContent = 'Not Subscribed';
const validProducts = store.products.filter(product => product.offers.length > 0);
productsElement.innerHTML =
validProducts
.map(product => `
...
`)
.join('');
// Render the products' DOM elements
validProducts.forEach(renderProductUI);
// Find a verified purchase for one of the provided products that passes the given filter.
function findVerifiedPurchase(products: CdvPurchase.Product[], filter: (purchase: CdvPurchase.VerifiedPurchase) => boolean): CdvPurchase.VerifiedPurchase | undefined {
for (const product of products) {
const purchase = store.findInVerifiedReceipts(product);
if (!purchase) continue;
if (filter(purchase)) return purchase;
}
}
// Find a local transaction for one of the provided products that passes the given filter.
function findLocalTransaction(products: CdvPurchase.Product[], filter: (transaction: CdvPurchase.Transaction) => boolean): CdvPurchase.Transaction | undefined {
// find if some of those products are part of a receipt
for (const product of products) {
const transaction = store.findInLocalReceipts(product);
if (!transaction) continue;
if (filter(transaction)) return transaction;
}
}
function isOwned(products: CdvPurchase.Product[]): boolean {
return !!findVerifiedPurchase(products, p => !p.isExpired);
}
function isApproved(products: CdvPurchase.Product[]) {
return !!findLocalTransaction(products, t => t.state === CdvPurchase.TransactionState.APPROVED);
}
function isInitiated(products: CdvPurchase.Product[]) {
return !!findLocalTransaction(products, t => t.state === CdvPurchase.TransactionState.INITIATED);
}
/**
* Refresh the displayed details about a product in the DOM
*/
function renderProductUI(product: CdvPurchase.Product) {
const productId = product.id;
const el = document.getElementById(`${productId}-purchase`);
if (!el) {
log.error(`HTML element ${productId}-purchase does not exists`);
return;
}
function strikeIf(when: boolean) { return when ? '' : ''; }
function strikeEnd(when: boolean) { return when ? '' : ''; }
// Create and update the HTML content
const id = `id: ${product.id} `;
const info =
(`title: ${product.title || ''} `) +
(product.description ? `desc: ${product.description || ''} ` : '');
const offers = product.offers ? 'offers: