Apple Receipts: latest_receipt_info order

Over the past few months, I’ve been doing a deep delve into auto-renewable subscriptions for one of our client projects. It’s been a roller coaster ride as we took on an established product with nearly 10,000 (mostly monthly) subscribers. You really don’t want to be responsible for that support call informing you that customers are unable to access the product they have paid for.   

Unfortunately, in the past month, we had been noticing more and more support cases reporting customers being locked out of their paid content. Our initial investigation into what could have changed to trigger the problem just confirmed that we hadn’t made any changes in that area, but the number of issues kept on increasing. Over some time, we increased the logging in the relevant areas and rolled out a few investigative fixes to see if we could pin down potential causes.

While we seemed to be pinning down that area in which the problem was hiding, the number of support cases continued to increase. Bizarrely, reaching a critical mass in support requests allowed us to finally pin down the exact area that was causing the problem. The app was calling back to the server with the Apple receipt to verify their subscription was still active, and it was this call that was (incorrectly) reporting that the subscription had expired and was locking the user our of their content. This code hadn’t changed since the inception of the application. It had always worked and continued to work for the majority of users. However, more and more customers were being affected).

Adding a little more logging in this area identified that the order of transactions in the verified receipt was not consistent. The majority of the receipts had the transactions ordered oldest to newest. Still, more and more receipts were being seen with transactions in the opposite order, and some even had what appeared to be a completely random order. As the API code was written to assume the last item was the most recent transaction, in certain situations, it was getting a historic transaction, which was why the check was then failing.

Light Bulb Moment

Digging around the internet, I came across an article which contained this gem:

With regards to the ordering of the items in the in_app array, I would make no assumption that the items are in chronological order. I would say the same holds true for the contents of the latest_receipt_info section.

https://developer.apple.com/forums/thread/69531

The Fix:

Luckily it was a quick and easy change to the API to read the array, and order on the transaction date, programmatically ensuring that the system was working with the most recent transaction. It was really satisfying to then deploying this change to live and watch the issue instantly disappear for the affected users.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *