I'm trying to call the Test Notification endpoint: https://developer.apple.com/documentation/appstoreserverapi/request_a_test_notification?language=objc
I'm creating a JWT bearer token using a script I run on the console with these 2 commands: npm install jsonwebtoken fs and node generate_jwt.js
Keys are taken from App Store Connect -> User and Access -> Integrations -> Keys -> In-App Purchase.
generate_jwt.js script:
const jwt = require('jsonwebtoken');
const fs = require('fs');
const keyId = 'MY_KEY_ID';
const issuerId = 'MY_ISSUER_ID';
const privateKey = `-----BEGIN PRIVATE KEY-----
MY_SECRET_KEY
-----END PRIVATE KEY-----`;
// Define JWT headers and claims
const token = jwt.sign({}, privateKey, {
algorithm: 'ES256',
expiresIn: '1h',
issuer: issuerId,
header: {
alg: 'ES256',
kid: keyId,
},
audience: 'appstoreconnect-v1'
});
console.log('JWT Token:', token);
When I run a POST https://api.storekit.itunes.apple.com/inApps/v1/notifications/test request on postman with Bearer token authentication, I get a 401 Unauthorized error.
App Store Server Notifications
RSS for tagMonitor subscription events in real time with server notifications from the App Store using App Store Server Notifications.
Posts under App Store Server Notifications tag
85 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
How can I get the App Store Server Notifications again if my server is down? As far as I know, Apple sends a notification once. What if the server was unavailable? How to get this notification again?
Hello,
About a month ago me and my team allocated a sprint to migrate the App Store Server Notifications service and the StoreKit library from v1 to v2.
Once the implementation was completed, we started testing using the sandbox environment (which was supposed to provide greater stability and maturity in v2).
The testing session went well, we managed to test various scenarios without noticing any issue (successful payment, failed payment, renewal etc).
This week, before doing the production deployment, a final testing session was scheduled.
Out of nowhere, we started to encounter all kinds of strange behaviours such as:
StoreKit2 error (in Xcode)
Received error that does not have a corresponding StoreKit Error: Error Domain=ASDErrorDomain Code=825 "No transactions in response" UserInfo={NSDebugDescription=No transactions in response}
Purchase did not return a transaction: Error Domain=ASDErrorDomain Code=825 "No transactions in response" UserInfo={NSDebugDescription=No transactions in response}
In some cases the transaction id resulting from the payment was retuned "" or nil, causing our server to raise an exception.
Newly created sandbox account that was raising an error that says "there is already a subscription made on this apple id".
Delays in the payment processing
Today, without doing any code changes, we managed to test all the scenarios without encountering any issue.
Due to the oscillating experience we had in the sandbox environment, we are considering postponing the release and maintaining StoreKit 1 for now, but even in this case, the fact that App Store Connect does not offer the possibility of rolling back the Notification Service to v1, causes inconvenience.
Has anyone encountered something similar? Is migrating to v2 a good choice?
I'm using my sandbox account to subscribed to something. I am now trying to open the subscribed item in Settings > Apple ID > Subscriptions > Click on the active sandbox subscription > Cannot Connect.
Has anyone else encountered this? How were you able to get around it?
My server receives App Store Server Notification v2 notifications. Recently, it has been receiving notifications for offer codes under offers that have been deactivated. The custom code value may be the same in the active offer as the deactivated offer.
When a user redeems the custom offer code for a deactivated offer, the notification payload's offerIdentifier value now contains the UUID associated with that offer in the URL in App Store Connect
(like https://appstoreconnect.apple.com/apps/my-app-id/distribution/subscriptions/my-subscription-id/pricing/offer-codes/offer-uuid)
The notification payload contains:
{"offerIdentifier": "offer-uuid"}
instead of
{"offerIdentifier": "<My offer identifier from App Store Connect>"}
Is it possible for a deactivated offer to be redeemed? If not, is this a known issue?
We need the actual offer identifier to understand which offers users are redeeming. Is this replacement with a UUID a known issue?
Hello everyone,
We have an app that implements in-app purchases, and we're using the notification settings outlined in this Apple Developer guide. Everything is functioning correctly in TestFlight, and our server successfully receives notifications from Apple.
However, after releasing the app to production, we're no longer receiving these notifications, while the TestFlight version continues to work as expected.
Has anyone encountered a similar issue or have any suggestions on how to resolve this?
Thank you for your help!
I keep getting 401 Unauthorized error when fetching Apple's public keys.
In [14]: print(f"Error fetching public keys: {response.status_code} {response.text}")
Error fetching public keys: 401 Unauthenticated
I've verified that the Key ID, Issuer ID, and private key file are all correct, with the private key having admin access. The server time is correctly set to UTC. Given this, I can't identify what might be causing the issue. Any insights?
def generate_apple_developer_token():
# Load the private key in PEM format
with open(PRIVATE_KEY_FILE, 'rb') as key_file:
private_key = serialization.load_pem_private_key(
key_file.read(),
password=None,
backend=default_backend()
)
# JWT header
headers = {
"alg": "ES256",
"kid": KEY_ID,
"typ": "JWT"
}
# JWT payload
payload = {
"iss": ISSUER_ID,
"iat": int(datetime.utcnow().timestamp()),
"exp": int((datetime.utcnow() + timedelta(minutes=10)).timestamp()),
"aud": "appstoreconnect-v1",
}
# Encode the header and payload as base64
header_base64 = base64.urlsafe_b64encode(json.dumps(headers).encode()).decode().rstrip("=")
payload_base64 = base64.urlsafe_b64encode(json.dumps(payload).encode()).decode().rstrip("=")
# Concatenate header and payload
message = f"{header_base64}.{payload_base64}".encode()
# Sign the message using ECDSA with SHA256
signature = private_key.sign(
message,
ec.ECDSA(hashes.SHA256())
)
# Convert the DER-encoded signature to raw format (r and s concatenated)
der_to_raw_ecdsa_format = lambda der: der[4:36] + der[-32:]
# Convert the signature to raw format (64 bytes)
signature_64 = der_to_raw_ecdsa_format(signature)
# Base64 URL-encode the signature
signature_base64 = base64.urlsafe_b64encode(signature_64).decode().rstrip("=")
# Concatenate header, payload, and signature to form the JWT
jwt_token = f"{header_base64}.{payload_base64}.{signature_base64}"
return jwt_token
def get_apple_public_keys():
try:
# Generate a fresh JWT
developer_token = generate_apple_developer_token()
# Set up headers with the authorization token
headers = {
"Authorization": f"Bearer {developer_token}"
}
# Fetch the public keys from Apple
response = requests.get('https://api.storekit.itunes.apple.com/in-app-purchase/publicKeys', headers=headers)
# Log the response if it's not successful
if response.status_code != 200:
print(f"Error fetching public keys: {response.status_code} {response.text}")
response.raise_for_status() # Raises an exception for 4xx/5xx errors
# Parse and return the public keys
response_data = response.json()
keys = response_data.get('keys')
if not keys:
print("No 'keys' found in the response from Apple.")
return []
return keys
except requests.exceptions.RequestException as e:
print(f"Error fetching Apple's public keys: {e}")
return []
Hello,
We’re implementing subscription validation on our server using Apple’s latest APIs and have run into a few issues and uncertainties. We are transitioning away from the deprecated /verifyReceipt endpoint and are now using the /inApps/v1/subscriptions/{transactionId} API. However, we have questions about how to handle transaction validation, particularly around older transactions and notification behavior in the sandbox environment. Additionally, we are facing challenges with Apple Server Notifications, especially regarding when we should expect to be notified of subscription cancellations or expirations.
Below are the specific questions we hope the community can help us with:
Question 1:
We are using the inApps/v1/subscriptions/{transactionId} API to retrieve the subscription status and validate subscriptions on our server side, since the /verifyReceipt endpoint has been deprecated. This API always returns the last transaction for a subscription. Should we only validate the latest transaction, and is it guaranteed that even if we provide an older transaction ID, the API will always return the most up-to-date transaction information?
https://developer.apple.com/documentation/appstoreserverapi/get_all_subscription_statuses/
https://developer.apple.com/documentation/appstorereceipts/verifyreceipt
Question 2:
In the sandbox environment, we encountered an empty response when trying to validate a transaction ID. We are attempting to validate older transactions made by the user to keep our system and store subscriptions in sync. Could you provide guidance on why this might be happening and how we can validate older transactions?
Question 3:
We are using Apple Server Notifications to track subscription renewals and changes. However, when a user disables auto-renewal, we do not receive a webhook notification when the subscription actually expires or is canceled. We only get notified when the user changes their renewal preferences. Should we expect a separate notification when the subscription fully expires or is canceled, or is this behavior expected?
https://developer.apple.com/documentation/appstoreservernotifications/notificationtype
I want to sell the same subscription in multiple apps so that if someone subscribes in one they show up as having a subscription in the other.
Apple's documentation states "To get started, use App Store Connect to create a separate and equivalent auto-renewable subscription for each app that offers the multi-app subscription so that users can subscribe from any app." (https://developer.apple.com/documentation/storekit/in-app_purchase/original_api_for_in-app_purchase/subscriptions_and_offers/offering_a_subscription_across_multiple_apps)
But I'm unable to create two subscriptions with the same Product ID. I could create two subscriptions that are equivalent but with different Product IDs that are treated as the same by our server, which would accomplish the main goal, but I believe this risks someone subscribing to both subscriptions if they do so directly through the App Store, for example using a promo code link, because they're still two different subscriptions to Apple.
Thanks!
We always receive six times about the same TransactionID.
You can see the image.
It's not five times.
We are under V2.
Any comments will be helpful.
We experienced an issue with delayed App Store Server notifications for an Auto-Renewable Subscription purchase in our app.
On September 27, 2024, at 22:28:28 GMT+0900, a user successfully purchased a Premium membership subscription (transaction ID: 190002223966278, webOrderLineItemId: 190001007274949).
However, our server did not receive the corresponding App Store notification for this transaction after purchase.
The App Store Server Notification was only received 66 minutes later, at 23:35:16 (transaction ID: 190002224000004, webOrderLineItemId: 190001007274949).
The delayed notification contained a different transaction ID than the initial purchase.
We would like to inquire about the cause of this delay and request assistance in understanding why the notification took 66 minutes to be delivered to our server, instead of arriving immediately after the transaction was completed.
Additionally, we would appreciate your guidance on how to prevent or mitigate such delays in the future, ensuring a seamless experience for our users.
Are there any best practices or recommended approaches we should implement to handle potential notification delays more effectively?
We have provided detailed information about the received notification and the related transactions in the Feedback Assistant (FB15330451).
Thank you for your assistance in resolving this matter.
Key Details
Purchase time: 2024-09-27T22:28:28 GMT+0900 (1727443708000)
Notification received: 2024-09-27T23:35:16 GMT+0900 (1727447716463)
Delay: 66 minutes and 48 seconds
Initial Purchase Transaction ID: 190002223966278
Initial Purchase Web Order Line Item ID: 190001007274949
Transaction ID in Delayed Notification: 190002224000004
Web Order Line Item ID in Delayed Notification: 190001007274949
Additional info
Bundle ID: com.reppley.ReppleyApp
SKU: com.reppley.ReppleyApp
Feedback Assistant Number: FB15330451
My App uses an auto-renewal subscription, and I've been using the CONSUMPTION_REQUEST event to track user refund requests. However, since yesterday morning, I haven't been receiving any CONSUMPTION_REQUEST notifications. All other notifications are functioning normally and I haven't changed anything. What could be the issue?
I have set up server notification in my app.
I have set up only production server URL and through that URL I can check "CONSUMPTION_REQUEST", "REFUND" notificationType.
However, I want to check all notifications for in-app purchases.
For example, "ONE_TIME_CHARGE" which is consumable in-app purchase type.
If I want to check more notificationTypes on my server,
Do I need to add another setting?
Test notifications are also checked in my server.
https://api.storekit.itunes.apple.com/inApps/v1/notifications/test
We haven't received App Store server notifications in 2 days. When we know we should be. I know the v1 notifications have been deprecated and we need to migrate. But have they now been totally disabled? I can't seem to find any documentation that says they were/will be?
I would like to clarify, do I understand correctly that Cancel and Refund events essentially have the same meaning, except that Cancel cancels the subscription, only the Cancel event applies to auto-renewable subscriptions, and refund applies to one-time purchases and non-renewable purchases?
I am developing and implementing App Store Server Notification V2 for IAP for renewable subscription and consumables for an app
My current flow is on receiving notification from apple, I will process the notification (e.g activate subscription, cancel subscription, etc.). But the ONE_TIME_PURCHASE notificationType only received in sandbox environment, the docs also said the same
The ONE_TIME_CHARGE notification is currently available only in the sandbox environment.
What is the best way for me to process user ONE_TIME_CHARGE transaction of consumables using App Store Server Notification V2 on production build app?
Thank you
Dear Apple Development Team,
I would like to draw attention to certain aspects of working with Server Notifications for In-App Purchases that could be improved to enhance development convenience and API efficiency.
1. Lack of Information on Non-Consumable Purchases in Server Notifications
Currently, Server Notifications do not provide information about non-consumable purchases. This creates certain inconveniences when validating such purchases on the server. It would be extremely useful to have the ability to verify non-consumable purchases in the same way as subscriptions.
Moreover, there is currently no way to obtain information about the amounts paid for non-consumable purchases, even with additional API requests. This limitation significantly complicates financial reporting and analytics for apps that utilize non-consumable purchases. While we can obtain information about the amount paid by the user for a subscription, we have no equivalent capability for non-consumable purchases.
Adding this information to Server Notifications or providing an API endpoint to retrieve it would greatly improve our ability to track and analyze non-consumable purchase data without relying on client-side reporting.
2. Inconsistency in Token and Signature Handling
There is some inconsistency in the approaches to authentication and verification between various Apple APIs. For example:
When using Sign In with Apple, the approach with keyid is applied for JWT verification.
In Server Notifications for In-App Purchases, certificate information is repeatedly duplicated in each notification.
This leads to the need to implement different methods of JWT verification depending on the API being used. Additionally, the current approach with Server Notifications results in data redundancy: the useful payload is about 1.5 KB, while repetitive certificate information takes up about 17 KB in each notification.
Unifying authentication and verification approaches across different APIs could significantly simplify development and improve data processing efficiency.
We would appreciate consideration of these suggestions for API improvement. This could substantially simplify developers' work and increase the efficiency of integrating Apple services into applications.
Thank you for your attention to this matter.
Hello, I'm using 'App Store Server Notifications V2'.
I have a question about 'CONSUMPTION_REQUEST' notification in 'notificationType'.
What problems can occur if the send consumption information API is called without user consent? For example, could there be penalties such as refusing to update the app or blocking the service?
I have triggered few notifications, and they were delivered to my iPhone with a delay of several hours. Could you please assist us in resolving this issue?
Device: iPhone 15
OS Version: 17.5.1
Sever notifications v1 is already deprecated and we are supposed to use the new v2 server notifications and yet arguably the most important notification type is not available for production.