Reçu de transaction invalide renvoyé par appStoreReceiptURL (NSData), dans iOS 7

J'utilise la méthode suivante pour get datatables de réception:

// 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; } 

J'utilise le code suivant pour lire le reçu JSON:

 NSData *receipt = [self appStoreReceiptForPaymentTransaction:transaction]; NSError *error = nil; NSDictionary *receiptDict = [receipt dictionaryFromPlistData:&error]; NSSsortingng *transactionPurchaseInfo = [receiptDict objectForKey:@"purchase-info"]; NSSsortingng *decodedPurchaseInfo = [NSSsortingng ssortingngWithUTF8Ssortingng:[[NSData dataFromBase64Ssortingng:transactionPurchaseInfo] bytes]]; NSDictionary *purchaseInfoDict = [[decodedPurchaseInfo dataUsingEncoding:NSUTF8SsortingngEncoding] dictionaryFromPlistData:&error]; NSSsortingng *transactionID = [purchaseInfoDict objectForKey:@"transaction-id"]; NSSsortingng *purchaseDateSsortingng = [purchaseInfoDict objectForKey:@"purchase-date"]; NSSsortingng *signature = [receiptDict objectForKey:@"signature"]; NSSsortingng *signatureDecoded = [NSSsortingng ssortingngWithUTF8Ssortingng:[[NSData dataFromBase64Ssortingng:signature] bytes]]; // Convert the ssortingng into a date NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init]; [dateFormat setDateFormat:@"yyyy-MM-dd HH:mm:ss z"]; NSDate *purchaseDate = [dateFormat dateFromSsortingng:[purchaseDateSsortingng ssortingngByReplacingOccurrencesOfSsortingng:@"Etc/" withSsortingng:@""]]; NSLog(@"Raw receipt content: \n%@", [NSSsortingng ssortingngWithUTF8Ssortingng:[receipt bytes]]); NSLog(@"Purchase Info: %@", purchaseInfoDict); NSLog(@"Transaction ID: %@", transactionID); NSLog(@"Purchase Date: %@", purchaseDate); NSLog(@"Signature: %@", signatureDecoded); 

La méthode dictionaryFromPlistData: renvoie un object NSDictionary correct pour datatables renvoyées par transactionReceipt , mais il renvoie nil utilisant datatables renvoyées à l'aide de appStoreReceiptURL – et en conséquence, je ne reçois pas de reçu valide!

 - (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; } 

Pourquoi le code ci-dessus ne fonctionne pas dans iOS 7?

Pour réitérer, dictionaryFromPlistData: convertit correctement le NSData returnné par transaction.transactionReceipt .

iOS 7 a modifié la manière dont la validation des reçus est effectuée. Je suis passé par le path exact où vous êtes et j'ai obtenu les mêmes résultats. Ce que j'ai trouvé, c'est que la réception de [[NSBundle mainBundle] appStoreReceiptURL] nécessite une méthode de déencoding différente de la transaction.transactionReceipt précédente.

Voici un extrait des documents d' Apple :

La partie la plus à l'extérieur est un conteneur PKCS # 7, tel que défini par la RFC 2315, avec sa charge utile codée en ASN.1 (notation de syntaxe abstraite numéro un), comme défini par l'UIT-T X.690. La charge utile est composée d'un set d'attributes de réception. Chaque atsortingbut de reçu contient un type, une version et une valeur.

Si vous cherchez une solution rapide, j'ai vu le succès ici: https://github.com/rmaddy/VerifyStoreReceiptiOS