In-App Purchases — это простой и удобный механизм для организации продаж своих приложений или дополнительных фич непосредственно из своего приложения. In-App Purchases легко встраивается и открывает для Вас новый канал продаж. Взаимодействие с App Store осуществляется с помощью StoreKit.framework, который поставляется вместе с SDK, начиная с версии 3.0.
In-App Purchases бывает трех типов:
Consumable — потребляемый тип. Purchase такого типа может покупаться несколько раз. Например, в игре Eliminate игрок покупает себе энергию, которая со временем растрачивается и приходится покупать ее заново, либо ждать три часа, пока энергия востановится.
Non-Consumable — непотребляемый тип. Purchase покупается только один раз. Его обычно используют для разблокировки новых тем, дополнительных уровней и т.п.
Subscription — подписка на что-либо. Например, Вы можете написать iPhone-приложение для Web-сервиса, в котором есть Premium аккаунт, открывающий дополнительные возможности. С помощью Subscription Вы сможете аккаунт активировать, скажем, на месяц или на год.
Реализовать In-App Purchases можно с помощью двух моделей:
Встроенная модель позволяет разблокировать фичи. Как правило, использование данной модели побуждает разработчиков встраивать их в приложение зарание. При такой реализации, StoreKit отвечает только за оплату фичи. В общем случае, с помощью StoreKit мы можем узнать прошла ли покупка или не прошла.
Серверная модель является более гибкой. В модели принимают участие три сущности: iPhone-приложение, сервер Apple и наш сервер. Все новые фичи хранятся на нашем сервере, поэтому нет необходимости обновлять приложение при добавлении новых фич или продуктов. Работает модель следующим образом:
В данном посте рассматривается встроенная модель.
Работу встроенной модели In-App Purchases я продемонстрирую на тестовом примере AppPurchasesExample. Это небольшое iPhone-приложение с 3 окнами. Первое (оно же главное) окно будет доступно пользователю по-умолчанию. Это окно будет содержать информацию о двух других окнах, разблокировать которые можно только за деньги.
Заходим на 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'.
Если профиль установился правильно, тогда в xCode откроется Organizer и вы увидите примерно следующее:
Для того, чтобы протестировать наше In-App Purchase приложение, его нужно обязательно создать в iTunes Connect. Чтобы это сделать:
Для тестового приложения я создал два In-App продукта с Product Id 'com.wordpress.indiedevelop.InAppPurchasesExample.f1' и 'com.wordpress.indiedevelop.InAppPurchasesExample.f2'. Обе фичи с типом Non-Consumables.
Для тестирования In-App Purchases необходимо создать хотя бы одного тестового пользователя. Делается это просто:
E-mail пользователя не обязательно должен быть реальным. Для своего примера я создал одного тестового пользователя:
Важный момент. Если у Вас не закончен контракт с Apple, тогда In-App Purchase работать у Вас не будет. Для того, чтобы закончить контракт, необходимо указать Contact Info, Bank Info и Tax Info.
Для своего тестового примера я создал каркас проекта и User Interface:
Для работы с App Store я рекомендую использовать MKStoreKit, разработанный в 2009 году разработчиком Кумаром (Mugunth Kumar). Данный набор классов значительно облегчит работу со StoreKit. Кроме MKStoreKit, в проект необходимо добавить StoreKit.framework.
В своем примере я использую слегка модернизированную первую весрию MKStoreKit. Для удобства я добавил к классу MKStoreManager делегат следующего вида:
Делегату посылается сообщение productAPurchased когда куплена фича 1, productBPurchased — когда куплена фича 2 и failed — когда пользователь либо отменил покупку, либо покупка не прошла.
Класс-Singleton MKStoreManager является основным в MKStoreKit. Так выглядит его объявление:
Рассмотрим использование класса на моем тестовом примере.
Сначала в файле MKStoreManager.m я прописал Product ID своих фич:
Также нужно проверить были ли куплены фичи программы. Основной класс примера унаследован от UIViewController, поэтому код проверки целесообразно встроить в метод viewDidLoad:
Внутри MKStoreKit информация о том, куплен ли продукт сохраняется через NSUserDefaults, поэтому при удалении приложения информация сбрасывается. Однако, пользователь не будет покупать фичи два раза, поскольку StoreKit откроет доступ к фиче бесплатно.
Дальше нужно реализовать методы 'Купить'. Они привязаны к событию TouchUpInside соотвествующих кнопок:
Далее я реализовал методы делегата MKStoreKitDelegate:
Новые фичи реализованы в виде отдельных UIView под управлением UIViewController. Переход на новые фичи я реализовал с помощь UINavigationController:
Также при манипуляции с магазином можно добавить проверку на его доступность. Это делается так:
Как видите все достаточно просто. Остается скопилировать и тестировать :)
Чтобы протестировать In-App Purchases нужно скомпилировать, установить и запустить приложение. При тестировании следует помнить следующее:
В результате у меня получилось приложение, которое может разблокировать два дополнительных окна. Это приложение можно использовать в качестве примера для создания своих In-App Purchase проектов.
Исходный код: InAppPurchasesExample.zip
Скриншоты:
Я очень надеюсь, что Вам помог этот пост. Если у Вас есть Вопросы, пожалуйста, задавайте. Я с удовольствием на них отвечу.
— Яков
Общая информация
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
* This source code was highlighted with Source Code Highlighter.
Делегату посылается сообщение 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
* This source code was highlighted with Source Code Highlighter.
Рассмотрим использование класса на моем тестовом примере.
Сначала в файле MKStoreManager.m я прописал Product ID своих фич:
static NSString *featureAId = @"com.wordpress.indiedevelop.InAppPurchasesExample.f1";
static NSString *featureBId = @"com.wordpress.indiedevelop.InAppPurchasesExample.f2";
* This source code was highlighted with Source Code Highlighter.
Также нужно проверить были ли куплены фичи программы. Основной класс примера унаследован от 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'
}
}
* This source code was highlighted with Source Code Highlighter.
Внутри MKStoreKit информация о том, куплен ли продукт сохраняется через NSUserDefaults, поэтому при удалении приложения информация сбрасывается. Однако, пользователь не будет покупать фичи два раза, поскольку StoreKit откроет доступ к фиче бесплатно.
Дальше нужно реализовать методы 'Купить'. Они привязаны к событию TouchUpInside соотвествующих кнопок:
-(IBAction)feature1ButtonPressed
{
[self showLockView]; // показываем пользователю, что происходит загрузка
[[MKStoreManager sharedManager] buyFeatureA]; // посылаем сообщение магазину 'Купить фичу 1'
}
-(IBAction)feature2ButtonPressed
{
[self showLockView]; // показываем пользователю, что происходит загрузка
[[MKStoreManager sharedManager] buyFeatureB]; // посылаем сообщение магазину 'Купить фичу 2'
}
* This source code was highlighted with Source Code Highlighter.
Далее я реализовал методы делегата 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]; // скрываем отображение загрузки
}
* This source code was highlighted with Source Code Highlighter.
Новые фичи реализованы в виде отдельных UIView под управлением UIViewController. Переход на новые фичи я реализовал с помощь UINavigationController:
// перейти на фичу 1
-(IBAction)seeFeature1
{
[self.navigationController pushViewController:feature1ViewController animated:YES];
}
// перейти на фичу 2
-(IBAction)seeFeature2
{
[self.navigationController pushViewController:feature2ViewController animated:YES];
}
* This source code was highlighted with Source Code Highlighter.
Также при манипуляции с магазином можно добавить проверку на его доступность. Это делается так:
if ([SKPaymentQueue canMakePayments])
{
... // Отобразить магазин пользователю
}
else
{
... // Уведомить пользователя, что Purchases недоступны
}
* This source code was highlighted with Source Code Highlighter.
Как видите все достаточно просто. Остается скопилировать и тестировать :)
Шаг 7. Тестирование
Чтобы протестировать In-App Purchases нужно скомпилировать, установить и запустить приложение. При тестировании следует помнить следующее:
- Тестировать Purchases можно только на устройстве.
- Перед тестированием необходимо выйти из iTunes на своем iPhone. Это делается через 'Settings->Store->Sign Out'.
- При тестировании, в сообщениях с предложением купить фичу, будет появляться [Environment: sandbox] — это признак тестового режима.
- Тестировать можно только тест-аккаунтами (см. Шаг 5)
Тестовый пример InAppPurchasesExample
В результате у меня получилось приложение, которое может разблокировать два дополнительных окна. Это приложение можно использовать в качестве примера для создания своих In-App Purchase проектов.
Исходный код: InAppPurchasesExample.zip
Скриншоты:
Я очень надеюсь, что Вам помог этот пост. Если у Вас есть Вопросы, пожалуйста, задавайте. Я с удовольствием на них отвечу.
— Яков