flutter_rustore_billing

Flutter RuStoreSDK для подключения платежей

Документация RuStore

Общее

Пример реализации

Для того, чтобы узнать как правильно интегрировать платежи, рекомендуется ознакомиться с приложением-примером

Условия работы платежей

Для работы проведения платежей необходимо соблюдение следующих условий:

  • На устройстве пользователя должен быть установлен RuStore.
  • RuStore должен поддерживать функциональность платежей.
  • Пользователь должен быть авторизован в RuStore.
  • Пользователь и приложение не должны быть заблокированы в RuStore.
  • Для приложения должна быть включена возможность покупок в консоли разработчика RuStore.

Подключение в проект

Для подключения пакета к проекту нужно выполнить команду

flutter pub add flutter_rustore_billing

Эта команда добавит строчку в файл pubspec.yaml

dependencies:
    flutter_rustore_billing: ^3.1.0

Для корректной работы оплаты через сторонние приложения (СБП или SberPay), вам необходимо правильно реализовать обработку deeplink. Для этого необходимо указать в AndroidManifest.xml intent-filter с scheme вашего проекта:

<activity
android:name=".sample.MainActivity">

    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
  
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="yourappscheme" />
    </intent-filter>

</activity>

где "yourappscheme" - схема вашего deeplink, может быть изменена на другую.

Эта схема должна совпадать со схемой, передаваемым в методе initialize().

Инициализация

Перед вызовом методов библиотеки необходимо выполнить ее инициализацию. Для инициализации вызовете метод RustoreBillingClient.initialize():

RustoreBillingClient.initialize(
    "123456",
    "yourappscheme://iamback",
    ).then((value) {
        print("initialize success: $value");
    }, onError: (err) {
        print("initialize err: $err");
});

123456 - код приложения из консоли разработчика RuStore (пример: https://console.rustore.ru/apps/123456). yourappscheme://iamback - cхема deeplink, необходимая для возврата в ваше приложение после оплаты через стороннее приложение (например, SberPay или СБП). SDK генерирует свой хост к данной схеме. Важно, чтобы схема deeplink, передаваемая в deeplinkScheme, совпадала со схемой, указанной в AndroidManifest.xml в разделе "Обработка deeplink".

Проверка доступности работы с платежами

Для проверки доступности платежей необходимы следующие условия:

  • На устройстве пользователя должен быть установлен RuStore.
  • RuStore должен поддерживать функциональность платежей.
  • Пользователь должен быть авторизован в RuStore.
  • Пользователь и приложение не должны быть заблокированы в RuStore.
  • Для приложения должна быть включена возможность покупок в консоли разработчика RuStore.
  • Если все условия выполняются, метод RustoreBillingClient.available() возвращает значение true.
RustoreBillingClient.available().then((value) {
        print("available success $value");
    }, onError: (err) {
        print("available err: $err");
});

Работа с продуктами

Получение списка продуктов

Для получения продуктов необходимо использовать метод RustoreBillingClient.products(ids):

RustoreBillingClient.products(ids).then((response) {
        for (final product in response.products) {
            print(product?.productId);
        }
    }, onError: (err) {
        print("products err: $err");
});

ids: List<String?> - список идентификаторов продуктов.

Метод возвращает ProductsResponse:

class ProductsResponse {
    int code;
    String? errorMessage;
    String? errorDescription;
    String? traceId;
    List<Product?> products;
    List<DigitalShopGeneralError?> errors;
}
  • code - код ответа.
  • errorMessage - сообщение об ошибке.
  • errorDescription - описание ошибки.
  • traceId - идентификатор ошибки.
  • errors - список ошибок.
  • products - список продуктов.

Структура ошибки DigitalShopGeneralError:

class DigitalShopGeneralError {
    String? name;
    int? code;
    String? description
}
  • name - имя ошибки.
  • code - код ошибки.
  • description - описание ошибки.

Структура продукта Product:

class Product {
    String productId;
    String? productType;
    String productStatus;
    String? priceLabel;
    int? price;
    String? currency;
    String? language;
    String? title;
    String? description;
    String? imageUrl;
    String? promoImageUrl;
    Subscription? subscription;
}
  • productId - идентификатор продукта.
  • productType - тип продукта.
  • productStatus - статус продукта.
  • priceLable - отформатированная цена товара, включая валютный знак на языке language.
  • price - цена в минимальных единицах.
  • currency - код валюты ISO 4217.
  • language - язык, указанный с помощью BCP 47 кодирования.
  • title - название продукта на языке language.
  • description - описание продукта на языке language.
  • imageUrl - ссылка на картинку.
  • promoImageUrl - ссылка на промо картинку.
  • subscription - описание подписки, возвращается только для продуктов с типом subscription.

Структура подписки Subscription:

class Subscription {
    SubscriptionPeriod? subscriptionPeriod;
    SubscriptionPeriod? freeTrialPeriod;
    SubscriptionPeriod? gracePeriod;
    String? introductoryPrice;
    String? introductoryPriceAmount;
    SubscriptionPeriod? introductoryPricePeriod;
}
  • subscriptionPeriod - период подписки.
  • freeTrialPeriod - пробный период подписки.
  • gracePeriod - льготный период подписки.
  • introductoryPrice - отформатированная вступительная цена подписки, включая знак валюты, на языке product:language.
  • introductoryPriceAmount - вступительная цена в минимальных единицах валюты (в копейках).
  • introductoryPricePeriod - расчетный период вступительной цены.

Структура периода подписки SubscriptionPeriod:

class SubscriptionPeriod {
    int years;
    int months;
    int days;
}
  • years - количество лет.
  • months - количество месяцев.
  • days - количество дней.

Работа с покупками

Получение списка покупок

Для получения списка покупок необходимо использовать метод RustoreBillingClient.purchases():

RustoreBillingClient.purchases().then((response) {
        for (final product in response.purchases) {
            print(product?.purchaseId);
        }
    }, onError: (err) {
        print("purchases err: $err");
});

Метод возвращает PurchasesResponse:

class PurchasesResponse {
    int code;
    String? errorMessage;
    String? errorDescription;
    String? traceId;
    List<Purchase?> purchases;
    List<DigitalShopGeneralError?> errors;
}
  • code - код ответа.
  • errorMessage - сообщение об ошибке.
  • errorDescription - описание ошибки.
  • traceId - идентификатор ошибки.
  • errors - список ошибок.
  • purchases - список покупок.

Структура ошибки DigitalShopGeneralError:

class DigitalShopGeneralError {
    String? name;
    int? code;
    String? description;
}
  • name - наименование ошибки.
  • code - код ошибки.
  • description - описание ошибки.

Структура покупки Purchase:

class Purchase { String? purchaseId; String? productId; String? description; String? language; String? purchaseTime; String? orderId; String? amountLabel; int? amount; String? currency; int? quantity; String? purchaseState; String? developerPayload; }

  • purchaseId - идентификатор покупки.
  • productId - идентификатор продукта.
  • description - описание покупки.
  • language - язык, указанный с помощью BCP 47 кодирования.
  • purchaseTime - время покупки (в формате RFC 3339).
  • orderId - уникальный идентификатор оплаты, сформированный приложением (uuid).
  • amountLable - отформатированная цена покупки, включая валютный знак на языке language.
  • amount - цена в минимальных единицах валюты.
  • currency - код валюты ISO 4217.
  • quantity - количество продукта.
  • purchaseState - состояние покупки.
    • CREATED - создана.
    • INVOICE_CREATED - создана, ожидает оплаты.
    • CONFIRMED - подтверждена.
    • PAID - оплачена.
    • CANCELLED - покупка отменена.
    • CONSUMED - потребление покупки подтверждено.
    • CLOSED - подписка была отменена.
  • developerPayload - указанная разработчиком строка, содержащая дополнительную информацию о заказе.

Покупка продукта

Для вызова покупки продукта используйте метод RustoreBillingClient.purchase(id):

RustoreBillingClient.purchase(id).then((response) {
        print("purchase success: $response");
    }, onError: (err) {
        print("purchase err: $err");
});
  • id - идентификатор продукта.

Структура результата покупки PaymentResult:

class PaymentResult {
    SuccessInvoice? successInvoice;
    InvalidInvoice? invalidInvoice;
    SuccessPurchase? successPurchase;
    InvalidPurchase? invalidPurchase;
}

Структура SuccessInvoice:

class SuccessInvoice {
    String invoiceId;
    String finishCode;
}

Структура InvalidInvoice:

class InvalidInvoice {
    String? invoiceId;
}

Структура SuccessPurchase:

class SuccessPurchase {
    String finishCode;
    String? orderId;
    String purchaseId;
    String productId;
}

Структура InvalidPurchase:

class InvalidPurchase {
    String? purchaseId;
    String? invoiceId;
    String? orderId;
    int? quantity;
    String? productId;
    int? errorCode;
}
  • SuccessInvoice - платежи завершились с результатом.
  • InvalidInvoice - платежи завершились без указания инвойса. Вероятно, они были запущены с некорректным инвойсом (пустая строка, например).
  • SuccessPurchase - результат успешного завершения покупки цифрового товара.
  • InvalidPurchase - при оплате цифрового товара платежи завершились c ошибкой.

Возможные статусы, которые может содержать finishCode:

  • SUCCESSFUL_PAYMENT - успешная оплата.
  • CLOSED_BY_USER - отменено пользователем.
  • UNHANDLED_FORM_ERROR - неизвестная ошибка.
  • PAYMENT_TIMEOUT - ошибка оплаты по таймауту.
  • DECLINED_BY_SERVER - отклонено сервером.
  • RESULT_UNKNOWN - неизвестный статус оплаты.

Потребление (подтверждение) покупки

RuStore содержит продукты следующих типов:

  • CONSUMABLE - потребляемый (можно купить много раз, например кристаллы в приложении).
  • NON_CONSUMABLE - непотребляемый (можно купить один раз, например отключение рекламы в приложении).
  • SUBSCRIPTION - подписка (можно купить на период времени, например подписка в стриминговом сервисе).

Потребления требуют только продукты типа CONSUMABLE, если они находятся в состоянии PurchaseState.PAID.

Для потребления покупки вы можете использовать метод RustoreBillingClient.confirm(id):

RustoreBillingClient.confirm(id).then((response) {
        print("confirm success: $response");
    }, onError: (err) {
        print("confirm err: $err");
});
  • id - идентификатор покупки.

Метод возвращает ConfirmPurchaseResponse:

class ConfirmPurchaseResponse {
    int code;
    String? errorMessage;
    String? errorDescription;
    String? traceId;
    List<DigitalShopGeneralError?> errors;
}
  • code - код ответа.
  • errorMessage - сообщение об ошибке для пользователя.
  • errorDescription - расшифровка сообщения об ошибке.
  • traceId - идентификатор ошибочного сообщения.
  • errors - список ошибок.

Структура ошибки DigitalShopGeneralError:

class DigitalShopGeneralError {
    String? name;
    int? code;
    String? description;
}
  • name - наименование атрибута ошибки.
  • code - код ошибки.
  • description - описание ошибки.

Тестовые данные

Ссылка на тестовые банковские карты.