Проблемы с получением оригинальной версии приложения, которую установил пользователь (подтверждение получения)?
У меня есть приложение, которое я недавно обновил для работы с покупками приложений. Предыдущая версия (платная, но без покупок в приложении) была 1.0, а текущая версия 1.1.
Поскольку покупка в приложении, по сути, разблокирует все функции (которые были включены в платную версию 1.0), я хотел, чтобы пользователи, которые изначально скачали версию 1.0, были обновлены, если они нажимали кнопку "Восстановить покупки".
Для этого я сначала пытаюсь восстановить покупки и, если в ответе:
- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue
Если это дает мне очередь с количеством транзакций 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];
}
}];
}
Затем вызывается следующий метод:
- (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 мой CFBundleShortVersionString равен 1.1, но мой CFBundleVersion равен 1.0.
Это может быть действительно глупый вопрос, но квитанция обеспечивает исходное_применение_версии 1.0 (из-за неправильного CFBundleVersion), даже если обновление имеет версию 1.1?
Так что, если я выпущу новое обновление с исправленной версией 1.2 (как для CFBundleShortVersionString, так и для CFBundleVersion), проблема будет решена?
-- ОБНОВИТЬ --
Поэтому я только что загрузил новую версию в магазин приложений с 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;
}
Какие-нибудь мысли?
2 ответа
Я наткнулся на ту же проблему - я перевел свое приложение с платного на freemium и попытался использовать original_application_version
в квитанции приложения, чтобы решить, для кого разблокировать новые функции Freemium. У меня тоже не получилось.
Однако то, что я узнал, было то, что я использовал original_application_version
неправильно. Имя ввело меня в заблуждение, когда я подумал, что эта строка соответствует номеру версии приложения. На iOS это не так. original_application_version
на самом деле номер сборки приложения.
Оригинальная версия приложения
Это соответствует значению CFBundleVersion (в iOS) или CFBundleShortVersionString (в macOS) в файле Info.plist, когда была совершена покупка. В среде "песочницы" значение этого поля всегда равно "1,0".
Я думаю, что это может быть причиной того, что вы получаете номер, который вы не ожидаете.
С помощью original_purchase_date
Как вы и сделали, это надежная альтернатива.
Прошло много времени с тех пор, как был задан этот вопрос, но он поднимает некоторые очень важные моменты:
Исходное поле версии приложения в квитанции соответствует CFBundleVersion, а не CFBundleShortVersionString. В среде "песочницы" (сборки разработчика) строка значения всегда равна "1,0".
Обратите внимание, что при конвертации из платного приложения во freemium, если оригинальный (платная версия) пользователь удаляет приложение, а затем переустанавливает из iTunes, локальная квитанция не будет. призвание SKPaymentQueue restoreCompletedTransactions
не приведет к загрузке новой квитанции, если этот пользователь никогда не делал покупки в приложении. В этой ситуации вам нужно попросить обновить квитанцию, используя SKReceiptRefreshRequest
и не полагаться на восстановление функциональности.