Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/extjs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios7 获取用户安装的原始应用程序版本时遇到问题(收据验证)?_Ios7_In App Purchase_Storekit_Receipt Validation - Fatal编程技术网

Ios7 获取用户安装的原始应用程序版本时遇到问题(收据验证)?

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的队列,我将检查收

我最近更新了一个应用程序,用于处理应用内购买。以前的版本(付费但没有应用内购买)为1.0,当前版本为1.1

由于应用内购买基本上解锁了所有功能(包括在付费版本1.0中),我想为最初下载版本1.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之前的版本总是有一个单位数字的版本号,所以现在很容易区分原始客户和新客户。