Closed b3nnee closed 7 years ago
Hey @b3nnee , your code seems correct, but you need to call the init
method in your app.js
before starting your application and not on the page where you have to use the purchases. Can you try to make this change and let me know if the problem resolves.
Hey Thanks Peter, I made the change and for the first time, the app did not crash. Will edit my code to ensure product details are delivered correctly and get back to you. Cheers!
UPDATE: Still getting a crash when I call purchase.restorePurchases().
It still gives me the same error as above. Maybe it could be my NativeScript version 2.3.0 that's the cause OR I am possibly doing something wrong...
restorePurchases() doesn't return anything - ergo the error.
restorePurchases() calls a callback on the on() method you registered.
Interesting, I actually figured that out but the error still remains. If getPurchases is called even without expecting anything in return I still get this:
java.lang.RuntimeException: Unable to start activity ComponentInfo{org.benditas.whodat/com.tns.NativeScriptActivity}: com.tns.NativeScriptException:
Calling js method onCreate failed
TypeError: Cannot read property 'getPurchases' of undefined
File: "/data/data/org.benditas.whodat/files/app/tns_modules/nativescript-purchase/purchase.js, line: 89, column: 26
StackTrace:
Frame: function:'restorePurchases', file:'/data/data/org.benditas.whodat/files/app/tns_modules/nativescript-purchase/purchase.js', line: 89, column: 27
Frame: function:'homePage.init', file:'/data/data/org.benditas.whodat/files/app/benmodel/home.js', line: 223, column: 19
Frame: function:'exports.init', file:'/data/data/org.benditas.whodat/files/app/main-page.js', line: 160, column: 11
Frame: function:'', file:'/data/data/org.benditas.whodat/files/app/app.js', line: 16, column: 14
Frame: function:'Observable.notify', file:'/data/data/org.benditas.whodat/files/app/tns_modules/data/observable/observable.js', line: 158, column: 23
In Home.js line line 218 - 236:
product = mypurchase.getProducts();
homePage.alerter("Products", product);
mypurchase.restorePurchases();
console.log("Purchase restored....");
if (mypurchase.canMakePayments()) {
// NOTE: 'product' must be the same instance as the one returned from getProducts()
//purchase.buyProduct(product);
homePage.alerter("YAY payments here", "Your account is eligible to make payments!");
} else {
homePage.alerter("No payments here", "Sorry, your account is not eligible to make payments!");
}
In the plugin's purchases.android.js code,
This is where the issue is:
function restorePurchases() {
futureToPromise(helper.getPurchases()) // <------ Issue is here, for some reason, helper is undefined!
.then(function (result) {
for (var loop = 0; loop < result.length; loop++) {
var tran = new transaction_1.Transaction(null);
tran.originalTransaction = new transaction_1.Transaction(result[loop]);
tran.transactionState = transaction_1.TransactionState.Restored;
common._notify(common.transactionUpdatedEvent, tran);
}
});
}
This is a console dump of the mypurchase variable in home.js:
=== dump(): dumping members ===
JS: {
JS: "transactionUpdatedEvent": "transactionUpdated",
JS: "_notify": "_notify()function _notify(eventName, data) {\n if (!observers[eventName]) {\n return;\n }\n observers[eventName].forEach(function (callback) { callback(data); });\n}",
JS: "on": "on()function on(eventName, handler) {\n if (!observers[eventName]) {\n observers[eventName] = [];\n }\n observers[eventName].push(handler);\n}",
JS: "off": "off()function off(eventName, handler) {\n if (!observers[eventName]) {\n return;\n }\n if (!handler) {\n observers[eventName].splice(0);\n return;\n }\n var index = observers[eventName].indexOf(handler);\n if (index !== -1) {\n observers[eventName].splice(index, 1);\n }\n}",
JS: "init": "init()function init(productIdentifiers) {\n var nativeArray = Array.create(java.lang.String, productIdentifiers.length);\n for (var loop = 0; loop < productIdentifiers.length; loop++) {\n nativeArray[loop] = productIdentifiers[loop].toLowerCase();\n }\n ensureApplicationContext().then(function () {\n helper = new com.tangrainc.inappbilling.InAppBillingHelper(application.android.context, nativeArray);\n });\n application.android.on(application.AndroidApplication.activityResultEvent, function (args) {\n if (args.requestCode === com.tangrainc.inappbilling.InAppBillingHelper.BUY_INTENT_REQUEST_CODE) {\n var intent = args.intent;\n var responseCode = intent.getIntExtra(\"RESPONSE_CODE\", 0);\n var purchaseData = intent.getStringExtra(\"INAPP_PURCHASE_DATA\");\n var dataSignature = intent.getStringExtra(\"INAPP_DATA_SIGNATURE\");\n var tran = void 0;\n if (args.resultCode === android.app.Activity.RESULT_OK && responseCode === 0 && !types.isNullOrUndefined(purchaseData)) {\n var nativeValue = new org.json.JSONObject(purchaseData);\n nativeValue.put(\"signature\", dataSignature);\n tran = new transaction_1.Transaction(nativeValue);\n }\n else {\n tran = new transaction_1.Transaction(null);\n tran.transactionState = transaction_1.TransactionState.Failed;\n tran.productIdentifier = currentBuyProductIdentifier;\n tran.developerPayload = currentBuyPayload;\n }\n common._notify(common.transactionUpdatedEvent, tran);\n }\n });\n}",
JS: "getProducts": "getProducts()function getProducts() {\n return new Promise(function (resolve, reject) {\n futureToPromise(helper.getProducts())\n .then(function (result) {\n var productArray = [];\n for (var loop = 0; loop < result.length; loop++) {\n productArray.push(new product_1.Product(result[loop]));\n }\n resolve(productArray);\n })\n .catch(reject);\n });\n}",
JS: "buyProduct": "buyProduct()function buyProduct(product, developerPayload) {\n var tran = new transaction_1.Transaction(null);\n tran.transactionState = transaction_1.TransactionState.Purchasing;\n tran.productIdentifier = product.productIdentifier;\n tran.developerPayload = developerPayload;\n common._notify(common.transactionUpdatedEvent, tran);\n currentBuyProductIdentifier = product.productIdentifier;\n currentBuyPayload = developerPayload;\n helper.startBuyIntent(application.android.foregroundActivity, product.productIdentifier, developerPayload || \"\");\n}",
JS: "consumePurchase": "consumePurchase()function consumePurchase(token) {\n return new Promise(function (resolve, reject) {\n futureToPromise(helper.consumePurchase(token)).then(resolve, reject);\n });\n}",
JS: "restorePurchases": "restorePurchases()function restorePurchases() {\n futureToPromise(helper.getPurchases())\n .then(function (result) {\n for (var loop = 0; loop < re
JS: sult.length; loop++) {\n var tran = new transaction_1.Transaction(null);\n tran.originalTransaction = new transaction_1.Transaction(result[loop]);\n tran.transactionState = transaction_1.TransactionState.Restored;\n common._notify(common.transactionUpdatedEvent, tran);\n }\n });\n}",
JS: "canMakePayments": "canMakePayments()function canMakePayments() {\n return true;\n}"
JS: }
JS: === dump(): dumping function and properties names ===
JS: _notify()
JS: on()
JS: off()
JS: init()
JS: getProducts()
JS: buyProduct()
JS: consumePurchase()
JS: restorePurchases()
JS: canMakePayments()
JS: === dump(): finished ===
The greatest help you could give now is simply ignore all what I have written here and create a sample of how to use your plugin via JS not typescript. If it works, I could use that as a guide to getting my code to work.
Thanks for your time, cheers!
Hey @b3nnee , the helper is initialized when you call init
so if you do that in the app.js
not sure how it can end up undefined. Since TS transpiles to JS, you can just clone this repo and run tns build android
in the sample dir. This will generate JS files from the TS ones and you can look in those.
OK, great will do that, thanks.
Hi,
Would really be nice to see a working javascript sample of how to use your plugin. I have tried porting your typescript code to js on {NS} 2.3.0 but I am not getting it right, always getting the error:
My references.d.ts looks like this:
In home js:
In Home.js I know var purchase is called right because I did a console.dump and got this: