cordova-plugin-purchase
cordova-plugin-purchase copied to clipboard
anyone have tested the library with ios 17.4?
anyone have tested the library with ios 17.4?
I'm not able to fetch the products on iOS 17.3, it's throwing error as Invalid parameters passed to "register"
.
Complete IAP flow got broken.
Can anyone facing the same?
We also have the same problem. Our monthly and yearly abos are broken.. Android works just fine. But iOS 17.4 seems broken :(.
Hello. Please, do you resolve this issue ? I have the same... Thanks a lot
@guenolefr @jhasenfuss The method implementations have been updated, please check the new documentation update accordingly. This was the fix in my case.
@pravinkumarputta Could you please be a little more specific about which method in particular you had to update in order to make this work? That would be greatly appreciated. Many thanks!
@pravinkumarputta please be more precise. Like @vesper8, I have no idea which docu you mean.
- Product Pricing
// Old
IAP_PRODUCT['currency']
IAP_PRODUCT['price']
IAP_PRODUCT['priceMicros']
// New
IAP_PRODUCT['pricing']['currency']
IAP_PRODUCT['pricing']['price']
IAP_PRODUCT['pricing']['priceMicros']
- IAP initialisation
// Old
const store = (<any>window).CdvPurchase.store;
store.register([{
id: IAP_PRODUCT,
type: store.CONSUMABLE,
}]);
store.when(IAP_PRODUCT).updated(async () => {
////console.log('purchase updated----');
this.IAP_PRODUCT = store.get(IAP_PRODUCT) || {};
if (this.IAP_PRODUCT.finished) {
status = 'Purchased';
} else if (this.IAP_PRODUCT.state === 'approved') {
status = 'Processing...';
await (() => {
this.IAP_PRODUCT.finish();//we need to await for it to finish
})();//we need to call this here also
//await this._updatePurchaseOnServer(this.IAP_PRODUCT);
}
});
store.when(IAP_PRODUCT).finished(async (product) => {
const transactionId = product['transaction']['id'];
});
store.refresh(); // Was used to initialise IAP
// New
const store = (<any>window).CdvPurchase.store;
store.register([{
id: IAP_PRODUCT,
type: store.CONSUMABLE,
platform: this.platform.is("ios") ? (<any>window).CdvPurchase.Platform.APPLE_APPSTORE : (<any>window).CdvPurchase.Platform.GOOGLE_PLAY,
}]);
store.when(IAP_PRODUCT).updated(async () => {
////console.log('purchase updated----');
this.IAP_PRODUCT = store.get(IAP_PRODUCT) || {};
if (this.IAP_PRODUCT.finished) {
status = 'Purchased';
} else if (this.IAP_PRODUCT.state === 'approved') {
status = 'Processing...';
await (() => {
this.IAP_PRODUCT.finish();//we need to await for it to finish
})();//we need to call this here also
//await this._updatePurchaseOnServer(this.IAP_PRODUCT);
}
});
store.when(IAP_PRODUCT).finished(async (product) => {
const transactionId = product['transactionId'];
// log the product to get clear idea
});
store.initialize(); // initialise IAP
-
Callbacks no longer accessible
-
refunded
-
error
-
cancelled
-
refresh
-
-
Make Purchase
// Old
let response = await store.order(product); // the response was getting through the callbacks
// New
try {
let response = await this.IAP_PRODUCT.getOffer().order(); // I get response here only
if (response && response.isError) {
if (response.message.includes('cancelled')) {
this._iap_purchase.next({ state: PURCHASE_STATUS.CANCELLED, product: product });
} else {
this._iap_purchase.next({ state: PURCHASE_STATUS.FAILED, product: product });
}
return;
}
} catch(err) {
// handle error
}
@jhasenfuss @vesper8 I hope this comparision will help you.
@pravinkumarputta thanks for your reply. But sadly, not really..
Maybe you can help me if i share my code:
AppComponent:
constructor(...) {
this.platform.ready().then(async () => {
await this.initializeApp();
});
}
async initializeApp() {
...
if (this.platform.is('mobile')) {
this.store = CdvPurchase.store;
if (!environment.production) {
// this.store.verbosity = LogLevel.DEBUG;
}
this.registerProducts();
this.store.error((err) => {
console.error('Store Error ' + JSON.stringify(err));
this.tracker.trackEvent('Store Error', err.message, JSON.stringify(err));
throw new Error('Store Error ' + JSON.stringify(err));
});
this.store.when().approved((transaction) => {
console.log('transaction approved', transaction);
transaction.verify();
}).verified((receipt) => {
console.log('receipt verified', receipt);
receipt.finish();
}).finished(transaction => {
console.log('Products owned: ' + transaction.products.map(p => p.id).join(','));
}).receiptUpdated(receipt => {
console.log('receiptUpdated');
receipt.transactions.forEach(transaction => {
transaction.products.forEach(trProduct => {
console.log(`product owned: ${trProduct.id}`);
});
});
}).productUpdated(t => {
console.log('productUpdated', t);
this.updateProVersion();
}).unverified((receipt) => {
console.log(`Receipt cannot be verified: ${receipt && receipt.payload && receipt.payload.message}`);
if (receipt.payload.code === CdvPurchase.ErrorCode.COMMUNICATION) {
console.log('HTTP ERROR: ' + receipt.payload.status);
}
}).receiptsVerified(() => {
console.log('receiptsVerified');
}).receiptsReady(() => {
console.log('All platforms are done loading their local receipts');
});
await this.store.initialize([
CdvPurchase.Platform.GOOGLE_PLAY,
CdvPurchase.Platform.APPLE_APPSTORE
]);
await this.store.update();
await this.store.restorePurchases();
console.log('STORE INIT DONE');
this.updateProVersion();
}
await this.checkTerms();
}
private registerProducts() {
this.store.register([
{
id : IOS_PRO_MONTH,
type : ProductType.PAID_SUBSCRIPTION,
platform: CdvPlatform.APPLE_APPSTORE,
group : 'pro_version_group'
}, {
id : IOS_PRO_YEAR,
type : ProductType.PAID_SUBSCRIPTION,
platform: CdvPlatform.APPLE_APPSTORE,
group : 'pro_version_group'
}, {
id : ANDROID_PRO_MONTH,
type : ProductType.PAID_SUBSCRIPTION,
platform: CdvPlatform.GOOGLE_PLAY,
group : 'pro_version_group'
}, {
id : ANDROID_PRO_YEAR,
type : ProductType.PAID_SUBSCRIPTION,
platform: CdvPlatform.GOOGLE_PLAY,
group : 'pro_version_group'
}
]);
}
private updateProVersion() {
const pro = this.store.get(this.gameInstanceService.storeProMonth);
const pro12 = this.store.get(this.gameInstanceService.storeProYear);
console.log(pro.owned, pro12.owned);
console.log(pro, pro12);
this.gameInstanceService.proWithAbo = pro.owned || pro12.owned;
console.log('-> this.gameInstanceService.proWithAbo', this.gameInstanceService.proWithAbo);
}
As you can see, i tried several events with console logs, but with no result.. Can you say what i am doing wrong?
@jhasenfuss Code looks okay, but what exactly is the problem you are facing? Are you getting some kind of error on the console? or is nothing happening?
Please share the code for purchase/order.
Thanks @pravinkumarputta. The problem is, users which purchased a monthly or yearly subscription can't use the pro version after a restart of the app. So the app doesn't load the purchased products or i don't really know, what the problem is. The purchase itself works, because they can't repurchase a subscription. Maybe something since 17.4? Android works just fine.
The purchase function:
proVersion: CdvPurchase.Product;
proVersion12: CdvPurchase.Product;
constructor(...){
this.proVersion = this.store.get(gameInstanceService.storeProMonth);
this.proVersion12 = this.store.get(gameInstanceService.storeProYear);
}
async subscribeProVersion() {
try {
let err: CdvPurchase.IError;
if (this.selPeriod === 1) {
err = await this.proVersion.getOffer().order();
} else if (this.selPeriod === 12) {
err = await this.proVersion12.getOffer().order();
}
console.log(err);
} catch (e) {
console.error(e);
}
}
Hi, meanwhile i switched to https://www.revenuecat.com and it works just fine. Even on the latest iOS version.. So from my side, this issue can be closed.
Hi, meanwhile i switched to https://www.revenuecat.com and it works just fine. Even on the latest iOS version..
So from my side, this issue can be closed.
RevenueCat will stop Cordova support.