Problem
When user opens a subscription page, native iTunes user / password modal appears. No matter what action does user next. Enter password or cancel it, my code does not handle this event. And loading never stops and purchase button never appears.
So, app rejected every time with reason: app loaded indefinitely in the subscription page
Any ideas how to solve the problem? I can't get it. .cancelled() does not handle native events.
Env:
Ionic 5.1.1
Capacitor 2.3.0
Device: iPhone 6S iOS 13.5.1
cordova-plugin-purchase: 10.2.0
App initialization:
this.platform.ready().then(() => {
this.registerProducts()
})
registerProducts() {
this.store.register([
{
id: 'premium1',
alias: 'premium',
type: this.store.PAID_SUBSCRIPTION,
},
{
id: 'product1',
alias: 'product1',
type: this.store.CONSUMABLE,
},
{
id: 'product2',
alias: 'product2',
type: this.store.CONSUMABLE,
},
])
this.store.refresh()
}
First page:
this.platform.ready().then(() => {
let m = this.store.get('premium')
if (!m.owned) {
this.setPremium(false)
this.cdref.detectChanges() // Angular ChangeDetectorRef
}
})
Then subscription page:
this.platform.ready().then(() => {
this.registerProducts()
this.setupListeners()
this.store.update()
})
registerProducts() {
let product = this.store.get('premium')
if (!product) {
this.loading = false
this.productError = true
} else if (product.state === this.store.INVALID) {
this.loading = false
this.productError = true
} else {
this.loading = false
this.product = product
}
this.cdref.detectChanges()
}
setupListeners() {
this.store.when('premium')
.error(e => {
this.dissmissAlert()
this.presentAlert(e.code, e.message)
})
.finished(() => {
this.loading = false
this.restoreLoading = false
})
.expired(() => {
this.loading = false
this.productError = true
})
.approved((p: IAPProduct) => {
p.verify()
this.cdref.detectChanges()
})
.verified((p: IAPProduct) => {
this.setPremium(true)
p.finish()
this.cdref.detectChanges()
})
}
purchase() {
this.btnLoading = true
try {
this.store.order('premium').then(() => {
this.btnLoading = false
}).catch((err) => {
this.presentAlert('', err)
})
} catch (error) {
this.presentAlert('', error)
}
}
restore() {
this.restoreLoading = true
this.store.refresh()
this.cdref.detectChanges()
}
<ng-container *ngIf="productError">
<div class="wait">
<span class="text">Error with Subcription. Try again later.</span>
</div>
</ng-container>
<ng-container *ngIf="!productError">
<ng-container *ngIf="loading">
<div class="wait">
<span class="text">Loading...</span>
<ion-spinner class="spinner" name="crescent"></ion-spinner>
</div>
</ng-container>
<ng-container *ngIf="!loading">
<p class="act" *ngIf="product.owned">Subscribed</p>
<button class="sub-btn" (click)="purchase()" *ngIf="!product.owned">
<ion-spinner class="spinner" name="crescent" *ngIf="btnLoading"></ion-spinner>
<ng-container *ngIf="!btnLoading">
<span class="text">Subscribe {{ product.price }} / {{ product.billingPeriod }} мес.</span>
<ion-icon class="icon" name="arrow-forward-circle" slot="end"></ion-icon>
</ng-container>
</button>
</ng-container>
</ng-container>
registerProducts()andsetupListeners()should be called ONCE upon app initialization.