Сегодня у нас статья Якова Ильина об In-App Purchases для iPhone-приложений.
Введение
In-App Purchases — это простой и удобный механизм для организации продаж своих приложений или дополнительных фич непосредственно из своего приложения. In-App Purchases легко встраивается и открывает для Вас новый канал продаж. Взаимодействие с App Store осуществляется с помощью StoreKit.framework, который поставляется вместе с SDK, начиная с версии 3.0.
Общая информация
In-App Purchases бывает трех типов:
- Consumables
- Non-Consumables
- Subscriptions
Consumable – потребляемый тип. Purchase такого типа может покупаться несколько раз. Например, в игре Eliminate игрок покупает себе энергию, которая со временем растрачивается и приходится покупать ее заново, либо ждать три часа, пока энергия востановится.
Non-Consumable— непотребляемый тип. Purchase покупается только один раз. Его обычно используют для разблокировки новых тем, дополнительных уровней и т.п.
Subscription— подписка на что-либо. Например, Вы можете написать iPhone-приложение для Web-сервиса, в котором есть Premium аккаунт, открывающий дополнительные возможности. С помощью Subscription Вы сможете аккаунт активировать, скажем, на месяц или на год.
Реализовать In-App Purchases можно с помощью двух моделей:
- Встроенная модель
- Серверная модель
Встроенная модель позволяет разблокировать фичи. Как правило, использование данной модели побуждает разработчиков встраивать их в приложение зарание. При такой реализации, StoreKit отвечает только за оплату фичи. В общем случае, с помощью StoreKit мы можем узнать прошла ли покупка или не прошла.
Серверная модель является более гибкой. В модели принимают участие три сущности: iPhone-приложение, сервер Apple и наш сервер. Все новые фичи хранятся на нашем сервере, поэтому нет необходимости обновлять приложение при добавлении новых фич или продуктов. Работает модель следующим образом:
- iPhone-приложение запрашивает список продуктов у своего сервера,
- iPhone-приложение отображает новые продукты пользователю,
- Пользователь покупает (или не покупает 🙂 )
- iPhone-приложение запрашивает покупку у сервера Apple через StoreKit,
- StoreKit возвращает ответ,
- iPhone-приложение отсылает ответ на свой сервер
- Еще раз проверяется ответ (обязательно проверяется, что ответ пришел от Apple),
- После этого iPhone-приложение скачивает со своего сервера новый продукт.
В данном посте рассматривается встроенная модель.
Реализация
Работу встроенной модели In-App Purchases я продемонстрирую на тестовом примере AppPurchasesExample. Это небольшое iPhone-приложение с 3 окнами. Первое (оно же главное) окно будет доступно пользователю по-умолчанию. Это окно будет содержать информацию о двух других окнах, разблокировать которые можно только за деньги.
Шаг 1. Создание App ID
Заходим на iPhone Developer Program Portal и открываем вкладку App IDs:
В правом верхнем углу экрана нажимаем New App ID. Затем вводим информацию о приложении. Для своего примера я заполнил форму так:
Для создания Bundle Identifier Apple рекомендует использовать нотацию Reverse DNS, что гарантирует уникальность Вашего Identifier и избавит Вас от дальнейших проблем при публикации приложения.Очень Важно не использовать символ ‘*’ в Bundle Identifier. Если ввести ‘com.wordpress.indiedevelop.*’, то In-App Purchases работать не будет.
Далее необходимо включить In App Purchases для App ID. В списке App IDs, напротив нужного Bundle Identifier в графе Action следует нажать Configure. Появится форма Configure App ID, на которой необходимо включить checkBox ‘Enable In App Purchase’.
Шаг 2. Создание Development профиля
- В левом столбце нужно нажать на ‘Provisioning’ и перейти на вкладку ‘Development’.
- Нажать ‘New Profile’ и заполнить всю необходимую информацию. Поле Profile Name может быть любое (я записал ‘InAppPurchasesExample Dev’).
- В появившемся списке созданный профиль имеет статус pending. Нужно обновить страницу, либо перейти на другую вкладку и обратно, тогда профиль станет доступен для скачивания.
- Профиль можно скачивать и устанавливать в xCode. Для установки достаточно просто нажать на профиль двойным кликом, либо перетащить профайл на иконку xCode.
Если профиль установился правильно, тогда в xCode откроется Organizer и вы увидите примерно следующее:
Шаг 3. Создание приложения в iTunes Connect
Для того, чтобы протестировать наше In-App Purchase приложение, его нужно обязательно создать в iTunes Connect. Чтобы это сделать:
- Необходимо перейти в iTunes Connect и нажать ‘Manage Your Applications->Add New Application’.
- На вопрос ‘Does your product contain encryption?’ ответить отрицательно.
- Заполнить форму, где нужно указать имя приложения, описание, номер версии, категорию и т.д. Все достаточно тривиально. Затруднения может вызвать разве что поле ‘SKU Number’. Это поле должно быть уникальным, я ввел в нем ‘IAPEX’ (сокращение от In-App Purchases Example).
- На форме ‘Upload’ необходимо выставить флаг ‘Upload application binary later’. Все остальные параметры и формы для тестого примера никакого значения не имеют.
Шаг 4. Создание In-App Purchases в iTunes Connect
- В iTunes Connect необходимо нажать ‘Manage Your In App Purchases->Create New’ и выбрать необходимое приложение.
- Выбрать Bundle ID и заполнить инфрормацию о Purchase (тип, название, цену и т.д.) Также нужно ввести ‘Product ID’, который может быть произвольным, но я советую использовать Reverse DNS. Лучше всего Product ID формировать из Bundle ID вашего приложения и имени фичи. Для моего примера это выглядит так:
Для тестового приложения я создал два In-App продукта с Product Id ‘com.wordpress.indiedevelop.InAppPurchasesExample.f1’ и ‘com.wordpress.indiedevelop.InAppPurchasesExample.f2’. Обе фичи с типом Non-Consumables.
Шаг 5. Создание тестового пользователя
Для тестирования In-App Purchases необходимо создать хотя бы одного тестового пользователя. Делается это просто:
- В iTunes Connect необходимо перейти на ‘Manage Users->In App Purchase Test User’
- Нажать ‘Add New User’
- Ввести информацию о пользователе
E-mail пользователя не обязательно должен быть реальным. Для своего примера я создал одного тестового пользователя:
Важный момент. Если у Вас не закончен контракт с Apple, тогда In-App Purchase работать у Вас не будет. Для того, чтобы закончить контракт, необходимо указать Contact Info, Bank Info и Tax Info.
Шаг 6. Программирование
Для своего тестового примера я создал каркас проекта и User Interface:
Для работы с App Store я рекомендую использовать MKStoreKit, разработанный в 2009 году разработчиком Кумаром (Mugunth Kumar). Данный набор классов значительно облегчит работу со StoreKit. Кроме MKStoreKit, в проект необходимо добавить StoreKit.framework.
В своем примере я использую слегка модернизированную первую весрию MKStoreKit. Для удобства я добавил к классу MKStoreManager делегат следующего вида:
@protocol MKStoreKitDelegate @optional - (void)productAPurchased; - (void)productBPurchased; - (void)failed; @end
Делегату посылается сообщение productAPurchased когда куплена фича 1, productBPurchased — когда куплена фича 2 и failed — когда пользователь либо отменил покупку, либо покупка не прошла.
Класс-Singleton MKStoreManager
является основным в MKStoreKit. Так выглядит его объявление:
@interface MKStoreManager : NSObject<SKProductsRequestDelegate> { ... } // делегат @property (nonatomic, retain) id<MKStoreKitDelegate> delegate; // продукты, доступные для покупки @property (nonatomic, retain) NSMutableArray *purchasableObjects; // фабричный метод для Singleton + (MKStoreManager*)sharedManager; // методы для покупки фич - (void) buyFeatureA; - (void) buyFeatureB; // методы позволяют узнать куплена ли фича + (BOOL) featureAPurchased; + (BOOL) featureBPurchased; ... @end
Рассмотрим использование класса на моем тестовом примере.
Сначала в файле MKStoreManager.m я прописал Product ID своих фич:
static NSString *featureAId = @"com.wordpress.indiedevelop.InAppPurchasesExample.f1"; static NSString *featureBId = @"com.wordpress.indiedevelop.InAppPurchasesExample.f2";
Также нужно проверить были ли куплены фичи программы. Основной класс примера унаследован от UIViewController
, поэтому код проверки целесообразно встроить в метод viewDidLoad:
- (void)viewDidLoad { [super viewDidLoad]; [MKStoreManager sharedManager].delegate = self; // назначаем делагата для объекта MKStoreManager if ([MKStoreManager featureAPurchased]) // если куплена фича 1 { feature1Button.hidden = YES; // скрываем кнопку 'Купить фичу 1' seeFeature1Button.hidden = NO; // показываем кнопку 'Перейти на фичу 1' } if ([MKStoreManager featureBPurchased]) // если куплена фича 2 { feature2Button.hidden = YES; // скрываем кнопку 'Купить фичу 2' seeFeature2Button.hidden = NO; // показываем кнопку 'Перейти на фичу 2' } }
Внутри MKStoreKit информация о том, куплен ли продукт сохраняется через NSUserDefaults
, поэтому при удалении приложения информация сбрасывается. Однако, пользователь не будет покупать фичи два раза, поскольку StoreKit откроет доступ к фиче бесплатно.
Дальше нужно реализовать методы ‘Купить’. Они привязаны к событию TouchUpInside
соотвествующих кнопок:
-(IBAction)feature1ButtonPressed { [self showLockView]; // показываем пользователю, что происходит загрузка [[MKStoreManager sharedManager] buyFeatureA]; // посылаем сообщение магазину 'Купить фичу 1' } -(IBAction)feature2ButtonPressed { [self showLockView]; // показываем пользователю, что происходит загрузка [[MKStoreManager sharedManager] buyFeatureB]; // посылаем сообщение магазину 'Купить фичу 2' }
Далее я реализовал методы делегата MKStoreKitDelegate
:
// фича 1 куплена - (void)productAPurchased { [self hideLockView]; // скрываем отображение загрузки feature1Button.hidden = YES; // скрываем кнопку 'Купить' seeFeature1Button.hidden = NO; // показываем кнопку 'Перейти' } // фича 2 куплена - (void)productBPurchased { [self hideLockView]; // скрываем отображение загрузки feature2Button.hidden = YES; // скрываем кнопку 'Купить' seeFeature2Button.hidden = NO; // показываем кнопку 'Перейти' } // покупка не прошла, либо была отменена - (void)failed { [self hideLockView]; // скрываем отображение загрузки }
Новые фичи реализованы в виде отдельных UIView
под управлением UIViewController
. Переход на новые фичи я реализовал с помощь UINavigationController
:
// перейти на фичу 1 -(IBAction)seeFeature1 { [self.navigationController pushViewController:feature1ViewController animated:YES]; } // перейти на фичу 2 -(IBAction)seeFeature2 { [self.navigationController pushViewController:feature2ViewController animated:YES]; }
Также при манипуляции с магазином можно добавить проверку на его доступность. Это делается так:
if ([SKPaymentQueue canMakePayments]) { ... // Отобразить магазин пользователю } else { ... // Уведомить пользователя, что Purchases недоступны }
Как видите все достаточно просто. Остается скопилировать и тестировать 🙂
Шаг 7. Тестирование
Чтобы протестировать In-App Purchases нужно скомпилировать, установить и запустить приложение. При тестировании следует помнить следующее:
- Тестировать Purchases можно только на устройстве.
- Перед тестированием необходимо выйти из iTunes на своем iPhone. Это делается через ‘Settings->Store->Sign Out’.
- При тестировании, в сообщениях с предложением купить фичу, будет появляться [Environment: sandbox] — это признак тестового режима.
- Тестировать можно только тест-аккаунтами (см. Шаг 5)
Тестовый пример InAppPurchasesExample
В результате у меня получилось приложение, которое может разблокировать два дополнительных окна. Это приложение можно использовать в качестве примера для создания своих In-App Purchase проектов.
Оригинал статьи в блоге автора.
Скриншоты:
Отличная статья, спасибо.