Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

Question: store.init() iOS
Started by d.mach Jun 27 2018 01:14 AM

7 replies to this topic
store init store.init ios inapp iap
[TOPIC CONTROLS]
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

d.mach

[GLOBAL: userInfoPane.html]
d.mach
  • Contributor

  • 644 posts
  • Corona SDK

I wonder if it can cause problems when calling the store.init() more than once on iOS?

 

And more in detail if I can do this:

I have a global listener... something like _G. transListener and then call a store.init(_G.transListener) in main.lua

Now I wonder how to handle things from here on when the following was called: store.finishTransaction( event.transaction )

 

Do I have to init the store again by using store.init(_G.transListener) now or can I still make calls like store.purchase(product) or store.restore() ?

What when I get store.isActive() ==false... do I have to init the store then again?

 

 

 

 



[TOPIC: post.html]
#2

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Moderator

  • 24,578 posts
  • Corona Staff

You should only initialize the store once. You only need one listener function. I recommend calling store.finishTransaction() in the listener before your code ever leaves that listener function. It's the logical place to do so since you are finished with that transaction. What you do internally (unlocking things, adding coins, etc.) has nothing to do with being done with the store transaction and calling store.finishTransaction() should not generate another transaction event.

 

To use other store.* API's in other modules, just simply require the store module and then you can call things like store.purchase() at times where it makes sense in your code.

 

You should only get store.isActive() returning false if you have not yet initialized the store, but if you do that in main.lua, it should be active, unless the user suspends your app, goes into settings and disables store purchases and then resumes your app. If that's the case, initializing the store again won't change the user's choice. It will still be inactive.

 

Rob



[TOPIC: post.html]
#3

d.mach

[GLOBAL: userInfoPane.html]
d.mach
  • Contributor

  • 644 posts
  • Corona SDK

Thanks for the info.

One more thing: Is there a difference in purchasing on an iPhoneX compared to other devices? We get some player feedback they are purchasing but the game is not unlocking content even when they try to purchase again and got told they already have purchased this product. But it seems the code in the transaction listener handling the purchase or restore state was not called before! And when asking it appears to be a problem happening on iPhoneX.

 

UPDATE:

 

It seems the store.purchase is called but there is some different handling on iPhoneX. The Android version also is working fine without any problems.

Here are some more details on how I call the purchase:

 

I have a table with the products like:

products ={"product1","product2","product3"}

then I do this:

_G.purchaseAProduct = function (product)
    
    if  store.isActive and store.canMakePurchases then
        
            store.purchase(product) -- purchasing the first product in the products list
            
    else

       ---

    end
end

I do the purchasing by calling

_G.purchaseAProduct (products[1])

... but somehow not getting into the "purchase" or "restored" state of the listener.



[TOPIC: post.html]
#4

d.mach

[GLOBAL: userInfoPane.html]
d.mach
  • Contributor

  • 644 posts
  • Corona SDK

One more thing: Players seem to have used touchID... is it possible this is handled differently?



[TOPIC: post.html]
#5

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Moderator

  • 24,578 posts
  • Corona Staff

It shouldn't, but that doesn't mean that it doesn't. Is this being reported by production purchases or test purchases? Can you reproduce it?

 

Can you make a test flight build? Maybe get some testing on it?

 

 

Rob



[TOPIC: post.html]
#6

d.mach

[GLOBAL: userInfoPane.html]
d.mach
  • Contributor

  • 644 posts
  • Corona SDK

Thank you Rob.

 

I have one more question (which probably can cause the problems)...

local store = require( "store" )

local json = require( "json" )


-- Transaction listener function
local function transactionListener( event )



    if not ( event.transaction.state == "failed" ) then  -- Successful transaction
        print( json.prettify( event ) )
        print( "event.transaction: " .. json.prettify( event.transaction ) )



                  if event.transaction.state == "purchased" or event.transaction.state == "restored" then



                        ERROR HERE IN CODE!!!



                  end



    else  -- Unsuccessful transaction; output error details
        print( event.transaction.errorType )
        print( event.transaction.errorString )
    end


    -- Tell the store that the transaction is finished
    store.finishTransaction( event.transaction )
end


-- Initialize Apple IAP
store.init( transactionListener )

I normally change a scene when the transaction is finished with store.finishTransaction (event.transaction) BUT this seems not to work with players who encounter the problem. I unlock some game content after the check of event.transaction.state == "purchased" ...

so my question (see code above): What happens when an error is appearing after event.transaction.state == "purchased" was checked true and then in the code right before I handle the unlocking of game content an ERROR is happening (Runtime Error).

This could be exactly the problem here, right!? Then all called purchases or restore calls would go right into the event.transaction.state == "purchased" (or restored) but never would get to the store.finishTransaction (event.transaction) part, right?



[TOPIC: post.html]
#7

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Moderator

  • 24,578 posts
  • Corona Staff

I think you're really overcomplicating your logic here. Your current logic will have a "canceled" state actually get into your purchased code.  It's best to have a linear if-then-elseif-end block to cover each state.

local function storeTransactionListener( event )
	print( json.prettify( event ))

	local transaction = event.transaction

	if ( transaction.state == "purchased" ) then
	    store.finishTransaction( event.transaction )
		-- do the work you need to do

	elseif ( transaction.state == "restored" ) then
            store.finishTransaction( event.transaction )
		-- do the work you need to do

	elseif ( transaction.state == "cancelled" ) then

	elseif ( transaction.state == "failed" ) then

	end
end

If you get runtime errors in any of the if-then-elseif blocks then the rest of that block will not execute, so it's safer to finish the transaction as soon as you can. The IAP servers have no clue about what you're doing in your code, so there isn't much of a reason to wait around until you complete your unlock code before you let Apple know you're done.

 

Also, be careful using concatenation when printing debug messages:  

print( "event.transaction: " .. json.prettify( event.transaction ) )

Instead, do

print( "event.transaction: ", json.prettify( event.transaction ) )

If for some reason json.prettify() were to return nil, it would cause a runtime error, the second form will not crash.

 

Rob



[TOPIC: post.html]
#8

d.mach

[GLOBAL: userInfoPane.html]
d.mach
  • Contributor

  • 644 posts
  • Corona SDK

Thank you for your detailed help!




[topic_controls]
[/topic_controls]

Also tagged with one or more of these keywords: store, init, store.init, ios, inapp, iap