Skip to content

Commit 2b566af

Browse files
Merge pull request #210 from alexanderjordanbaker/AppStoreServerNotificationsV2.17
Adding support for App Store Server Notifications v2.17
2 parents 4c855d0 + 22f1a73 commit 2b566af

6 files changed

Lines changed: 49 additions & 2 deletions

File tree

‎appstoreserverlibrary/models/ExternalPurchaseToken.py‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import attr
66

77
from .LibraryUtility import AttrsRawValueAware
8+
from .TokenType import TokenType
89

910
@define
1011
class ExternalPurchaseToken(AttrsRawValueAware):
@@ -40,4 +41,23 @@ class ExternalPurchaseToken(AttrsRawValueAware):
4041
The bundle identifier of an app.
4142
4243
https://developer.apple.com/documentation/appstoreservernotifications/bundleid
44+
"""
45+
46+
tokenType: Optional[TokenType] = TokenType.create_main_attr('rawTokenType')
47+
"""
48+
The type of an external purchase custom link token.
49+
50+
https://developer.apple.com/documentation/appstoreservernotifications/tokentype
51+
"""
52+
53+
rawTokenType: Optional[str] = TokenType.create_raw_attr('tokenType')
54+
"""
55+
See tokenType
56+
"""
57+
58+
tokenExpirationDate: Optional[int] = attr.ib(default=None)
59+
"""
60+
The field of a custom link token that contains the UNIX date, in milliseconds, when the token expires.
61+
62+
https://developer.apple.com/documentation/appstoreservernotifications/tokenexpirationdate
4363
"""

‎appstoreserverlibrary/models/Subtype.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,5 @@ class Subtype(str, Enum, metaclass=AppStoreServerLibraryEnumMeta):
2727
SUMMARY = "SUMMARY"
2828
FAILURE = "FAILURE"
2929
UNREPORTED = "UNREPORTED"
30+
ACTIVE_TOKEN_REMINDER = "ACTIVE_TOKEN_REMINDER"
31+
CREATED = "CREATED"
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Copyright (c) 2026 Apple Inc. Licensed under MIT License.
2+
3+
from enum import Enum
4+
5+
from .LibraryUtility import AppStoreServerLibraryEnumMeta
6+
7+
class TokenType(str, Enum, metaclass=AppStoreServerLibraryEnumMeta):
8+
"""
9+
The type of an external purchase custom link token.
10+
11+
https://developer.apple.com/documentation/appstoreservernotifications/tokentype
12+
"""
13+
SERVICES = "SERVICES"
14+
ACQUISITION = "ACQUISITION"

‎tests/resources/models/signedExternalPurchaseTokenNotification.json‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
"externalPurchaseId": "b2158121-7af9-49d4-9561-1f588205523e",
99
"tokenCreationDate": 1698148950000,
1010
"appAppleId": 55555,
11-
"bundleId": "com.example"
11+
"bundleId": "com.example",
12+
"tokenType": "ACQUISITION",
13+
"tokenExpirationDate": 1698149000000
1214
}
1315
}

‎tests/resources/models/signedExternalPurchaseTokenSandboxNotification.json‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
"externalPurchaseId": "SANDBOX_b2158121-7af9-49d4-9561-1f588205523e",
99
"tokenCreationDate": 1698148950000,
1010
"appAppleId": 55555,
11-
"bundleId": "com.example"
11+
"bundleId": "com.example",
12+
"tokenType": "ACQUISITION",
13+
"tokenExpirationDate": 1698149000000
1214
}
1315
}

‎tests/test_decoded_payloads.py‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from appstoreserverlibrary.models.RevocationType import RevocationType
2020
from appstoreserverlibrary.models.Status import Status
2121
from appstoreserverlibrary.models.Subtype import Subtype
22+
from appstoreserverlibrary.models.TokenType import TokenType
2223
from appstoreserverlibrary.models.TransactionReason import TransactionReason
2324
from appstoreserverlibrary.models.Type import Type
2425
from appstoreserverlibrary.models.AdvancedCommercePeriod import AdvancedCommercePeriod
@@ -360,6 +361,9 @@ def check_environment_and_bundle_id(bundle_id: Optional[str], app_apple_id: Opti
360361
self.assertEqual(1698148950000, notification.externalPurchaseToken.tokenCreationDate)
361362
self.assertEqual(55555, notification.externalPurchaseToken.appAppleId)
362363
self.assertEqual("com.example", notification.externalPurchaseToken.bundleId)
364+
self.assertEqual(TokenType.ACQUISITION, notification.externalPurchaseToken.tokenType)
365+
self.assertEqual("ACQUISITION", notification.externalPurchaseToken.rawTokenType)
366+
self.assertEqual(1698149000000, notification.externalPurchaseToken.tokenExpirationDate)
363367

364368
def test_external_purchase_token_sandbox_notification_decoding(self):
365369
signed_external_purchase_token_notification = create_signed_data_from_json('tests/resources/models/signedExternalPurchaseTokenSandboxNotification.json')
@@ -389,6 +393,9 @@ def check_environment_and_bundle_id(bundle_id: Optional[str], app_apple_id: Opti
389393
self.assertEqual(1698148950000, notification.externalPurchaseToken.tokenCreationDate)
390394
self.assertEqual(55555, notification.externalPurchaseToken.appAppleId)
391395
self.assertEqual("com.example", notification.externalPurchaseToken.bundleId)
396+
self.assertEqual(TokenType.ACQUISITION, notification.externalPurchaseToken.tokenType)
397+
self.assertEqual("ACQUISITION", notification.externalPurchaseToken.rawTokenType)
398+
self.assertEqual(1698149000000, notification.externalPurchaseToken.tokenExpirationDate)
392399

393400
def test_realtime_request_decoding(self):
394401
signed_realtime_request = create_signed_data_from_json('tests/resources/models/decodedRealtimeRequest.json')

0 commit comments

Comments
 (0)