iOS Tutorial iStore - In App Purchases

The iStore library allows you to use the store In-App Purchases features inside your app.
You can let the user purchase digital products from inside your app.

(Unsurprisingly) the configuration required is a bit tedious.

In order to test this feature (and later release it) you need to create an app in iTunes Connect and create one or more in-app products. You don't need to actually upload the app binary file however you do need to fill all the fields and prepare the app. Later you can change them as needed.

After you've created an app placeholder in iTunes you need to carefully follow these instructions:
https://developer.apple.com/library/ios/technotes/tn2259/_index.html

The main steps:
  1. iOS Paid Applications contract should appear under "contracts in effect".
  2. You need to create an explicit App Id (without wildcards) and download a new provision file.
    You can use #ProvisionFile to tell the IDE which provision file should be used.
  3. Create a test account as explained in the tech note. Later you will sign out of the store from the Settings app. Note that you should not sign in to the store with the test account from the Settings app. The test account should only be used inside your app.
  4. Create one or more in-app products and make sure not to upload a screenshot during development.
iStore library supports two types of products: consumable and non-consumable products.
Consumable - The user can purchase these products multiple times. For example in a game a user can purchase extra health or coins.
Non-consumable - The user can purchase such products once. For example the user can use such product to permanently remove ads from the app. If you are selling such products then you need to allow the user to restore such products if the user switches to a different device (with a "restore transactions" button).

Code

The code is quite simple.
First you initialize a Store object and check whether the device supports this feature:
B4X:
Dim MyStore As Store 'declare it in Process Globals
...
MyStore.Initialize("MyStore")
If MyStore.CanMakePayments = False Then ...

Later you can request a payment and then handle the PurchaseCompleted event:
B4X:
MyStore.RequestPayment("product.id")

Sub MyStore_PurchaseCompleted (Success As Boolean, Product As Purchase)
   Log("Purchase completed")
   If Product.IsInitialized Then
     Log("Product: " & Product.ProductIdentifier & ", date=" & DateTime.Time(Product.TransactionDate) & _
       ", Transaction identifier=" & Product.TransactionIdentifier)
   End If
   Log("Success = " & Success)
End Sub

The user will be asked to log in to his store account (use the test account here) and approve the purchase.

Restoring non-consumable purchases

As noted above, if you are selling such products then you are expected to provide a way for the user to restore completed transaction.
Once the user requests to restore transactions you need to call MyStore.RestoreTransactions. The PurchaseCompleted event will be raised for each previous purchase of non-consumable products.
The TransactionsRestored event will be raised at the end.

Note that the user might be asked to log in to his account, therefore you shouldn't call this method when the apps starts to find existing purchases (unlike the Android library).
 
Last edited:

tufanv

Expert
Licensed User
Longtime User
Yes. I solved it by using purchasecompleted instead transactionsrestores TY. !
 

tufanv

Expert
Licensed User
Longtime User
Erel,

Do we check if the subscriptions are active woth each app start just like the non consumable items ?
 

tufanv

Expert
Licensed User
Longtime User
Ok Understood now. With first subscription event will b e raised and i will have to store the dates on a db for example. When the date ends if renewed event will be raised again and the app will automaticly update the dates in the database if not dates will not be updated and some features will be disabled .
 

JonPM

Well-Known Member
Licensed User
Longtime User
When should you initialize the store? When a button is pressed to purchase something, or at every app start?
 

tufanv

Expert
Licensed User
Longtime User
Erel,
Due to compl
Go over that link. It answers these questions.
Specifically see the Expiration and renewal sections. The PurchaseCompleted event will be raised when the app starts if the user has renewed the subscription.

Erel,

according to your answers above I would like to ask again :

-with first subscription we enter the data into a db with start end dates. LEts say its a weekly subscription. So at the en of 7 days if the subscriptions are renewed how do my app raises purchasecompleted event at startup ? Automaticly ? so that with every purchasecomplete i will update my data with new dates ?

-I go over the link you provided but could not understand testing enviroenment exactly. IS it the same we do with standard in app purchases ( with another account ) ? How can i rapidly test if subscriptions are reneewd and my app does the correct database changes without waiting 1 week for example ?

ty
 
Last edited:

Erel

B4X founder
Staff member
Licensed User
Longtime User

tufanv

Expert
Licensed User
Longtime User
Based on this discussion (read it) the PurchaseCompleted event will be raised when the app starts, on the first device only: http://stackoverflow.com/questions/...d-an-skpaymenttransactionstatepurchased-trans

Not sure about testings. You can see the short section here: https://developer.apple.com/library...s.html#//apple_ref/doc/uid/TP40008267-CH7-SW8

I have read a lot before writing this message so please dont get angry with me :) . I tried a renewing subscription in sandbox environment. ( accelerated time , renews every 5 minutes for 6 times maximum / daily means in real : 1 week for every transaction 6 time renewing total of 42 days of total subscription ). Anyway, The first transatcion log showed : Product: weeklyfootball, date=2015/11/06 14:02:45, Transaction identifier=1000000179087652. Later i tired to run the app after 5 minutes ( which apple says that it will be renewed to simulate 1 week passed and subscription renewed ) and as you said purchasecompleted event fired automaticly with a new transaction id and date&time . Up to this point it is good. When it is automaticly fired , i can update my sql database for 1 more week for my customer. The problem is this: If the customer deletes the app on 3rd day of a subscription, if i request the restorepurchases, I get 2 transactions (1 main subscripton and 1 renewal / simulated as 1 week) which the time and date and transaciton id is the main subscription , so i cant get the info about when the subscription renewed because with each renewal it fires a new purchasecompleted event with a new transaciton id and date but when i request to restorepurchases i see 6 times of purchases of the main subscription. ( all transaciton id time , date is same ). At this point i think it is impossible to corectly enter data into a local db about expiry dates because i can only get the original subscriptions date. As I looked for this issue on some forums , I came to a solution i think.( please see: https://developer.apple.com/library...ral/ValidateAppStoreReceipt/Introduction.html) at the end of page there is a section : validating receipts with itunes. With this system i can get the expiry and start date of each receipt but it is a bit complicated for me. ( https://developer.apple.com/library...html#//apple_ref/doc/uid/TP40010573-CH104-SW1 ) Is there any way i can use this or am i thinking wrong ?
 

JonPM

Well-Known Member
Licensed User
Longtime User
B4X:
MyStore.RequestPayment("product.id")

Sub MyStore_PurchaseCompleted (Success As Boolean, Product As Purchase)
   Log("Purchase completed")
   If Product.IsInitialized and Product.ProductIdentifier = "product.id" then
   'product is purchased?
   End If
End Sub

When selling multiple IAP's is the above code the correct way to check if a specific one was purchase? Or is it better:

B4X:
Sub MyStore_PurchaseCompleted (Success As Boolean, Product As Purchase)
   If Success and Product.ProductIdentifier = "product.id" then
   'product is purchased?
   End If
End Sub
 

marcick

Well-Known Member
Licensed User
Longtime User
Can a free app (created with a wildcard id) that is already on the store be turned in an app with in-app purchase options ?
Or do I have to create a new app, with a new name, that include this option ?
 

ilan

Expert
Licensed User
Longtime User
You dont need to create a new app, you need a new provisions file and new certification that include inapp purchases
 

ilan

Expert
Licensed User
Longtime User
Btw as i remember you cannot use a wildchart id with in app purchases, you will need to choose your app id after you check in your dev console the in app option.
 

marcick

Well-Known Member
Licensed User
Longtime User
Ok, The important is that I can keep the same app name and just need to change the certificate/profile to remove the wildcard
 

sorex

Expert
Licensed User
Longtime User
this new provisioning profile (step 2) what kind of profile is this?

Just an app store > distribution one?

Do I need both a development & distribution profile linked to this new app ID to be able to test it in both debug and release?
 
Top