Automatic Renewal Subscription works on fresh installs, not on updating Version - ios

In version 1.0 ,the app content was free. Whereas in version 1.1 , I implemented Automatic renewal Subscription for some content and used IAPHelper for implementing InApp purchase. The Subscription is working fine in case of fresh installs whereas the users who updated the version they can access the paid content for free. If any one know ,what could be the reason behind this ,please help me.
this is my code for purchase
[[SubIAPHelper sharedInstance] requestProductsWithCompletionHandler:^(BOOL success, NSArray *products) {
if (success) {
inAppproducts=products;
SKProduct *product =products[0];
if (![[SubIAPHelper sharedInstance] productPurchased:product.productIdentifier]) {
/* purchasing UI shown here and after successful purchase content is downloaded */
}
else
{
/*Content downloaded as previously purchased and rest of the flow*/
}
}
}];
Any kind of help will be appreciable.

Related

Inconsistent in app purchase results on iOS 11/10

In a previous version of my app I had in app purchases(IAPs) working fine. In my latest release I am getting some strange inconsistencies reported to me by users.
The IAP simply grants access to the "Pro" version of the app that removes ads and allows users to play audio files while the app is backgrounded.
The Issue:
Users can successfully purchases the IAP within the app. They receive the message stating that the purchase was successful. However when they restart the app (as instructed to do by the successful purchase UIAlert) the Pro features are not unlocked.
When the users then use the "Restore Purchases" button, they receive an error message stating that "Nothing to restore" basically tell them that they have not purchased anything.
The interesting things is if they press the purchase button again, then they are told that they have already purchased the IAP and can re-download it for free. Again this doesn't unlock the Pro features.
Reported Cases
I have had numerous cases of this issue being reported to me. Users on both iOS 10 and 11 have encountered this issue. However, other users on both iOS 11 and 10 have also been able to purchase the upgrade without any problem. So I am a little confused on what could of caused the issue.
Tools
I am using SwiftyStoreKit 0.10.5 to manage my IAPs. I am on Xcode 9.0 using Swift 4.
Below is the code I use to purchase and restore purchases.
I have covered my bundleID with *** for safety reasons as I don't know what can be done with it.
// Purchase Product
func purchase(purchase: RegisteredPurchases) {
NetworkActivityIndicatorManager.NetworkOperationStarted()
SwiftyStoreKit.purchaseProduct(bundleID + "." + purchase.rawValue, completion: {
result in
NetworkActivityIndicatorManager.NetworkOperationFinished()
if case .success(let product) = result {
if product.productId == "com.************.RemoveAds" {
self.defaults.set(true, forKey: "NoAds")
}
if product.needsFinishTransaction {
SwiftyStoreKit.finishTransaction(product.transaction)
}
self.showAlert(alert: self.alertForPurchaseResult(result: result))
}
})
}
// Restore Purchases
func restorePurchases() {
NetworkActivityIndicatorManager.NetworkOperationStarted()
SwiftyStoreKit.restorePurchases(atomically: true, completion: {
result in
NetworkActivityIndicatorManager.NetworkOperationFinished()
for product in result.restoredPurchases {
if product.needsFinishTransaction {
SwiftyStoreKit.finishTransaction(product.transaction)
}
if product.productId == "com.************.RemoveAds" {
self.defaults.set(true, forKey: "NoAds")
}
print(product.productId)
self.defaults.set(true, forKey: "\(product.productId)")
}
self.showAlert(alert: self.alertForRestorePurchases(result: result))
})
}
Any information on what could be the cause of this I would really appreciate it. As I am at a bit of a lose at the moment on what the cause could be.
Thanks!

Auto renewable IAP subscription user flow & refreshing receipts

I am using the library RMStore - here's what I have currently.
1) Purchase auto renewable subscription & verify the returned receipt.
[[RMStore defaultStore]addPayment:[Environment environment].premiumProductIAPId success:^(SKPaymentTransaction *transaction) {
[[RMStore defaultStore].receiptVerificator verifyTransaction:transaction success:^{
//enable premium service
} failure:^(NSError *error) {
}];
} failure:^(SKPaymentTransaction *transaction, NSError *error) {
}];
2) On each app launch check the subscription is active for the date and enable the premium service if it is
RMAppReceipt *appReceipt = [RMAppReceipt bundleReceipt];
if (appReceipt){
NSInteger isActive = [appReceipt containsActiveAutoRenewableSubscriptionOfProductIdentifier:[Environment environment].premiumProductIAPId forDate:[NSDate date]];
//enable premium service if active
}
3) If user launches app on another device allow them to restore purchases by refreshing the receipt if it exists and checking if there is an active subscription in the purchases.
"In most cases, all your app needs to do is refresh its receipt and deliver the products in its receipt."
- That's from the guide. Here's the code:
[[RMStore defaultStore]refreshReceiptOnSuccess:^{
if ([receipt containsActiveAutoRenewableSubscriptionOfProductIdentifier:[Environment environment].premiumProductIAPId forDate:[NSDate date]]){
//enable
}else{
//no longer active
}
} failure:^(NSError *error) {
}];
My questions:
When RMStore checks if the subscription is active it can return no, I look in the receipt and it is correct and I am assuming it hasn't been auto renewed. When I go to purchase another subscription I get a message from itunes saying I'm already subscribed. On subsequent launch I see the new receipt. This indicates the receipt needed to be refreshed on launch, but I don't want to refresh it as it brings up the username & password pop up which is unnecessary. What is the best practice here?
Am I restoring the subscriptions for another device the right way? It seems to sometimes take more than one attempt to restore the subscriptions.
Is there any need apart from record keeping to store the subscriptions on my server?
I'm going to try and answer my question.
There may be a renewal which is not detected first thing on launch hence the subscription appears inactive.
I added an observer to listen for finished transactions (RMStore extends this StoreKit functionality).
Each time I receive this notification I check the (now updated) receipt for an active subscription and enable the premium service if there is one.
- (void)storePaymentTransactionFinished:(NSNotification*)notification
{
BOOL isActive = [[RMAppReceipt bundleReceipt] containsActiveAutoRenewableSubscriptionOfProductIdentifier:[Environment environment].premiumProductIAPId forDate:[NSDate date]];
if (isActive){
//enable premium
}
}
This seems to be working. If anyone has any other suggestions let me know.

Restore purchases with RMStore

I'm trying to get the RMStore library to work, but therefore I need to be able to restore the in app purchases the user could have possible made. I'm aware of the method: restoreTransactionsOnSuccess: but with this method I don't get to know which in app purchases are restored.
[[RMStore defaultStore] restoreTransactionsOnSuccess:^{
} failure:^(NSError *error) {
}];
The above code is what I used, and it's working because in the logging I see the bought in app purchases. Do I miss something?
Could somebody point me to the right direction?
Thanks in advance!
As Merlea Dan mentioned, you can achieve this with notifications. The RMStore documentation states:
Payment transaction notifications are sent after a payment has been
requested or for each restored transaction.
Simply register as an observer and implement:
- (void)storePaymentTransactionFinished:(NSNotification*)notification
{
SKPaymentTransaction *transaction = notification.rm_transaction;
if (transaction.state == SKPaymentTransactionStateRestored)
{
// Do something
}
}
It's worth mentioning that a few others have requested to have restoreTransactionsOnSuccess return the list of restored product ids in the success block. You might want to subscribe to this issue in case it gets added.

in app purchase "Error Domain=SKErrorDomain Code=0"

In my app I have an in-app-purchase where I allow to purchase some items. (with mkstorekit)
A think that I notice in iOS 7 is this:
if In general setting of my iPhone I'm logged with my Apple id and I proceed to purchase an item I have an error "Error Domain=SKErrorDomain Code=0" and the code finish in "canceled" block.
Then I logout from my apple id, I start again the app and when I must purchase an item it ask me id and password and its correct (naturally I insert a tester user data that I created in iTunes Connect)
At this time I stop my app and in my general setting is stored the tester user, then I start again my app and when I must purchase an item I have not the problem that I had with my personal apple id and it work fine.
In iOS 6 it didn't happen because if I was logged with my apple id in general settings and I tried to purchase an item, it showed me my apple id and asked me to insert the password (naturally it didn't work)
Finally this is not a big problem, I solve it because I used my tester account, but when I release my app in App Store can I have the same problem? If an user is logged in general setting the mkstorekit sto purchase and go in "canceled" block?
I show the method where is the cancel block:
- (void)purchaseFeature:(NSString *)productID
{
[[MKStoreManager sharedManager] buyFeature:productID
onComplete:^(NSString* purchasedFeature,
NSData* purchasedReceipt,
NSArray* availableDownloads)
{
[HUD hide:YES];
/*** CODE TO OPEN VIEW IF THE PURCHASE IS DONE ****/
}
onCancelled:^
{
NSLog(#"User Cancelled Transaction");
[HUD hide:YES];
/*** HERE FINISH MY CODE IF I'M JUST LOGGED IN GENERAL SETTING WITH MY APPLE ID ***/
}];
}

Testing In App Purchase issues. IAP iOS

I have got one big problem with an IAP purchase testing.
There are next steps which I have made:
Create App ID (com.domainname.appname)
Create Development Provisioning Profile with an App ID (com.domainname.appname)
Create App on iTunes Connect (Bundle ID com.domainname.appname)
Manage IAP. Create non-consumable products with Product ID com.testitem1, com.testitem2, com.testitem3 (there is Ready to Submit status for each products)
Configurate XCode project settings
Bundle identifier: com.domainname.appname
Code Signing Identity: Development Provisioning Profile that I have made on the step 2
Deployment target: 4.0
Device
iPod Touch 4gen iOS 5.1.1
Write source code
My class support SKProductsRequestDelegate
in - viewDidLoad callback method I have wrote these lines:
if ([SKPaymentQueue canMakePayments])
{
NSLog(#"YES, I CAN MAKE PAYMENTS");
}
else
{
NSLog(#"NO, I CAN NOT MAKE PAYMENTS");
}
On this stage everything is okay. I can make payments.
Next, I'm try to create request for my products:
SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers: [NSSet setWithObjects:#"com.testitem1", #"com.testitem2", #"com.testitem3", nil]];
request.delegate = self;
[request start];
On this stage everything is okay also and on next stage my request object invoke callback method below:
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
NSArray *myProduct = response.products;
NSLog(#"%#", myProduct);
}
But there are not any products in response and I can not understand why.
I already have this problem before (i just reset my device and everything worked good), but in this case I can not figure out what's wrong.
I have went through this guide:
https://developer.apple.com/library/ios/#technotes/tn2259/_index.html
In my case this is was related that I have not got Banking Information. If you want to test your IAP you must have an iOS Paid Applications contract (iOS) with a your tax information.
This happens because you haven't yet uploaded the app's binary in iTunes Connect. Go to iTunes Connect, upload the app's binary. Once it's uploaded, reject it straight away so that it's marked as "Developer Rejected".
This is a necessary step for you to receive SKProductResponse if it's the first version of your app. It won't affect your app's review.

Resources