Post not yet marked as solved
I don't often get CONSUMPTION_REQUEST or indeed REFUND but when I do I receive the same CONSUMPTION_REQUEST 3 times, 8 hours apart, before I do get the REFUND notification several hours after the 3rd and final CONSUMPTION_REQUEST.
The response I get from the PUT of /inApps/v1/transactions/consumption/{transactionId} is 202 so I can only assume it was accepted and good.
Is the fact I received it 3 times an indication that it was poorly formatted or incorrect somehow?
Is there anyway to test the consumption PUT?
I've yet to see an in-app consumable that I received a CONSUMPTION_REQUEST for, that was 100% consumed, and wasn't REFUND_DECLINED.
They have all been refunded to date.
This makes me suspicious that I'm doing something wrong even though all the information I'm getting says otherwise?
Post not yet marked as solved
Hi,
We are trying to verify transaction IDs using the App Store Server Library for Python. We have been able to successfully send a test notification, but then when trying to get transaction information for a specific transaction ID we are receiving the InvalidAppIdentifierError (error code: 4000002). We have verified that the bundle_id is correct and matches what we see in App Store Connect, and the bundle_id seems to be valid and work when we sent a test notification. We have also tried setting the bundle_id to be equal to our <TEAM ID>.<BUNDLE_ID>, which is the format for the application-identifier in our TestFlight Build Metadata, but we still receive the same error when doing so.
We would greatly appreciate any help or advice on how to resolve this, and please let me know if any more information is needed to help us.
import os
from appstoreserverlibrary.api_client import AppStoreServerAPIClient, APIException
from appstoreserverlibrary.models.Environment import Environment
from appstoreserverlibrary.signed_data_verifier import VerificationException, SignedDataVerifier
from typing import List
private_key_path = "REDACTED"
with open(private_key_path, 'rb') as file:
private_key = file.read()
key_id = "REDACTED"
issuer_id = "REDACTED"
bundle_id = "REDACTED"
environment = Environment.SANDBOX
client = AppStoreServerAPIClient(private_key, key_id, issuer_id, bundle_id, environment)
def load_root_certs(root_certificate_dir: str) -> List[bytes]:
root_certificates = []
for file_name in os.listdir(root_certificate_dir):
if not file_name.endswith('.cer'):
continue
root_cert = file_name
with open(os.path.join(root_certificate_dir, root_cert), 'rb') as file:
root_certificates.append(file.read())
return root_certificates
root_certificates = load_root_certs("REDACTED")
enable_online_checks = True
signed_data_verifier = SignedDataVerifier(root_certificates, enable_online_checks, environment, bundle_id)
try:
response = client.get_transaction_info(transaction_id_ios)
signed_transaction_info = response.signedTransactionInfo or ""
print(signed_transaction_info)
payload = signed_data_verifier.verify_and_decode_notification(signed_transaction_info)
print(payload)
except (APIException, VerificationException) as e:
print(e)```
Post not yet marked as solved
Hi,
Please take a response to me about my Notification Service Entitlement Request.
I have requested 5 times but i didn't get any repsonses.
The application cannot be released because authorization is not granted.
Please check my case and leave a response as soon as.
Thanks,
Post not yet marked as solved
Hello
With V1 notifications, all you had to do was check status 21007 in production to switch to sandbox, but with V2 how do you do that? At best you get a 401 if you query production with a sandbox transactionID.
How can I ensure that transaction validation via AppStore Server uses the correct environment during the Apple review?
What is the procedure for V2 notifications and Apple review?
If my code deployed in production is on the product environment, what happens at review time?
I don't think anyone on the web has asked this question...
Any help would be appreciated
Nicolas
Post not yet marked as solved
Hi,
I have some questions about App Store Server Notifications that I can't seem to figure out. Specifically, those related to Family Shared purchases, that contain the 'FAMILY_SHARED' inAppOwnershipType.
I'll focus on 'OFFER_REDEEMED' notifications, but I have the same questions for regular subscription purchases (with no offers involved):
When a user redeems an offer code for a given subscription, do we receive a notifications for each of the family members? In that case, should we receive one with ownership 'PURCHASED', and the rest with the 'FAMILY_SHARED', or could we just receive notifications for 'FAMILY_SHARED' if that's the one who redeemed it?
Assuming the redeemed offer was a free trial, whenever that user disables auto renewal, should we again receive one notification for each family member? We are certainly receiving disabled_renewal notifications with ownership type 'FAMILY_SHARED'.
Is there any way of linking a given 'FAMILY_SHARED' ownership event/notification to the original or parent 'PURCHASED' notification/purchase? They usually come later in time, with no specific order.
If we were to track the proceeds or active subscriptions, should we just ignore any notification with ownership 'FAMILY_SHARED', and focus on 'PURCHASED' ones ? In other words, is it safe to assume that we would always receive a notification of ownership 'PURCHASED', even if the one redeeming the offer code is a family member? (not sure if that is a possible scenario).
Thank you.
Post not yet marked as solved
Received 'REFUND' notification from server for 'App Store Server Notification V1'.
Among the 'responseBodyV1' properties, the 'original_transaction_id' value and
Should I find and process transactions that match 'unified_receipt' > 'latest_receipt_info' > 'original_transaction_id'?
Sometimes there are no transactions in the history of 'latest_receipt_info' that match 'original_transaction_id'.
Hello,
I have configured V2 server notifications for my applications. I am receiving different types of notifications (https://developer.apple.com/documentation/appstoreservernotifications/notificationtype) in my webhook.
Something changed after November 18th. EXPIRED notifications are no longer received. Has something changed in the API? Other notification types still work.
Post not yet marked as solved
We are currently managing four root certificates.
Checked the ChainVerifier class code in 'App Store Server Library'.
I checked that the root certificate was excluded when I called the CertPathValidator.validate method. So the root certificate is not falsified?
Is it okay if I don't even check my fingerprints?
Post not yet marked as solved
Our live app uses V1 notifications in both production and sandbox.
We deployed a new endpoint, registered it in the App Store, and switched to V2 for Sandbox only.
After that, we created a subscription from a debug build with a sandbox account. This resulted in our old endpoint still being hit with V1 notifications. Do you have any idea what are we missing?
We're able to successfully perform test notifications using the app-store-server-library-python in SANDBOX environment, but the second we switch to PRODUCTION (for testing purposes), the call fails with 401 and it doesn't seem to reach our server at all. This suggests that something is wrong with singing production environment headers, however I've seen posts from others that suggest this is not specific to the App Store server library code.
It's very clear that the libraries are marked Beta – however, most replies to questions about the v2 API are replied to with suggestions to use the library. Just FWIW – there's some contradictory advice there.
Anyway, the main point is that we're currently blocked on making sure that our v2 API hooks are working properly, since we can't send production test notifications.
Any idea why the signed requests would work to send sandbox test notifications, but not production environment? We've triple checked the URLs, etc – as far as we know, the private key should be the same regardless of environment.
Thanks!
(P.S. If anyone has been able to send v2 test notifications with the PRODUCTION environment, please let us know!)
Post not yet marked as solved
Hello,
We have a few FAMILY_SHARED subscriptions which received a DID_RENEW notification, with all the cancellation fields completed, the expiration date in the future and no pending_renewal_info array in it.
We are not sure why did we get the DID_RENEW notification with the cancelation details, shouldn't we get a REVOKE notification?
We found this in the Apple documentation: The pending_renewal_info array is returned only for app receipts that contain auto-renewable subscriptions. If customers voluntarily cancel a subscription renewal while in the grace period, the App Store pauses billing retry, and removes the transaction from pending_renewal_info. The subscription is in the grace period if the key grace_period_expires_date_ms is present and the expiration date hasn't passed.
We do not handle any cancelation related logic for the DID_RENEW notification. Should we adjust the logic for this scenario or there should be a different notification type sent out.
This is how the latest element looks like from the lattest_recipt_info:
"auto_renew_status": "true",
"unified_receipt": {
"status": 0,
"environment": "Production",
"latest_receipt_info": [{
"quantity": "1",
"product_id": "product_id",
"transaction_id": "transaction_id",
"purchase_date": "2023-11-07 23:01:41 Etc/GMT",
"purchase_date_ms": "1699398101000",
"purchase_date_pst": "2023-11-07 15:01:41 America/Los_Angeles",
"original_purchase_date": "2021-10-07 22:01:42 Etc/GMT",
"original_purchase_date_ms": "1633644102000",
"original_purchase_date_pst": "2021-10-07 15:01:42 America/Los_Angeles",
"expires_date": "2024-11-07 23:01:41 Etc/GMT",
"expires_date_ms": "1731020501000",
"expires_date_pst": "2024-11-07 15:01:41 America/Los_Angeles",
"web_order_line_item_id": "web_order_line_item_id",
"is_trial_period": "false",
"is_in_intro_offer_period": "false",
"original_transaction_id": "original_transaction_id",
"cancellation_date": "2023-11-07 15:37:03 Etc/GMT",
"cancellation_date_ms": "1699371423020",
"cancellation_date_pst": "2023-11-07 07:37:03 America/Los_Angeles",
"cancellation_reason": "0",
"in_app_ownership_type": "FAMILY_SHARED",
"subscription_group_identifier": "subscription_group_identifier"
}
Post not yet marked as solved
Is the Apple root certificate in the App Store Server API response always 'Apple Root CA - G3'?
When isn't it?
What criteria should I set for the 'performRevocationChecking' parameter value of the verifyChain method of the ChainVerifier class in the App Store Server Library?
I am implementing the 'App Store Server API' call myself. Do you include the root certificate in the certificate chain verification process?
Can root certificates be forged?
Post not yet marked as solved
Currently, 'Get Transaction History', 'Get Transaction Info', 'Get All Subscription Statuses' and 'Notifications V2' are being used in the App store Server API.
When I decoded the JWS received in response and checked the root certificate, it was always 'AppleRootCA-G3'.
Are there cases where the root certificate is not 'AppleRootCA-G3'?
Post not yet marked as solved
We are currently implementing a feature that will allow us to extend the subscription period for users who have suffered losses due to our negligence.
Regarding the problem that is occurring in the sandbox environment during the testing stage, please check whether it is due to the sandbox specifications.
■Reproduction steps
Sandbox account A starts charging in the sandbox environment (sandbox account A is in the state of automatic contract renewal)
Execute extension process for a specific period for sandbox account A.
Confirm that the period of sandbox account A has been extended.
Confirm that sandbox account A has reached the expiration date after the extension and that the next contract renewal will be performed automatically.
Delete the purchase history of sandbox account A by following the steps below.AppStoreConnect->Users and Access->Sandbox->Test Account->Edit "Clear Purchase History".
Proceed with steps 1 to 3 again for sandbox account A.
Due to the expiration of the period in step 4, the automatic contract renewal for sandbox account A was canceled and subsequent contract renewals were no longer performed. (This is the problem)
I've run similar tests with other accounts, and in every test the problem doesn't occur until I clear my purchase history, but the problem occurs after I clear my purchase history.
When I checked the log information, the following notification was received at the timing of step 7, and it seems that the user took the initiative to cancel the automatic update.
「"notificationType": "EXPIRED", "subtype": "VOLUNTARY"」
Please let me know if the behavior is as specified.
Post not yet marked as solved
We're having problems with the Sandbox Server URL for the App Store Server Notifications. Unfortunately, we're not getting any callbacks from Apple Server while making in app purchase(Non-Renewing Subscription).
Post not yet marked as solved
What is the best way to trigger App Store Server Notifications to test your endpoint? There is a document on Request Test Notification but this only has information on the URL without any info on the expected request parameters, etc.
The ideal experience would be that StoreKit2 debugging inside XCode fires server notifications to a specified URL, but it doesn't seem to be supported.
Post not yet marked as solved
We have a server to server setup for subscription management for the Apple subscriptions. Lately we observed that we are getting a lot of DID_RENEW notification, after decoded with the /verifyReceipt endpoints, these notifications have no purchase in them. We are in the Production environment.
The original_purchase_date is set to "1970-01-20 11:45:27 Etc/GMT" and we can se also the preorder_date field set to the date when we receive the notification. All our products are approved and released at the moment(nothing to be released). There are no other "usable" details for us in the decoded notification(data to identify user).
Can somebody please help explaining this scenario? Why are we receiving these notifications?
Thanks, David.
Post not yet marked as solved
Here is a summary of the steps we have taken:
Endpoint Configuration: We have set up an HTTPS endpoint on our server hosted with Heroku. Our application is built with Node.js and Express, and it is designed to listen for POST requests for processing Apple's server notifications.
App Store Connect Setup: We have entered the correct endpoint URL in App Store Connect for both production and sandbox environments. We have also ensured that we are set up to receive version 2 notifications, as this is the latest format.
TLS Support: We have verified that Heroku supports TLS 1.2 by default, and our server is configured to utilize this protocol.
Receipt and Shared Secret: We have generated the shared secret from App Store Connect and stored it securely as a config var in Heroku. This shared secret is used to validate receipts with Apple's verifyReceipt endpoint.
Testing: We have conducted tests using Apple's sandbox environment by performing transactions to trigger server notifications. Additionally, we have also checked the Heroku logs for any incoming requests and haven't observed any related to the Apple server notifications.
Firewall and IP Whitelisting: Our server does not have any IP whitelisting or firewall rules that would block incoming HTTP POST requests from external services.
However, despite these measures, we have not been able to receive any server-to-server notifications
Post not yet marked as solved
I'm using the flutter_local_notificationspackage to display notifications in and outside the app (background mode). Everything is working as expected on Android (debug + release) and iOS debug mode but, strangely, local notifications are not displayed in background mode for iOS release.
I don't know why the iOS release mode behaves differently, any thoughts?
Thanks.
What I already checked:
use of the latest version of the flutter_local_notifications package (v16.1.0)
checking "Signing & Capabilities" for both debug and release mode (Background modes : fetch, remote notifications)
Post not yet marked as solved
I am facing this issue.
I create curl command with jwt token like this
import jwt from "jsonwebtoken"
import { readFileSync } from "fs"
import {bid, iss, kid, p8FilePath} from "./values.js"
const currentDate = Math.floor(new Date().getTime() / 1000);
const expiryDate = currentDate + (10 * 60);
const header = {
typ: "JWT",
alg: "ES256",
kid: kid,
};
const payload = {
iss: iss,
aud: "appstoreconnect-v1",
iat: currentDate,
exp: expiryDate,
bid: bid,
};
const privateKey = readFileSync(p8FilePath);
const token = jwt.sign(payload, privateKey, {
algorithm: "ES256",
header,
});
// curl command
console.log(`curl -v -H 'Authorization: Bearer ${token}' -X POST "https://api.storekit-sandbox.itunes.apple.com/inApps/v1/notifications/test"`)
and curl responds always
* Trying 17.36.202.8:443...
* Connected to api.storekit-sandbox.itunes.apple.com (17.36.202.8) port 443 (#0)
* ALPN: offers h2,http/1.1
* (304) (OUT), TLS handshake, Client hello (1):
* CAfile: /etc/ssl/cert.pem
* CApath: none
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* (304) (IN), TLS handshake, CERT verify (15):
* (304) (IN), TLS handshake, Finished (20):
* (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-AES256-GCM-SHA384
* ALPN: server accepted h2
* Server certificate:
* subject: businessCategory=Private Organization; jurisdictionCountryName=US; jurisdictionStateOrProvinceName=California; serialNumber=C0806592; C=US; ST=California; L=Cupertino; O=Apple Inc.; CN=api.storekit-sandbox.itunes.apple.com
* start date: Oct 17 19:50:08 2023 GMT
* expire date: Oct 16 20:00:08 2024 GMT
* subjectAltName: host "api.storekit-sandbox.itunes.apple.com" matched cert's "api.storekit-sandbox.itunes.apple.com"
* issuer: C=US; O=Apple Inc.; CN=Apple Public EV Server ECC CA 1 - G1
* SSL certificate verify ok.
* using HTTP/2
* h2 [:method: POST]
* h2 [:scheme: https]
* h2 [:authority: api.storekit-sandbox.itunes.apple.com]
* h2 [:path: /inApps/v1/notifications/test]
* h2 [user-agent: curl/8.1.2]
* h2 [accept: */*]
* h2 [authorization: Bearer eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ilc1QjVRNzJONUwifQ.eyJpc3MiOiI2OWE2ZGU3Yy0yMmFlLTQ3ZTMtZTA1My01YjhjN2MxMWE0ZDEiLCJhdWQiOiJhcHBzdG9yZWNvbm5lY3QtdjEiLCJpYXQiOjE2OTkyMjE2MTIsImV4cCI6MTY5OTIyMjIxMiwiYmlkIjoiY29tLm1pcmFpamEudGVzdCJ9.xLDfV6oDmx0RM6soUix7XMM-ilzV3YtSjrbGXe3ZzAj8jbEpGoFLafhPtRYEnEoSYWAY6GZmFPSzxQxO2i60MA]
* Using Stream ID: 1 (easy handle 0x7ff1d000b800)
> POST /inApps/v1/notifications/test HTTP/2
> Host: api.storekit-sandbox.itunes.apple.com
> User-Agent: curl/8.1.2
> Accept: */*
> Authorization: Bearer eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ilc1QjVRNzJONUwifQ.eyJpc3MiOiI2OWE2ZGU3Yy0yMmFlLTQ3ZTMtZTA1My01YjhjN2MxMWE0ZDEiLCJhdWQiOiJhcHBzdG9yZWNvbm5lY3QtdjEiLCJpYXQiOjE2OTkyMjE2MTIsImV4cCI6MTY5OTIyMjIxMiwiYmlkIjoiY29tLm1pcmFpamEudGVzdCJ9.xLDfV6oDmx0RM6soUix7XMM-ilzV3YtSjrbGXe3ZzAj8jbEpGoFLafhPtRYEnEoSYWAY6GZmFPSzxQxO2i60MA
>
< HTTP/2 401
< server: daiquiri/3.0.0
< date: Sun, 05 Nov 2023 22:07:20 GMT
< content-type: text/plain
< strict-transport-security: max-age=31536000; includeSubDomains
< x-apple-jingle-correlation-key: MDKTT2CACBWVV4F4V37D6QV6KI
< x-daiquiri-instance: daiquiri:45824002:st44p00it-hyhk15104701:7987:23RELEASE169:daiquiri-amp-commerce-clients-ext-001-st
<
Unauthenticated
Request ID: MDKTT2CACBWVV4F4V37D6QV6KI.0.0
* Connection #0 to host api.storekit-sandbox.itunes.apple.com left intact
how can I fix this????