Подтвердить что ты не робот

Хранение в приложении Покупка квитанций в приложении Keychain

Я никогда не реализовывал в App Purchase раньше, поэтому я использовал оболочку MKStoreKit и имею рабочую реализацию. MKStoreKit хранит все квитанции в UserDefaults.plist как BOOL, поэтому пиратам очень просто распространять покупки в приложениях в "потрескавшемся" состоянии. После первой покупки пакет может быть распределен, а .plist можно воссоздать, чтобы включить блокировки IAP.

Я хотел бы расширить MKStoreKit, чтобы создать данные о проверке In App Purchase в цепочке ключей iOS. Есть ли какой-либо недостаток или возможная причина для отказа в оплате пользователям, ненадежность или любая другая причина, по которой это было бы общей плохой идеей? Я понимаю, что пиратство неизбежно, и я определенно не хочу отчуждать платных пользователей, но я чувствую, что UserDefaults.plist - это слишком простой способ обойти.

В моем сценарии простая цепочка будет помещена в цепочку ключей при совершении покупки. Таким образом, если бинарный файл будет распределен, открываемые блокировки еще не включены. Конечно, можно было бы придумать обходной путь, но потребовалось бы немного больше усилий и узнать, как найти флаг TRUE/FALSE и заставить его всегда возвращать правильное значение. Через обфускацию я мог бы даже немного усложнить отслеживание этого.

Спасибо за все ваши идеи, и я ценю ответы, избегая обязательного неизбежного пиратства, соглашаясь с ним. Меня больше интересуют технические возможности этого решения.

4b9b3361

Ответ 1

Мы делаем именно это в наших приложениях, и это отлично работает. Это бесплатное приложение, которое можно обновить до полной версии, и мы сохраняем индикатор обновления в цепочке ключей. Индикатор обновления - это произвольная строка, которую вы выбираете, но для целей связки ключей она рассматривается как пароль, то есть значение для kSecValueData зашифровывается в цепочке ключей. Хороший бонус в этом подходе заключается в том, что если пользователь удаляет приложение, а затем снова его устанавливает, все снова включается, как магия, потому что элементы keychain хранятся отдельно от приложения. И его небольшая дополнительная работа над хранением чего-то в пользовательских настройках по умолчанию, что мы решили, что это того стоит.

Вот как создать элемент безопасности:

NSMutableDictionary* dict = [NSMutableDictionary dictionary];

[dict setObject: (id) kSecClassGenericPassword  forKey: (id) kSecClass];
[dict setObject: kYourUpgradeStateKey           forKey: (id) kSecAttrService];
[dict setObject: kYourUpgradeStateValue         forKey: (id) kSecValueData];

SecItemAdd ((CFDictionaryRef) dict, NULL);

Вот как найти элемент безопасности, чтобы проверить его значение:

NSMutableDictionary* query = [NSMutableDictionary dictionary];

[query setObject: (id) kSecClassGenericPassword forKey: (id) kSecClass];
[query setObject: kYourUpgradeStateKey          forKey: (id) kSecAttrService];
[query setObject: (id) kCFBooleanTrue           forKey: (id) kSecReturnData];

NSData* upgradeItemData = nil;
SecItemCopyMatching ( (CFDictionaryRef) query, (CFTypeRef*) &upgradeItemData );
if ( !upgradeItemData )
{
    // Disable feature
}
else
{
    NSString* s = [[[NSString alloc] 
                        initWithData: upgradeItemData 
                            encoding: NSUTF8StringEncoding] autorelease];

    if ( [s isEqualToString: kYourUpgradeStateValue] )
    {
        // Enable feature
    }
}

Если updateItemData имеет значение nil, тогда ключ не существует, поэтому вы можете предположить, что обновление отсутствует или, что мы делаем, помещается в значение, которое не обновляется.

Обновление

Добавлен kSecReturnData (спасибо @Luis за указание его)

Код в GitHub (вариант ARC)