3

This is a painful topic which has been discussed many times on stack, however, with all the posts I read and things I tried, I was not able to get the IAP verification using PHP working and I'll be damned if I know why.

This is how I get the receipt on the iOS:

purchaseReceipt = [[NSString alloc] initWithData:transaction.transactionReceipt encoding:NSUTF8StringEncoding];

I send it to my PHP script, which encodes it and sends it to the server:

$receipt = base64_encode($_POST["rcpt"]);
$postData = json_encode(
    array('receipt-data' => $receipt)
);

$ch = curl_init($endpoint);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);

$response = curl_exec($ch);
$errno    = curl_errno($ch);
$errmsg   = curl_error($ch);
curl_close($ch);

The problem I'm getting is quite baffling. All receipts tested return as invalid with status -42352 . Yes, I'm sending them to proper environment. Receipt JSON seems to be properly encoded, since if I make any changes to $receipt after encoding, the script returns error 21002 (The data in the receipt-data property was malformed). So it looks like a genuine bad receipt, which can't be since it's from the purchase I'm making on the Sandbox.

I would appreciate any help, as I'm out of ideas.

Here is the value of $_POST["rcpt"] from example purchase made on the Sandbox:

{
    "signature" = "Aqi3Y/UKAYEJUqtFxjRx0DDQ1BV7W/3VtLpVq/l85SIxGXTJOF9WrlBVryQTVgWvUWY6poJVpWQjXrgoSQEjGapN4RmaBChWmHNUgyBy03HKzZ5gQupfHxvxK I3xRaoqyb0jJC4VOmTavU46LqjDfqNuMQvwdT9Y57zoIplBylVAAADVzCCA1MwggI7oAMCAQICCGUUkU3ZWAS1MA0GCSqGSIb3DQEBBQUAMH8xCzAJBgNVBAYTAlVTMRMwEQYDVQQKDApBcHBsZSBJbmMuMSYwJAYDVQQLDB1BcHBsZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEzMDEGA1UEAwwqQXBwbGUgaVR1bmVzIFN0b3JlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA5MDYxNTIyMDU1NloXDTE0MDYxNDIyMDU1NlowZDEjMCEGA1UEAwwaUHVyY2hhc2VSZWNlaXB0Q2VydGlmaWNhdGUxGzAZBgNVBAsMEkFwcGxlIGlUdW5lcyBTdG9yZTETMBEGA1UECgwKQXBwbGUgSW5jLjELMAkGA1UEBhMCVVMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMrRjF2ct4IrSdiTChaI0g8pwv/cmHs8p/RwV/rt/91XKVhNl4XIBimKjQQNfgHsDs6yju  DrKJE7uKsphMddKYfFE5rGXsAdBEjBwRIxexTevx3HLEFGAt1moKx509dhxtiIdDgJv2YaVs49B0uJvNdy6SMqNNLHsDLzDS9oZHAgMBAAGjcjBwMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUNh3o4p2C0gEYtTJrDtdDC5FYQzowDgYDVR0PAQH/BAQDAgeAMB0GA1UdDgQWBBSpg4PyGUjFPhJXCBTMzaN mV8k9TAQBgoqhkiG92NkBgUBBAIFADANBgkqhkiG9w0BAQUFAAOCAQEAEaSbPjtmN4C/IB3QEpK32RxacCDXdVXAeVReS5FaZxc t88pQP93BiAxvdW/3eTSMGY5FbeAYL3etqP5gm8wrFojX0ikyVRStQ /AQ0KEjtqB07kLs9QUe8czR8UGfdM1EumV/UgvDd4NwNYxLQMg4WTQfgkQQVy8GXZwVHgbE/UC6Y7053pGXBk51NPM3woxhd3gSRLvXj loHsStcTEqe9pBDpmG5 sk4tw GK3GMeEN5/ e1QT9np/Kl1nj aBw7C0xsy0bFnaAd1cSS6xdory/CUvM6gtKsmnOOdqTesbp0bs8sn6Wqs0C9dgcxRHuOMZ2tm8npLUm7argOSzQ==";
    "purchase-info" = "ewoJIm9yaWdpbmFsLXB1cmNoYXNlLWRhdGUtcHN0IiA9ICIyMDEyLTA3LTE0IDA2OjAyOjQ4IEFtZXJpY2EvTG9zX0FuZ2VsZXMiOwoJIm9yaWdpbmFsLXRyYW5zYWN0aW9uLWlkIiA9ICIxMDAwMDAwMDUyODIxNzk1IjsKCSJidnJzIiA9ICIxLjIuMCI7CgkidHJhbnNhY3Rpb24taWQiID0gIjEwMDAwMDAwNTI4MjE3OTUiOwoJInF1YW50aXR5IiA9ICIxIjsKCSJvcmlnaW5hbC1wdXJjaGFzZS1kYXRlLW1zIiA9ICIxMzQyMjcwOTY4Njg1IjsKCSJwcm9kdWN0LWlkIiA9ICJjb20uZHJhZ29ubG9yZHNtb2JpbGUuVDFfMzBjb2lucyI7CgkiaXRlbS1pZCIgPSAiNDUzMDEzMDUzIjsKCSJiaWQiID0gImNvbS5kcmFnb25sb3Jkc21vYmlsZS5kcmFnb25sb3JkcyI7CgkicHVyY2hhc2UtZGF0ZS1tcyIgPSAiMTM0MjI3MDk2ODY4NSI7CgkicHVyY2hhc2UtZGF0ZSIgPSAiMjAxMi0wNy0xNCAxMzowMjo0OCBFdGMvR01UIjsKCSJwdXJjaGFzZS1kYXRlLXBzdCIgPSAiMjAxMi0wNy0xNCAwNjowMjo0OCBBbWVyaWNhL0xvc19BbmdlbGVzIjsKCSJvcmlnaW5hbC1wdXJjaGFzZS1kYXRlIiA9ICIyMDEyLTA3LTE0IDEzOjAyOjQ4IEV0Yy9HTVQiOwp9";
    "environment" = "Sandbox";
    "pod" = "100";
    "signing-status" = "0";
}
AragornSG
  • 633
  • 1
  • 7
  • 22
  • What is the value of $_POST["rcpt"] before its base64'd? – craig1231 Jul 14 '12 at 15:42
  • It looks like this: { "signature" = "Aj1zPe(...lots characters...)gcxRHuOMZ2tm8npLUm7argOSzQ=="; "purchase-info" = "ewoJIm9yaWdpbmFsLXB1cmN(...lots characters...)tZXJpY2EvTG9zX0FuZ2VsZXMiOwp9"; "pod" = "6"; "signing-status" = "0"; } – AragornSG Jul 14 '12 at 15:47
  • OK can you edit your post to show a complete var_dump of $_POST["rcpt"]? – craig1231 Jul 14 '12 at 15:49
  • The signature shouldn't contain any spaces... could you encode the receipt on the device, then send it to the PHP script? Im not sure if sending the response via URL (for example) is binary safe. – craig1231 Jul 14 '12 at 16:10
  • This may help - http://stackoverflow.com/questions/1298998/verify-receipt-for-in-app-purchase – craig1231 Jul 14 '12 at 16:17
  • Thanks Craig, that does pinpoint the issue. I did the encoding on the iOS side and receipts are coming back as valid. It does not solve my problem though. I have a couple of thousand receipts in my database I need to verify. Any idea what could have happened to them between getting spit out and getting saved in the DB? – AragornSG Jul 14 '12 at 17:19
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/13888/discussion-between-craig1231-and-aragornsg) – craig1231 Jul 14 '12 at 17:49

1 Answers1

1

Have you tried encoding the receipt before sending it to the server?

Base64 iOS sample code

Chars such as + were being interpreted as a space char.

Community
  • 1
  • 1
craig1231
  • 3,769
  • 4
  • 31
  • 34
  • Indeed, encoding on the iOS side or parsing the JSON on the server side was the solution. Thank you! – AragornSG Jul 14 '12 at 21:59
  • @AragornSG can you be more specific about what you mean by "parsing the JSON on the server side"? Seems odd that doing the base64 encoding on the client rather than backend would make a difference. – Ariel Vardi Dec 10 '13 at 22:18