she*_*efy 7 storekit in-app-purchase ios7 receipt-validation
我有一个应用程序,我最近更新,以便在应用程序购买中使用.之前的版本(付费但没有在应用内购买)是1.0,当前版本是1.1.
由于应用程序内购买实际上解锁了所有功能(包含在付费版本1.0中),我想要一种方式,如果用户按下我的恢复购买按钮,则最初下载的版本1.0将被升级.
为此,我首先尝试恢复购买,如果回复:
- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue
Run Code Online (Sandbox Code Playgroud)
如果这为我提供了一个事务计数为0的队列,我检查收据以查看安装的原始版本是否为1.0.
获得收据的代码是根据Apple的文档
- (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];
}
}];
}
Run Code Online (Sandbox Code Playgroud)
然后调用以下方法:
- (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
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在这不起作用.当有人安装1.1版本并点击恢复购买时,它会在不应该恢复时成功恢复.
我刚刚意识到在我的Info.plist中,我的CFBundleShortVersionString是1.1,但我的CFBundleVersion是1.0.
这可能是一个非常愚蠢的问题,但即使更新版本为1.1,收据提供的original_application_version为1.0(由于错误的CFBundleVersion)?
因此,如果我发布一个新更新,并将其更正为版本1.2(对于CFBundleShortVersionString和CFBundleVersion),问题是否会得到解决?
- 更新 -
所以我刚刚将新版本上传到app商店,其中CGBundleVersion和CFBundleShortVersionString都等于1.2.但是,我仍然面临同样的问题 - 用户首次下载1.2版本并点击恢复购买正在免费升级(由于上面列出的收据检查).似乎original_application_version总是达到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;
}
Run Code Online (Sandbox Code Playgroud)
有什么想法吗?
And*_*Wei 16
我偶然发现了同样的问题 - 我将我的应用程序从付费转换为免费增值,并尝试original_application_version在应用收据中使用以决定解锁新的免费增值功能的用户.我也是不成功的.
但是,我发现的是我使用original_application_version不正确.该名称误以为我认为这个字符串对应于应用程序的版本号.在iOS上,它没有.original_application_version实际上是应用程序的内部版本号.
原始应用版本
这对应于最初购买时Info.plist文件中CFBundleVersion(在iOS中)或 CFBundleShortVersionString(在macOS中)的值.在沙箱环境中,此字段的值始终为"1.0".
资料来源:https://developer.apple.com/library/archive/releasenotes/General/ValidateAppStoreReceipt/Chapters/ReceiptFields.html
我想这可能是你得到一个你没想到的数字的原因.
使用original_purchase_date,当你最后还是没买,是一个可靠的选择,但.
小智 5
自问这个问题已经有一段时间了,但它提出了一些非常重要的观点:
收据中的原始应用程序版本字段对应于CFBundleVersion,而不是CFBundleShortVersionString。在沙盒(开发人员构建)环境中,值字符串始终为 “ 1.0”。
请注意,从付费应用程序转换为免费增值版时,如果原始(付费版本)用户卸载了该应用程序,然后从iTunes重新安装,则不会有本地收据。SKPaymentQueue restoreCompletedTransactions如果该用户从未进行过应用内购买,则通话不会导致下载新收据。在这种情况下,您需要使用SKReceiptRefreshRequest而不是依靠还原功能来刷新收据。