Error 21002 when validating receipt

Hello,

I am trying to validate consumable purchase server side (python) and here is my code :

url = "https://buy.itunes.apple.com/verifyReceipt"
request_body = {"receipt-data": token}
headers = {'Content-Type': 'application/json'}
response = requests.post(url=url, headers=headers, data=request_body)
data = response.json()
if "status" in data:
    if data["status"] != 0:
        print(f"Response from Apple verification : {data['status']}")

The status code i am getting is : 21002 which means that the receipt is malformed or something. The token var contains the base64 encoded value and is a String here.

What i am missing here please ? PS : i am also using the sandbox URL as a fallback, and this is giving the same status code.

Thanks in advance

Answered by tomtom1 in 714388022

The answer was so simple i am sorry, i should pass a String object to the POST request. Instead, i was passing a Dict in python which doesn't make sense.

The code should be : request_body = json.dumps({"receipt-data": token})

Thanks for your time, you can close my case as well !

Hello, is your password included in the request_body being sent? If not, please see this article for more information.

Hello, thanks for the update (i had already read this documentation) but i thought the password was only needed for subscriptions (which i don't use). I will try tomorrow with the app's shared secret in the request !

Accepted Answer

The answer was so simple i am sorry, i should pass a String object to the POST request. Instead, i was passing a Dict in python which doesn't make sense.

The code should be : request_body = json.dumps({"receipt-data": token})

Thanks for your time, you can close my case as well !

Hi there, this is interesting because I am experiencing the same issue with my node.js server. Here is my code:

    const body = {
        "receipt-data": receipt,
        password: APPLE_IAP_SECRET,
        "exclude-old-transactions": true,
    };

    const ret = await fetch(url, { method: "POST", headers: { "Content-Type": "application/json" }, body: data });
    const parsed = await ret.json();
    return parsed;

Where url is either https://buy.itunes.apple.com/verifyReceipt or https://sandbox.itunes.apple.com/verifyReceipt .

Pretty sure the object body is correct json, as this is being coded in javascript.

@tomtom1 Not too sure what you mean by "i should pass a String object to the POST request".. ?

Hey !

If i had to guess, you should do the same as i did meaning convert your data to a String object before passing it to the request. I think in general you can only pass String objects in HTTP requests.

The only question is : does the JS request SDK automatically converts your "dict" - "object" to String. if i remember, you can do something like :

var body = {"receipt-data": token}
body = str(body)

then in your request (actually you have a "data" var that should be "body" in your request body.

@tomtom1 if I JSON.stringify(body) it goes through perfectly! Thanks for the help :)

Also worth checking the system status (https://developer.apple.com/system-status/). Currently the service is returning 21002 even for correctly formatted requests.

Error 21002 when validating receipt
 
 
Q