La mise en œuvre de la Réception de la Validation de Swift 3

Je développe une application iOS dans Swift 3 et tentent de mettre en œuvre la réception de validation suivant ce tutoriel: http://savvyapps.com/blog/how-setup-test-auto-renewable-subscription-ios-app. Cependant, le tutoriel semble avoir été écrit à l'aide d'une version antérieure de Swift, donc j'ai eu à faire plusieurs changements. Voici mon receiptValidation() fonction:

func receiptValidation() {
let receiptPath = Bundle.main.appStoreReceiptURL?.path
if FileManager.default.fileExists(atPath: receiptPath!){
var receiptData:NSData?
do{
receiptData = try NSData(contentsOf: Bundle.main.appStoreReceiptURL!, options: NSData.ReadingOptions.alwaysMapped)
}
catch{
print("ERROR: " + error.localizedDescription)
}
let receiptString = receiptData?.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
let postString = "receipt-data=" + receiptString! + "&password=" + SUBSCRIPTION_SECRET
let storeURL = NSURL(string:"https://sandbox.itunes.apple.com/verifyReceipt")!
let storeRequest = NSMutableURLRequest(url: storeURL as URL)
storeRequest.httpMethod = "POST"
storeRequest.httpBody = postString.data(using: .utf8)
let session = URLSession(configuration:URLSessionConfiguration.default)
let task = session.dataTask(with: storeRequest as URLRequest) { data, response, error in
do{
let jsonResponse:NSDictionary = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as! NSDictionary
let expirationDate:NSDate = self.expirationDateFromResponse(jsonResponse: jsonResponse)!
self.updateIAPExpirationDate(date: expirationDate)
}
catch{
print("ERROR: " + error.localizedDescription)
}
}
task.resume()
}
}

Le problème s'affiche lorsque j'essaie d'appeler le expirationDateFromResponse() la méthode. Il s'avère que le jsonResponse qui est transmis à cette méthode contient: status = 21002;. J'ai regardé et il signifie "les données de La réception de données de propriété a été mal formé ou manquant." Cependant, l'appareil je suis en essais sur dispose d'un sandbox de l'abonnement pour le produit, et l'abonnement semble fonctionner correctement à côté de cette question. Est-il autre chose que je besoin de le faire pour s'assurer que le receiptData valeur sera lu et codé correctement, ou de quelque autre problème qui peut être à l'origine de ce problème?

EDIT:

J'ai essayé une autre façon de mettre en storeRequest.httpBody:

func receiptValidation() {
let receiptPath = Bundle.main.appStoreReceiptURL?.path
if FileManager.default.fileExists(atPath: receiptPath!){
var receiptData:NSData?
do{
receiptData = try NSData(contentsOf: Bundle.main.appStoreReceiptURL!, options: NSData.ReadingOptions.alwaysMapped)
}
catch{
print("ERROR: " + error.localizedDescription)
}
let receiptString = receiptData?.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0)) //.URLEncoded
        let dict = ["receipt-data":receiptString, "password":SUBSCRIPTION_SECRET] as [String : Any]
var jsonData:Data?
do{
jsonData = try JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted)
}
catch{
print("ERROR: " + error.localizedDescription)
}
let storeURL = NSURL(string:"https://sandbox.itunes.apple.com/verifyReceipt")!
let storeRequest = NSMutableURLRequest(url: storeURL as URL)
storeRequest.httpMethod = "POST"
storeRequest.httpBody = jsonData!
let session = URLSession(configuration:URLSessionConfiguration.default)
let task = session.dataTask(with: storeRequest as URLRequest) { data, response, error in
do{
let jsonResponse:NSDictionary = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as! NSDictionary
let expirationDate:NSDate = self.expirationDateFromResponse(jsonResponse: jsonResponse)!
self.updateIAPExpirationDate(date: expirationDate)
}
catch{
print("ERROR: " + error.localizedDescription)
}
}
task.resume()
}
}

Cependant, lorsque je lance l'application du présent code, il se bloque au moment d'atteindre la ligne jsonData = try JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted). Il n'a même pas le bloc catch, il s'arrête juste rien faire. De ce que j'ai vu en ligne, d'autres personnes semblent avoir de la difficulté à utiliser JSONSerialization.données pour la définition de la demande httpBody dans Swift 3.

Assurez-vous que vous avez % codé tout + caractères dans le base64 réception. Ie remplacer les occurrences de + %2b
J'ai changé mon code pour faire cette modification pour les receiptString juste après sa déclaration, mais je suis toujours de voir la même erreur. Aussi, quand j'imprime le receiptString, je remarque qu'il contient beaucoup de caractères "/" séparant le long de la base de 64 chaînes. Est-ce la façon dont il est censé le regarder quand il est correctement codé?
Je devrais aussi mentionner que j'ai essayé de supprimer les caractères"/", mais je vois encore le 21002 état.
J'ai mis à jour mon Essentiel de montrer le code que j'utilise pour récupérer de la réception et de coder les données base64. Dans mon cas, c'est envoyé de mon code php qui envoie sur les serveurs Apple pour gist.github.com/paulw11/fa76e10f785e055338ce06673787c6d2
En regardant le code, les données que vous envoyez n'est pas correct. Vous êtes l'envoi, la réception et le mot de passe que les données POST, mais vous avez besoin d'envoyer un objet JSON qui contient votre reçu et votre mot de passe. Si vous le faites, alors vous ne devriez pas avoir à vous soucier de l' % de l'encodage, c'était quelque chose dont j'avais besoin pour fonctionner avec mon PHP.

OriginalL'auteur user3726962 | 2016-09-26