youknowone / itunes-iap

Apple iTunes In-app purchase verification tool
http://itunes-iap.readthedocs.io
Other
136 stars 50 forks source link

MissingFieldError: expires_date_ms during validation on Server Notification reception #48

Closed FrancoisDupayrat closed 6 years ago

FrancoisDupayrat commented 7 years ago

Important informations to reproduce:

I am at a loss if this issue is poor documentation by Apple or an actual bug with Apple API, but when trying to verify a receipt with those conditions, itunes-iap will throw "MissingFieldError: expires_date_ms". I sent a bug report to Apple, but have no idea if it will move the needle on their side.

In the meantime, it would be great if itunes-iap could handle this gracefully without waiting for Apple to acknowledge the issue and fix it.

Please find attached an anonymised status notification call and anonymised response of the API which exhibit the issue when trying to validate after that status notification.

You'll notice that the Status Notification doesn't have expires_date_ms either, so if itunes-iap want to support it at some point, it'll need to be able to work without that field.

apple-status-notification.txt verify-result.txt

Here is the full unedited stacktrace: 17-09-27T15:08:20.564417+00:00 app[web.1]: ERROR [django.request:132] Internal Server Error: /api/apple_subscription_notif/ 2017-09-27T15:08:20.564419+00:00 app[web.1]: Traceback (most recent call last): 2017-09-27T15:08:20.564420+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/itunesiap/receipt.py", line 141, in _get 2017-09-27T15:08:20.564421+00:00 app[web.1]: value = self.[name] 2017-09-27T15:08:20.564422+00:00 app[web.1]: KeyError: 'expires_date_ms' 2017-09-27T15:08:20.564423+00:00 app[web.1]: 2017-09-27T15:08:20.564423+00:00 app[web.1]: During handling of the above exception, another exception occurred: 2017-09-27T15:08:20.564424+00:00 app[web.1]: 2017-09-27T15:08:20.564425+00:00 app[web.1]: Traceback (most recent call last): 2017-09-27T15:08:20.564425+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/django/core/handlers/exception.py", line 42, in inner 2017-09-27T15:08:20.564426+00:00 app[web.1]: response = get_response(request) 2017-09-27T15:08:20.564427+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/django/core/handlers/base.py", line 187, in _get_response 2017-09-27T15:08:20.564428+00:00 app[web.1]: response = self.process_exception_by_middleware(e, request) 2017-09-27T15:08:20.564429+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/django/core/handlers/base.py", line 185, in _get_response 2017-09-27T15:08:20.564429+00:00 app[web.1]: response = wrapped_callback(request, *callback_args, callback_kwargs) 2017-09-27T15:08:20.564430+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view 2017-09-27T15:08:20.564431+00:00 app[web.1]: return view_func(*args, *kwargs) 2017-09-27T15:08:20.564431+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/tastypie/resources.py", line 219, in wrapper 2017-09-27T15:08:20.564432+00:00 app[web.1]: response = callback(request, args, kwargs) 2017-09-27T15:08:20.564433+00:00 app[web.1]: return self.dispatch('list', request, kwargs) 2017-09-27T15:08:20.564433+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/tastypie/resources.py", line 450, in dispatch_list 2017-09-27T15:08:20.564434+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/tastypie/resources.py", line 482, in dispatch 2017-09-27T15:08:20.564434+00:00 app[web.1]: response = method(request, kwargs) 2017-09-27T15:08:20.564435+00:00 app[web.1]: File "/app/licensing/api.py", line 828, in post_list 2017-09-27T15:08:20.564436+00:00 app[web.1]: notif = self.obj_create(bundle=basic_bundle, **self.remove_api_resource_names(kwargs)) 2017-09-27T15:08:20.564436+00:00 app[web.1]: File "/app/licensing/api.py", line 804, in obj_create 2017-09-27T15:08:20.564437+00:00 app[web.1]: False 2017-09-27T15:08:20.564438+00:00 app[web.1]: File "/app/licensing/models.py", line 93, in authorize_purchase 2017-09-27T15:08:20.564439+00:00 app[web.1]: if (in_app.expires_date_ms is not None and 2017-09-27T15:08:20.564439+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/itunesiap/receipt.py", line 148, in getattr 2017-09-27T15:08:20.564440+00:00 app[web.1]: return self.getattribute(name) 2017-09-27T15:08:20.564440+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/itunesiap/tools.py", line 14, in get 2017-09-27T15:08:20.564441+00:00 app[web.1]: value = self.function(obj) 2017-09-27T15:08:20.564442+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.5/site-packages/itunesiap/receipt.py", line 143, in _get 2017-09-27T15:08:20.564442+00:00 app[web.1]: raise MissingFieldError(name) 2017-09-27T15:08:20.564446+00:00 app[web.1]: itunesiap.receipt.MissingFieldError: expires_date_ms

youknowone commented 6 years ago

Hello, I am not sure it is Apple's bug or intended result. But itunes-iap should work for any kind of Apple receipt in real world.

Thanks for the report, and especially about attached files. Usually it is hard to get related receipt data, thanks :)

FrancoisDupayrat commented 6 years ago

Hello, I just got a response from my report to Apple. This is an intended result. Here is the response I got:

Hi François, This is a courtesy email regarding Bug ID# 34687028. Engineering has provided the following feedback regarding this issue: There should be a field called “expires_date” in the JSON response with the same value. Thank you for your feedback. Engineering has determined that this issue behaves as intended. We are now closing this bug report. If you just have questions about the resolution, then please update your bug report with that information so we can respond.