2011-03-09 184 views
8

我知道这里有不少文章,但似乎没有解决我们遇到的问题。到目前为止,我认为我已按照iOS Reference Library Verifying Store Receipts documentation中的说明正确设置了所有设置。但是,在我们向AppStore验证URL发送POST请求期间,我们正在收到21002“java.lang.NullPointerException”,所以我必须做错了什么。AppStore应用内购买收据验证问题

有些问题我已经注意到,可能会引起这样的:

1)RECEIPT歧义

该文件指出,我们的iPhone应用程序,应通过只是收据到我们的服务器进行验证,但不能确切地说明收据是什么。起初我以为它可能是整个JSON对象,但现在我想知道收据是否只是“购买信息”字段。

Encoded Receipt 
ewoJInNpZ25hdHVyZSIgPSAiQWx1SFVsb0dxejZjOVNvSlFVejF0OThhemI2WjJCb2N3WVBhK2ZVYllmdUI5ZE5RQkViV2dTNXVIUUluakdSQ2RScVkxUHhQY2cvMk1kSVlONEN2anc0RkNuc0JqT0d2NGFqNjVBczQ2SERseGd4WjdlTElGUXcrcG9QVlpTZHlEWWF6NHBPaGxxNVBmVXNqdmlZNENYd3VaQzkrSTBHdk55bVZWNkhnR2FCRUFBQURWekNDQTFNd2dnSTdvQU1DQVFJQ0NHVVVrVTNaV0FTMU1BMEdDU3FHU0liM0RRRUJCUVVBTUg4eEN6QUpCZ05WQkFZVEFsVlRNUk13RVFZRFZRUUtEQXBCY0hCc1pTQkpibU11TVNZd0pBWURWUVFMREIxQmNIQnNaU0JEWlhKMGFXWnBZMkYwYVc5dUlFRjFkR2h2Y21sMGVURXpNREVHQTFVRUF3d3FRWEJ3YkdVZ2FWUjFibVZ6SUZOMGIzSmxJRU5sY25ScFptbGpZWFJwYjI0Z1FYVjBhRzl5YVhSNU1CNFhEVEE1TURZeE5USXlNRFUxTmxvWERURTBNRFl4TkRJeU1EVTFObG93WkRFak1DRUdBMVVFQXd3YVVIVnlZMmhoYzJWU1pXTmxhWEIwUTJWeWRHbG1hV05oZEdVeEd6QVpCZ05WQkFzTUVrRndjR3hsSUdsVWRXNWxjeUJUZEc5eVpURVRNQkVHQTFVRUNnd0tRWEJ3YkdVZ1NXNWpMakVMTUFrR0ExVUVCaE1DVlZNd2daOHdEUVlKS29aSWh2Y05BUUVCQlFBRGdZMEFNSUdKQW9HQkFNclJqRjJjdDRJclNkaVRDaGFJMGc4cHd2L2NtSHM4cC9Sd1YvcnQvOTFYS1ZoTmw0WElCaW1LalFRTmZnSHNEczZ5anUrK0RyS0pFN3VLc3BoTWRkS1lmRkU1ckdYc0FkQkVqQndSSXhleFRldngzSExFRkdBdDFtb0t4NTA5ZGh4dGlJZERnSnYyWWFWczQ5QjB1SnZOZHk2U01xTk5MSHNETHpEUzlvWkhBZ01CQUFHamNqQndNQXdHQTFVZEV3RUIvd1FDTUFBd0h3WURWUjBqQkJnd0ZvQVVOaDNvNHAyQzBnRVl0VEpyRHRkREM1RllRem93RGdZRFZSMFBBUUgvQkFRREFnZUFNQjBHQTFVZERnUVdCQlNwZzRQeUdVakZQaEpYQ0JUTXphTittVjhrOVRBUUJnb3Foa2lHOTJOa0JnVUJCQUlGQURBTkJna3Foa2lHOXcwQkFRVUZBQU9DQVFFQUVhU2JQanRtTjRDL0lCM1FFcEszMlJ4YWNDRFhkVlhBZVZSZVM1RmFaeGMrdDg4cFFQOTNCaUF4dmRXLzNlVFNNR1k1RmJlQVlMM2V0cVA1Z204d3JGb2pYMGlreVZSU3RRKy9BUTBLRWp0cUIwN2tMczlRVWU4Y3pSOFVHZmRNMUV1bVYvVWd2RGQ0TndOWXhMUU1nNFdUUWZna1FRVnk4R1had1ZIZ2JFL1VDNlk3MDUzcEdYQms1MU5QTTN3b3hoZDNnU1JMdlhqK2xvSHNTdGNURXFlOXBCRHBtRzUrc2s0dHcrR0szR01lRU41LytlMVFUOW5wL0tsMW5qK2FCdzdDMHhzeTBiRm5hQWQxY1NTNnhkb3J5L0NVdk02Z3RLc21uT09kcVRlc2JwMGJzOHNuNldxczBDOWRnY3hSSHVPTVoydG04bnBMVW03YXJnT1N6UT09IjsKCSJwdXJjaGFzZS1pbmZvIiA9ICJld29KSW1sMFpXMHRhV1FpSUQwZ0lqUXlORGMwTWpVeE1DSTdDZ2tpYjNKcFoybHVZV3d0ZEhKaGJuTmhZM1JwYjI0dGFXUWlJRDBnSWpFd01EQXdNREF3TURFMk1qUTRNVEFpT3dvSkluQjFjbU5vWVhObExXUmhkR1VpSUQwZ0lqSXdNVEV0TURNdE1EZ2dNREk2TkRRNk16Y2dSWFJqTDBkTlZDSTdDZ2tpY0hKdlpIVmpkQzFwWkNJZ1BTQWlZMjl0TG1OdmJYQmhibmt1UVhCd1RtRnRaUzR4TURBd01EQWlPd29KSW5SeVlXNXpZV04wYVc5dUxXbGtJaUE5SUNJeE1EQXdNREF3TURBeE5qSTBPREV3SWpzS0NTSnhkV0Z1ZEdsMGVTSWdQU0FpTVNJN0Nna2liM0pwWjJsdVlXd3RjSFZ5WTJoaGMyVXRaR0YwWlNJZ1BTQWlNakF4TVMwd015MHdPQ0F3TWpvME5Eb3pOeUJGZEdNdlIwMVVJanNLQ1NKaWFXUWlJRDBnSW1OdmJTNWpiMjF3WVc1NUxrRndjRTVoYldVaU93b0pJbUoyY25NaUlEMGdJakV1TUM0eElqc0tmUT09IjsKCSJwb2QiID0gIjEwMCI7Cgkic2lnbmluZy1zdGF0dXMiID0gIjAiOwp9 

Decoded Receipt 
{ 
    "signature" = "AluHUloGqz6c9SoJQUz1t98azb6Z2BocwYPa+fUbYfuB9dNQBEbWgS5uHQInjGRCdRqY1PxPcg/2MdIYN4Cvjw4FCnsBjOGv4aj65As46HDlxgxZ7eLIFQw+poPVZSdyDYaz4pOhlq5PfUsjviY4CXwuZC9+I0GvNymVV6HgGaBEAAADVzCCA1MwggI7oAMCAQICCGUUkU3ZWAS1MA0GCSqGSIb3DQEBBQUAMH8xCzAJBgNVBAYTAlVTMRMwEQYDVQQKDApBcHBsZSBJbmMuMSYwJAYDVQQLDB1BcHBsZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEzMDEGA1UEAwwqQXBwbGUgaVR1bmVzIFN0b3JlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA5MDYxNTIyMDU1NloXDTE0MDYxNDIyMDU1NlowZDEjMCEGA1UEAwwaUHVyY2hhc2VSZWNlaXB0Q2VydGlmaWNhdGUxGzAZBgNVBAsMEkFwcGxlIGlUdW5lcyBTdG9yZTETMBEGA1UECgwKQXBwbGUgSW5jLjELMAkGA1UEBhMCVVMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMrRjF2ct4IrSdiTChaI0g8pwv/cmHs8p/RwV/rt/91XKVhNl4XIBimKjQQNfgHsDs6yju++DrKJE7uKsphMddKYfFE5rGXsAdBEjBwRIxexTevx3HLEFGAt1moKx509dhxtiIdDgJv2YaVs49B0uJvNdy6SMqNNLHsDLzDS9oZHAgMBAAGjcjBwMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUNh3o4p2C0gEYtTJrDtdDC5FYQzowDgYDVR0PAQH/BAQDAgeAMB0GA1UdDgQWBBSpg4PyGUjFPhJXCBTMzaN+mV8k9TAQBgoqhkiG92NkBgUBBAIFADANBgkqhkiG9w0BAQUFAAOCAQEAEaSbPjtmN4C/IB3QEpK32RxacCDXdVXAeVReS5FaZxc+t88pQP93BiAxvdW/3eTSMGY5FbeAYL3etqP5gm8wrFojX0ikyVRStQ+/AQ0KEjtqB07kLs9QUe8czR8UGfdM1EumV/UgvDd4NwNYxLQMg4WTQfgkQQVy8GXZwVHgbE/UC6Y7053pGXBk51NPM3woxhd3gSRLvXj+loHsStcTEqe9pBDpmG5+sk4tw+GK3GMeEN5/+e1QT9np/Kl1nj+aBw7C0xsy0bFnaAd1cSS6xdory/CUvM6gtKsmnOOdqTesbp0bs8sn6Wqs0C9dgcxRHuOMZ2tm8npLUm7argOSzQ=="; 
    "purchase-info" = "ewoJIml0ZW0taWQiID0gIjQyNDc0MjUxMCI7Cgkib3JpZ2luYWwtdHJhbnNhY3Rpb24taWQiID0gIjEwMDAwMDAwMDE2MjQ4MTAiOwoJInB1cmNoYXNlLWRhdGUiID0gIjIwMTEtMDMtMDggMDI6NDQ6MzcgRXRjL0dNVCI7CgkicHJvZHVjdC1pZCIgPSAiY29tLmNvbXBhbnkuQXBwTmFtZS4xMDAwMDAiOwoJInRyYW5zYWN0aW9uLWlkIiA9ICIxMDAwMDAwMDAxNjI0ODEwIjsKCSJxdWFudGl0eSIgPSAiMSI7Cgkib3JpZ2luYWwtcHVyY2hhc2UtZGF0ZSIgPSAiMjAxMS0wMy0wOCAwMjo0NDozNyBFdGMvR01UIjsKCSJiaWQiID0gImNvbS5jb21wYW55LkFwcE5hbWUiOwoJImJ2cnMiID0gIjEuMC4xIjsKfQ=="; 
    "pod" = "100"; 
    "signing-status" = "0"; 
} 

2)无效JSON

的数据进行编码以base64和解码一次应该提供的信息在一个有效的JSON对象但是从我所看到的物体definitately不是有效的JSON。 Apple似乎在使用“=”,其中“:”应该是“and”;“其中“”应该是:

{ 
    "item-id" = "424742510"; 
    "original-transaction-id" = "1000000001624810"; 
    "purchase-date" = "2011-03-08 02:44:37 Etc/GMT"; 
    "product-id" = "com.company.AppName.100000"; 
    "transaction-id" = "1000000001624810"; 
    "quantity" = "1"; 
    "original-purchase-date" = "2011-03-08 02:44:37 Etc/GMT"; 
    "bid" = "com.company.AppName"; 
    "bvrs" = "1.0.1"; 
} 

我不知道是否如此,我们收到的错误可能是因为他们所提供的收据是无效的JSON,所以当我们发布的数据进行验证的一个原因服务器拒绝它。我们是否应该解码所有内容,将对象修改为有效的JSON,对其进行重新编码,然后将其提交给Apple进行验证?

我希望有其他人有这项工作可以指出我在上述两个问题的正确方向或更好,但提供正确的CURL电话接收有效的答复,这将完全解决我的问题。

在此先感谢您的帮助!

回答

10

如果我正确地阅读了文档,那么你就错了。您发送的用于验证的收据是由transactionReceipt属性返回的大块数据。你不应该关心它解码到什么,或者如果解码到任何东西。您只需对它进行64位编码,将其作为关键字“receipt-data”的值放入一个json对象中,然后将该json对象发布到Apple。

当你得到苹果的回应,是应该包含json格式的收据数据。

+0

这就是我想要做的,但我不能当我这样做时,得到Apple的有效答复,所以我开始深入研究它。任何想法为什么苹果会在这种情况下返回一个错误?是否有任何我们可能忽略的陷阱? – 2011-03-09 02:22:26

+0

似乎这是LWP :: UserAgent Perl模块的问题。我能够通过CURL代替它。感谢您帮助我专注于问题。 – 2011-03-09 18:53:29

2

看起来像是ASCII Property List - 您应该可以使用NSPropertyListSerialization类对其进行解码。

编辑

什么是类解码对象的?这看起来像当你使用NSLog转储NSDictionary时得到的东西()

+0

所以你说我们应该解码ASCII属性列表,然后将其编码为JSON?我尝试手动执行此操作,似乎仍然在验证时收到错误。任何其他想法?如果我能找到一种使用CURL获得有效响应的方法,那么我们应该全部设置。 – 2011-03-09 01:06:17

+0

检查我的编辑,我认为你得到的数据可能来自NSLog()调用 - 如果你想要JSON,你必须把NSDictionary转换成JSON – Dre 2011-03-09 01:08:40

4

对于将来获得21002错误的其他人。花了几个小时才知道出了什么问题。这通常意味着您发送给Apple服务器的JSON中的base 64编码字符串不正确。这可能意味着你不是Base-64编码,或者你的编码例程有问题。这些是您应该使用的步骤:

1)Base-64将您从SKPaymentTransaction对象的transactionReceipt属性收到的所有NSData编码为NSString对象。您可以使用下面的方法。

2)将其插入到JSON字符串中。在Objective-C代码,这将是:

NSString* json = [NSString stringWithFormat:@"{ 'receipt-data' : '%@' }", base64String]; 

3)HTTP POST是

4)你会得到一个JSON字符串返回 - 提取 '状态' 的值。如果它是0,您的收据已被确认 - 否则它是未经验证的购买。

下面是我用NSData的转换为base-64编码字符串代码:

@interface NSData (Base64Encoding) 

- (NSString*)base64Encode; 

@end 

@implementation NSData (Base64Encoding) 

- (NSString*)base64Encode 
{ 
    static char table [] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/="; 

    NSInteger length = [self length]; 
    NSMutableData* data = [NSMutableData dataWithLength:((length + 2)/3) * 4]; 
    uint8_t* input = (uint8_t*)[self bytes]; 
    uint8_t* output = (uint8_t*)data.mutableBytes; 

    for (NSInteger i = 0; i < length; i += 3) 
    { 
     NSInteger value = 0; 
     for (NSInteger j = i; j < (i + 3); ++j) 
     { 
      value <<= 8; 

      if (j < length) 
      { 
       value |= (0xff & input[j]); 
      } 
     } 

     NSInteger index = (i/3) * 4; 
     output[index + 0] =     table[(value >> 18) & 0x3f]; 
     output[index + 1] =     table[(value >> 12) & 0x3f]; 
     output[index + 2] = (i + 1) < length ? table[(value >> 6) & 0x3f] : '='; 
     output[index + 3] = (i + 2) < length ? table[(value >> 0) & 0x3f] : '='; 
    } 

    return [[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding] autorelease]; 
} 

@end 

要使用它,这样做:

NSString* base64string = [transaction.transactionReceipt base64Encode];