Store.isActive replies with false

I have been adding In app purchases in my app and am having trouble getting it to work.

I call store.init() but it doesn’t activate the transactionCallback listener.

I’m running on Mac OSX 10.10.5 with Corona 2769. I have double checked my key in build.settings and its fine.

Does anybody have any ideas on why it wouldn’t work - I’ll post some code below.

local store = require( "plugin.google.iap.v3" )         local function transactionCallback( event )                      native.showAlert("Store active", "Store active", {"ok"});     -- Log transaction info.     print( "transactionCallback: Received event " .. tostring( event.name ) )     print( "state: " .. tostring( event.transaction.state ) )     print( "errorType: " .. tostring( event.transaction.errorType ) )     print( "errorString: " .. tostring( event.transaction.errorString ) )     if event.transaction.state == "purchased" then         --storeUI.printToConsole( "Transaction successful!" )         print( "receipt: " .. tostring( event.transaction.receipt ) )         print( "signature: " .. tostring( event.transaction.signature ) )     elseif  event.transaction.state == "restored" then         -- Reminder: your app must store this information somewhere         -- Here we just display some of it         --storeUI.printToConsole( "Restoring transaction:" ..         --                        "\n   Original ID: " .. tostring( event.transaction.originalTransactionIdentifier ) ..         --                        "\n   Original date: " .. tostring( event.transaction.originalDate ) )         print( "productIdentifier: " .. tostring( event.transaction.productIdentifier ) )         print( "receipt: " .. tostring( event.transaction.receipt ) )         print( "transactionIdentifier: " .. tostring( event.transaction.transactionIdentifier ) )         print( "date: " .. tostring( event.transaction.date ) )         print( "originalReceipt: " .. tostring( event.transaction.originalReceipt ) )     elseif event.transaction.state == "consumed"  then         -- Consume notifications is only supported by the Google Android Marketplace.         -- Apple's app store does not support this.         -- This is your opportunity to note that this object is available for purchase again.         --storeUI.printToConsole( "Consuming transaction:" ..         --                        "\n   Original ID: " .. tostring( event.transaction.originalTransactionIdentifier ) ..         --                        "\n   Original date: " .. tostring( event.transaction.originalDate ) )         print( "productIdentifier: " .. tostring( event.transaction.productIdentifier ) )         print( "receipt: " .. tostring( event.transaction.receipt ) )         print( "transactionIdentifier: " .. tostring( event.transaction.transactionIdentifier ) )         print( "date: " .. tostring( event.transaction.date ) )         print( "originalReceipt: " .. tostring( event.transaction.originalReceipt ) )     elseif  event.transaction.state == "refunded" then         -- Refunds notifications is only supported by the Google Android Marketplace.         -- Apple's app store does not support this.         -- This is your opportunity to remove the refunded feature/product if you want.         --storeUI.printToConsole( "A previously purchased product was refunded by the store:" ..         --                        "\n       For product ID = " .. tostring( event.transaction.productIdentifier ) )     elseif event.transaction.state == "cancelled" then         --storeUI.printToConsole( "Transaction cancelled by user." )     elseif event.transaction.state == "failed" then                 --storeUI.printToConsole( "Transaction failed, type: " ..         --    tostring( event.transaction.errorType ) .. " " .. tostring( event.transaction.errorString ) )     else         --storeUI.printToConsole( "Unknown event" )     end     -- Tell the store we are done with the transaction.     -- If you are providing downloadable content, do not call this until     -- the download has completed.     --store.finishTransaction( event.transaction )     -- Tell the user to select another option now that this transaction has finished     --timer.performWithDelay( 2000, storeUI.printOptionPrompt ) end             store.init("google", transactionCallback) if store.canLoadProducts and store.isActive then end

Hi @MatthewCharlesHarrop,

I assume you’re testing on a device, not the Mac itself? Because of course IAP doesn’t work in the Simulator. Anyway, does the device have the Google Play app installed? You may want to try omitting the “google” argument from init() as shown here:

https://docs.coronalabs.com/plugin/google-iap-v3/init.html

Brent

Hi Brent, thanks for your reply!

So I’ve double checked our device (Sorry, i should have made the clear. Also, if it helps, the device we’re testing on is a Nexus 7) and it has google play (I’m assuming this is Google play store? - Please correct me if I’m wrong though)

I removed the “google” part of store.init() and that didn’t help, however I added some notifications to help me debug and they returned store.canLoadProducts() is true but store.isActive() is false.

What is weird is that It doesn’t display the alert within the “transactionCallback” listener but still returns store.canLoadProducts() as true. Any ideas?

Could you print out a copy your build.settings file to double check the settings?

Simon

Build.Settings: -- Supported values for orientation: -- portrait, portraitUpsideDown, landscapeLeft, landscapeRight -- $Id: build.settings,v 1.4 2014/10/16 16:35:47 root Exp $ settings = { orientation = { default = "landscapeRight", supported = { "landscapeRight", "landscapeLeft", }, }, plugins = { --["plugin.openssl"] = { publisherId = "com.coronalabs", }, -- ["plugin.zip"] = -- { -- publisherId = "com.coronalabs" -- }, ["CoronaProvider.native.popup.quickLook"] = { publisherId = "com.coronalabs", supportedPlatforms = { iphone = true }, }, ["plugin.notifications"] = { publisherId = "com.coronalabs" }, ["plugin.google.iap.v3"] = { publisherId = "com.coronalabs", supportedPlatforms = { android=true }, }, ["plugin.zip"] = { publisherId = "com.coronalabs" }, }, iphone = { plist = { UIStatusBarHidden = false, UIPrerenderedIcon = true, -- set to false for "shine" overlay --UIApplicationExitsOnSuspend = true, -- uncomment to quit app on suspend --[[-- iOS app URL schemes: CFBundleURLTypes = { { CFBundleURLSchemes = { "fbXXXXXXXXXXXXXX", -- example scheme for facebook "coronasdkapp", -- example second scheme } } } --]] } }, -- Android permissions androidPermissions = { "android.permission.INTERNET", "android.permission.ACCESS\_NETWORK\_STATE", "android.permission.READ\_PHONE\_STATE", "android.permission.ACCESS\_FINE\_LOCATION", "android.permission.CAMERA", "android.permission.WRITE\_EXTERNAL\_STORAGE", "android.permission.CALL\_PHONE", "com.android.vending.BILLING", "com.android.vending.CHECK\_LICENSE", }, usesFeatures = { -- If you set permissions "ACCESS\_FINE\_LOCATION" and "ACCESS\_COARSE\_LOCATION" above, -- then you may want to set up your app to not require location services as follows. -- Otherwise, devices that do not have location sevices (such as a GPS) will be unable -- to purchase this app in the app store. { name = "android.hardware.location", required = false }, { name = "android.hardware.location.gps", required = false }, { name = "android.hardware.location.network", required = false }, }, }

--$Id: config.lua,v 1.2 2014/10/05 16:53:25 root Exp $ application = { content = { graphicsCompatibility = 1, --iPad: width = 768, height = 1024, --iPhone: --width = 320, --height=480, scale = "letterBox", fps = 30, --[[imageSuffix = { ["@2x"] = 2, } --]] }, Licence = { google = { key = "The worlds longest key..." -- I took my key out and substituted it. } }, --[[-- Push notifications notification = { iphone = { types = { "badge", "sound", "alert", "newsstand" } } } --]] settings = { iphone = { plist = { CFBundleIconFile = "Icon.png", CFBundleIconFiles = { "Icon.png", "Icon@2x.png", "Icon-Small-40.png", "Icon-Small-40@2x.png", "Icon-60.png", "Icon-60@2x.png", "Icon-72.png", "Icon-72@2x.png", "Icon-76.png", "Icon-76@2x.png", "Icon-Small-50.png", "Icon-Small-50@2x.png", "Icon-Small.png", "Icon-Small@2x.png" }, }, } } }

I’ve included my config.lua just in case :slight_smile:

Am I correct in that you wrote “Licence” in the config? That’s not spelled correctly and no doubt that’s the problem. See the proper code example here:

https://docs.coronalabs.com/plugin/google-iap-v3/index.html

Brent

Hi Brent,

Thanks for pointing that out (English Vs American there, the war continues :stuck_out_tongue: )

I changed that and it had no effect, store.isActive still replies with false and store.init() still fails to call the transactionCallback

Hi @MatthewCharlesHarrop,

I don’t believe the transaction listener expected to trigger on store.init(), but rather just on other purchase-related events. Have you (in the past) seen different behavior on that point?

Brent

Hi again,

A couple of thoughts:

  • Can you successfully download others apps from Google Play on your Nexus device? (to eliminate the chance there’s a problem with the device setup)
  • Does a store.purchase function call work, even though Corona’s returning false for store.isActive?

Hi Brent,

No, one of the problems I’m currently facing, with regards to this, is my low level of knowledge (This is the first time I’ve added In-App Purchases)

Its more that the .isActive() returns with false on both the Nexus 7 Tablet and My Motorola Android phone.

Hi Simon,

Yes, I have downloaded several (Turbo dismount for example)

store.purchase doesn’t work because store.loadProducts doesn’t activate its callback listener either (It fails to return any products at all…)

UPDATE: I decided that I would go back to the very beginning. I created a basic app through corona, copied in the monetisation sample code config.lua and build.settings files (with the appropriate key) and built it. It returns the same results…

Hi Matthew,

I’ve just noticed that you are an Enterprise user, and all of my experience is with the standard Corona setup.

I’m just wondering if there are any additional steps you have to go through on Enterprise to get Google IAP v3 running correctly?

Someone else may be able to advise you better with this, but could it be something to do with including all the correct JAR libraries or the entries in your AndroidManifest.xml file?

Hi Matthew,

Following up on happymongoose’s suggestions regarding Enterprise, there are a few additional steps to get Google IAP v3 working with Enterprise:

  1. Ensure that plugin.google.iap.v3.jar is in your project’s libs folder.

  2. Ensure the BILLING permission is added to your AndroidManifest.xml as such:

    … <uses-sdk android:minSdkVersion=“10” android:targetSdkVersion=“21”/> <!-- Permissions required for Google IAP v3. --> <uses-permission android:name=“com.android.vending.BILLING” /> <uses-permission android:name=“android.permission.INTERNET”/> <uses-feature android:glEsVersion=“0x00020000”/> …

Assuming the issue isn’t with setup, can you provide the adb logcat output of your app starting at the point where you call store.init() and including immediately after store.isActive()?

As a side note, build.settings is ignored in Corona Enterprise for Android, so you’ll also need to transfer the androidPermissions lua table to AndroidManifest.xml as shown above.

Kinda late to this thread, but after scanning it…  store.init() itself does not call the call back listener. The call back listener won’t fire until there is a purchase or restore request.  Are we assuming you’re calling store.purchase()? In the top post, you say .init() doesn’t call it.

I just want to make sure we are not overlooking the obvious…

Rob

Hi All, thanks for your replies, I really appreciate your help :slight_smile:

I don’t use the enterprise version just SDK :slight_smile:

Ok, so now it seems to be working…

store.isActive returns true and I can request a list of products (They all display as invalid mind)
 

 local store = require( "plugin.google.iap.v3" ) local function listener(event) local totalCounter = 1; local prodText = {} local invalidProd = {} native.showAlert("Products", #event.products, {"Ok"}); for i = 1, #event.products do prodText[i] = display.newText(event.products[i].title, 100, 100 + (50 \*i), native.systemFont); prodText[i]:setFillColor(255, 255, 255); end native.showAlert("Invalid Products", #event.invalidProducts, {"Ok"}); for i = 1, #event.invalidProducts do invalidProd[i] = display.newText(event.invalidProducts[i], 200, 100 + (50 \*i), native.systemFont); invalidProd[i]:setFillColor(255, 255, 255); end end local function callBack(event) native.showAlert("init Call Back", "Init call back", {"Ok"}) end local productList = {"productOne"} store.init(callBack) --native.showAlert("store.canLoadProducts", tostring(store.canLoadProducts), {"Ok"}) --native.showAlert("store.isActive", tostring(store.isActive), {"Ok"}) store.loadProducts( productList, listener )

I’m not really sure whats changed, if somebody could enlighten me, I would be incredibly grateful - I hate not knowing why something didn’t work and now does.

I just want to post this here for future reference (Incase I forget/somebody else has that same problem I did)

If you do what I did (Which was make a small test program to test your in-app purchases) you must make sure the package IDs are the same, when building (For android of course), as the ID you’ve uploaded to the store.

Further, the product ID Numbers should also match the build ID (i.e. com.companyname.product should match com.companyname.app - its the com.companyname that’s important)

Hi @MatthewCharlesHarrop,

I assume you’re testing on a device, not the Mac itself? Because of course IAP doesn’t work in the Simulator. Anyway, does the device have the Google Play app installed? You may want to try omitting the “google” argument from init() as shown here:

https://docs.coronalabs.com/plugin/google-iap-v3/init.html

Brent

Hi Brent, thanks for your reply!

So I’ve double checked our device (Sorry, i should have made the clear. Also, if it helps, the device we’re testing on is a Nexus 7) and it has google play (I’m assuming this is Google play store? - Please correct me if I’m wrong though)

I removed the “google” part of store.init() and that didn’t help, however I added some notifications to help me debug and they returned store.canLoadProducts() is true but store.isActive() is false.

What is weird is that It doesn’t display the alert within the “transactionCallback” listener but still returns store.canLoadProducts() as true. Any ideas?

Could you print out a copy your build.settings file to double check the settings?

Simon

Build.Settings: -- Supported values for orientation: -- portrait, portraitUpsideDown, landscapeLeft, landscapeRight -- $Id: build.settings,v 1.4 2014/10/16 16:35:47 root Exp $ settings = { orientation = { default = "landscapeRight", supported = { "landscapeRight", "landscapeLeft", }, }, plugins = { --["plugin.openssl"] = { publisherId = "com.coronalabs", }, -- ["plugin.zip"] = -- { -- publisherId = "com.coronalabs" -- }, ["CoronaProvider.native.popup.quickLook"] = { publisherId = "com.coronalabs", supportedPlatforms = { iphone = true }, }, ["plugin.notifications"] = { publisherId = "com.coronalabs" }, ["plugin.google.iap.v3"] = { publisherId = "com.coronalabs", supportedPlatforms = { android=true }, }, ["plugin.zip"] = { publisherId = "com.coronalabs" }, }, iphone = { plist = { UIStatusBarHidden = false, UIPrerenderedIcon = true, -- set to false for "shine" overlay --UIApplicationExitsOnSuspend = true, -- uncomment to quit app on suspend --[[-- iOS app URL schemes: CFBundleURLTypes = { { CFBundleURLSchemes = { "fbXXXXXXXXXXXXXX", -- example scheme for facebook "coronasdkapp", -- example second scheme } } } --]] } }, -- Android permissions androidPermissions = { "android.permission.INTERNET", "android.permission.ACCESS\_NETWORK\_STATE", "android.permission.READ\_PHONE\_STATE", "android.permission.ACCESS\_FINE\_LOCATION", "android.permission.CAMERA", "android.permission.WRITE\_EXTERNAL\_STORAGE", "android.permission.CALL\_PHONE", "com.android.vending.BILLING", "com.android.vending.CHECK\_LICENSE", }, usesFeatures = { -- If you set permissions "ACCESS\_FINE\_LOCATION" and "ACCESS\_COARSE\_LOCATION" above, -- then you may want to set up your app to not require location services as follows. -- Otherwise, devices that do not have location sevices (such as a GPS) will be unable -- to purchase this app in the app store. { name = "android.hardware.location", required = false }, { name = "android.hardware.location.gps", required = false }, { name = "android.hardware.location.network", required = false }, }, }

--$Id: config.lua,v 1.2 2014/10/05 16:53:25 root Exp $ application = { content = { graphicsCompatibility = 1, --iPad: width = 768, height = 1024, --iPhone: --width = 320, --height=480, scale = "letterBox", fps = 30, --[[imageSuffix = { ["@2x"] = 2, } --]] }, Licence = { google = { key = "The worlds longest key..." -- I took my key out and substituted it. } }, --[[-- Push notifications notification = { iphone = { types = { "badge", "sound", "alert", "newsstand" } } } --]] settings = { iphone = { plist = { CFBundleIconFile = "Icon.png", CFBundleIconFiles = { "Icon.png", "Icon@2x.png", "Icon-Small-40.png", "Icon-Small-40@2x.png", "Icon-60.png", "Icon-60@2x.png", "Icon-72.png", "Icon-72@2x.png", "Icon-76.png", "Icon-76@2x.png", "Icon-Small-50.png", "Icon-Small-50@2x.png", "Icon-Small.png", "Icon-Small@2x.png" }, }, } } }

I’ve included my config.lua just in case :slight_smile:

Am I correct in that you wrote “Licence” in the config? That’s not spelled correctly and no doubt that’s the problem. See the proper code example here:

https://docs.coronalabs.com/plugin/google-iap-v3/index.html

Brent