In-app purchase tutorial

CT is correct, you cannot interact with the UI in the callback from RequestProductsWithCompletionHandler because it is not called on a Xojo thread. Sometimes it will work, but as you have seen, sometimes it will crash with a stack overflow exception (these happen when Xojo code is called on unmanaged threads). To fix this, you can do as CT did and save everything then process later. One thing to note, is you should check that success is true in the callback, otherwise do not update everything since the value passed back will be invalid.

@Jason King & @Ryan Hartz
Using Xojo 2019r3 I am stuck with a stackoverflow exception in SKProductsRequest.impl_didReceiveResponse

I tried calling InAppPurchaseHelpeter.RequestProductsWithCompletionHandler from a different thread and from a timer but it still crashes. Any ideas to fix this?

EDIT:
Exception stack:

[quote]RuntimeRaiseException
rbframework.dylib$4085
RuntimeStackCheck
StoreKit.SKProductsRequest.!impl_requestDidFinish%%ppp
__27-[SKProductsRequest _start]_block_invoke_2
_dispatch_call_block_and_release
_dispatch_client_callout
_dispatch_root_queue_drain
_dispatch_worker_thread2
_pthread_wqthread[/quote]

I noticed a crash on the physical device a while ago when CT posted about it. This was also running 2019r3 (no crash in Simulator). Yet, there was no crash (Simulator or device) when built in 2019r2.

I haven’t had any time to work on this lately. Maybe @Jason King has an idea. In the next month or so, I will hopefully be working more on another IAP project for the market, and I think you posted recently that starting in June, we’ll need to use 2019r3.1 and later for the latest SDK, so this device crash is a deal breaker

Starting in June, Xojo 2019r3.1 is mandatory for any iOS app update
Starting yesterday (a few weeks/months ago), Xojo 2019r3.1 is mandatory for new iOS app releases. I am now stuck with a new app that can’t be published on the App Store

Well this isn’t what I wanted to see today :slight_smile:

Looks like that delegate is now being invoked from a background thread. You can try two approaches to fix it:

  1. Add #pragmas to disable the background checking by the framework

#Pragma StackOverflowChecking #Pragma DisableBackgroundTasks

  1. Create a CompletionHandler/Watcher implementation I did for some AVFoundation classes where a timer checks to see if the transaction is complete: https://github.com/kingj5/iOSKit/blob/master/Modules/AVFoundation/AVCaptureStillImageOutput.xojo_code

Unfortunately I do not have the time to look into this, but one or both of those approaches should fix the problem.

Thanks Jason for your prompt response and workaround.

It actually doesn’t sound as bad as it seems. I commented out the call to InAppPurchaseHelpeter.RequestProductsWithCompletionHandler when in DebugBuild and tested on a real device and it works.

I will do some further testing with your suggestions.

I have tried several things mentioned in this thread but none of them with success.

Jeremie, I tried your approach with commenting it out in the simulator but not on the actual device. Somehow the app doesn’t find any product. Adding #pragmas didn’t work either.vIf I don’t do anything it’s the stack overflow message.

Does anybody have a good solution for this? Thank you!

General questions on the testing procedures for in-app purchases.

  1. I have set up the in-app purchase in AppStore Connect and saved it with a screenshot. I have not yet submitted it for review because I have no finished app build to submit for review. Is this enough for sandbox testing?
  2. To test the in-app purchase, I copied the ipa-file to the device via Xcode. Is this the right way to test or do I have to upload the build to AppStore Connect and test it through TestFlight?

Thank you!

I’m coming back to this thread because I haven’t been able to solve the problem yet. I don’t understand two things about the “LoadProduct” method:

  1. Is this method even called? I’m having a breakpoint in that method and it never breaks there.

  2. This is the code of the “LoadProduct”, so if it’s called I don’t know how the code in the for-next loop will ever be run because products.Count is always 0. The only place where products.Append is being called is within that loop.

Using StoreKit
Using Foundation

Dim prod As SKProduct

For i as Integer = 0 to products.Count-1
prod = new SKProduct(products.Value(i))

lblProduct.Text = prod.localizedTitle
lblPrice.Text = “One-time purchase of $” + prod.price.ToText(Locale.Current, “##0.00”) + “!”
lblDescription.Text = prod.localizedDescription

self.products.Append prod
Next i

Just trying to follow the Tutorial.

ActivatePremium is set to True when purchase is made but what happens the next time the App is run? Where is purchase saved to?

You need to save it. NSUserDefaults is what I have used for this in the past

As far as I understand Ryan’s sample IAP project, the purchase is being saved to NSUserDefaults with the help of Jason’s StoreKit InAppPurchaseHelper. When you open the App later, the View1’s open method reads the info from there. I could be wrong though because I haven’t got anything to work with regards to In-App Purchase. If you are more successful, I’d appreciate any help. Thank you!

Hi Jason,
Thanks I see the NSUserDefaults.

There seems to be an issue with a StackOverFlow error happening in the example what could be causing that? Checking further it works on ios12.4 but not on ios13+

Private Shared Sub impl_didReceiveResponse(pid as ptr, sel as ptr, request as ptr, response as ptr)
const CurrentMethodName = “StoreKit.SKProductsRequest.impl_didReceiveResponse”
dim w as xojo.Core.WeakRef = xojo.core.WeakRef(dispatch.Value(pid))
if w.Value <> nil Then
SKProductsRequest(w.Value).HandleDidReceiveResponse(new StoreKit.SKProductsResponse(response))
end if

#Pragma unused sel
#Pragma unused request
End Sub

Hi Ryan,
Ok, looks like I have everything configured properly and have had a successful test… yah!
Data being pulled from App Store correctly
Problem is it only works on IOS12.4 (perfectly) so far and crashes on my IOS13.6.

Did you get the IAP working on a range of IOS versions?..
If so did you make any changes to the Example or Tutorial?

Thanks
Martin

Hi Martin. I worked with Jeremie a couple of months ago because I was noticing the crash on the device too. Not sure where your crash is occurring, but mine was when you open the purchase modal window. I was looking back in my activity but could not find the one-on-one discussion with Jeremie which included a small change in the StoreKit class (wonder if that did not transition over from the old forum).

After looking at both my pre-add in new class and the one included from Jeremie, I think I found the class that changed, and I have it below in my Dropbox. Maybe try to replace the one you have in your project and see if it resolves the crash

Keep us posted if this works. If so, we can have Jason update this in iOSKit. I merely only replaced this in my sample project. I haven’t had the chance yet to get a new product up on the store yet with this change, but after I included this updated class (and I think this was all that changed), I tested it on the device, and it worked with no crashes

Good luck!

edit… Note, this was tested on Xojo 2019 r3.1 and it worked. I haven’t gotten around to downloading 2020r1 yet, but I would imagine it should work

1 Like

Thanks Ryan, I now have it working on both the IOS’s I can test. The only thing I’m not sure on is if the updated code you sent me for IOSKit did the trick or I hadn’t logged out of iTunes account while testing the Sandbox User was the issue. Either way very happy not I can do IAP which might change the way I release my products :slight_smile:
Also thanks to Jeremie for the cool popup window which suits making a store purchase and Jason for StoreKit.

1 Like

Awesome! And all the credit for that class goes to Jérémie. I’m just happy I found it in my project through all the other pieces in StoreKit. You’ll have to let us know how it goes if it passes review. Like I said, I hadn’t deployed mine yet to the App Store. If it works, I’ll send that class to Jason to update that piece in iOSKit

1 Like

I can’t get my IAP product to load properly. I’m getting an “invalid product identifier” message. The identifier string seems correct. How do I need to set up the IAP product in AppStore Connect? It is currently flagged as “Ready to Submit” but I can only submit it with a productive version, not a test version. Correct?

I have activated “In-App Purchases” in the Xojo Entitlements and the “In-App Purchases” capability in the Apple Developer app identifier is also activated. What are the required/recommended Code Signing settings in Xojo? Team = None and not build for AppStore to test it?

FYI, GameCenter works with that same app.

“invalid product identifier” sounds like it’s something with your bundle identifier. What does it look like in Apple Developer, Xojo, and ITC? Do they match?

For testing on the device, you can leave as None and not build for the App Store or fill in your team and build for AS. I don’t think that matters. In my IAP Sample app (the one from the tutorial), I have my team selected and Build for App Store off. I was able to test this on a device with success, so maybe at least choose a team.

Make sure your bundle identifier in Xojo matches the bundle ID in iTunes Connect General Info and also matches the product ID in iTunes Connect Manage In-App Purchases (matches but also includes the IAP product name

ps… no wildcard bundle identifiers. These haven’t been working for folks lately (or ever in Xojo)

1 Like