In App Purchase

I have released an OS X product with In App Purchases using the Monkeybread plugin. Now want to port the app to iOS.
I have to Jason King iOSKit with StoreKit declares BUT…
There is a reason I have used Xojo for many years. I am lost when it comes to dealing with NSSet, NSArray, NSObject, etc.
For example, the first thing I tried to port was a product request. In OS X I supplied a string (text) array of product IDs. Now I need an NSSet containing product IDs. How do I get that?
Any suggestions of a resource to teach me how to deal with this arcane stuff?

Hi,

I started looking into StoreKit yesterday and ran into the same issues.

Here is how you initialize StoreKit and get a list of products:

[code] StoreKit.InAppPurchaseHelper.productIDArray.Append productID1
StoreKit.InAppPurchaseHelper.productIDArray.Append productID2
// List other productIDs here

//Helper is a property in the View
Helper = StoreKit.InAppPurchaseHelper.GetInstance()

//LoadTable uses RequestProductsCompletionHandler delegate
Helper.RequestProductsWithCompletionHandler(WeakAddressOf LoadTable)[/code]

Using the above code in the View.Open event, I am able to get a list of Products in the form of an NSArray.

But now I can’t find how to get SKProduct out of the NSArray

Hi Jeremie
I saw your PM and I’ll post a reply on it later on.

I should make a convenience mehod for all of this too…

Jason

I think I got it.

Adding a Constructor method to SKProduct :

[code]Public Sub Constructor(ref as NSObject)

super.Constructor(ref)

needsExtraRelease = True
End Sub
[/code]

In the LoadTable method I can list all products.

Here is an example project: http://www.jeremieleroy.com/upload/Storekit%20Example.xojo_binary_project.zip

Believe it or not, the super.constructor that you added into that method does the same thing as the constructor you created so you don’t even need that constructor because they do the same thing! It makes it more clear though, but every class can be instantiated from a pointer just by doing

dim instance as new NSClass(pointer)
Where NSClass is the name of the class, and pointer is the pointer the the instance obtained from a declare or handle.

After trying myself I believe it :slight_smile:

Hi Thomas,
I thought that there was an example view for storekit in the examples of iOSKit but it seems that I never copied it from my own example project. Take a look at this view which provides a basic example. Creating an NSSet, etc is all done for you behind the scenes with the helper class included in iOSKit.

https://www.dropbox.com/s/ttspe492hirmjx9/StoreKitExampleView.xojo_xml_code?dl=0

SKProduct still misses one property priceLocale

Adding this to SKProduct fixes the issue.

[code]Public Property priceLocale as xojo.Core.Locale
Get
declare function priceLocale_ lib StoreKitLib selector “priceLocale” (obj_id as ptr) as ptr
declare function identifier_ lib FoundationLib selector “identifier” (ref as ptr) as CFStringRef

dim localePtr As Ptr = priceLocale_(self)

Dim identifier As Text = identifier_(localePtr)

Return new xojo.core.Locale(identifier)
End Get

Set

End Set

End Property
[/code]

Thank you Jason for the example :slight_smile:

I’ll add price locale - can’t believe I missed it!

I’m trying to get IAP working and I have managed to get a list of products using Jrmie Leroy’s example above.
(http://www.jeremieleroy.com/upload/Storekit%20Example.xojo_binary_project.zip)
I am unable to get the example by Jason King to work.
(https://www.dropbox.com/s/ttspe492hirmjx9/StoreKitExampleView.xojo_xml_code?dl=0)

In Jrmie’s example the list does not do anything when the item is clicked (no event handler for the list).
In Jason’s example I dee there is an Action event handler for the list but I am unable to get the list to populate with my IAP products.

I have made some progress on this (I think). I am able to initiate a purchase but the transaction does not seem to complete and I am not sure how to monitor the transaction.
Here is my file if someone wants to take a look that would be great!
http://jpkelly.net/xojo/Storekit_Example_mod.xojo_binary_project.zip
Thanks!

JP,
Finally got around to looking at your example.
I ported your example code to a project for the next release of an existing app and enabled the In App Purchase entitlement in Xojo.
In iTunes Connect created an In App Purchase upgrade product for that app. Also create Sandbox Testers in iTunes Connect if you haven’t done that.
Built the app.
Used Xcode to install the app in my iPhone which is connected to my Mac. Note that I am still on OS X 10.11 (El Capitan) and using Xcode 8.2. My iPhone is running iOS 10.3.2 so Xcode gave me a warning that it may not support this iOS version. Ignored that and proceeded.
On iPhone signed out of my regular AppleID. Run the app and purchased the upgrade product. When asked to sign in used a Sandbox Tester ID and everything worked perfectly.
So I would say your code example is good; thanks for helping me with something I have wanted to do for some time. Now I have to complete the code which captures the upgrade purchase and enables the new features in the product.

JP,
Now I see the problem. Although the purchase executes and the user gets a message to that effect, the app can’t capture the successful purchase because the iOSKit StoreKit.Helper.isProductPurchased method always returns false. I tried to follow what it was doing but it doesn’t make sense to me. Maybe Jason can take a look at that.

JP,
The Helper.isProductPurchased method started to work and then stopped again. But it doesn’t matter. You can leave that code as you have it in your example. If it works the great; if it doesn’t the user will be put through the purchase process only to be told at the end that they already have purchased. But the real way for the app to capture the purchase is as follows.
There are events that return the information about whether an In App Purchase has been purchased. An important one is the StoreKit.inAppPurchaseHelper UpdatedTransactions event which will fire during the purchasing process. That event returns transactions() as StoreKit.SKPaymentTransaction. In a SelectCase statement, if the StoreKit.SKPaymentTransaction.SKPaymentTransactionState is Purchased or Restored then inAppPurchaseHelper methods CompleteTransaction or RestoreTransaction are called respectively. Both of those methods call inAppPurchaseHelper.ProvideContentForProductID(ID as Foundation.NSString) method. At the end of this method I have added a call to a method to capture this state for the application –

app.UpdatePurchased(ID.StringValue)

This method should configure the app appropriately and save the purchased state in a file for future reference.