在iOS 7中,由appStoreReceiptURL(NSData)返回无效的事务接收

我使用以下方法获取收据数据:

// Use this method instead of accessing transaction.transactionReceipt directly! - (NSData *)appStoreReceiptForPaymentTransaction:(SKPaymentTransaction *)transaction { NSData *receiptData = nil; // This is just a quick/dummy implementation! if (kiOS7) { NSURL *receiptFileURL = [[NSBundle mainBundle] appStoreReceiptURL]; receiptData = [NSData dataWithContentsOfURL:receiptFileURL]; // Returns valid NSData object } else { receiptData = transaction.transactionReceipt; // Returns valid NSData object } return receiptData; } 

我正在使用以下代码来阅读JSON收据:

 NSData *receipt = [self appStoreReceiptForPaymentTransaction:transaction]; NSError *error = nil; NSDictionary *receiptDict = [receipt dictionaryFromPlistData:&error]; NSString *transactionPurchaseInfo = [receiptDict objectForKey:@"purchase-info"]; NSString *decodedPurchaseInfo = [NSString stringWithUTF8String:[[NSData dataFromBase64String:transactionPurchaseInfo] bytes]]; NSDictionary *purchaseInfoDict = [[decodedPurchaseInfo dataUsingEncoding:NSUTF8StringEncoding] dictionaryFromPlistData:&error]; NSString *transactionID = [purchaseInfoDict objectForKey:@"transaction-id"]; NSString *purchaseDateString = [purchaseInfoDict objectForKey:@"purchase-date"]; NSString *signature = [receiptDict objectForKey:@"signature"]; NSString *signatureDecoded = [NSString stringWithUTF8String:[[NSData dataFromBase64String:signature] bytes]]; // Convert the string into a date NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init]; [dateFormat setDateFormat:@"yyyy-MM-dd HH:mm:ss z"]; NSDate *purchaseDate = [dateFormat dateFromString:[purchaseDateString stringByReplacingOccurrencesOfString:@"Etc/" withString:@""]]; NSLog(@"Raw receipt content: \n%@", [NSString stringWithUTF8String:[receipt bytes]]); NSLog(@"Purchase Info: %@", purchaseInfoDict); NSLog(@"Transaction ID: %@", transactionID); NSLog(@"Purchase Date: %@", purchaseDate); NSLog(@"Signature: %@", signatureDecoded); 

dictionaryFromPlistData:方法为transactionReceipt返回的数据返回合适的NSDictionary对象,但是它返回nil使用使用appStoreReceiptURL返回的数据 – 并且很appStoreReceiptURL ,我没有得到有效的收据!

 - (NSDictionary *)dictionaryFromPlistData:(NSError **)outError { NSError *error; NSDictionary *dictionaryParsed = [NSPropertyListSerialization propertyListWithData:self options:NSPropertyListImmutable format:nil error:&error]; if (!dictionaryParsed) { if (error) { *outError = error; } return nil; } return dictionaryParsed; } 

为什么上面的代码不在iOS 7中工作?

只要重申, dictionaryFromPlistData:正确地转换由transaction.transactionReceipt返回的NSData

iOS 7已经改变了接收validation的完成方式。 我经历了你下来的确切path,并得到相同的结果。 我发现从[[NSBundle mainBundle] appStoreReceiptURL]的收据需要一个不同于以前的transaction.transactionReceipt解码方法。

以下是苹果公司的文档片段:

最外面的部分是由RFC 2315定义的PKCS#7容器,其有效负载使用ITU-T X.690定义的ASN.1(抽象语法表示法1)编码。 有效载荷由一组收据属性组成。 每个收据属性都包含一个types,一个版本和一个值。

如果你正在寻找一个快速解决scheme,我已经看到成功在这里: https : //github.com/rmaddy/VerifyStoreReceiptiOS