Ios7 获取用户安装的原始应用程序版本时遇到问题(收据验证)?
我最近更新了一个应用程序,用于处理应用内购买。以前的版本(付费但没有应用内购买)为1.0,当前版本为1.1 由于应用内购买基本上解锁了所有功能(包括在付费版本1.0中),我想为最初下载版本1.0的用户提供一种升级方式,如果他们按下“恢复购买”按钮 为此,我首先尝试恢复购买,如果响应:Ios7 获取用户安装的原始应用程序版本时遇到问题(收据验证)?,ios7,in-app-purchase,storekit,receipt-validation,Ios7,In App Purchase,Storekit,Receipt Validation,我最近更新了一个应用程序,用于处理应用内购买。以前的版本(付费但没有应用内购买)为1.0,当前版本为1.1 由于应用内购买基本上解锁了所有功能(包括在付费版本1.0中),我想为最初下载版本1.0的用户提供一种升级方式,如果他们按下“恢复购买”按钮 为此,我首先尝试恢复购买,如果响应: - (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue 如果这为我提供了一个事务计数为0的队列,我将检查收
- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue
如果这为我提供了一个事务计数为0的队列,我将检查收据,查看安装的原始版本是否为1.0
获取收据的代码符合苹果的文档
- (void)tryRestoreFromOriginalPurchase
{
// Load the receipt from the app bundle
NSError *error;
NSData *receipt = [NSData dataWithContentsOfURL:[[NSBundle mainBundle] appStoreReceiptURL]];
if (receipt == nil) {
[self restoreFromOriginalVersionWithReceipt:nil];
return;
}
// Create the JSON object that describes the request
NSDictionary *requestContents = @{@"receipt-data": [receipt base64EncodedStringWithOptions:0]};
NSData *requestData = [NSJSONSerialization dataWithJSONObject:requestContents options:0 error:&error];
if (!requestData) {
[self restoreFromOriginalVersionWithReceipt:nil];
return;
}
// Create a POST request with the receipt data
NSURL *storeURL = [NSURL URLWithString:@"https://buy.itunes.apple.com/verifyReceipt"];
NSMutableURLRequest *storeRequest = [NSMutableURLRequest requestWithURL:storeURL];
[storeRequest setHTTPMethod:@"POST"];
[storeRequest setHTTPBody:requestData];
// Make a connection to the iTunes Store on a background queue
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:storeRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (!connectionError) {
NSError *error;
NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
if (jsonResponse) [self restoreFromOriginalVersionWithReceipt:jsonResponse];
else [self restoreFromOriginalVersionWithReceipt:nil];
} else {
[self restoreFromOriginalVersionWithReceipt:nil];
}
}];
}
然后调用以下方法:
- (void)restoreFromOriginalVersionWithReceipt:(NSDictionary *)receipt
{
if (receipt == nil) {
// CALL METHOD TO HANDLE FAILED RESTORE
} else {
NSInteger status = [[receipt valueForKey:@"status"] integerValue];
if (status == 0) {
NSString *originalApplicationVersion = [[receipt valueForKey:@"receipt"] valueForKey:@"original_application_version"];
if (originalApplicationVersion != nil && [originalApplicationVersion isEqualToString:@"1.0"]) {
// CALL METHOD TO HANDLE SUCCESSFUL RESTORE
} else {
// CALL METHOD TO HANDLE FAILED RESTORE
}
} else {
// CALL METHOD TO HANDLE FAILED RESTORE
}
}
}
现在这不起作用了。当有人安装1.1版并点击“恢复购买”时,它会在不应该的情况下成功恢复
我刚刚意识到,在我的Info.plist中,我的CbundleShortVersionString是1.1,但我的CbundLeverVersion是1.0。
这可能是一个非常愚蠢的问题,但即使更新版本为1.1,收据是否提供了1.0的原始应用程序版本(由于CbundLeverVersion错误)
因此,如果我发布了一个新的更新,并将其更正为1.2版(针对CbundleShortVersionString和CbundLeverVersion),问题会得到解决吗
--更新--
所以我刚刚上传了一个新版本到应用商店,CGBundleVersion和CbundleShortVersionString都等于1.2。然而,我仍然面临着同样的问题——用户第一次下载1.2版并点击恢复购买的内容是免费升级的(由于上面列出的收据检查)。看起来原来的应用程序版本一直都是1.0
注意:我正在使用一个新的iTunes帐户下载该应用程序,该帐户以前没有下载过该应用程序
这是我的收据,如果我从应用商店安装,然后尝试通过Xcode获得收据
2014-08-27 08:46:42.858 AppName[4138:1803] {
environment = Production;
receipt = {
"adam_id" = AppID;
"application_version" = "1.0";
"bundle_id" = "com.CompanyName.AppName";
"download_id" = 94004873536255;
"in_app" = (
);
"original_application_version" = "1.0";
"original_purchase_date" = "2014-08-26 22:30:49 Etc/GMT";
"original_purchase_date_ms" = 1409092249000;
"original_purchase_date_pst" = "2014-08-26 15:30:49 America/Los_Angeles";
"receipt_type" = Production;
"request_date" = "2014-08-26 22:46:42 Etc/GMT";
"request_date_ms" = 1409093202544;
"request_date_pst" = "2014-08-26 15:46:42 America/Los_Angeles";
};
status = 0;
}
有什么想法吗?我偶然发现了同样的问题-我将我的应用程序从付费转换为freemium,并尝试在应用程序收据中使用原始应用程序版本,以决定为谁解锁新的freemium功能。一、 也没有成功 然而,我发现我使用的
原始应用程序版本
不正确。这个名字让我误以为这个字符串对应于应用程序的版本号。在iOS上,它不是<代码>原始应用程序版本实际上是应用程序的版本号
原始应用程序版本
这对应于CbundLeverVersion的值(在iOS中)或
Info.plist文件中的CFBundleShortVersionString(在macOS中),当
最初是购买的。在沙箱环境中,此字段的值始终为“1.0”
资料来源:
我认为这可能是你得到一个你不期望的数字的原因
不过,正如您最后所做的那样,使用原始购买日期是一个可靠的选择。这个问题提出已经有一段时间了,但它提出了一些非常重要的问题: 收据中的原始应用程序版本字段对应于CbundLeverVersion,而不是CbundleShortVersionString。在沙盒(开发人员构建)环境中,值字符串始终为“1.0”
请注意,从付费应用程序转换为freemium时,如果原始(付费版本)用户卸载该应用程序,然后从iTunes重新安装,则不会有本地收据。如果用户从未进行过应用内购买,则调用
SKPaymentQueue restoreCompletedTransactions
不会导致下载新收据。在这种情况下,您需要使用SKReceiptRefreshRequest
请求收据刷新,而不是依赖恢复功能。如果任何人遇到此问题并出现相同的问题,我将无法使用上述代码。相反,我通过检查原始的购买日期得到了预期的结果。我尝试了这段代码,但每次它都显示receipt=nil@NCF这方面运气好吗?@sheefy你会说即使现在你也更习惯于原始的购买日期而不是版本号吗?我也要这么做,您的代码是否足够高,可以重复使用?@NCFUSN正在从Xcode运行本地测试?如果是,收据将为零IIRC。创建一个TestFlight构建,您将得到一个收据。我还可以确认原始应用程序\u编号
是原始版本的构建编号,这对于确定实际原始版本几乎毫无用处。所以,当我切换到freemium时,我将版本号改为以版本号为前缀。因此,对于版本2.1.5,构建1将是2.1.5.1。freemium之前的版本总是有一个单位数字的版本号,所以现在很容易区分原始客户和新客户。