cordova-plugin-purchase
Advanced tools
Comparing version 13.8.0 to 13.8.2
{ | ||
"name": "cordova-plugin-purchase", | ||
"version": "13.8.0", | ||
"version": "13.8.2", | ||
"description": "Cordova Purchase plugin for iOS, Android, Windows (AppStore, Play, UWP)", | ||
@@ -34,2 +34,3 @@ "cordova": { | ||
"scripts": { | ||
"test": "cd tests && jest", | ||
"typedoc": "typedoc --hideGenerator --excludePrivate --excludeProtected --excludeInternal --disableSources --readme src/ts/README.md --hideBreadcrumbs true --hideInPageTOC false --out api --pretty --plugin typedoc-plugin-markdown --theme markdown --basePath src/ts src/ts/store.ts", | ||
@@ -45,20 +46,24 @@ "typedoc-dev": "typedoc --hideGenerator --readme src/ts/README.md --out api-dev --pretty --plugin typedoc-plugin-markdown --theme markdown --basePath src/ts src/ts/store.ts" | ||
"devDependencies": { | ||
"acorn": "^6.3.0", | ||
"babel-eslint": "^10.0.3", | ||
"eslint": "^5.16.0", | ||
"eslint-config-defaults": "^9.0.0", | ||
"eslint-plugin-import": "^2.18.2", | ||
"eslint-plugin-react": "^7.14.3", | ||
"istanbul": "^0.4.5", | ||
"jshint": "^2.10.2", | ||
"mocha": "^6.2.0", | ||
"preprocessor": "^1.4.0", | ||
"@types/jest": "^29.5.4", | ||
"jest": "^29.7.0", | ||
"jest-environment-jsdom": "^29.7.0", | ||
"ts-jest": "^29.1.1", | ||
"typedoc": "^0.23.15", | ||
"typedoc-github-wiki-theme": "^1.0.1", | ||
"typedoc-plugin-markdown": "^3.13.6", | ||
"typescript": "^4.7.4", | ||
"uglify-js": "^3.6.0" | ||
"typescript": "^4.7.4" | ||
}, | ||
"main": "./www/store.js", | ||
"types": "./www/store.d.ts" | ||
"types": "./www/store.d.ts", | ||
"files": [ | ||
"/README.md", | ||
"/RELEASE_NOTES.md", | ||
"/src/android", | ||
"/src/ios", | ||
"/src/ts", | ||
"/src/windows", | ||
"/tests", | ||
"/tsconfig.ts", | ||
"/www" | ||
] | ||
} |
# Release Notes - Cordova Plugin Purchase | ||
## 13.8.0 | ||
## 13.8 | ||
### 13.8.2 | ||
#### store.applicationUsername can return `undefined` | ||
If no user is logged in, you `applicationUsername` function can return | ||
undefined. | ||
#### Add "productId" and "platform" to Error objects | ||
All errors now include the "platform" and "productId" field (when applicable), | ||
to get more context. | ||
### 13.8.1 | ||
#### Fix AppStore eligibility determination of intro period | ||
In the case where the StoreKit SDK doesn't return a "discounts" array, | ||
determining the eligility of the intro period using iaptic was not functional. | ||
### 13.8.0 | ||
#### Upgrade to Google Play Billing library 5.2.1 | ||
@@ -6,0 +27,0 @@ |
@@ -86,5 +86,5 @@ namespace CdvPurchase { | ||
*/ | ||
export function storeError(code: ErrorCode, message: string): IError { | ||
return { isError: true, code, message }; | ||
export function storeError(code: ErrorCode, message: string, platform: Platform | null, productId: string | null): IError { | ||
return { isError: true, code, message, platform, productId }; | ||
} | ||
} |
@@ -71,3 +71,3 @@ namespace CdvPurchase { | ||
this.log.info('clientTokenProvider error: ' + JSON.stringify(err)); | ||
callback(storeError(err as ErrorCode, 'ERROR ' + err)); | ||
callback(storeError(err as ErrorCode, 'ERROR ' + err, Platform.BRAINTREE, null)); | ||
}, | ||
@@ -98,3 +98,3 @@ }) | ||
return (_appStoreReceipt: AppleAppStore.ApplicationReceipt, requests: AppleAppStore.DiscountEligibilityRequest[], callback: (response: boolean[]) => void) => { | ||
const determiner = (_appStoreReceipt: AppleAppStore.ApplicationReceipt, requests: AppleAppStore.DiscountEligibilityRequest[], callback: (response: boolean[]) => void) => { | ||
this.log.debug("AppStore eligibility determiner"); | ||
@@ -116,2 +116,8 @@ if (latestReceipt) { | ||
determiner.cacheReceipt = function(receipt: VerifiedReceipt) { | ||
latestReceipt = receipt; | ||
} | ||
return determiner; | ||
function analyzeReceipt(receipt: VerifiedReceipt, requests: AppleAppStore.DiscountEligibilityRequest[]) { | ||
@@ -118,0 +124,0 @@ const ineligibleIntro = receipt.raw.ineligible_for_intro_price; |
@@ -54,3 +54,3 @@ namespace CdvPurchase { | ||
'Invalid parameter to "register", expected "id", "type" and "platform". ' | ||
+ 'Got: ' + JSON.stringify(p))); | ||
+ 'Got: ' + JSON.stringify(p), null, null)); | ||
} | ||
@@ -57,0 +57,0 @@ return errors; |
@@ -58,4 +58,4 @@ namespace CdvPurchase { | ||
*/ | ||
static failed(code: ErrorCode, message: string) { | ||
return new PaymentRequestPromise().trigger(storeError(code, message)); | ||
static failed(code: ErrorCode, message: string, platform: Platform | null, productId: string | null) { | ||
return new PaymentRequestPromise().trigger(storeError(code, message, platform, productId)); | ||
} | ||
@@ -62,0 +62,0 @@ |
@@ -31,3 +31,5 @@ /// <reference path="../../types.ts" /> | ||
*/ | ||
export type DiscountEligibilityDeterminer = (applicationReceipt: ApplicationReceipt, requests: DiscountEligibilityRequest[], callback: (response: boolean[]) => void) => void; | ||
export type DiscountEligibilityDeterminer = ((applicationReceipt: ApplicationReceipt, requests: DiscountEligibilityRequest[], callback: (response: boolean[]) => void) => void) & { | ||
cacheReceipt?: (receipt: VerifiedReceipt) => void; | ||
}; | ||
@@ -256,3 +258,3 @@ /** | ||
else { | ||
this.context.error(storeError(code, message)); | ||
this.context.error(appStoreError(code, message,options?.productId || null)); | ||
} | ||
@@ -338,3 +340,3 @@ }, | ||
this.log.info('bridge.init failed: ' + code + ' - ' + message); | ||
resolve(storeError(code, message)); | ||
resolve(appStoreError(code, message, null)); | ||
}); | ||
@@ -404,3 +406,3 @@ }); | ||
this._appStoreReceiptLoading = false; | ||
callCallbacks(storeError(ErrorCode.REFRESH, 'No appStoreReceipt')); | ||
callCallbacks(appStoreError(ErrorCode.REFRESH, 'No appStoreReceipt', null)); | ||
return; | ||
@@ -457,3 +459,5 @@ } | ||
private async loadEligibility(validProducts: Bridge.ValidProduct[]): Promise<Internal.DiscountEligibilities> { | ||
this.log.debug('load eligibility: ' + JSON.stringify(validProducts)); | ||
if (!this.discountEligibilityDeterminer) { | ||
this.log.debug('No discount eligibility determiner, skipping...'); | ||
return new Internal.DiscountEligibilities([], []); | ||
@@ -471,2 +475,11 @@ } | ||
}); | ||
if (!valid.discounts && valid.introPrice) { | ||
// sometime apple returns the discounts in the deprecated "introductory" info | ||
// we create a special "discount" with the id "intro" to check for eligibility. | ||
eligibilityRequests.push({ | ||
productId: valid.id, | ||
discountId: 'intro', | ||
discountType: 'Introductory', | ||
}); | ||
} | ||
}); | ||
@@ -508,3 +521,3 @@ | ||
const eligibilities = await this.loadEligibility(validProducts); | ||
this.log.info('eligibilities ready.'); | ||
this.log.info('eligibilities ready: ' + JSON.stringify(eligibilities)); | ||
// for any valid product that includes a discount, check the eligibility. | ||
@@ -514,3 +527,3 @@ const ret = products.map(p => { | ||
this.log.debug(`${p.id} is invalid`); | ||
return storeError(ErrorCode.INVALID_PRODUCT_ID, 'Product not found in AppStore. #400'); | ||
return appStoreError(ErrorCode.INVALID_PRODUCT_ID, 'Product not found in AppStore. #400', p.id); | ||
} | ||
@@ -521,3 +534,3 @@ else { | ||
if (!valid) | ||
return storeError(ErrorCode.INVALID_PRODUCT_ID, 'Product not found in AppStore. #404'); | ||
return appStoreError(ErrorCode.INVALID_PRODUCT_ID, 'Product not found in AppStore. #404', p.id); | ||
let product = this.getProduct(p.id); | ||
@@ -540,3 +553,3 @@ if (product) { | ||
(code: ErrorCode, message: string) => { | ||
return products.map(p => storeError(code, message)); | ||
return products.map(p => appStoreError(code, message, null)); | ||
}); | ||
@@ -559,6 +572,6 @@ }); | ||
if (discountId && !discount) { | ||
return callResolve(storeError(ErrorCode.MISSING_OFFER_PARAMS, 'Missing additionalData.appStore.discount when ordering a discount offer')); | ||
return callResolve(appStoreError(ErrorCode.MISSING_OFFER_PARAMS, 'Missing additionalData.appStore.discount when ordering a discount offer', offer.productId)); | ||
} | ||
if (discountId && (discount?.id !== discountId)) { | ||
return callResolve(storeError(ErrorCode.INVALID_OFFER_IDENTIFIER, 'Offer identifier does not match additionalData.appStore.discount.id')); | ||
return callResolve(appStoreError(ErrorCode.INVALID_OFFER_IDENTIFIER, 'Offer identifier does not match additionalData.appStore.discount.id', offer.productId)); | ||
} | ||
@@ -570,3 +583,3 @@ this.setPaymentMonitor((status: PaymentMonitorStatus, code?: ErrorCode, message?: string) => { | ||
case 'cancelled': | ||
callResolve(storeError(code ?? ErrorCode.PAYMENT_CANCELLED, message ?? 'The user cancelled the order.')); | ||
callResolve(appStoreError(code ?? ErrorCode.PAYMENT_CANCELLED, message ?? 'The user cancelled the order.', offer.productId)); | ||
break; | ||
@@ -577,3 +590,3 @@ case 'failed': | ||
setTimeout(() => { | ||
callResolve(storeError(code ?? ErrorCode.PURCHASE, message ?? 'Purchase failed')); | ||
callResolve(appStoreError(code ?? ErrorCode.PURCHASE, message ?? 'Purchase failed', offer.productId)); | ||
}, 500); | ||
@@ -593,3 +606,3 @@ break; | ||
this.log.info('order.error'); | ||
callResolve(storeError(ErrorCode.PURCHASE, 'Failed to place order')); | ||
callResolve(appStoreError(ErrorCode.PURCHASE, 'Failed to place order', offer.productId)); | ||
} | ||
@@ -624,3 +637,3 @@ // When we switch AppStore user, the cached receipt isn't from the new user. | ||
else { | ||
resolve(storeError(ErrorCode.FINISH, 'Failed to finish transaction')); | ||
resolve(appStoreError(ErrorCode.FINISH, 'Failed to finish transaction', transaction.products[0]?.id ?? null)); | ||
} | ||
@@ -639,3 +652,3 @@ } | ||
const error = (code: ErrorCode, message: string): void => { | ||
resolve(storeError(code, message)); | ||
resolve(appStoreError(code, message, null)); | ||
} | ||
@@ -704,3 +717,3 @@ this.bridge.refreshReceipts(success, error); | ||
async requestPayment(payment: PaymentRequest, additionalData?: CdvPurchase.AdditionalData): Promise<IError | Transaction | undefined> { | ||
return storeError(ErrorCode.UNKNOWN, 'requestPayment not supported'); | ||
return appStoreError(ErrorCode.UNKNOWN, 'requestPayment not supported', null); | ||
} | ||
@@ -744,3 +757,7 @@ | ||
} | ||
function appStoreError(code: ErrorCode, message: string, productId: string | null) { | ||
return storeError(code, message, Platform.APPLE_APPSTORE, productId); | ||
} | ||
} | ||
} |
@@ -39,3 +39,3 @@ namespace CdvPurchase { | ||
if (skOffer.offerType === 'Default') return true; | ||
return eligibilities.isEligible(this.id, skOffer.offerType, offer.id) | ||
return eligibilities.isEligible(this.id, skOffer.offerType, offer.id); | ||
}); | ||
@@ -90,3 +90,3 @@ } | ||
// it's not always the case (when there are no discount offers maybe?)... | ||
if (valid.introPrice && valid.introPriceMicros !== undefined) { | ||
if (valid.introPrice && valid.introPriceMicros !== undefined && eligibilities.isEligible(valid.id, 'Introductory', 'intro')) { | ||
const introPrice: PricingPhase = { | ||
@@ -93,0 +93,0 @@ price: valid.introPrice, |
@@ -230,3 +230,3 @@ namespace CdvPurchase { | ||
else | ||
callback(storeError(ErrorCode.CLIENT_INVALID, 'Braintree iOS Bridge requires a clientTokenProvider or tokenizationKey')); | ||
callback(braintreeError(ErrorCode.CLIENT_INVALID, 'Braintree iOS Bridge requires a clientTokenProvider or tokenizationKey')); | ||
}, this.options.applePay); | ||
@@ -255,3 +255,3 @@ this.iosBridge.initialize(this.context, resolve); | ||
async loadProducts(products: IRegisterProduct[]): Promise<(Product | IError)[]> { | ||
return products.map(p => storeError(ErrorCode.PRODUCT_NOT_AVAILABLE, 'N/A')); | ||
return products.map(p => braintreeError(ErrorCode.PRODUCT_NOT_AVAILABLE, 'N/A')); | ||
} | ||
@@ -265,3 +265,3 @@ | ||
async order(offer: Offer): Promise<undefined | IError> { | ||
return storeError(ErrorCode.UNKNOWN, 'N/A: Not implemented with Braintree'); | ||
return braintreeError(ErrorCode.UNKNOWN, 'N/A: Not implemented with Braintree'); | ||
} | ||
@@ -302,3 +302,3 @@ | ||
if (this.iosBridge) return this.iosBridge.launchDropIn(paymentRequest, dropInRequest); | ||
return storeError(ErrorCode.PURCHASE, 'Braintree is not available'); | ||
return braintreeError(ErrorCode.PURCHASE, 'Braintree is not available'); | ||
} | ||
@@ -368,3 +368,3 @@ | ||
if (!dropInResult.paymentMethodNonce?.nonce) { | ||
return storeError(ErrorCode.BAD_RESPONSE, 'launchDropIn returned no paymentMethodNonce'); | ||
return braintreeError(ErrorCode.BAD_RESPONSE, 'launchDropIn returned no paymentMethodNonce'); | ||
} | ||
@@ -457,3 +457,3 @@ | ||
log.warn("launchDropIn failed: no response"); | ||
return storeError(ErrorCode.BAD_RESPONSE, 'Braintree failed to launch drop in'); | ||
return braintreeError(ErrorCode.BAD_RESPONSE, 'Braintree failed to launch drop in'); | ||
} | ||
@@ -470,3 +470,7 @@ else { | ||
} | ||
export function braintreeError(code: ErrorCode, message: string) { | ||
return storeError(code, message, Platform.BRAINTREE, null); | ||
} | ||
} | ||
} |
@@ -80,3 +80,3 @@ namespace CdvPurchase { | ||
this.log.warn("initialization failed: " + (err as Error)?.message); | ||
callback(storeError(ErrorCode.SETUP, 'Failed to initialize Braintree Android Bridge: ' + (err as Error)?.message)); | ||
callback(braintreeError(ErrorCode.SETUP, 'Failed to initialize Braintree Android Bridge: ' + (err as Error)?.message)); | ||
} | ||
@@ -130,9 +130,9 @@ } | ||
if (errCode === "UserCanceledException") { | ||
resolve(storeError(ErrorCode.PAYMENT_CANCELLED, errMessage)); | ||
resolve(braintreeError(ErrorCode.PAYMENT_CANCELLED, errMessage)); | ||
} | ||
else if (errCode === "AuthorizationException") { | ||
resolve(storeError(ErrorCode.UNAUTHORIZED_REQUEST_DATA, errMessage)); | ||
resolve(braintreeError(ErrorCode.UNAUTHORIZED_REQUEST_DATA, errMessage)); | ||
} | ||
else { | ||
resolve(storeError(ErrorCode.UNKNOWN, err)); | ||
resolve(braintreeError(ErrorCode.UNKNOWN, err)); | ||
} | ||
@@ -139,0 +139,0 @@ }, |
@@ -30,3 +30,3 @@ namespace CdvPurchase { | ||
if (!ApplePayPlugin.get()?.installed) { | ||
return resolve(storeError(ErrorCode.SETUP, 'cordova-plugin-purchase-braintree-applepay does not appear to be installed.')); | ||
return resolve(braintreeError(ErrorCode.SETUP, 'cordova-plugin-purchase-braintree-applepay does not appear to be installed.')); | ||
} | ||
@@ -39,3 +39,3 @@ else { | ||
const message = err ?? 'payment request failed'; | ||
resolve(storeError(ErrorCode.PURCHASE, 'Braintree+ApplePay ERROR: ' + message)); | ||
resolve(braintreeError(ErrorCode.PURCHASE, 'Braintree+ApplePay ERROR: ' + message)); | ||
}; | ||
@@ -42,0 +42,0 @@ window.cordova.exec(success, failure, PLUGIN_ID, 'presentDropInPaymentUI', [request]); |
@@ -114,3 +114,3 @@ namespace CdvPurchase { | ||
if (result.userCancelled) { | ||
return storeError(ErrorCode.PAYMENT_CANCELLED, 'User cancelled the payment request'); | ||
return braintreeError(ErrorCode.PAYMENT_CANCELLED, 'User cancelled the payment request'); | ||
} | ||
@@ -145,6 +145,6 @@ return { | ||
if (errCode === "UserCanceledException") { | ||
resolve(storeError(ErrorCode.PAYMENT_CANCELLED, errMessage)); | ||
resolve(braintreeError(ErrorCode.PAYMENT_CANCELLED, errMessage)); | ||
} | ||
else { | ||
resolve(storeError(ErrorCode.UNKNOWN, 'ERROR ' + errCode + ': ' + errMessage)); | ||
resolve(braintreeError(ErrorCode.UNKNOWN, 'ERROR ' + errCode + ': ' + errMessage)); | ||
} | ||
@@ -151,0 +151,0 @@ } |
@@ -151,3 +151,3 @@ /// <reference path="../../receipt.ts" /> | ||
this.initialized = false; | ||
this.context.error(storeError(ErrorCode.SETUP, "Init failed - " + err)); | ||
this.context.error(playStoreError(ErrorCode.SETUP, "Init failed - " + err, null)); | ||
this.retry.retry(() => this.initialize()); | ||
@@ -201,3 +201,3 @@ } | ||
else { | ||
return storeError(ErrorCode.INVALID_PRODUCT_ID, `Product with id ${registeredProduct.id} not found.`); | ||
return playStoreError(ErrorCode.INVALID_PRODUCT_ID, `Product with id ${registeredProduct.id} not found.`, registeredProduct.id); | ||
} | ||
@@ -215,3 +215,3 @@ }); | ||
this.retry.retry(go); | ||
this.context.error(storeError(ErrorCode.LOAD, 'Loading product info failed - ' + err + ' - retrying later...')) | ||
this.context.error(playStoreError(ErrorCode.LOAD, 'Loading product info failed - ' + err + ' - retrying later...', null)) | ||
}); | ||
@@ -235,19 +235,20 @@ } | ||
}; | ||
const onFailure = (message: string, code?: ErrorCode) => resolve(storeError(code || ErrorCode.UNKNOWN, message)); | ||
const firstProduct = transaction.products[0]; | ||
const firstProduct = transaction.products[0]; | ||
if (!firstProduct) | ||
return resolve(storeError(ErrorCode.FINISH, 'Cannot finish a transaction with no product')); | ||
return resolve(playStoreError(ErrorCode.FINISH, 'Cannot finish a transaction with no product', null)); | ||
const product = this._products.getProduct(firstProduct.id); | ||
if (!product) | ||
return resolve(storeError(ErrorCode.FINISH, 'Cannot finish transaction, unknown product ' + firstProduct.id)); | ||
return resolve(playStoreError(ErrorCode.FINISH, 'Cannot finish transaction, unknown product ' + firstProduct.id, firstProduct.id)); | ||
const receipt = this._receipts.find(r => r.hasTransaction(transaction)); | ||
if (!receipt) | ||
return resolve(storeError(ErrorCode.FINISH, 'Cannot finish transaction, linked receipt not found.')); | ||
return resolve(playStoreError(ErrorCode.FINISH, 'Cannot finish transaction, linked receipt not found.', product.id)); | ||
if (!receipt.purchaseToken) | ||
return resolve(storeError(ErrorCode.FINISH, 'Cannot finish transaction, linked receipt contains no purchaseToken.')); | ||
return resolve(playStoreError(ErrorCode.FINISH, 'Cannot finish transaction, linked receipt contains no purchaseToken.', product.id)); | ||
const onFailure = (message: string, code?: ErrorCode) => resolve(playStoreError(code || ErrorCode.UNKNOWN, message, product.id)); | ||
if (product.type === ProductType.NON_RENEWING_SUBSCRIPTION || product.type === ProductType.CONSUMABLE) { | ||
@@ -311,3 +312,3 @@ if (!transaction.isConsumed) | ||
this.log.warn('getPurchases failed: ' + message + ' (' + code + ')'); | ||
setTimeout(() => resolve(storeError(code || ErrorCode.UNKNOWN, message)), 0); | ||
setTimeout(() => resolve(playStoreError(code || ErrorCode.UNKNOWN, message, null)), 0); | ||
} | ||
@@ -325,3 +326,3 @@ this.bridge.getPurchases(success, failure); | ||
this.log.warn('Order failed: ' + JSON.stringify({message, code})); | ||
resolve(storeError(code ?? ErrorCode.UNKNOWN, message)); | ||
resolve(playStoreError(code ?? ErrorCode.UNKNOWN, message, offer.productId)); | ||
}; | ||
@@ -417,3 +418,3 @@ if (offer.productType === ProductType.PAID_SUBSCRIPTION) { | ||
async requestPayment(payment: PaymentRequest, additionalData?: CdvPurchase.AdditionalData): Promise<IError | Transaction | undefined> { | ||
return storeError(ErrorCode.UNKNOWN, 'requestPayment not supported'); | ||
return playStoreError(ErrorCode.UNKNOWN, 'requestPayment not supported', null); | ||
} | ||
@@ -448,4 +449,7 @@ | ||
function playStoreError(code: ErrorCode, message: string, productId: string | null) { | ||
return storeError(code, message, Platform.GOOGLE_PLAY, productId); | ||
} | ||
} | ||
} | ||
@@ -75,3 +75,3 @@ namespace CdvPurchase { | ||
if (!testProductsArray.find(p => p.id === registerProduct.id && p.type === registerProduct.type)) { | ||
return storeError(ErrorCode.PRODUCT_NOT_AVAILABLE, 'This product is not available'); | ||
return testStoreError(ErrorCode.PRODUCT_NOT_AVAILABLE, 'This product is not available', registerProduct.id); | ||
} | ||
@@ -90,3 +90,3 @@ // Ensure it's not been loaded already. | ||
const product = initTestProduct(registerProduct.id, this.context.apiDecorators); | ||
if (!product) return storeError(ErrorCode.PRODUCT_NOT_AVAILABLE, 'Could not load this product'); | ||
if (!product) return testStoreError(ErrorCode.PRODUCT_NOT_AVAILABLE, 'Could not load this product', registerProduct.id); | ||
this.products.push(product); | ||
@@ -101,12 +101,12 @@ this.context.listener.productsUpdated(Platform.TEST, [product]); | ||
if (offer.id.indexOf("-fail-") > 0) { | ||
return storeError(ErrorCode.PURCHASE, 'Purchase failed.'); | ||
return testStoreError(ErrorCode.PURCHASE, 'Purchase failed.', offer.productId); | ||
} | ||
const product = this.products.find(p => p.id === offer.productId); | ||
if (!Internal.LocalReceipts.canPurchase(this.receipts, product)) { | ||
return storeError(ErrorCode.PURCHASE, 'Product already owned'); | ||
return testStoreError(ErrorCode.PURCHASE, 'Product already owned', offer.productId); | ||
} | ||
// a receipt containing a transaction with the given product. | ||
const response = prompt(`Do you want to purchase ${offer.productId} for ${offer.pricingPhases[0].price}?\nEnter "Y" to confirm.\nEnter "E" to fail with an error.\Anything else to cancel.`); | ||
if (response?.toUpperCase() === 'E') return storeError(ErrorCode.PURCHASE, 'Purchase failed'); | ||
if (response?.toUpperCase() !== 'Y') return storeError(ErrorCode.PAYMENT_CANCELLED, 'Purchase flow has been cancelled by the user'); | ||
if (response?.toUpperCase() === 'E') return testStoreError(ErrorCode.PURCHASE, 'Purchase failed', offer.productId); | ||
if (response?.toUpperCase() !== 'Y') return testStoreError(ErrorCode.PAYMENT_CANCELLED, 'Purchase flow has been cancelled by the user', offer.productId); | ||
// purchase succeeded, let's generate a mock receipt. | ||
@@ -183,3 +183,3 @@ const receipt = new Receipt(platform, this.context.apiDecorators); | ||
const response = prompt(`Mock payment of ${(paymentRequest.amountMicros ?? 0) / 1000000} ${paymentRequest.currency}. Enter "Y" to confirm. Enter "E" to trigger an error.`); | ||
if (response?.toUpperCase() === 'E') return storeError(ErrorCode.PAYMENT_NOT_ALLOWED, 'Payment not allowed'); | ||
if (response?.toUpperCase() === 'E') return testStoreError(ErrorCode.PAYMENT_NOT_ALLOWED, 'Payment not allowed', null); | ||
if (response?.toUpperCase() !== 'Y') return; | ||
@@ -280,3 +280,7 @@ const receipt = new Receipt(platform, this.context.apiDecorators); | ||
} | ||
function testStoreError(code: ErrorCode, message: string, productId: string | null) { | ||
return storeError(code, message, Platform.TEST, productId); | ||
} | ||
} | ||
} |
@@ -14,3 +14,3 @@ namespace CdvPurchase { | ||
async loadProducts(products: IRegisterProduct[]): Promise<(Product | IError)[]> { | ||
return products.map(p => storeError(ErrorCode.PRODUCT_NOT_AVAILABLE, 'TODO')); | ||
return products.map(p => windowsStoreError(ErrorCode.PRODUCT_NOT_AVAILABLE, 'TODO', p.id)); | ||
} | ||
@@ -21,6 +21,6 @@ async loadReceipts(): Promise<Receipt[]> { | ||
async order(offer: Offer): Promise<undefined | IError> { | ||
return storeError(ErrorCode.UNKNOWN, 'TODO: Not implemented'); | ||
return windowsStoreError(ErrorCode.UNKNOWN, 'TODO: Not implemented', offer.productId); | ||
} | ||
async finish(transaction: Transaction): Promise<undefined | IError> { | ||
return storeError(ErrorCode.UNKNOWN, 'TODO: Not implemented'); | ||
return windowsStoreError(ErrorCode.UNKNOWN, 'TODO: Not implemented', null); | ||
} | ||
@@ -34,9 +34,9 @@ async handleReceiptValidationResponse(receipt: Receipt, response: Validator.Response.Payload): Promise<void> { | ||
async requestPayment(payment: PaymentRequest, additionalData?: CdvPurchase.AdditionalData): Promise<IError | Transaction | undefined> { | ||
return storeError(ErrorCode.UNKNOWN, 'requestPayment not supported'); | ||
return windowsStoreError(ErrorCode.UNKNOWN, 'requestPayment not supported', null); | ||
} | ||
async manageSubscriptions(): Promise<IError | undefined> { | ||
return storeError(ErrorCode.UNKNOWN, 'manageSubscriptions not supported'); | ||
return windowsStoreError(ErrorCode.UNKNOWN, 'manageSubscriptions not supported', null); | ||
} | ||
async manageBilling(): Promise<IError | undefined> { | ||
return storeError(ErrorCode.UNKNOWN, 'manageBilling not supported'); | ||
return windowsStoreError(ErrorCode.UNKNOWN, 'manageBilling not supported', null); | ||
} | ||
@@ -49,3 +49,7 @@ checkSupport(functionality: PlatformFunctionality): boolean { | ||
} | ||
function windowsStoreError(code: ErrorCode, message: string, productId: string | null) { | ||
return storeError(code, message, Platform.WINDOWS_STORE, productId); | ||
} | ||
} | ||
} |
@@ -0,1 +1,2 @@ | ||
/// <reference path="types.ts" /> | ||
/// <reference path="utils/compatibility.ts" /> | ||
@@ -5,4 +6,8 @@ /// <reference path="validator/validator.ts" /> | ||
/// <reference path="internal/adapters.ts" /> | ||
/// <reference path="internal/adapter-listener.ts" /> | ||
/// <reference path="internal/callbacks.ts" /> | ||
/// <reference path="internal/ready.ts" /> | ||
/// <reference path="internal/register.ts" /> | ||
/// <reference path="internal/transaction-monitor.ts" /> | ||
/// <reference path="internal/receipts-monitor.ts" /> | ||
@@ -29,3 +34,3 @@ /** | ||
*/ | ||
export const PLUGIN_VERSION = '13.8.0'; | ||
export const PLUGIN_VERSION = '13.8.2'; | ||
@@ -79,3 +84,3 @@ /** | ||
/** Return the identifier of the user for your application */ | ||
public applicationUsername?: string | (() => string); | ||
public applicationUsername?: string | (() => string | undefined); | ||
@@ -481,3 +486,3 @@ /** | ||
const adapter = this.adapters.findReady(offer.platform); | ||
if (!adapter) return storeError(ErrorCode.PAYMENT_NOT_ALLOWED, 'Adapter not found or not ready (' + offer.platform + ')'); | ||
if (!adapter) return storeError(ErrorCode.PAYMENT_NOT_ALLOWED, 'Adapter not found or not ready (' + offer.platform + ')', offer.platform, null); | ||
const ret = await adapter.order(offer, additionalData || {}); | ||
@@ -500,3 +505,3 @@ if (ret && 'isError' in ret) store.triggerError(ret); | ||
if (!adapter) | ||
return PaymentRequestPromise.failed(ErrorCode.PAYMENT_NOT_ALLOWED, 'Adapter not found or not ready (' + paymentRequest.platform + ')'); | ||
return PaymentRequestPromise.failed(ErrorCode.PAYMENT_NOT_ALLOWED, 'Adapter not found or not ready (' + paymentRequest.platform + ')', paymentRequest.platform, null); | ||
@@ -523,3 +528,3 @@ // fill-in missing total amount as the sum of all items. | ||
if (paymentRequest.currency !== item.pricing.currency) { | ||
return PaymentRequestPromise.failed(ErrorCode.PAYMENT_INVALID, 'Currencies do not match'); | ||
return PaymentRequestPromise.failed(ErrorCode.PAYMENT_INVALID, 'Currencies do not match', paymentRequest.platform, item.id); | ||
} | ||
@@ -627,3 +632,3 @@ } | ||
const adapter = this.adapters.findReady(platform); | ||
if (!adapter) return storeError(ErrorCode.SETUP, "Found no adapter ready to handle 'manageSubscription'"); | ||
if (!adapter) return storeError(ErrorCode.SETUP, "Found no adapter ready to handle 'manageSubscription'", platform ?? null, null); | ||
return adapter.manageSubscriptions(); | ||
@@ -646,3 +651,3 @@ } | ||
const adapter = this.adapters.findReady(platform); | ||
if (!adapter) return storeError(ErrorCode.SETUP, "Found no adapter ready to handle 'manageBilling'"); | ||
if (!adapter) return storeError(ErrorCode.SETUP, "Found no adapter ready to handle 'manageBilling'", platform ?? null, null); | ||
return adapter.manageBilling(); | ||
@@ -712,3 +717,9 @@ } | ||
// Create the CdvPurchase.store object at startup. | ||
setTimeout(() => { | ||
if (window.cordova) { | ||
setTimeout(initCDVPurchase, 0); // somehow with Cordova this needs to be delayed. | ||
} | ||
else { | ||
initCDVPurchase(); | ||
} | ||
function initCDVPurchase() { | ||
console.log('Create CdvPurchase...'); | ||
@@ -732,5 +743,5 @@ /* | ||
Object.assign(window.CdvPurchase.store, CdvPurchase.LogLevel, CdvPurchase.ProductType, CdvPurchase.ErrorCode, CdvPurchase.Platform); | ||
}, 0); | ||
} | ||
// Ensure utility are included when compiling typescript. | ||
/// <reference path="utils/format-billing-cycle.ts" /> |
@@ -21,2 +21,8 @@ /// <reference path="store.ts" /> | ||
message: string; | ||
/** Optional platform the error occured on */ | ||
platform: Platform | null; | ||
/** Optional ID of the product the error occurred on */ | ||
productId: string | null; | ||
} | ||
@@ -23,0 +29,0 @@ |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Mixed license
License(Experimental) Package contains multiple licenses.
Found 1 instance in 1 package
8
0
1304520
91
23253