apple / app-store-server-library-node

MIT License
155 stars 29 forks source link

API works in sandbox not production #37

Closed mhan8796 closed 9 months ago

mhan8796 commented 9 months ago

I used the same settings, the only thing I changed is the Environment.SANDBOX to PRODUCTION.

I used the same notification url in app connect

SANDBOX works fine.

Then I got 401 from the API exception in PRODUCTION.

mhan8796 commented 9 months ago

Is the beta version of this library currently only working in sandbox? I am using the same key. My understanding is the key should allow me to access both prod and sandbox.

alexanderjordanbaker commented 9 months ago

Hello, no this library works in both Sandbox and Production environments. Make sure your issueId and keyId match your app. If you are still experiencing issues, I recommend filing a ticket in Feedback Assistant and include your calling parameters and the response headers. You can post the FB number you receive here as well.

mhan8796 commented 9 months ago

Thanks for clarifying. The key is def the good one because the only thing I ever changed is the environment.sandbox to environment.production. My app is new and not reviewed and so is my in app purchase. I guess the reason could be my production account in apple store server is not provisioned? Do you have any insights? However, my app review was rejected because of this 401 issue lol, so it looks like chicken and egg problem to me. I will submit a ticket, thank you.

alexanderjordanbaker commented 9 months ago

Ah, yes, if your app is not approved for production, you will receive a 401. Are you seeing App Review use production receipts?

mhan8796 commented 9 months ago

Thanks for the fast response, that indeed helped me understand the issue.

The comment I got is below:

When validating receipts on your server, your server needs to be able to handle a production-signed app getting its receipts from Apple’s test environment. The recommended approach is for your production server to always validate receipts against the production App Store first. If validation fails with the error code "Sandbox receipt used in production," you should validate against the test environment instead.

Took me a while to understand, so apple send a prod receipt from a sandbox server? The one I submitted for review is using production client. Does this mean I should validate it against prod client first then if it is not working, I should validate it against sandbox client? So I should create two clients in my code? Also, I cannot get error code "Sandbox receipt used in production", if the only response I got is 401. Or do I submit my sandbox build for review so that the app can be approved first?

What is your recommendation?

alexanderjordanbaker commented 9 months ago

What kind of transactions are you sending to your server? That is a quote that makes sense really only in the context of Original StoreKit. Generally you shouldn’t even need to use the App Store Server API you can just verify the signed transaction directly on your server if using StoreKit 2 on the client side.

mhan8796 commented 9 months ago

I am doing something like this. I didn't trust the client side receipt so I query apple server again. You recommend I should just verify purchaseReceipt directly using verifier?

    const transactionId = receiptUtil.extractTransactionIdFromAppReceipt(purchaseReceipt);
    if (transactionId != null) {
        try {
            const transactionInfo = await client.getTransactionInfo(transactionId);
            const verifiedNotification = await verifier.verifyAndDecodeTransaction(transactionInfo['signedTransactionInfo']);
    } catch (e) {
       ...}
   }
alexanderjordanbaker commented 9 months ago

If you are able, I recommend using https://developer.apple.com/documentation/storekit/transaction, as this is signed, can be verified directly, and has more information. See https://developer.apple.com/videos/play/wwdc2021/10114/ for more info. Otherwise I recommend calling the production endpoint, and if you get an error of 404 (or 401 in this case) then call the sandbox endpoint after and check if there is a successful response

mhan8796 commented 9 months ago

The framework I am using is not on storekit2 yet so I cannot use that to verify. I was able to verify against prod first then sandbox. It passed production test. I am all good now. This apple store sending prod transaction through sandbox environment is intriguing.

darvelo commented 8 months ago

Thanks for the fast response, that indeed helped me understand the issue.

The comment I got is below:

When validating receipts on your server, your server needs to be able to handle a production-signed app getting its receipts from Apple’s test environment. The recommended approach is for your production server to always validate receipts against the production App Store first. If validation fails with the error code "Sandbox receipt used in production," you should validate against the test environment instead.

Took me a while to understand, so apple send a prod receipt from a sandbox server? The one I submitted for review is using production client. Does this mean I should validate it against prod client first then if it is not working, I should validate it against sandbox client? So I should create two clients in my code? Also, I cannot get error code "Sandbox receipt used in production", if the only response I got is 401. Or do I submit my sandbox build for review so that the app can be approved first?

What is your recommendation?

@alexanderjordanbaker Is this something devs should implement for Notifications V2? Should I create two SignedDataVerifiers, one with Environment.SANDBOX and the other with Environment.PRODUCTION, then catching an exception from await verifier.verifyAndDecodeNotification(signedPayload) for production first and retrying with the sandbox verifier to call the same decode method?

alexanderjordanbaker commented 8 months ago

@darvelo For notifications, we recommend using two different URLs, so you already know which environment you are in.

darvelo commented 8 months ago

@darvelo For notifications, we recommend using two different URLs, so you already know which environment you are in.

@alexanderjordanbaker Ok, thanks for the guidance! I implemented it that way successfully. 👍🏽

sahil-patel6 commented 6 months ago

@darvelo @mhan8796 , Can you please confirm when app goes for review, will apple send webhook in sandbox URL with transactions environment set to Sandbox or Production? I think it should be Sandbox Right?

darvelo commented 6 months ago

@sahil-patel6 Honestly, I don't know. What I do is I have two SignedDataVerifiers, one for each environment, and which one is used depends on which webhook URL was called. Once I use it to decode the transaction, I read the transaction's environment property to match against the environment I store for each transaction in my database and create or update a transaction record in my DB accordingly based on the environment and signedDate, ignoring the transaction if my DB record has a newer signed date.

Doing it this way IMO should cover every possible situation.

sahil-patel6 commented 6 months ago

@sahil-patel6 Honestly, I don't know. What I do is I have two SignedDataVerifiers, one for each environment, and which one is used depends on which webhook URL was called. Once I use it to decode the transaction, I read the transaction's environment property to match against the environment I store for each transaction in my database and create or update a transaction record in my DB accordingly based on the environment and signedDate, ignoring the transaction if my DB record has a newer signed date.

Doing it this way IMO should cover every possible situation.

Thanks for the reply