В какой-то момент всё становится серьёзным — даже в приложениях про любовь. Команда Redspell, создатели игры Senses (интерактивные романтические истории), решили стать одними из первых, кто интегрировал новую платёжку от RuStore — Pay SDK. И встроили — с нуля, но в итоге с ростом метрик.

Вот честный рассказ о том, как ребята внедряли RuStore Pay SDK, что пошло не так, как с этим справились и какие результаты в итоге получили. Если вы тоже раздумываете, стоит ли связываться — читайте до конца. Там есть приятные цифры.

Зачем вообще этот Pay SDK

Если коротко: Pay SDK — это способ встроить в приложение платежи, которые работают быстро, выглядят нативно и не заставляют пользователя вводить свой email в 2025 году (серьёзно, хватит уже). Разработан специально в RuStore, адаптируется под вашу архитектуру и не требует танцев с дебагером в полнолуние.

Что внутри:

  • Простая интеграция без лишних зависимостей;

  • Одно- и двухстадийная оплата (на любой вкус);

  • Вся логика платежей — у вас под контролем;

  • VK ID  — всё быстро и удобно;

  • Работает даже если у пользователя нет RuStore.

И да, вскоре он станет достойной альтернативой BillingClient SDK. Но уже сейчас умеет больше:

  • Купоны, возвраты, список продуктов без авторизации;

  • И даже чеки в мессенджер или почту, если вы по олдскулу.

Как всё начиналось

Когда Senses появился в RuStore, перед Redspell встал вполне логичный вопрос: как получить максимальную выгоду от монетизации. Всё-таки 85% дохода с приложения — это внутриигровые покупки, а значит, платёжка должна быть быстрой, нативной и не раздражать пользователя (ну, и разработчика, конечно). 

И тут на горизонте — Pay SDK: всё ещё в beta, но уже с полноценной функциональностью, официальной поддержкой и гибкостью под разные сценарии. Раньше Redspell использовали сторонние веб-интерфейсы для монетизации — решение не самое удобное, не нативное и не всегда стабильное. Поэтому переход на Pay SDK стал логичным шагом: хотелось, чтобы весь процесс оплаты проходил прямо внутри приложения — быстро, аккуратно и под контролем.

Выбирая между BillingClient SDK и новым Pay SDK, команда Redspell сразу сделала ставку на второй вариант — он уже закрывал нужные задачи и, что важно, активно развивается RuStore.

В итоге ребята не растерялись — и пошли в пилот.

Технический квест на Unity

Платформа у Redspell — Unity. SDK нужно было аккуратно прикрутить, не развалив игру.

Вкратце, что было не так:

Вызовы Pay SDK встроили через стандартный Unity Purchase Module — без лома кода.

Код
class RuStoreModule: AbstractPurchasingModule
{

public const string STORE_NAME = "RuStore";
private static RuStoreModule _instance;
public static IPurchasingModule Instance()
{
_instance ??= new RuStoreModule();
return _instance;
}
public override void Configure()
{
RegisterStore(STORE_NAME,new RuStore());
}
}

internal class RuStore : IStore
{

private IStoreCallback _storeCallback;
public void Initialize(IStoreCallback callback)
{
_storeCallback = callback;

bool isRuStoreInstalled = RuStorePayClient.Instance.IsRuStoreInstalled();
if (!isRuStoreInstalled)
{
_storeCallback.OnSetupFailed(InitializationFailureReason.PurchasingUnavailable, "RuStore is not installed");
return;
}
var settings = BlackMagicSettings.Instance;

RuStorePayClient.Instance.GetPurchaseAvailability(
onFailure: (error) =>
{
// Process error
_storeCallback.OnSetupFailed(InitializationFailureReason.PurchasingUnavailable,$"{error.name}:{error.description}");
},
onSuccess: (response) =>
{
if (response.isAvailable)
{
RuStorePayClient.Instance.GetPurchases(OnGetPurchasesFailure,onGetPurchasesSuccess);
}
else
{
var error = response.cause;
_storeCallback.OnSetupFailed(InitializationFailureReason.PurchasingUnavailable, $"{error.name}:{error.description}");
}
}
);
}

Но не обошлось без затыков: нужно было переопределить стандартный Unity Activity, добавить Java-файл и всё это собрать на CI под Android.

Ещё и уведомления с этим не дружили — конфликтовали.

Код
#if UNITY_ANDROID // && !UNITY_EDITOR
public class RuStorePostProcessor : IPostGenerateGradleAndroidProject
{
public int callbackOrder => 100;
public void OnPostGenerateGradleAndroidProject(string path)
{
var gradleDir = path;

#if RUSTORE
PatchAndroidManifest(gradleDir);
GenerateJavaHandler(gradleDir);
#else
Debug.Log("RuStore disabled");
RemoveJavaHandler(gradleDir);
#endif

}

#if RUSTORE

void PatchAndroidManifest(string gradleDir)
{
string manifestPath = Path.Combine(
gradleDir, "src", "main", "AndroidManifest.xml");
var doc = XDocument.Load(manifestPath);

XNamespace androidNs = "http://schemas.android.com/apk/res/android";
var application = doc.Root.Element("application");
// e.g. add an <activity> or <meta-data> entry:
var activity = new XElement("activity",
new XAttribute(androidNs + "name", "games.extras.blackmagic.RuStoreDeeplinkActivity"),
new XAttribute(androidNs + "exported", "true")
);

activity.Add(
new XElement("intent-filter",
new XElement("action", new XAttribute(androidNs + "name", "android.intent.action.VIEW")),
new XElement("category", new XAttribute(androidNs + "name", "android.intent.category.DEFAULT")),
new XElement("category", new XAttribute(androidNs + "name", "android.intent.category.BROWSABLE")),
new XElement("data", new XAttribute(androidNs + "scheme", "@string/rustore_PayClientSettings_deeplinkScheme"))
)
);
application.Add(activity);
....
}
void GenerateJavaHandler(string gradleDir)
{
string javaDir = Path.Combine(
gradleDir, "src", "main", "java", "games", "extras", "blackmagic");
Directory.CreateDirectory(javaDir);
string javaFile = Path.Combine(javaDir, "RuStoreDeeplinkActivity.java");

string code = @"
package games.extras.blackmagic;

import android.app.Activity;
import android.os.Bundle;
import android.content.Intent;
import ru.rustore.unitysdk.payclient.RuStoreUnityPayClient;
import com.unity3d.player.UnityPlayerActivity;
import android.util.Log;


public class RuStoreDeeplinkActivity extends Activity {
@Override protected void onCreate(Bundle savedInstanceState) {
.....

Как выкрутились:

Сделали дополнительный Activity, который ловит Intent и запускает SDK. Код генерируется через Unity Post-Processor — только когда надо. Гибко, красиво, работает.

Что в итоге?

Через пару месяцев стало ясно: SDK живёт, платежи идут, пользователи довольны. А главное — метрики сказали «да»:

  • Процент платящих пользователей в RuStore более чем в 3 раза превышает аналогичный показатель на Google Play.

  • Прирост APRU (Average Revenue Per User, средняя выручка на одного пользователя) составил +207 % по сравнению с Google Play и +63 % по отношению к App Store.

  • ARPPU (Average revenue per paying user, средняя выручка на одного платящего пользователя) на 29 % выше, чем в Google Play.

  • RuStore демонстрирует самый высокий средний чек среди всех платформ, опережая App Store на 28,4 %.

  • Huawei-пользователи остались в игре — отсутствие GMS больше не препятствует стабильным платежам.

А вам зачем это знать?

Если вы тоже публикуетесь в RuStore и вам нужна платёжка, которая:

  • быстро ставится;

  • не ломает архитектуру;

  • дружит с VK ID;

  • и в целом работает как надо —

то Pay SDK — рабочий инструмент, с которым можно запускать монетизацию уже сейчас. Redspell интегрировал его без драмы, метрики пошли вверх, пользователи не убежали — разве что в очередной виртуальный роман с новым пиксельным красавчиком или красавицей.

Плюс, если что-то не клеится — команда поддержки действительно отвечает, а не «мы передали вашу заявку в параллельную вселенную». 

А ещё у нас есть телеграм-канал — подписывайтесь, там регулярно появляется всякое полезное (и местами весёлое) для разработчиков.

Комментарии (0)