apple / app-store-server-library-node

MIT License
167 stars 33 forks source link

verifyAndDecodeNotification - Error with status 3, or INVALID_ENVIRONMENT #209

Closed occassionally closed 1 hour ago

occassionally commented 2 hours ago

I'm using this library similar to the example in the documentation:

import { SignedDataVerifier } from "@apple/app-store-server-library"

const bundleId = "com.example"
const appleRootCAs: Buffer[] = loadRootCAs() // Specific implementation may vary
const enableOnlineChecks = true
const environment = Environment.SANDBOX
const appAppleId = undefined // appAppleId is required when the environment is Production
const verifier = new SignedDataVerifier(appleRootCAs, enableOnlineChecks, environment, bundleId, appAppleId)

const notificationPayload = "ey..."
const verifiedNotification = await verifier.verifyAndDecodeNotification(notificationPayload)
console.log(verifiedNotification)

I've done the following:

When environment was Environment.SANDBOX, this worked fine. I was able to receive, decode, handle, and respond to notifications for the entire lifecycle of a subscription. The only issue was not being able to test retry notifications.

Now, I've changed environment to Environment.PRODUCTION because I want to test retry notifications when my server sends an error response. (The sandbox environment only sends one attempt and does not attempt more, regardless of the server's response.)

As soon as I changed the environment, I started getting this error. Nothing else has changed. I need to be able to test these retries to make sure they work, but also, at some point this will have to change when the app is launched.

https://github.com/apple/app-store-server-library-node/blob/5f344871b21f3882611c5cf791b0c0ca7428d56f/jws_verification.ts#L353-L361

What has gone wrong?

In case it matters, I'm testing this via a TestFlight app. It's not through Xcode since server notifications don't work with the Xcode environment. As far as I've read, TestFlight apps should work with the production environment.

alexanderjordanbaker commented 2 hours ago

@occassionally I don’t see the specific error listed here, but if you are verifying a Sandbox notification with the verifier set to expect production, an INVALID_ENVIRONMENT error would be expected. Note from a server perspective TestFlight is Sandbox, not Production

occassionally commented 1 hour ago

@alexanderjordanbaker Thanks for the quick response.

The error is simply { "status": 3 }. Very unhelpful error, but based on one of your earlier comments, I found this is VerificationStatus.INVALID_ENVIRONMENT.

This isn't necessarily a Sandbox notification - in the sense that I'm not requesting a TEST notification.

Do you mean that TestFlight can't be used to test a production environment at all? So there is no way to ever test the behavior of retry App Store notifications until the app is actually in production? This page of the documentation mentions:

Retry notifications are available only in the production environment. In the sandbox environment, the App Store server attempts to send the notification one time.

That would be really surprising to hear, if it is actually the case that retry notifications can never be tested until the app is live.

I thought the problem might have been that my project was automatically managing signing using a development signing certificate. So I set up a provisioning profile with a distribution certificate, updated the project, released a new build on TestFlight, and still have the same issue.

alexanderjordanbaker commented 1 hour ago

Sandbox is anything from TestFlight or App Store Connect created Sandbox accounts. Access to the production App Store Server API or Notifications requires a production release of the app.

occassionally commented 1 hour ago

Got it, thanks for the clarification.

So, just for peace of mind - when I'm ready to submit the app for production review, I can change environment to Environment.PRODUCTION and without any other changes it will work as expected once the app is launched on the App Store, right? I just want to ask for safety to avoid any surprises on launch!

alexanderjordanbaker commented 1 hour ago

@occassionally We would recommend having a separate URL for prod and have that setup with your real data stores and with environment set to production, and then yes, it should work

occassionally commented 1 hour ago

Got it, yeah I will have the production URL updated when launching. Thanks!