Дополнительные возможности для работы с платежами в Unity SDK🔗
Открытие Менеджера по управлению подписками.🔗
Некоторые магазины позволяют пользователю управлять своими подписками (IOS, Google, Amazon, Huawei), а некоторые магазины требуют добавить данную возможность в ваше приложение (Google). Для открытия менеджера по управлению подписками, то есть перенаправить пользователя в магазин в нужный раздел, достаточно воспользоваться следующей функцией:
Поддержка промокодов🔗
MRGS поддерживает работу с промокодами создателей контента - при его использовании создатель получает бонус. Системы добавляются по запросу.
Для проверки наличия промокода, введенного пользователем, можно воспользоваться методом:
MRGSBank.Instance.CheckPromocode("PromoTest", (valid, error) =>
{
if (valid)
{
// Apply for later purchases
}
});
Затем, при начале платежа, необходимо добавить промокод в параметры платежа:
После успешной покупки и проверки платежа, MRGS сообщит об использовании промокода сервису (тогда создатель контента, выпустивший промокод, получает бонус).
Возможности для iOS🔗
[iOS] In-app покупки прямо из the App Store на IOS 11 и выше🔗
В IOS 11 Apple представила новый способ покупок - прямо из AppStore.
MRGS умеет работать с такими платежами. Если пользователь начал покупку в AppStore, то будет открыто Ваше приложение, и мы сохраним покупку пользователя в pendingPayment, и будем ожидать вашего решения о продолжении покупки. Для того, чтобы работать с отложенными платежами, мы предоставляем API:
// Checks for a pending payment
public bool HasPendingAppStorePromotionPayment();
// Get the product the user wants to buy
public MRGSBankProduct GetPendingAppStorePromotionPaymentProduct();
// Start pending payment with optional setting of payload
public void ProceedPendingAppStorePromotionPayment(string developerPayload = null);
Также, мы умеем работать с витринами в AppStore (например, если пользователь купил продукт, то стоит убрать его с витрины AppStore для этого пользователя) Для того, чтобы работать с витриной, мы предоставляем следующий API:
// Get order of products
GetPromoProductsOrder(Action<List<String>, String>);
// Reset products order
ResetPromoProductsOrder(Action<String>);
// Set the order of products
SetPromoProductsOrder(List<String>, Action<String>);
// Checks if the in-app is shown on the store page
GetPromoProductVisibility(String, Action<Boolean, String>);
// Hides/Shows in-app on the store page
SetPromoProductVisibility(String, Boolean, Action<String>);
[iOS] Поддержка Apple subscription offers и introductory price🔗
Для описание объекта скидки мы добавили класс MRGSBankProductDiscount. Он описывает все необходимые параметры скидки (как Apple subscription offers, так и introductory price) , такие как цену, локаль, локализованную цену, тип скидки, длительность скидки, количество периодов, метод списания средств, символ валюты и идентификатор(идентификатор будет только у Apple subscription offers).
Для того, чтобы использовать скидки, Вам сначала нужно завести их в админке appStoreConnect. Затем, Вы должны получить список скидок для данного продукта - воспользуйтесь полями MRGSBankProduct.iOS.Discounts (скидки Apple subscription offers) и MRGSBankProduct.IntroductoryPrice (первоначальные скидки), каждая скидка имеет тип MRGSBankProductDiscount и содержит описание, цену, и период, в течении которого она действует. Если указанные поля не null, то скидка заведена в iTunes, и ей можно воспользоваться. Также, необходимо определить, может ли пользователь получить скидку, так как вышеуказанные поля сообщают только лишь о наличии скидки в iTunesConnect (AppStore Connect). Для этого воспользуйтесь классом MRGSBankReceiptProcessor. Затем можно показывать интерфейс с предложением скидки.
Apple subscription offers🔗
В iOS 12.2 были представлены скидки для подписки. Получить их может только пользователь, который ранее был подписан, но отменил подписку.
Для того, чтобы начать покупку подписки со скидкой (имеются в виду скидки Apple subscription offers, introductory скидки применяются автоматически), воспользуйтесь классом MRGSBankPurchaseRequest, в котором необходимо заполнить поля DiscountIdentifier, указав идентификатор скидки, с которой вы хотите купить подписку, а также поле ApplicationUsername, в котором необходимо указать хеш от идентификатора пользователя. Поле ApplicationUsername служит для того, чтобы Apple могла внутри своей системы определить, что пользователь мошенник (например, часто делает рефанды). Если вы не заполните данное поле, то мы автоматически подставим хеш идентификатора пользователя, установленный через MRGSUsers:
var purchaseRequest = new MRGSBankPurchaseRequest("games.my.mrgs.framework.subscription", "{\"item\": 123,\"store\": 546}");
purchaseRequest.iOS.DiscountIdentifier = "MRGSPromo_5";
purchaseRequest.iOS.ApplicationUsername = "userHash";
MRGSBank.Instance.PurchaseProduct(purchaseRequest);
Далее мы проведем покупки и сообщим Вам о результате через делегат, как обычно.
Также мы добавили специальное поле MRGSBankTransaction.iOS.SelctedDiscount, в котором будет находиться объект скидки, если покупка была произведена со скидкой.
Важно
Для того, чтобы мы могли сгенерировать подпись и провести платеж, нам необходим ключ и его идентификатор. Для получения ключа необходимо перейти в AppStoreConnect-Users-Keys-Subscription, и сгенерировать ключ и идентификатор. Затем их необходимо отправить нам (напрямую в личных сообщениях или по почте).
Introductory price🔗
Также, мы поддерживаем introductory price как на клиенте, так и на сервере, и сможем нормально отслеживать не только бесплатные пробные периоды, но и обычную первоначальную скидку любого формата.
Для Вашего удобства, чтобы Вы могли правильно предоставить пользователю данные о первоначальной скидке, у объекта MRGSBankProduct есть поле IntroductoryPrice, которое содержит в себе объект MRGSBankProductDiscount, описывающий цену, и период, и другие параметры скидки. Подробнее о MRGSBankProductDiscount читайте в описании данного класса.
[iOS] Работа с чеком приложения🔗
Мы поддерживаем работу с общим чеком покупок приложения. С помощью данной функциональности Вы можете определить доступность(eligability) скидки для пользователя, узнать про активные подписки, а также получить информацию о подписках. Работает только на iOS.
Основной класс для работы с чеком - MRGSBankReceiptProcessor.
Чек приложения - локальный файл, который содержит в себе записи обо всех сделанных покупках (за исключением consumable покупок) и продлениях. Именно с ним мы и работаем.
Важно
Для работы с чеком нам необходим ключ проверки платежей, поэтому не забудьте на сайте MRGS в настройках приложения добавить специальный ключ, необходимый для проверки платежей. Найти его можно в iTunesConnect-YourApp-InappPurcases-SharedSecret.
Чаще всего чек находится в приложении сразу после скачивания, но бывают ситуации (например, установка из iTunes, или восстановление из резервной копии), когда чека может не оказаться. Если чека нет, то необходимо сделать запрос обновления, который потребует от пользователя ввод пароля. Беспричинный попап может насторожить пользователя, поэтому мы сделали метод IsReceiptAvailable, который позволит Вам узнать наличие чека, и, если он отсутствует, показать пользователю окно о том, что сейчас будет запрашивать пароль для таких-то целей.
Пример:
if(!MRGSBankReceiptProcessor.Instance.IsReceiptAvailable()){
// Show warning window
}else{
// Call required methods
}
Необходимо знать
Первый запрос к любому из методов ниже(тем, которые с колбеком) может быть долгим и потребует интернет-соединение, так как нам необходимо отправить чек на наш сервер, и получить его расшифровку. Но после него мы будем работать с закешированными данными (за исключением особых случаев, когда данные нужно обновить), и запросы будут происходить мгновенно, а при необходимости в актуальных данных, мы снова загрузим их с сервера. Даже если Вы одновременно вызовете все методы, то на наш сервер все равно будет отправлен всего один запрос, и после его окончания все методы получат callback.
Возможная ошибка SSErrorDomain Code=100
Если при тестировании Вы получаете ошибку SSErrorDomain Code=100 (ошибка обновления чека со стороны Apple), то обратитесь к данной статье:
The operation couldn’t be completed. (SSErrorDomain error 100.) If you’re trying to test iOS App Store receipt validation, and you perform a receipt refresh using SKReceiptRefreshRequest, you are almost certainly going to come across the mysterious and enigmatic SSErrorDomain Error 100. There’s not a lot of information on the googles, so here’s what I know/suspect. As far as I can tell, code 100 is the App Store’s way of telling you “Sorry, I have no receipt for that bundle ID for that user”. That’s unlikely to happen in production unless shenanigans are underway (a receipt is generated even for a free app ‘Get’), but it can happen often in development. The sandbox App Store appears to have the ability to generate fake receipts when requested, but all ducks need to be in a row for this to happen. In the sandbox (Development/Ad Hoc builds):
- If you don’t have an app record set up in iTunes Connect, you’ll get a Code 100
- If you’re signed in with your regular Apple ID instead of a sandbox account: Code 100
- If you’re signed in with a sandbox account associated with a different iTunes Connect account: Code 100
The story is a bit different for Apple Testflight builds – these are production builds with special handling for in-app purchases, and the App Store (currently) does NOT generate a fake original purchase receipt. I haven’t tested this myself, but from a developer report on the dev forums (login required):
- If you have a virgin install from TestFlight, you’ll get a Code 100
- If you’ve previously installed the App Store version of the app, you’ll get a receipt
- If you have a virgin install from TestFlight but have made an in-app purchase, you’ll get a receipt
[iOS] Получение списка купленных non-consumable товаров🔗
Если Вы используете непотребляемые товары, то Вам необходимо их восстанавливать для пользователя в некоторых ситуациях (например, переезд на новый девайс/аккаунт). Получить список купленных непотребляемых товаров можно вызвав метод restore (по гайдам это должна быть отдельная кнопка, чтобы пользователь понимал зачем ему нужно будет входить в аккаунт). Также, получить список купленных товаров можно из чека. Для этого воспользуйтесь методом:
public void GetAllPurchasedNonConsumableProducts(Action<List<MRGSBankReceiptItem>, string> completion);
В ответ придет блок, который будет вызван после получения списка. Содержит в себе массив купленных non-consumable товаров, а также ошибку, если таковая произошла.
Note
Есть вероятность, что данный функционал работает только в production, а в Sandbox/Testflight нет.
[iOS] Определение доступности скидок и начальных скидок (Determine eligability for apple subscription offers and introductory prices)🔗
Если вы используете introductory prices или apple subscription offers, то Вам необходимо определить доступность (eligability) данных предложений для пользователя, так как он мог уже покупать подписку по скидке, и больше ему данное предложение не актуально (технически невозможно купить).
Подписки разбиты по группам (в iTunesConnect), и возможность предоставления скидки определяется именно для всех подписок одной группы. Именно для групп мы и создали методы проверки. (Например, если он купил подписку на месяц из одной группы с начальной скидкой, то он не может купить(перейти) со скидкой подписку на год из той же группы)
Для того, чтобы проверить, для каких групп доступна скидка, воспользуйтесь методами:
public void GetUserIntroductoryEligibility(List<MRGSBankSubscriptionGroup> subscriptionGroups, Action<List<MRGSBankSubscriptionGroup>, string> completion);
public void GetUserDiscountEligibility(List<MRGSBankSubscriptionGroup> subscriptionGroups, Action<List<MRGSBankSubscriptionGroup>, string> completion);
Предварительно создав необходимые группы подписок. Группа состоит из названия (его не обязательно заполнять), и массива идентификаторов подписок, входящих в эту группу.
Пример использования:
var groups = new List<MRGSBankSubscriptionGroup>();
groups.Add(new MRGSBankSubscriptionGroup("group1", new List<string> { "games.my.mrgs.framework.AutoRenew1", "games.my.mrgs.framework.AutoRenew2" }));
groups.Add(new MRGSBankSubscriptionGroup(name: "group2", identifiers: new List<string> { "games.my.mrgs.framework.AutoRenew3", "games.my.mrgs.framework.AutoRenew4" }));
MRGSBankReceiptProcessor.Instance.GetUserIntroductoryEligibility(groups, (List<MRGSBankSubscriptionGroup> eligable, string error) => {
foreach (MRGSBankSubscriptionGroup eligableGroup in eligable)
{
//Eligable group process
}
});
MRGSBankReceiptProcessor.Instance.GetUserDiscountEligibility(groups, (List<MRGSBankSubscriptionGroup> eligable, string error) => {
foreach (MRGSBankSubscriptionGroup eligableGroup in eligable)
{
//Eligable group process
}
});
[iOS] Работа с информацией о подписках🔗
При работе с подписками возникает необходимость проверить, есть ли сейчас активные (действующие) подписки, когда они заканчиваются, или проверить информацию по конкретной подписке. Обычно такая информация приходит с сервера игры, но некоторые игры без сервера делают восстановление платежей на каждом старте, чтобы узнать состояние подписки, что не очень верно с точки зрения user experience. С помощью нас Вы сможете:
- Получить список активных подписок
- Получить список всех когда-либо купленных подписок
- Получить интересующую информацию о конкретной подписке
Для описания объекта подписки из чека мы сделали класс MRGSBankReceiptItem, который содержит в себе информацию о идентификаторе продукта (productIdentifier), а также времени истечения(для подписок).
Для получения информации о подписках воспользуйтесь методами:
public void GetActiveSubscriptionsAndExpirations(Action<List<MRGSBankReceiptItem>, string> completion);
public void GetAllSubscriptionsExpirationDates(Action<List<MRGSBankReceiptItem>, string> completion);
public void GetExpirationDateForSubscription(string productIdentifier, Action<MRGSBankReceiptItem, string> completion);
Примеры использования:
// Get all active subscriptions, even those that have been renewed
MRGSBankReceiptProcessor.Instance.GetActiveSubscriptionsAndExpirations((List<MRGSBankReceiptItem> subscriptions, string errorIn) => {
foreach (MRGSBankReceiptItem subscriptionInfo in subscriptions)
{
//Process active subscription
}
});
// Get a list of all subscriptions ever purchased
MRGSBankReceiptProcessor.Instance.GetAllSubscriptionsExpirationDates((List<MRGSBankReceiptItem> subscriptions, string errorIn) => {
foreach (MRGSBankReceiptItem subscriptionInfo in subscriptions)
{
//Process subscription, that was bought any time ago
}
});
// Get information about a specific subscription
MRGSBankReceiptProcessor.Instance.GetExpirationDateForSubscription(groups[0].SubscriptionsIdentifiers[0], (MRGSBankReceiptItem subscription, string errorIn) => {
Debug.Log("MRGSBankReceiptProcessor subscription - " + subscription);
});
Важно
Мы учитываем продления подписок. Таким образом, если подписка была продлена, а локальный чек не был обновлен (обычно так и происходит), мы все равно предоставим актуальную, самую последнюю информацию о подписках.
Обнаружение мошенничества🔗
Для того чтобы помочь Apple обнаружить мошенничество в покупках внутри приложения, при начале покупки, вы можете выставить параметр:
var purchaseRequest = new MRGSBankPurchaseRequest(<sku>, <developerPayload>);
purchaseRequest.iOS.ApplicationUsername = <user_id_hash>;
MRGSBank.Instance.PurchaseProduct(purchaseRequest);
В случае, если вы не установите данный идентификатор, MRGS автоматически установит его значение как хеш от пользователя, выставленного нам при старте
Эмулирование разрешения на покупку от родителей🔗
Apple дает возможность родителям подтверждать покупки детей. В таком случае при проведении платежа придет статус pending. Для того, чтобы протестировать данный функционал, вы можете выставить параметр:
var purchaseRequest = new MRGSBankPurchaseRequest(<sku>, <developerPayload>);
purchaseRequest.iOS.SimulatesAskToBuyInSandbox = true;
MRGSBank.Instance.PurchaseProduct(purchaseRequest);
Возможности для Android (Google Play)🔗
Все дополнительные возможности доступны только при использовании магазина приложений Google Play
Смена подписки🔗
Пользователь может сменить одну подписку на другую. Например - с помесячной оплатой на годовую. Для этого необходимо воспользоваться методом changeItem. Первым параметром необходимо указать новую подписку, вторым параметром - старую
var request = new MRGSBankPurchaseRequest("some.product.id", "optional payload");
request.Android.OldSubscriptionIdentifierToMoveFrom = "old.subscription.id";
MRGSBank.Instance.PurchaseProduct(request);
Подробнее о смене подписки читайте на сайте Google Billing
Скидки на подписки🔗
В консоли Google Play вы можете указать скидку на первую покупку подписки и период, в течении которого будет списываться именно эта, начальная цена. Например подписка стоит 100р в месяц, а вы можете для первых трех месяцев указать цену 50р в месяц. Для того чтобы узнать на клиенте доступна ли пользователю скидка на подписку, необходимо проверить цену в поле IntroductoryPrice класса MRGSBankProduct
public void OnReceiveProductsResponse(MRGSBankProductsResponse productsResponse)
{
foreach (var product in productsResponse.ValidProducts)
{
var discount = product.IntroductoryPrice;
Debug.Log("Product discount: " + discount);
}
}
Активация промо-кодов🔗
Вы можете выдать определенный товар в игре с помощью активации промо-кода. Промокоды можно завести в консоли Google Play, подробнее читайте в документации Google Billing
Для активации промо-кода внутри приложения воспользуйтесь методом redeemPromoCode
Обнаружение мошенничества (Karaganda Fraud Prevention API)🔗
Для того чтобы помочь Google обнаружить мошенничество до того, как это произойдет вы можете воспользоваться следующими методами: setObfuscatedAccountId и setObfuscatedProfileId
var request = new MRGSBankPurchaseRequest("some.product.id", "optional payload");
request.Android.ObfuscatedAccountId = <obfuscatedAccountId>;
request.Android.ObfuscatedProfileId = <obfuscatedProfileId>;
MRGSBank.Instance.PurchaseProduct(request);
В случае, если вы не установите данный идентификатор, MRGS автоматически установит его значение как хеш от пользователя, выставленного нам при старте
В данный момент подписки не поддерживаются
Поддержка платежей в сторонних магазинах приложений на Android🔗
Помимо биллинга Google, MRGS поддерживает работу с магазинами Samsung и Amazon
Подключение платежей Samsung🔗
- Загрузите последнюю версию библиотеки с сайта Unity
- Извлеките из архива файлы
- Добавьте библиотеку IAP5Helper.aar в свой проект
- При инициализации MRGS укажите тип биллинга "samsung"
using MRGS;
public class MasterController : MonoBehaviour
{
void Awake()
{
var serviceParams = new MRGServiceParams(APP_ID, APP_SECRET);
// Setting MRGS params
// ...
// Choosing a store to work on Android
// Available MRGSPlatform: Amazon, Android, Huawei, Samsung, and FacebookCloud
serviceParams.AndroidExtraOptions.Platform = MRGSPlatformAndroid.Samsung;
// Configuring External SDKs
MRGSExternalSDKParams sdkParams = new MRGSExternalSDKParams();
// Where mode:
// 1) "test" - is equivalent to OperationMode.OPERATION_MODE_TEST
// 2) "production" - is equivalent to OperationMode.OPERATION_MODE_PRODUCTION
sdkParams.SamsungBillingParams = new MRGSSamsungBillingParams(mode)
// ...
// Initializing MRGS
// ...
}
}
Подключение платежей Amazon🔗
- Загрузите последнюю версию библиотеки с сайта Unity
- Извлеките из архива файлы
- Добавьте библиотеку in-app-purchasing-2.0.61.jar в свой проект
- При инициализации MRGS укажите тип биллинга "amazon"
using MRGS;
public class MasterController : MonoBehaviour
{
void Awake()
{
var serviceParams = new MRGServiceParams(APP_ID, APP_SECRET);
// Setting MRGS params
// ...
// Choosing a store to work on Android
// Available MRGSPlatform: Amazon, Android, Huawei, Samsung, and FacebookCloud
serviceParams.AndroidExtraOptions.Platform = MRGSPlatformAndroid.Amazon;
// Configuring External SDKs and initializing MRGS
// ...
}
}
Подключение платежей Huawei/AppTouch🔗
- Добавьте библиотеку согласно документации
- При инициализации MRGS укажите тип биллинга "huawei"
using MRGS;
public class MasterController : MonoBehaviour
{
void Awake()
{
var serviceParams = new MRGServiceParams(APP_ID, APP_SECRET);
// Setting MRGS params
// ...
// Choosing a store to work on Android
// Available MRGSPlatform: Amazon, Android, Huawei, Samsung, and FacebookCloud
serviceParams.AndroidExtraOptions.Platform = MRGSPlatformAndroid.Huawei;
// Configuring External SDKs and initializing MRGS
// ...
}
}
Дата создания: 2020-01-20