iOS 7中appStoreReceiptURL(NSData)返回的无效交易收据

Mus*_*afa 6 in-app-purchase ios receipt

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

// 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;
}
Run Code Online (Sandbox Code Playgroud)

我正在使用以下代码来读取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);
Run Code Online (Sandbox Code Playgroud)

dictionaryFromPlistData:方法返回NSDictionary由返回的数据的正确对象transactionReceipt,但它返回nil使用返回的数据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;
}
Run Code Online (Sandbox Code Playgroud)

为什么以上代码不适用于iOS 7?

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

cap*_*kaw 4

iOS 7 改变了收据验证的完成方式。我经历了与你完全相同的路径并得到了相同的结果。我发现来自的收据[[NSBundle mainBundle] appStoreReceiptURL]需要与以前不同的解码方法transaction.transactionReceipt

这是苹果文档的一个片段:

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

如果您正在寻找快速解决方案,我在这里看到了成功: https: //github.com/rmaddy/VerifyStoreReceiptiOS