iOS in app purchases through cordova-plugin-purchase? - ios

I'm using Capacitor (but not Ionic) to package a SvelteKit application for iOS and am trying to get an in-app-purchase working.
Capacitor's page on in-app-purchases is surprisingly unhelpful. I've done my best and:
I have the products set up in appstoreconnect and they're status is "ready to submit"
I've installed cordova-plugin-purchase and run npx cap update and npx cap sync and it's installing
[info] Found 1 Cordova plugin for ios:
cordova-plugin-purchase#13.0.3
I've tried to make the simplest test I could just to see what's going on:
import 'cordova-plugin-purchase'; // This seems to add `CdvPurchase` to the global scope.
function buy() {
const {store, ProductType, Platform} = CdvPurchase;
store.verbosity = store.DEBUG;
store.register([{
type: ProductType.CONSUMABLE,
id: "my-product-id",
platform: Platform.APPLE_APPSTORE,
}]);
store.error(e => {
console.log('error', e);
});
store.when()
.productUpdated(() => {
console.log('product updated', product);
})
.approved(value => {
console.log('approved', value);
})
.verified(value => {
console.log('verified', value);
})
.finished(value => {
console.log('finished', value);
});
store.ready(() => {
console.log('ready', store.products);
store.order('my-product-id');
});
store.initialize(Platform.APPLE_APPSTORE)
.then(() => {
console.log('initialize resolved', store.products);
store.order('my-product-id');
});
}
But I run the buy function, all I get is:
[log] - [CordovaPurchase] INFO: initialize()
The store never reports as ready. None of the listeners are triggered, not even .error().
Have I missed something? How do I debug this?

Related

How auto update my electron app with electron-forge + electron-release-server?

How i can update my app using electron-forge with electron-release-server?
I deployed the implementation server and uploaded two assemblies .exe and.nupkg to it
and I'm trying to get these updates in the application according to the documentation
const url = `${server}download/latest`
autoUpdater.setFeedURL({ url })
setInterval(() => {
autoUpdater.checkForUpdates()
}, 10000)
autoUpdater.on('update-downloaded', (event, releaseNotes, releaseName) => {
const dialogOpts = {
type: 'info',
buttons: ['Restart', 'Later'],
title: 'Application Update',
message: process.platform === 'win32' ? releaseNotes : releaseName,
detail:
'A new version has been downloaded. Restart the application to apply the updates.',
}
dialog.showMessageBox(dialogOpts).then((returnValue) => {
if (returnValue.response === 0) autoUpdater.quitAndInstall()
})
})
but in development i get error:
There was a problem updating the application Error: Can not find
Squirrel
If I understood correctly I can't use checkForUpdates() in development
but in production build the update doesn't work either

launching Theia based electron app (artifact/package) isn't working

Almost new in using playwright. Exploring the things and checking what we can do with this tool.
I am trying to launch our Theia based electon app in Ubuntu 18.04 with below source.
const { _electron: electron } = require('playwright');
//const { _electron } = require('playwright');
//import { test, expect, Page } from '#playwright/test';
(async () => {
// Launch Electron app.
const electronApp = await electron.launch('./my_executable_file_path');
//this executable is an artifact/packgae
})();
test.describe('New Todo', () => {
test('should allow me to add todo items', async ({ page }) => {
//let's not do anything before the app launch.
});
});
In my package.json file, i have this already
"devDependencies": {
"#playwright/test": "^1.20.2",
I can successfully run test cases based on the browser but not able to launch the electron app.
electron.launch: Cannot find module 'electron/index.js'
We don't have this index.js in our jenkins generated artifact.
This is how I launched electron successfully
const electronApp = await _electron.launch({
args: ['theia-electron-main.js'],
cwd: 'cube-electron/apps/studio/electron/scripts'
});

cordova-plugin-purchase on iOS: order() does not work without uninstalling the app first

We are developing an application that uses Ionic (Angular) and Capacitor together with cordova-plugin-purchase to offer subscriptions (monthly and yearly). Purchases work perfectly on Android. However, on iOS, while the first purchase works fine, after that purchase expires (via cancelling the subscription, since it is actually automatically renewing) and the user purchases any product again (now on valid status since it expired already), calling the order() function does not do anything. The product status remains valid, no logs are written in the JavaScript console, nor Xcode. No errors, too. We have verified that our verification servers are returning correct responses. However, when we uninstall the app and install it from Xcode again, purchases start working again, and calling the order() function does show the purchase dialog again, and things work as expected. Until the subscription expires and they try to purchase again.
However, if the product is not yet expired, and the user tries to change subscription by subscribing to another subscription type, calling the order() function works as expected. It is only when a subscription expires, and then it starts to not work until the application is deleted/uninstalled and then installed again.
We implement the purchase using pretty standard code--we tried as minimal as possible to make it simple.
Initialization:
this.store.validator = 'https://xxxxxxx/api/app/purchased';
this.store.register([
{
type: this.store.PAID_SUBSCRIPTION,
id: this.YEARLY_SUBSCRIPTION
},
{
type: this.store.PAID_SUBSCRIPTION,
id: this.MONTHLY_SUBSCRIPTION
}
]);
this.subscriptions.add(
this.status.userData.subscribe(ud => {
this.user = ud;
this.store.applicationUsername = ud.id.toString(10);
})
);
this.store.when(this.YEARLY_SUBSCRIPTION)
.cancelled(this.purchaseCancelled)
.updated(this.purchaseYearlyUpdated)
.approved(this.purchaseApproved)
.verified(this.purchaseVerified)
.owned(this.purchaseOwned);
this.store.when(this.MONTHLY_SUBSCRIPTION)
.cancelled(this.purchaseCancelled)
.updated(this.purchaseMonthlyUpdated)
.approved(this.purchaseApproved)
.verified(this.purchaseVerified)
.owned(this.purchaseOwned);
this.store.error(this.handleError);
this.store.autoFinishTransactions = true;
this.store.refresh();
Other functions:
purchaseCancelled = (p: IAPProduct) => {
console.log(`${ p.id } cancelled`);
}
purchaseYearlyUpdated = (p: IAPProduct) => {
console.log(`${ p.id } updated`);
this.yearlyProduct = p;
this.changeDetectorRef.detectChanges();
}
purchaseMonthlyUpdated = (p: IAPProduct) => {
console.log(`${ p.id } updated`);
this.monthlyProduct = p;
this.changeDetectorRef.detectChanges();
}
purchaseApproved = (p: IAPProduct) => {
console.log(`${ p.id } approved`);
p.verify();
}
purchaseVerified = (p: IAPProduct) => {
console.log(`${ p.id } verified`);
p.finish();
}
purchaseOwned = (p: IAPProduct) => {
console.log(`${ p.id } owned`);
}
handleError = (error) => {
console.log('Error event:', error);
}
purchase(id: string) {
this.store.order(id);
}
ngOnDestroy() {
this.subscriptions.unsubscribe();
this.store.off(this.purchaseCancelled);
this.store.off(this.purchaseYearlyUpdated);
this.store.off(this.purchaseMonthlyUpdated);
this.store.off(this.purchaseApproved);
this.store.off(this.purchaseVerified);
this.store.off(this.purchaseOwned);
this.store.off(this.handleError);
}
Steps to reproduce:
Install the app from Xcode.
Purchase a product (user clicks the purchase button, that button triggers store.order)
Exit app
Cancel subscription so it expires
Subscription expires
Open app, and confirm that subscription is indeed expired (status goes from approved to valid)
Try to purchase subscription again by clicking the purchase button (any subscription)
Nothing happens. No logs. No errors. Product status remains valid.
Closing the app and then running again does not help.
Uninstall app
Install app again from Xcode
Purchase works again
I can't see anything wrong with the code, and since it's working perfectly fine on Android, we're guessing that it might be something wrong with the phone or maybe the cordova-plugin-purchase plugin.
I would really appreciate any suggestions, ideas, opinions, anything. Thank you very much in advance. I'm getting quite desperate.

DetoxRuntimeError: Detox instance has not been initialized

After updating to react-native 0.63.3 and xcode 12.0.1 the tests are not working anymore. First had some issues building detox but that was solved. Now this error is there and I cannot go further:
DetoxRuntimeError: Detox instance has not been initialized
HINT: Make sure to call detox.init() before your test begins
detox.init() is being called and I can see it in the logs.
This is my init.js
import { device } from 'detox';
const detox = require('detox');
const config = require('../package.json').detox;
const adapter = require('detox/runners/jest/adapter');
const specReporter = require('detox/runners/jest/specReporter');
const assignReporter = require('detox/runners/jest/assignReporter');
jest.setTimeout(180000);
jasmine.getEnv().addReporter(adapter);
jasmine.getEnv().addReporter(specReporter);
jasmine.getEnv().addReporter(assignReporter);
beforeAll(async () => {
await detox.init(config, { launchApp: false });
const permissions = {
notifications: 'NO',
camera: 'NO',
};
await device.launchApp({ permissions });
});
beforeEach(async () => {
await adapter.beforeEach();
});
afterAll(async () => {
await adapter.afterAll();
await detox.cleanup();
});
My environment:
React-Native: 0.63.3 Detox: 17.10.3 xcode: 12.0.1 iOS: 14.0
Running on ios.sim.debug
After long search I have found out that the actual tests are in a submodule/subrepo of the project. The tests are triggered from the app root level. Before the update even those tests were triggered correctly. Now, they only work if I move them to from the submodule level to the app root level

React Native: RNIap.getPurchaseHistory().then runs infinately

The project is at this Github Repository. The file with the code is at components/Soundboard.js
This code was working previously, but now it looks like the promise is running forever. It looks like neither the resolve function, nor the reject function are executing because if I uncomment all the commented lines below and call the function askForPurchase() the only things printed to the console are
an object that looks like "_40": 0, "_55": {"_40": 0, "_55": null, "_65": 0, "_72": null}, "_65": 3, "_72": null} for the line console.log(RNIap.getPurchaseHistory())
and then the word end.
The buyProduct() function also is no longer initializing an IAP.
const buyProduct = function(){
RNIap.requestPurchase("1985162691", false).then(purchase => {
store.dispatch(setPurchases(purchase))
await RNIap.finishTransaction(purchase, false) //developerPayloadAndroid?: string Should I use this argument? I don't get how to use it
}).catch((error) => {
console.log(error.message);
})
}
const askForPurchase = function(){
if (!store.getState().purchase){
//console.log(RNIap.getPurchaseHistory())
RNIap.getPurchaseHistory().then(purchase => {
//console.log(`test1`)
store.dispatch(setPurchases(purchase))
if (purchase.length == 0){
//console.log(`test if`)
buyProduct()
}else{
//console.log(`test else`)
RNIap.getAvailablePurchases()
}
}, reason => {
console.log(reason)
})
//console.log(`end`)
}
}
EXTRA
This code was working a few months ago and I even pulled a commit(1b9cb81f229680e173ce910892dddedc632c1651, comment: "Made the seal pic more cartoony") from that time to test out. After pulling this commit, I deleted my node_modules and pods, and cleaned my build folder, but the askForPurchase() and buyProduct() functions no longer work in that commit either.
I am testing this on a real iPhone SE running ios 13.6.1
I created a sandbox tester if you need to test it out, but I don't think you'll need it
email: rniapsandbox#gmail.com
pw: Somepassword1
hello #Sam problem is async await problem they are not able to get value because they are not waiting to get data before getting data its firing without data and it was returning promise so you have to use async function
so your code be like
const buyProduct = async()=>{
await RNIap.requestPurchase("1985162691", false).then(purchase => {
store.dispatch(setPurchases(purchase))
await RNIap.finishTransaction(purchase, false) //developerPayloadAndroid?: string Should I use this argument? I don't get how to use it
}).catch((error) => {
console.log(error.message);
})}
const askForPurchase = async()=>{
if (!store.getState().purchase){
//console.log(await RNIap.getPurchaseHistory())
await RNIap.getPurchaseHistory().then(purchase => {
//console.log(`test1`)
store.dispatch(setPurchases(purchase))
if (purchase.length == 0){
//console.log(`test if`)
buyProduct()
}else{
//console.log(`test else`)
RNIap.getAvailablePurchases()
}
}, reason => {
console.log(reason)
})
//console.log(`end`)
}}
You will need to change from
console.log(RNIap.getPurchaseHistory())
to
console.log(await RNIap.getPurchaseHistory())

Resources