使用AFNetworking objective-c进行自动续订的应用内购买收据验证

时间:2015-12-24 12:19:23

标签: objective-c in-app-purchase ios9 afnetworking xcode7.2

我在下面的代码中使用AFNetworking进行收据验证,它给我状态= 210002 虽然它在NSMutableURLRequest

中给我status = 0

请通过解决方案帮助我

 NSString *strurl = @"https://sandbox.itunes.apple.com/verifyReceipt";   
 NSData *receipt = [NSData dataWithContentsOfURL:[[NSBundle mainBundle] appStoreReceiptURL]];

 NSDictionary *parameter=@{
                          @"receipt-data" : [receipt base64EncodedStringWithOptions:0],
                          @"password" : @"xxxxxxxxxxxxxxxxxxxx",
                         };


 NSData *jsonParam = [NSJSONSerialization dataWithJSONObject:parameter options:NSJSONWritingPrettyPrinted error:nil];

 AFHTTPRequestOperationManager *manager =  [AFHTTPRequestOperationManager manager];
 manager.responseSerializer.acceptableContentTypes = [manager.responseSerializer.acceptableContentTypes setByAddingObject:@"text/plain"];
 [manager POST:strurl parameters:jsonParam success:^(AFHTTPRequestOperation *oprtation, id responseObject){
    NSLog(@"JSON: %@", responseObject);

 }failure:^(AFHTTPRequestOperation *operation, NSError *error){
    NSLog(@"Error: %@", error);

 }];

谢谢

2 个答案:

答案 0 :(得分:1)

这是我在我的应用程序中使用的Receipt验证代码,但我在swift中实现了。

我也在使用NSMutableURLRequest对iTunes服务进行Web服务调用。

    func verifyPaymentReceipt(){

    let mainBundle = NSBundle.mainBundle() as NSBundle;
    let receiptUrl = mainBundle.appStoreReceiptURL;
    let isPresent = receiptUrl?.checkResourceIsReachableAndReturnError(NSErrorPointer());

    if(isPresent == true){

        let data = NSData(contentsOfURL: receiptUrl! );

        // Create the JSON object that describes the request

        let requestContents  = NSMutableDictionary();
        //            let encodeddata = data!.base64EncodedStringWithOptions(NSDataBase64EncodingOptions());
        let encodeddata = data!.base64EncodedString();

        print("encodeddata = \(encodeddata)");

        requestContents.setObject(encodeddata, forKey: "receipt-data");
        requestContents.setObject("xxxxxxxxxxxxxxxxxxxxxxx", forKey: "password");
        var requestData : NSData?
        do{
            requestData = try NSJSONSerialization.dataWithJSONObject(requestContents, options: NSJSONWritingOptions());
        }catch{
            NSLog("Error in json data creation at verifyPaymentReceipt");
        }

        let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString
        let file = "\(documentsPath)/requestData"

        if(NSFileManager.defaultManager().createFileAtPath(file, contents: data, attributes: nil)){
            NSLog("File %@ ",file);
        }
        else{
            NSLog("error File %@ ",file);
        }



        if(requestData != nil){

            let strRequestData = NSString(data: requestData!, encoding: NSUTF8StringEncoding);
            print(" strRequestData = \(strRequestData)");
            // Create a POST request with the receipt data.

            let storeURL = NSURL(string: "https://sandbox.itunes.apple.com/verifyReceipt");
            let storeRequest = NSMutableURLRequest(URL: storeURL!);
            storeRequest.HTTPMethod = "POST";
            storeRequest.HTTPBody = requestData;

            // Make a connection to the iTunes Store on a background queue.

            let queue = NSOperationQueue();
            NSURLConnection.sendAsynchronousRequest(storeRequest, queue: queue, completionHandler: { (response : NSURLResponse?, data : NSData?, error : NSError?) -> Void in

                if(error != nil){
                    //Handle Error
                }
                else{
                    let d = NSString(data: data!, encoding: NSUTF8StringEncoding);
                    NSLog("DATA:%@", d!);

                    var jsonResponse: NSMutableDictionary?
                    do{
                        jsonResponse = try NSJSONSerialization.JSONObjectWithData(data!,
                            options: NSJSONReadingOptions.AllowFragments) as? NSMutableDictionary;
                        print(jsonResponse);

                    }catch{
                        NSLog("Parsing issue : verifyPaymentReceipt");
                    }

                    if(jsonResponse != nil){

                        let expirationDate: NSDate? = self.expirationDateFromResponse(jsonResponse!);
                        NSLog("Expiration Date: %@", expirationDate!);

                    }
                }
            });

        }

    }

}

As you mention that your code works fine with NSMutableURLRequest but it returns 21002 with AFNetworking.

21002 - receipt-data属性中的数据格式错误或丢失。

这意味着您在使用AFNetworking时编码收据数据格式错误。所以我认为这是使用AFNetworking进行编码的问题。

在iOS 7中,Apple在NSData上引入了新的base64方法,因此无需使用第三方base 64解码库,但我仍建议您尝试使用Base64编码进行收据编码。我希望这可以用AFNetworkig解决你的问题。因为当我验证来自服务器端的收据时,我也面临21002的相同问题,并且此编码库在这种情况下有效。不知道如何,但它解决了我在服务器端的问题,以便接收验证电话。希望它也适合你。

答案 1 :(得分:0)

这是我在目标C中使用的iOS收据验证代码的摘要,以检查应用程序启动时的续订。这有助于我在应用启动时从App Store获取订阅续订收据数据。

- (void)verifyPurchaseWithPaymentTransaction:(SKPaymentTransaction *)transaction isTestServer:(BOOL)flag{
    NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
    NSData *receipt = [NSData dataWithContentsOfURL:receiptURL];
    [self handleActionWithType:kIAPPurchSuccess data:receipt];

    NSError *error;
    NSDictionary *requestContents = @{
                                      @"receipt-data": [receipt base64EncodedStringWithOptions:0],
                                      @"password": @"INSERT_PASSWORD_HERE",
                                      @"exclude-old-transactions": @"true"
                                      };
    NSData *requestData = [NSJSONSerialization dataWithJSONObject:requestContents
                                                          options:0
                                                            error:&error];

    NSString *serverString = @"https://buy.itunes.apple.com/verifyReceipt";
    NSURL *storeURL = [NSURL URLWithString:serverString];
    NSMutableURLRequest *storeRequest = [NSMutableURLRequest requestWithURL:storeURL];
    [storeRequest setHTTPMethod:@"POST"];
    [storeRequest setHTTPBody:requestData];

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [NSURLConnection sendAsynchronousRequest:storeRequest queue:queue
                           completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
                               if (connectionError) {
                                   [self handleActionWithType:KIAPPurchVerFailed data:nil];
                               } else {
                                   NSError *error;
                                   NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
                                   if (!jsonResponse) {
                                       [self handleActionWithType:KIAPPurchVerFailed data:nil];
                                   }
                                   NSString *status = [NSString stringWithFormat:@"%@",jsonResponse[@"status"]];
                                   if (status && [status isEqualToString:@"21007"]) {
                                       [self verifyPurchaseWithPaymentTransaction:transaction isTestServer:YES];
                                   }else if(status && [status isEqualToString:@"0"]){
                                       [self handleActionWithType:KIAPPurchVerSuccess data:nil];
                                   }
#if DEBUG
                                   NSLog(@"log-IAP> jsonResults: %@",jsonResponse);
#endif
                               }
                           }];
    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}

希望这会有所帮助。最好的办法是尽快将Objective C项目转换为快速项目,因为越来越难找到关于Objective C的教程,尤其是对于较新的实现。