Хранение в приложении квитанций о покупке в приложении Keychain
Я никогда не реализовывал In App Purchase, поэтому я использовал оболочку MKStoreKit и получил работающую реализацию. MKStoreKit хранит все чеки в списке UserDefaults .plist в виде BOOL, поэтому пиратам очень просто распределять покупки в приложении в "взломанном" состоянии. Как только первая покупка сделана, пакет может быть распределен, и.plist может быть воссоздан для разблокировки IAP.
Я хотел бы расширить MKStoreKit для создания данных проверки покупки в приложении в цепочке для ключей iOS. Есть ли какой-либо недостаток или возможная причина, по которой это может не сработать для платящих пользователей, ненадежность или какая-либо другая причина, почему это было бы в целом плохой идеей? Я понимаю, что пиратство неизбежно, и я определенно не хочу отталкивать платящих пользователей, но я чувствую, что UserDefaults .plist - слишком простой способ обхода.
В моем сценарии простая цепочка будет помещена в цепочку для ключей при совершении покупки. Таким образом, если двоичный файл распространяется, разблокируемые блоки еще не включены. Конечно, было бы возможно найти обходной путь, но потребовалось бы немного больше усилий и узнать, как найти флаг ИСТИНА / ЛОЖЬ и заставить его всегда возвращать правильное значение. Через запутывание я мог даже усложнить это.
Спасибо за все ваши идеи, и я ценю ответы, избегая обязательных ответов: пиратство, сделка с ним. Меня больше интересуют технические возможности этого решения.
1 ответ
Мы делаем именно это в наших приложениях, и это прекрасно работает. Это бесплатное приложение, которое вы можете обновить до полной версии, и мы храним индикатор обновления в цепочке для ключей. Индикатор обновления представляет собой произвольную строку, которую вы выбираете, но для целей цепочки для ключей он обрабатывается как пароль, то есть значение для kSecValueData шифруется в цепочке для ключей. Приятным плюсом этого подхода является то, что если пользователь удаляет приложение, а затем переустанавливает его, все снова включается, как по волшебству, поскольку элементы цепочки для ключей хранятся отдельно от приложения. И так мало дополнительной работы по сохранению чего-либо в пользовательских настройках по умолчанию, что мы решили, что оно того стоило.
Вот как создать элемент безопасности:
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
}
}
Если upgradeItemData равен nil, то ключ не существует, поэтому вы можете предположить, что обновления нет, или, что мы делаем, присвоено значение, которое означает, что не обновлено.
Обновить
Добавлена kSecReturnData (спасибо @Luis за указание на это)