restore problem in in-app purchase

ok here is my code

first i created buttons and their event listeners

 local inAppHelper = require "inAppPurchase" inAppHelper.initialize() -- METHOD DEFINED IN SECNOD CODE BLOCK local purchasebutton=display.newImage("Purchase.png") purchasebutton.x=200 purchasebutton.y=330 purchasebutton:scale(0.5,0.5) screenGroup:insert(purchasebutton) purchasebutton:addEventListener("tap", onBuyNowButtonClick) local restoreButton=display.newImage("Restore.png") restoreButton.x=200 restoreButton.y=200 restoreButton:scale(0.5,0.5) screenGroup:insert(restoreButton) restoreButton:addEventListener("tap", onRestoreButtonClick) function onBuyNowButtonClick() inAppHelper.loadProducts(transactionCompletionListener) end function onRestoreButtonClick() inAppHelper.restorePurchase() end

I have created a method “log” that simply shows the native alert, because i can not see print statements while running the app on device, so i call this method to debug.

function log(message) native.showAlert("", message) end

then in inAppPurchase.lua, 

-- TO INITIALIZE THE STORE function initialize() if ( store.availableStores.apple ) then currentProductList = appleProductList store.init( "apple", storeTransaction ) elseif ( store.availableStores.google ) then currentProductList = googleProductList store.init( "google", storeTransaction ) else log( "In-app purchases are not supported on this system/device." ) end end -- TO LOAD PRODUCTS function loadProducts(completionListener) listener = completionListener alert.showLoader("Retrieving Products...") if (store.canLoadProducts) then if ( store.availableStores.apple ) then log("going to load apple products list") store.loadProducts( appleProductList, loadProductsCallback ) end else if ( store.availableStores.google ) then alert.showLoader("Loading...") store.purchase( googleProductList ) else log( "this store does not support an app fetching products" ) listener(true) end end end --- AND THE CALL BACK IS local function loadProductsCallback( event ) alert.hideLoader() local validProducts = event.products local invalidProducts = event.invalidProducts for i = 1,#validProducts do local currentItem = validProducts[i] -- log("Title = ".. currentItem.title.."Description = "..currentItem.description.."Price = "..currentItem.price.."Product Identifier = "..currentItem.productIdentifier ) alert.showLoader("Loading...") store.purchase( validProducts ) -- SINCE I HAVE ONLY ONE PRODUCT.. DIRECTLY CALLING PURCHASE end end -- AND FINALLY THE TRANSACTION CALLBACK IS function storeTransaction( event ) alert.hideLoader() local transaction = event.transaction if ( transaction.state == "purchased" ) then log( " Transaction successfully completed" ) elseif ( transaction.state == "cancelled" ) then log( " Transaction was cancelled" ) elseif ( transaction.state == "restored" ) then log( " Transaction RESTORED SUCCESSFULLY" ) elseif ( transaction.state == "failed" ) then log( " Transaction was failed because: "..transaction.errorString ) elseif ( transaction.state == "refunded" ) then log( " Transaction REFUNDED" ) log( "productIdentifier", transaction.productIdentifier ) else log( "transaction state is: "..transaction.state ) end store.finishTransaction( event.transaction ) end -- RESTORE METHOD function restorePurchase() alert.showLoader("Restoring Products...") store.restore() end

Working on iOS for now:

As mentioned in the code, First I call initialize store, then I click buy, it first loads products, and after loading calls store.purchase, after giving my account credentials, i get the callback called and it displays native alert saying " Transaction successfully completed".

Then I click on restore button, which calls the method inAppHelper.restorePurchase(), it asks for account credentials, i enter them, but i get no native alert.
 

may be store.finishTransaction is not working properly. I’m using the daily build 2013.1193

Please let me know if i’m doing anything wrong in the code.

also can you please share with me the sample IAP code, i couldn’t find it yet.

Thanks,

Hi again!

Hm, it looks like the store.finishTransaction would be called…

The sample code I was refering to is included in the installation of CoronaSDK. (On a mac: CoronaSDK/SampleCode/Store/InAppPurchase)

This code works, but I would comment out all code in the transactionCallback were it says:

descriptionArea.text = infoString

That is because, if you get the scenario I described above the descriptionArea is not created at first init and will give you a runtime error. (And the store.finishTransaction will not run.)

By the way, have you created a InAppPurchase test user in iTunesConnect? If you use the the developer provisioning profile, i don’t think you can make a valid purchase on a real appleID.

yes I have created a test id on itunesconnect, and with that im able to make successfull purchase in sandbox environment.

I’d suggest not using native alerts for debugging.  Instead, use print statements and look at the output in the Xcode console log.  Here’s a blog post with instructions how to see it: http://www.coronalabs.com/blog/2013/07/09/tutorial-basic-debugging/.

In fact, the fact that you’re using native alerts for debugging may actually *be* the cause of the problem.  I’ve occasionally run into some funky behavior on iOS when using native alerts in quick succession.  Since only one native alert can be displayed at a time, trying to display more than one, or trying to display one too soon after a previous one was dismissed, can cause unexpected behavior.  This is especially important in the IAP flow, since the IAP flow itself uses native alerts generated by the OS to prompt for the user’s password and confirm the transaction.  I also notice that in your transaction callback, you call your log function twice, which attempts to display two native alerts immediately, which again, may be the source of the issue.

  • Andrew

@aukStudios

Thanks, I figured out the problem by checking the Xcode device logs, there was a line of code i was printing on successful purchase event, that is, 

log("productIdentifier = ".. transaction.productIdentifier.."receipt = "..transaction.receipt.."signature = "..transaction.signature.."transactionIdentifier= "..transaction.identifier.."Date = "..transaction.date)

and for some reason transaction.signature was nil, app was crashed at this point and hence store.finishTransaction didn’t get called. 
after crash, UI was still responsive, and I was trying to restore.

removing this lead to the successful purchase, and successful restore.

Thanks Again,

In Google play,If it is possible to test IAP restore using android.test.purchased.because already i quested about this.but the answer is in Google play return restore state as a purchased state but i tried usingandroid.test.purchased but no wonder.so if restore only work in live product id means i am going to buy one product and check.so please help me to give some suggestion.

For Google Play, restored transactions are always returned as “purchased” events (take a look at the Restored Purchased Items section of the documentation here: http://docs.coronalabs.com/guide/monetization/IAP/index.html).  That’s just the way Google Play works – there’s no way to change it.  So your code needs to handle this case appropriately.

  • Andrew