Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

anyone have tested the library with ios 17.4? #1532

Open
luk156 opened this issue Feb 15, 2024 · 11 comments
Open

anyone have tested the library with ios 17.4? #1532

luk156 opened this issue Feb 15, 2024 · 11 comments

Comments

@luk156
Copy link

luk156 commented Feb 15, 2024

anyone have tested the library with ios 17.4?

@pravinkumarputta
Copy link

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?

@jhasenfuss
Copy link

We also have the same problem.
Our monthly and yearly abos are broken..
Android works just fine. But iOS 17.4 seems broken :(.

@guenolefr
Copy link

Hello. Please, do you resolve this issue ? I have the same... Thanks a lot

@pravinkumarputta
Copy link

@guenolefr @jhasenfuss The method implementations have been updated, please check the new documentation update accordingly.
This was the fix in my case.

@vesper8
Copy link

vesper8 commented Apr 8, 2024

@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!

@jhasenfuss
Copy link

@pravinkumarputta please be more precise. Like @vesper8, I have no idea which docu you mean.

@pravinkumarputta
Copy link

pravinkumarputta commented Apr 29, 2024

  1. 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']
  1. 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
  1. Callbacks no longer accessible

    • refunded
    • error
    • cancelled
    • refresh
  2. 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.

@jhasenfuss
Copy link

@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?

@pravinkumarputta
Copy link

@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.

@jhasenfuss
Copy link

jhasenfuss commented May 1, 2024

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);
        }
    }

@jhasenfuss
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants