finishTransaction fails on brand new 16" MacBook Pro

For days I've been banging my head against an issue with developing an In-App-Purchase based application on a 2 day old 16" MacBook Pro running macOS 10.15.4.


When my application calls [[SKPaymentQueue defaultQueue] finishTransaction:inTransaction] it gets stuck in an infinte login loop.


This ONLY happens on this brand new 16" MacBook Pro running 10.15.4. It works on a 12" MacBook running macOS 10.15.4 and a (2012) 15" MacBook Pro running macOS 10.14.6.


There's two things here I want to know.

1. I can't find any evidence online of this ever occuring, is there someone who's come across this before and if so, how did you solve it?


2. As it only occurs on this machine, I've tried the following to see if I can fix it (thinking that the machine is a lemon).

a) Boot into "Safe" mode [no change].

b) Run Disk Fist Aid from Recovery [no change].

c) Re-installed the OS from Recovery [no change].

d) Created and tried a new user [no change].

e) Reset PRAM & NVRAM [no change].


There was one change which kinda worked, but is back to failing again this morning. I deleted all the cache relating the App Store that I could and rebooted. I still got stuck in an infintie login loop, but the transaction did actually complete and the item was added to the receipt. However this morning when I tried it again, it's back to just getting stuck in the loop and transaction is never added to the receipt.


There two options left that I can think of right now.


1. Obliterate the drive (using Disk Utility) and with just a clean OS, test my app. I am reluctant to do this because of the increased down time in testing a theory that I suspect will not show any difference.

Replies

I've now obliterated the SSD & performed a clean installed macOS 10.15.4. Reset NVRAM & PRAM.

The problem continues to occur on a clean factory default setup.

Just to be sure, I've also tested it on a different network and no change.


I suspect now that I have a dud MacBook Pro.


Your 'loop' is it responding to an IAP that was never finished? Is it asking for a particular test user to log in?

Describe your 'loop' more exactly.

Thanks for responding to my post.


In my SKPaymentTransactionObserver delegate,

I receive the event "paymentQueue:updatedTransactions:".

I process the array of transactions and read their status.

If it encounters the status "purchased", I then unlock the application.

I call transactionFinished for everything but "purchasing" and "deffered" transactions.


On t'other two machines.

After calling paymentWithProduct on the defaultQueue, the second dialog asks me if I want to extend the subscription. Click "OK".

On quitting and relaunching the application, the app reads the new item from the receipt and carries on.


On this 16" MacBook Pro.

After calling paymentWithProduct on the defaultQueue, the second dialog tells me that I've already purchased this item and it will be restored for free. Click "OK".

Moments after calling "finishTransaction", I get asked to login, it's auto populated the account e-mail, so I enter the password and click Login. The dialog goes away, only to re-appear shortly after. The most # of times I tried this was 30, before clicking on Cancel.

On quitting and relauching the application, there's no new item in the receipt, so the application reverts back to it's "Subscription Expired" state. Once again asking the user to Renew their subscription.


Now one time on Sunday night (after clearing all the App Store caches I could find), the 16" MacBook Pro did *almost* work correctly, I got the dialog asking if I wanted to extend the subscription. Clicked "OK" and still got stuck in the Log-in loop, but on cancelling the loop, the new transaction was written to to the receipt.


In both cases the "paymentQueue:removedTransactions:" event fires with the transaction.


I hope that this all makes sense. I have several concerns.

1. Why does this only happen for this one machine out of three (same account) even same OS?

2. Does this mean that this 16" MacBook Pro is somehow faulty, I have until the 18th of April to swap it for another one?

3. If this happened to me, I must assume it can happen to a customer, so I need to prepare for it somehow and hopefully offer a suggestion to the user to help resolve it.

Further information:

I have now tested this on a 2009 17" MacBook Pro running macOS 10.11.6, this fault doesn't occur there either.


I have added a non-consumable IAP item and was able to purchase this item on the 16" MacBook Pro without a problem. The IAP item that I'm having problems with is a non-renewing subscription.


In a final test, I tried to repurchase the non-consumable item again. As expected it offered to restore the item for FREE, then it got stuck in the log-in loop.


Attempting to re-purchase the non-consumable item on the other machines, works as expected.


Another thing that I've noticed, is that IAP transactions or at least the display of dialogs are much slower on the 16" MacBook Pro than other machines. Running speedtest.net in a browser, shows that download speed is 4x times faster than a 2012 MacBook Pro, while upload speed is about the same, the speedtest.net upload indicator would hesitate for a few seconds, while the other machines would continue to animate. I realize that this is not an actual indicator of an issue with the MacBook as it could be a lot of things.


I now beleive this problem is actually two issues.

1. Trying to extend a non-renewing subscription (on the 16" MacBook Pro), returns an existing IAP transaction instead of a new one.

2. Trying to call finishTransaction on an SKPaymentTransaction that is being purchased a subsequent time, sends the machine into a log-in loop.

We've been seeing the Sign In prompt loop for weeks on multiple Macs and MacOS versions with different Apple IDs. It fails the same with non-consumable products and subscriptions. I sent in a Feedback report #FB7648381on it on April 1, but it was happening even before that. Our app is an unreleased MacCatalyst app, so we were hoping there were still a few kinks getting worked out in the App Store, but they're still occuring (I realize this isn't a normal time for anyone, of course).


Yesterday I sent a request through Apple Developer Technical Support. Here's basically what I sent:


PLATFORM AND VERSION

OS X

MacBook Pro with MacOS 10.15.5 Beta 1 and MacBook with MacOS 10.15.4. Xcode 11.4.


DESCRIPTION OF PROBLEM

We have a new MacCatalyst app that's based on an existing iOS app. In-app-purchase works fine on iOS for both production and sandbox. But on MacOS, an in-app-purchase correctly prompts for the user's Apple ID password, but when you tap the Buy button after entering ID and password, it just re-presents the Sign-In prompt. If you enter an invalid password, it correctly shows an invalid password error.


We have not been able to release the Mac version of our app yet because we're unable to test the in-app-purchases.


STEPS TO REPRODUCE

// Queue up a payment request to purchase the specified product.

let payment = SKPayment(product: product)

SKPaymentQueue.default().add(payment)

Good explaination, thanks.

The login requirement comes from transactions in the queue that have never been 'finished'. A transaction goes to each device that makes a purchase - I can't tell whether you are always finishing (and always have finished) the transactions on this abberant device.


A device is aware of a bunch of test users - each device may be aware of different test users. So if your abberant device once logged in to a test user account, made a bunch of purchases, received a bunch of transactions, and did not finish the received transactions then it will forever be asked to log in to that test user account until the transactions are finished. If you refuse the login then your machine may wait a few days to a week before asking you again to log in to that test user's account for that unfinsihed transaction. The machine will not tell you who that test user is - you need to remember.


It may well be that your problem today is because of something that happened once, many months ago, in that machine. The thing about a non-renewable transaction is that you could attempt purchases 10 times and fail because of some code problem back when you were developing the IAP function. Then when you fix the code problem - bam - the transactions are all there waiting for you. If you delete that test user you are screwed for life on that machine. It gets even worse with autorenewables - one purchase - 5 transactions. And....it gets even worse if the 'only 5 renewals' is turned off one weekend by Apple. That problem is called 'the endless loop'. I had over 2000 log in requests.

Our app does support auto-renewing subscriptions and our test users (including me) have been testing for months with iOS, so there are probably lots of them per user. However, nothing like this sign-in loop occurs on iOS. Is there a fix or workaround for MacOS?

Assuming the problem is unfinished transactions, you 'just' need to sign in with the correct test user and finish the transaction. It may be possible to figure out who that test user is - I don't know how to do that but it might be in some log on the device. If you can't do that (e.g. the test user has been deleted) the other approach is through DTS. In my case, they were able to clean my queue remotely after much begging on my part.

For me personally, the problems only started when I received this 16" MacBook Pro running macOS 10.15.4 on April the 4th. I spent the entire weekend trying various things to resolve it myself (see above).


The problem doesn't occur on the following machines.

* 2015 12" MacBook running macOS 10.15.4.

* 2012 15" MacBook Pro running macOS 10.14.6.

* 2009 17" MacBook Pro running macOS 10.11.6.


For one of the tests, I added a new non-consumable product and attempted to purchase it on the 16". The first time worked, the second time it got stuck in the endless loop. Again performing the same test on t'other 3 machines works.


Feedback report: FB7657917

DTS case # 101060342886

As it's a brand new machine I also have an AppleCare case # 101060171758

Update.


1. I have created and tested with a new testing account [no change].

2. 2015 12" MacBook running macOS 10.15.4 continues to extend non-renewing subscriptions, but has now started showing the endless log-in loop when calling finishTransaction.

3. 2020 16" MacBook Pro will still not extend an non-renewing subscription (returns an existing item) and continues to show endless log-in loop after calling finishTransaction.

4. When the endless log-in loop in going, it does not display the application icon, meanwhile the first request to log-in does.

5. 2012 15" MacBook Pro with macOS 10.14.6 extends the non-renewing subscription and DOES NOT fall into the endless log-in loop after calling finishTransaction.


I now believe that the endless log-in loop is an issue in the macOS, especially as it's started occurring on a second machine running 10.15.4. Because the log-in loop doesn't appear to actually affect purchases, and looking in this forums, appears quite wide spread, I do not consider it a major issue. However the problem that's preventing purchases from occurring is still present and that IMHO is a major issue.


Problem:

Attempting to extend a non-renewing subscription fails on this brand new 16" MacBook Pro running macOS 10.15.4


What should happen:

The user should be asked to extend the non-renewing subscription, and a new item is then issued through the App Store IAP API.


What actually happens:

The user is informed that the item has already been purchased and it will be restored for FREE. An existing item is then issued through the App Store IAP API.


Reproduction steps:

1. Download the sample code from https://developer.apple.com/documentation/storekit/in-app_purchase/offering_completing_and_restoring_in-app_purchases?language=objc

2. Make sure you have an IAP item configured in App Store connect, that is a non-renewing subscription.

3. Add your product identifier to the project and the IAP item identifiers to the productIDs.plist file.

4. Run the project and purchase the non-renewable subscription.

5. Attempt to purchase the non-renewing subscription a second time, if you are told that you've already purchased this item and it will be restored for FREE, this is the show stopping issue with this 16" MacBook Pro.

I began seeing similar behavior on a 12" MacBook - but only in the last week or two. This is purely speculative, but I suspect the culprit may be the macOS 10.15.4 Supplemental Update. This was released on April 8 - but maybe it was preinstalled on your 16" MBP? From the release notes:


Resolves an issue where you may repeatedly receive a password prompt for an Office 365 account


If they were tinkering with the password prompt code, it's possible they slipped in a bug.


My question for you: Did you install the Supplemental Update on the machines that are working correctly?

Your app is responsible for restoring non-renewing subscriptions. The easiest way to do that is through the user's iCloud key-value file.


Another approach is to refresh the receipt and use that information.


You wrote "extend a non-renewing subscription" - what does 'extend' mean???? restoreCompletedTransactions? No such thing for a non-renewing subscription.



>The user is informed that the item has already been purchased and it will be restored for FREE. An existing item is then issued through the App Store IAP API.


It is unlikely this is the response you get from a purchaseRequest for a non-renewing subscription. I suspect this is from a purchaseRequest for a non-consumable IAP - is that possible?

Thank you for your response.


I have only been dealing with non-renewing subscriptions since Apple informed me to do so on March the 28th 2020, until then I had only experience with non-consumables and auto-renewing subscriptions.


> Your app is responsible for restoring non-renewing subscriptions. The easiest way to do that is through the user's iCloud key-value file.


This is not the behavior that I have been experiencing, nor have I been recommended to do so by DTS. Non-renewing subscriptions have been appearing in the receipt, since I started working with them.


> Another approach is to refresh the receipt and use that information.


I have attempted this to see if it would help. Sadly it didn't, neither did restoreCompletedTransactions.


> You wrote "extend a non-renewing subscription" - what does 'extend' mean???? restoreCompletedTransactions? No such thing for a non-renewing subscription.


In my expereince; when a user attempts to purchase a non-renewing subscription item for the subsequent time (on macOS 10.14.6 & 10.11.6), they are given the option to "Extend" the subscription, upon accepting, a new item is transferred with the current date & time. The new item is also written to the receipt. Since the day this 16" MBP arrived, it has not offered to extend the subscription, instead only offering to restore the previous item for FREE. Also when the 16" MBP first arrived, t'other 10.15.4 machine was working like the 10.14.6 & 10.11.6 machines, but that changed this weekend and now it is also not able to "extend" a non-renewing subscription.


> It is unlikely this is the response you get from a purchaseRequest for a non-renewing subscription. I suspect this is from a purchaseRequest for a non-consumable IAP - is that possible?


In attempts to gather further information to help narrow down the cause the of the issue, I have tested with a non-consumable item, and this is how they appear to work. As 75% of the machines **were** offering to extend the non-renewing subscription, I believed that this is the correct behavior.


I have been in touch with ACS since last monday and finally got through to DTS later in the week. I am continuing to perform various tests and providing logging information to DTS. The exact cause of the issue has yet to be determined.


Today I am going to see if ACS will extend the return period on this machine as I have been unable to use its intended purpose (macOS app development, specifically for this latest round of changes to IAP handling). Apple can see that I am working with their various departments in regards to this problem.

To be simple and clear - my issue was that you wrote the alert said "for free". When a non-renewing subscription is purchased, except for the first time, the App Store says ''do you want to extend it" but NOT for free. When a non-consumable is purchased, except for the first time, the App Store says 'do you want to download it again for free?' If the 'for free' is in there it is either an App Store bug or a code bug in which you are issuing a paymentRequest for a non-consumable without realizing it.


You cannot do a restoreCompletedTransactions for a non-renewing subscription. If there are no non-consumable IAPs or autorenewable IAPs to restore, the receipt is not refreshed. You must either do a receipt referesh and decode the receipt (although I wonder if this really works on new devices - I have not tried it) or you can use your own technique for restoring the subscription to other devices owned by the user (and iCloud key-value is easy).

Thank you for your response.


> If the 'for free' is in there it is either an App Store bug or a code bug in which you are issuing a paymentRequest for a non-consumable without realizing it.


I have verified each time I attempt the purchase that it is purchasing the non-renewing subscription. I only added the non-consumable to test with later, once the issue first started appearing. With the log files that I have supplied to DTS, they have confirmed that the failure (I am expereincing) is occurring for the non-renewing subscription.


> You cannot do a restoreCompletedTransactions for a non-renewing subscription. If there are no non-consumable IAPs or autorenewable IAPs to restore, the receipt is not refreshed. You must either do a receipt referesh and decode the receipt (although I wonder if this really works on new devices - I have not tried it) or you can use your own technique for restoring the subscription to other devices owned by the user (and iCloud key-value is easy).


So far in my testing, I have not been experiencing this behavior. When ignoring any receipt verification on startup, and calling restoreCompletedTransactions the non-renewable subscriptions appear in the receipt that is then inserted by (I assume) StoreKit.


Right now, my guess is that it's combination of issues that have to be lined up. I am assuming it's an issue within macOS 10.15.4 (or maybe broader) and potentially an issue with the App Store servers. As indicated by it working correctly on older OS versions, but failing on different machines running 10.15.4 (albeit taking a week for the issue to progate to start occuring on an existing machine).


I realize that you may be skeptical because I am experiencing different behaviors to you, and this may actually be a clue, so I will forward this information on to DTS.