使用 AFNetworking objective-c 进行自动续订的应用内购买收据验证
In-app purchase receipt verification for auto renewal using AFNetworking objective-c
我正在使用 AFNetworking 编写以下代码进行收据验证,它给了我 status=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);
}];
谢谢
这是我在我的应用程序中使用的收据验证代码,但我在 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 - 收据数据 属性 中的数据格式错误或丢失。
这意味着您在使用 AFNetworking 时编码收据数据格式错误。所以我认为这是使用 AFNetworking 进行编码的问题。
在 iOS7 中,Apple 在 NSData 上引入了新的 base64 方法,因此无需使用第三方 base 64 解码库,但我仍然建议您尝试使用 Base64 编码用于收据编码。我希望这会解决您的 AFNetworkig 问题。当我验证来自服务器端的收据并且此编码库在这种情况下有效时,我也面临同样的 21002 问题。不知道如何,但它解决了我在服务器端的收据验证调用问题。希望它也对你有用。
这是我在 objective 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 项目转换为 swift,因为越来越难找到关于 Objective C 的教程,尤其是对于较新的实施。
我正在使用 AFNetworking 编写以下代码进行收据验证,它给了我 status=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);
}];
谢谢
这是我在我的应用程序中使用的收据验证代码,但我在 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 - 收据数据 属性 中的数据格式错误或丢失。
这意味着您在使用 AFNetworking 时编码收据数据格式错误。所以我认为这是使用 AFNetworking 进行编码的问题。
在 iOS7 中,Apple 在 NSData 上引入了新的 base64 方法,因此无需使用第三方 base 64 解码库,但我仍然建议您尝试使用 Base64 编码用于收据编码。我希望这会解决您的 AFNetworkig 问题。当我验证来自服务器端的收据并且此编码库在这种情况下有效时,我也面临同样的 21002 问题。不知道如何,但它解决了我在服务器端的收据验证调用问题。希望它也对你有用。
这是我在 objective 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 项目转换为 swift,因为越来越难找到关于 Objective C 的教程,尤其是对于较新的实施。