Matching original_transaction_id to subscriber id.

I'm stuck!

For starters, mobile is not the primary platform for our app so I apologize ahead of time if I don't know enough about this to ask the right questions. But I'm learning :)

We are saving the original transaction id when a user makes an in-app purchase for a subscription to our product, but their subscriber id is not included in the receipt. I can download sales reports with subscriber ids but even the "transaction level" subscriber reports do not contain the transaction id. I do not care in the slightest who the subscriber id belongs to so I don't need any user information. Nothing like that. I just need to match transactions to records in our system for reporting purposes.

Has anybody found a way to tie subscriber ids to transaction ids or vice versa?
There is no support for matching appStoreReceipt information to a subscriber id - for customer privacy reasons. What is not clear is what you are trying to match. The validation of an appStoreReceipt can provide you a complete list of the auto-renewing subscription In-App Purchases made by an iTunes user account - by validating the appStoreReceipt and not specifying the "exclude-old-transactions" JSON key in the request. In such case, the validated response will show the complete transaction history in the "latest_receipt_info". Your desire "match" transactions is not clear - are you trying to match transaction from a validated appStoreReceipt to the contents of a server-to-server notification? This is the common reason for asking such question.

You should note that for an appStoreReceipt with numerous auto-renewing subscription transactions, the original_transaction_id can increment over time. If the issue is to match a user's appStoreReceipt to a server-to-server notification, for most cases, the original_transaction_id is useful for this purpose, however the system needs to verify with renewals on the validated appStoreReceipt whether the original_transaction_id changes. If on a re-validated appStoreReceipt the original_transaction_id does increment for the current subscription, then for server-to-server notifications sent for the same renewal period, for the same user, will use the incremented original_transaction_id.

The key here is to not assume that the original_transaction_id specified in the initial appStoreReceipt validation will remain the same. As renewals occur, the original_transaction_id may increment, and new server-to-server for the same user will use the incremented - matching value.

On the other hand, if you are trying to match something else, please clarify.

rich kubota - rkubota@apple.com
developer technical support CoreOS/Hardware/MFI
Thank you, Rich!

I have a dev background but moved into a data analyst role a couple years ago and am no longer involved in app development, so I know just enough about this to get really confused. In short, I am responsible for pulling together the transactions from payment gateways and tying them to subscriptions in our system for the CFO to calculate the royalty payments we need to send out. Those payments are based on the variable sale price of subscriptions. Our system is subscription based but was not really designed for mobile applications. The receipt info is saved for each subscription-related events. The problem is that receipts have transaction ids in them but no prices or promo codes and any reports I can get through the app store connect api have prices and promo codes in them but no transaction ids. I am struggling to find a way to tie them together. Is this even possible?
Hello, ajhank2.



In English:


Since in server notifications Apple does not send data that allows you to relate a user to the notification received, when you receive a notification of an initial purchase (INITIAL_BUY) you will not know which user it corresponds to.

When you receive the INITIAL_BUY notification you should save the record in your database, waiting to be able to relate it later with a user.

To obtain that information you would have to ask the user to connect to the app, retrieve the receipt and the original_transaction_id related to that purchase, send it to the backend server along with the user's ID in your system (logged in the app), so that it executes the call to the verifyReceipt URL using the receipt (obtained from the app). In the value returned by verifyReceipt you should have that original_transaction_id (which confirms the validity of the receipt) and on the server you can now link the values of original_transaction_id and the user ID. The next notifications you receive with the renewals will arrive with the original_transaction_id, which you will already have linked in your database with a user, so you have no problem to know who they correspond to.

If you let the subscriptions expire, from the app you can resubscribe and the same original_transaction_id that was generated in the first purchase will be used. If you go more than 180 days without renewing any subscription, the next time you buy you will receive another INITIAL_BUY notification, and you will be in the same case again.

In our case it is normal that the first purchase is made in the app, so at that moment, when we have the receipt, the original_transaction_id and the user ID, in the call to our backend (API Gateway in AWS), is when we make the data binding, so that the following notifications we have all the data we need.



In Spanish:


Dado que en las notificaciones de servidor Apple no envía datos que permitan relacionar un usuario con la notificación recibida, cuando recibes una notificación de la una compra inicial (INITIAL_BUY) no sabrás a qué usuario corresponde.

Cuando te llegue la notificación INITIAL_BUY deberías guardar el registro en tu base de datos, a la espera de poder relacionarla posteriormente con un usuario.

Para obtener esa información tendrías que pedirle al usuario que se conectara a la app, recuperar en ella el receipt y el original_transaction_id relacionado con esa compra, enviarla al servidor de backend junto con el ID del usuario en tu sistema (logado en la app), para que este ejecute la llamada a la URL de verifyReceipt con usando el receipt (obtenido de la app). En el valor devuelto por verifyReceipt deberias tener ese original_transaction_id (lo que confirma la validez del receipt) y en el servidor ya puedes vincular los valores de original_transaction_id y el ID del usuario. Las siguientes notificaciones que te lleguen con las renovaciones llegarán con el original_transaction_id, que ya tendrás vinculado en tu base de datos con un usuario, con lo que no tienes problema para saber a quién corresponden.

Si dejas que las suscripciones caduquen, desde la app puedes resuscribirte y se usará el mismo original_transaction_id que se generó en la primera compra. Si estás más de 180 días sin renovar ninguna suscripción, la proxima vez que compres se recibirá otra notificación INITIAL_BUY, y volverás a estar en el mismo caso.

En nuestro caso lo normal es que la primera compra se haga en la app, por lo que en ese momento, en el que tenemos el receipt, el original_transaction_id y el ID del usuario, en la llamada a nuestro backend (API Gateway en AWS), es cuando hacemos la vinculación de los datos, para que las siguientes notificaciones tengamos todos los datos que necesitaremos.



Kind regards,
Oscar

It's very strage that Apple chose to make it so complicated. In other "normal" payment providers you simply have the option to pass a CUSTOM_FIELD when sending the user to the payment screen. Then, in the IPN (The server notification) they simply send you back this CUSTOM_FIELD. So you can for example simply pass the user_id in this field, and get it back from the server, to easily correlate the server notification to a user. That's it.

If I understand correctly, this architecture that Apple chose, besides being complicated, is also not safe. When a user buys inside the app, you need to take the receipt from the App, send to your server (together with the customer id!), and then verifyReceipt with Apple, and then save in your DB. If, for any reason, after the customer finishes the buy, the app crashes OR the internet communcation fails, and you dont send the receipt to your server, it will never be correlated to the user id => serious bug.

@oscaretu does it mean that original_transaction_id is globally unique and we can use it to identify user? I mean Apple documentation says original_transaction_id / transaction_id are unique to particular user. But can 2 different users have transaction with the same original_transaction_id / transaction_id?

In our app and backend we do exactly what you have described. But we've faced some issue. So,

  1. User purchases subscription in the App
  2. The App sends request to the backend with transaction_id and our internal user_id
  3. Backend creates record in database to link transaction_id with user_id.
  4. Apple sends INITIAL_BUY notification to our backend
  5. Backend process verifyReceipt and based on the response data creates subscription record in our database. Because we have transaction_id linked with the user_id we know that this subscription belongs to this particular user.

However, we have faced an issue that Apple Notification comes to the backend quicker than App sends request to the backend to link transaction_id with the user_id. So, processing INITIAL_BUY notification fails, as we cannot fetch user_id by transaction_id and save subscription to our database.

We've been thinking to save subscription without user_id when processing INITIAL_BUY notification and then link subscription to the user_id afterwards, when app sends transaction_id and user_id to the backend. But how do we know which subscription to link with the user? How to identify correct subscription? We don't want the case that one user will "steal" some other user's subscription.

Matching original_transaction_id to subscriber id.
 
 
Q