return same transaction_id with different receipt

I use https://buy.itunes.apple.com/verifyReceipt as the URL,Validating Receipts With the App Store

After quering the server log,I find there are two requests with different receipts,but same transaction_id.The only difference value is original_purchase_date_ms.

ewoJInNpZ25hdHVyZSIgPSAiQWlRRjE1WVRQckNTLzd1ejV1Vmw4SVdvUFFVSW55Yi9NeFVaZGdVY2dkdEF5ZUE4VnF4OGV5ZjM1NUhPNE1lV2k2RzFJeDAvNkdYSlk4WmowY0IwR092cG9DSEVsUHFLaTBwMVkxU0NOb296UkdVTGxLT3N3ckRZTVRGYm1CL0x4ZmFzOXZyajI1a3lmNUI2T2Z3Snk2c0NsSnVDUVdwTWRCaUQvSi9xR0NMR0FBQURWekNDQTFNd2dnSTdvQU1DQVFJQ0NCdXA0K1BBaG0vTE1BMEdDU3FHU0liM0RRRUJCUVVBTUg4eEN6QUpCZ05WQkFZVEFsVlRNUk13RVFZRFZRUUtEQXBCY0hCc1pTQkpibU11TVNZd0pBWURWUVFMREIxQmNIQnNaU0JEWlhKMGFXWnBZMkYwYVc5dUlFRjFkR2h2Y21sMGVURXpNREVHQTFVRUF3d3FRWEJ3YkdVZ2FWUjFibVZ6SUZOMGIzSmxJRU5sY25ScFptbGpZWFJwYjI0Z1FYVjBhRzl5YVhSNU1CNFhEVEUwTURZd056QXdNREl5TVZvWERURTJNRFV4T0RFNE16RXpNRm93WkRFak1DRUdBMVVFQXd3YVVIVnlZMmhoYzJWU1pXTmxhWEIwUTJWeWRHbG1hV05oZEdVeEd6QVpCZ05WQkFzTUVrRndjR3hsSUdsVWRXNWxjeUJUZEc5eVpURVRNQkVHQTFVRUNnd0tRWEJ3YkdVZ1NXNWpMakVMTUFrR0ExVUVCaE1DVlZNd2daOHdEUVlKS29aSWh2Y05BUUVCQlFBRGdZMEFNSUdKQW9HQkFNbVRFdUxnamltTHdSSnh5MW9FZjBlc1VORFZFSWU2d0Rzbm5hbDE0aE5CdDF2MTk1WDZuOTNZTzdnaTNvclBTdXg5RDU1NFNrTXArU2F5Zzg0bFRjMzYyVXRtWUxwV25iMzRucXlHeDlLQlZUeTVPR1Y0bGpFMU93QytvVG5STStRTFJDbWVOeE1iUFpoUzQ3VCtlWnRERWhWQjl1c2szK0pNMkNvZ2Z3bzdBZ01CQUFHamNqQndNQjBHQTFVZERnUVdCQlNKYUVlTnVxOURmNlpmTjY4RmUrSTJ1MjJzc0RBTUJnTlZIUk1CQWY4RUFqQUFNQjhHQTFVZEl3UVlNQmFBRkRZZDZPS2RndElCR0xVeWF3N1hRd3VSV0VNNk1BNEdBMVVkRHdFQi93UUVBd0lIZ0RBUUJnb3Foa2lHOTJOa0JnVUJCQUlGQURBTkJna3Foa2lHOXcwQkFRVUZBQU9DQVFFQWVhSlYyVTUxcnhmY3FBQWU1QzIvZkVXOEtVbDRpTzRsTXV0YTdONlh6UDFwWkl6MU5ra0N0SUl3ZXlOajVVUllISytIalJLU1U5UkxndU5sMG5rZnhxT2JpTWNrd1J1ZEtTcTY5Tkluclp5Q0Q2NlI0Szc3bmI5bE1UQUJTU1lsc0t0OG9OdGxoZ1IvMWtqU1NSUWNIa3RzRGNTaVFHS01ka1NscDRBeVhmN3ZuSFBCZTR5Q3dZVjJQcFNOMDRrYm9pSjNwQmx4c0d3Vi9abEwyNk0ydWVZSEtZQ3VYaGRxRnd4VmdtNTJoM29lSk9PdC92WTRFY1FxN2VxSG02bTAzWjliN1BSellNMktHWEhEbU9Nazd2RHBlTVZsTERQU0dZejErVTNzRHhKemViU3BiYUptVDdpbXpVS2ZnZ0VZN3h4ZjRjemZIMHlqNXdOelNHVE92UT09IjsKCSJwdXJjaGFzZS1pbmZvIiA9ICJld29KSW05eWFXZHBibUZzTFhCMWNtTm9ZWE5sTFdSaGRHVXRjSE4wSWlBOUlDSXlNREUyTFRBekxURXdJREExT2pVNU9qVTBJRUZ0WlhKcFkyRXZURzl6WDBGdVoyVnNaWE1pT3dvSkluQjFjbU5vWVhObExXUmhkR1V0YlhNaUlEMGdJakUwTlRjMk1UZ3pPVFF3TURBaU93b0pJblZ1YVhGMVpTMXBaR1Z1ZEdsbWFXVnlJaUE5SUNJNE16STJZbUZpWmpFNU5XUTJNRGMwTlRVNFlUVXhPV1psTTJVNVlUQTFZemxoWTJabE56bG1JanNLQ1NKdmNtbG5hVzVoYkMxMGNtRnVjMkZqZEdsdmJpMXBaQ0lnUFNBaU16UXdNREF3TURrNU5USTNOemsySWpzS0NTSmlkbkp6SWlBOUlDSTFMak11TUM0eElqc0tDU0poY0hBdGFYUmxiUzFwWkNJZ1BTQWlORFU0TlRnM056VTFJanNLQ1NKMGNtRnVjMkZqZEdsdmJpMXBaQ0lnUFNBaU16UXdNREF3TURrNU5USTNOemsySWpzS0NTSnhkV0Z1ZEdsMGVTSWdQU0FpTVNJN0Nna2liM0pwWjJsdVlXd3RjSFZ5WTJoaGMyVXRaR0YwWlMxdGN5SWdQU0FpTVRRMU56WXhPRE01TkRBd01DSTdDZ2tpZFc1cGNYVmxMWFpsYm1SdmNpMXBaR1Z1ZEdsbWFXVnlJaUE5SUNKQ1JUZzBNREl5UlMwNVFUSXhMVFF4TURjdFFUZzRPQzFFUVRjeU1VTXdSRU00TTBRaU93b0pJbWwwWlcwdGFXUWlJRDBnSWpreU1USXdORE0zTmlJN0Nna2lkbVZ5YzJsdmJpMWxlSFJsY201aGJDMXBaR1Z1ZEdsbWFXVnlJaUE5SUNJNE1UWXhNalF4T1RJaU93b0pJbkJ5YjJSMVkzUXRhV1FpSUQwZ0lqVTBJanNLQ1NKd2RYSmphR0Z6WlMxa1lYUmxJaUE5SUNJeU1ERTJMVEF6TFRFd0lERXpPalU1T2pVMElFVjBZeTlIVFZRaU93b0pJbTl5YVdkcGJtRnNMWEIxY21Ob1lYTmxMV1JoZEdVaUlEMGdJakl3TVRZdE1ETXRNVEFnTVRNNk5UazZOVFFnUlhSakwwZE5WQ0k3Q2draVltbGtJaUE5SUNKamIyMHVjMjlvZFM1cFVHaHZibVZXYVdSbGJ5STdDZ2tpY0hWeVkyaGhjMlV0WkdGMFpTMXdjM1FpSUQwZ0lqSXdNVFl0TURNdE1UQWdNRFU2TlRrNk5UUWdRVzFsY21sallTOU1iM05mUVc1blpXeGxjeUk3Q24wPSI7CgkicG9kIiA9ICIzNCI7Cgkic2lnbmluZy1zdGF0dXMiID0gIjAiOwp9

ewoJInNpZ25hdHVyZSIgPSAiQWo5TFRudC9HcDV3MjdHRU1jY1RpUW83ZFdyc1Q3Wm5qVW9XN29HQkpxY0l0clB6MHBrdlFkSEswb083eWNrN3dVOW5KRURWUzdtQ21Rak1ITHNSQ0hVY2w1UThIVjNJWUtBMnpURzJHbkM1Snp6MkdUQWpJTUViU1RmanBmNmJwS1VIajR3bTdQN2hZYSswd0E5QVNJQUhLVjVjbXlhd29ETHdqMXJoajA5QUFBQURWekNDQTFNd2dnSTdvQU1DQVFJQ0NCdXA0K1BBaG0vTE1BMEdDU3FHU0liM0RRRUJCUVVBTUg4eEN6QUpCZ05WQkFZVEFsVlRNUk13RVFZRFZRUUtEQXBCY0hCc1pTQkpibU11TVNZd0pBWURWUVFMREIxQmNIQnNaU0JEWlhKMGFXWnBZMkYwYVc5dUlFRjFkR2h2Y21sMGVURXpNREVHQTFVRUF3d3FRWEJ3YkdVZ2FWUjFibVZ6SUZOMGIzSmxJRU5sY25ScFptbGpZWFJwYjI0Z1FYVjBhRzl5YVhSNU1CNFhEVEUwTURZd056QXdNREl5TVZvWERURTJNRFV4T0RFNE16RXpNRm93WkRFak1DRUdBMVVFQXd3YVVIVnlZMmhoYzJWU1pXTmxhWEIwUTJWeWRHbG1hV05oZEdVeEd6QVpCZ05WQkFzTUVrRndjR3hsSUdsVWRXNWxjeUJUZEc5eVpURVRNQkVHQTFVRUNnd0tRWEJ3YkdVZ1NXNWpMakVMTUFrR0ExVUVCaE1DVlZNd2daOHdEUVlKS29aSWh2Y05BUUVCQlFBRGdZMEFNSUdKQW9HQkFNbVRFdUxnamltTHdSSnh5MW9FZjBlc1VORFZFSWU2d0Rzbm5hbDE0aE5CdDF2MTk1WDZuOTNZTzdnaTNvclBTdXg5RDU1NFNrTXArU2F5Zzg0bFRjMzYyVXRtWUxwV25iMzRucXlHeDlLQlZUeTVPR1Y0bGpFMU93QytvVG5STStRTFJDbWVOeE1iUFpoUzQ3VCtlWnRERWhWQjl1c2szK0pNMkNvZ2Z3bzdBZ01CQUFHamNqQndNQjBHQTFVZERnUVdCQlNKYUVlTnVxOURmNlpmTjY4RmUrSTJ1MjJzc0RBTUJnTlZIUk1CQWY4RUFqQUFNQjhHQTFVZEl3UVlNQmFBRkRZZDZPS2RndElCR0xVeWF3N1hRd3VSV0VNNk1BNEdBMVVkRHdFQi93UUVBd0lIZ0RBUUJnb3Foa2lHOTJOa0JnVUJCQUlGQURBTkJna3Foa2lHOXcwQkFRVUZBQU9DQVFFQWVhSlYyVTUxcnhmY3FBQWU1QzIvZkVXOEtVbDRpTzRsTXV0YTdONlh6UDFwWkl6MU5ra0N0SUl3ZXlOajVVUllISytIalJLU1U5UkxndU5sMG5rZnhxT2JpTWNrd1J1ZEtTcTY5Tkluclp5Q0Q2NlI0Szc3bmI5bE1UQUJTU1lsc0t0OG9OdGxoZ1IvMWtqU1NSUWNIa3RzRGNTaVFHS01ka1NscDRBeVhmN3ZuSFBCZTR5Q3dZVjJQcFNOMDRrYm9pSjNwQmx4c0d3Vi9abEwyNk0ydWVZSEtZQ3VYaGRxRnd4VmdtNTJoM29lSk9PdC92WTRFY1FxN2VxSG02bTAzWjliN1BSellNMktHWEhEbU9Nazd2RHBlTVZsTERQU0dZejErVTNzRHhKemViU3BiYUptVDdpbXpVS2ZnZ0VZN3h4ZjRjemZIMHlqNXdOelNHVE92UT09IjsKCSJwdXJjaGFzZS1pbmZvIiA9ICJld29KSW05eWFXZHBibUZzTFhCMWNtTm9ZWE5sTFdSaGRHVXRjSE4wSWlBOUlDSXlNREUyTFRBekxURXdJREExT2pVNU9qVTBJRUZ0WlhKcFkyRXZURzl6WDBGdVoyVnNaWE1pT3dvSkluQjFjbU5vWVhObExXUmhkR1V0YlhNaUlEMGdJakUwTlRjMk1UZ3pPVFEyTnpNaU93b0pJblZ1YVhGMVpTMXBaR1Z1ZEdsbWFXVnlJaUE5SUNJNE16STJZbUZpWmpFNU5XUTJNRGMwTlRVNFlUVXhPV1psTTJVNVlUQTFZemxoWTJabE56bG1JanNLQ1NKdmNtbG5hVzVoYkMxMGNtRnVjMkZqZEdsdmJpMXBaQ0lnUFNBaU16UXdNREF3TURrNU5USTNOemsySWpzS0NTSmlkbkp6SWlBOUlDSTFMak11TUM0eElqc0tDU0poY0hBdGFYUmxiUzFwWkNJZ1BTQWlORFU0TlRnM056VTFJanNLQ1NKMGNtRnVjMkZqZEdsdmJpMXBaQ0lnUFNBaU16UXdNREF3TURrNU5USTNOemsySWpzS0NTSnhkV0Z1ZEdsMGVTSWdQU0FpTVNJN0Nna2liM0pwWjJsdVlXd3RjSFZ5WTJoaGMyVXRaR0YwWlMxdGN5SWdQU0FpTVRRMU56WXhPRE01TkRZM015STdDZ2tpZFc1cGNYVmxMWFpsYm1SdmNpMXBaR1Z1ZEdsbWFXVnlJaUE5SUNKQ1JUZzBNREl5UlMwNVFUSXhMVFF4TURjdFFUZzRPQzFFUVRjeU1VTXdSRU00TTBRaU93b0pJbWwwWlcwdGFXUWlJRDBnSWpreU1USXdORE0zTmlJN0Nna2lkbVZ5YzJsdmJpMWxlSFJsY201aGJDMXBaR1Z1ZEdsbWFXVnlJaUE5SUNJNE1UWXhNalF4T1RJaU93b0pJbkJ5YjJSMVkzUXRhV1FpSUQwZ0lqVTBJanNLQ1NKd2RYSmphR0Z6WlMxa1lYUmxJaUE5SUNJeU1ERTJMVEF6TFRFd0lERXpPalU1T2pVMElFVjBZeTlIVFZRaU93b0pJbTl5YVdkcGJtRnNMWEIxY21Ob1lYTmxMV1JoZEdVaUlEMGdJakl3TVRZdE1ETXRNVEFnTVRNNk5UazZOVFFnUlhSakwwZE5WQ0k3Q2draVltbGtJaUE5SUNKamIyMHVjMjlvZFM1cFVHaHZibVZXYVdSbGJ5STdDZ2tpY0hWeVkyaGhjMlV0WkdGMFpTMXdjM1FpSUQwZ0lqSXdNVFl0TURNdE1UQWdNRFU2TlRrNk5UUWdRVzFsY21sallTOU1iM05mUVc1blpXeGxjeUk3Q24wPSI7CgkicG9kIiA9ICIzNCI7Cgkic2lnbmluZy1zdGF0dXMiID0gIjAiOwp9

Replies

Yes, this is a change in the new receipts going back some time. My bug report is 23828636. It is a security issue, big time.


In the earlier receipts the transaction_id was, in fact, the transactionIdentifier. It was unique for all transactions and could be used to detect copied receipts and to differentiate repurchase-for-free and restore transactions from original paid purchases. It was included in the receipt. Now that transaction.transactionReceipt is deprecated we must use the new receipts. The transaction_id in post iOS6 receipts is now the same as original_transaction_id. There is no separate field for the transactionIdentifier for the latest transaction, just for each idividual IAP - and they all reflect the original purchase transaction. This means transaction_id can no longer be used to identifiy a copied receipt nor can it be used to tell whether the user has restored a transaction or repurchased an item for free. What you can do is detect the value of "receipt_creation_date" aka "creation_date" and compare that to the value for "original_purchase_date". If they are within a few seconds of each other then the purchase is a new paid purchase not a restore and not a repurchase-for-free. Also, if "creation_date" is close to [[NSDate alloc] init] then the receipt is not copied - you have to get the NSDate format correct.

Thank you for your reply.What you mean is it's a bug of Apple for a long time,and you'v reported the bug.

I can't post my JSON format result to this forums ,so I post the receip and result to my Facebook.There is not a value receipt_creation_date in in the result.I still use transactionIdentifier to differentiate transactions.The only difference of two result is original_purchase_date_ms.


We still use the deprecated API transaction.transactionReceipt ,the reason is when we use the new API [NSData dataWithContentsOfURL:[[NSBundle mainBundle] appStoreReceiptURL]] .The transactionReceipt returned is too long .when receipt is sent to Apple for to validate the status returned by Apple is 21002 sometimes ,and sometimes it's valid.


the receip and result

So do we. We still use deprecated api as the same reason as you guys. It's a little bit annoying.....


contact me if you want discuss about this issue at QQ 53701845

Is this problem have been solved? Or it's not a bug at all?

This problem has not been addressed by Apple. They say it is not a security problem. They are wrong. But actually here is a solution that is just as good as before. Use the combination of transaction_id and creation_date in your server to identify a receipt that is a duplicate of another receipt that you have received. Reject any duplicates.


This does not protect you from someone doing a restore and grabbing the receipt before it is sent to your server and using that receipt to allow someone steal the IAP. But that scam could also have been used even when the receipt had unique transaction_id's.


If you want full protection then either decode the receipt yourself relying on the uniqueness of the device's identifierForVendor or check to be sure that the creation_date comes very shortly after the date of the actual purchaseRequest (except for an ask-to-buy purchase - so it's not fool-proof).