← Все расширения

Нативное расширение

KlugBilling

com.klug.billing

APM НЕ НУЖЕН. Скачайте и пользуйтесь. Проще уже некуда. Просто обновите Adobe AIR SDK. Если нужна помощь, мы рядом.

Встроенные покупки и подписки для приложений AIR в App Store и Google Play с единым API ActionScript для обоих магазинов.

iOS Android В продакшене От €19 / год · Купить

Обзор

KlugBilling продаёт разовые товары и подписки из вашего приложения AIR. На iPhone и iPad расширение работает с App Store, на Android — с Google Play, а ваш код ActionScript остаётся одинаковым для обоих.

Расширение загружает ваши товары с локализованными названиями и ценами, открывает окно покупки магазина, сообщает о каждом шаге транзакции и закрывает её, как только вы предоставили товар. Восстановление прежних покупок, чек приложения iOS и подписанные данные покупок Google Play включены, так что ваш сервер может проверить каждую продажу.

На Android KlugBilling использует актуальную Google Play Billing Library 8. Она добавляется автоматически при упаковке приложения и соответствует требованиям Google Play к новым приложениям и обновлениям.

KlugBilling продаёт подписки наших приложений на iOS и Android, нашего доказательства работоспособности.

Возможности

  • Автономность: один ANE, без базовой библиотеки и зависимых ANE
  • Единый API для App Store и Google Play
  • Разовые товары и автоматически продлеваемые подписки
  • Локализованные названия, описания и цены прямо из магазина
  • Периоды подписки, предложения и ценовые фазы
  • Каждое состояние транзакции как событие: покупка, куплено, ошибка, отменено, восстановлено, отложено
  • Восстановление покупок (iOS) и список имеющихся покупок (Android)
  • Данные для проверки на сервере: чек приложения iOS, подписанные данные покупки Google и подпись
  • Android: покупки проверяются по вашему открытому ключу Play

Поддерживаемые платформы

iOS iPhone · iPad · App Store
Android телефоны · планшеты · складные устройства · Google Play Billing Library 8

На других платформах InAppBilling.isSupported возвращает false, поэтому один и тот же код можно оставить в кроссплатформенном приложении.

Начало работы

Добавьте расширение в дескриптор вашего приложения:

app.xml
<extensions>
    <extensionID>com.klug.billing</extensionID>
</extensions>

Записи в манифесте и activity не нужны. Создайте товары в App Store Connect и в Google Play Console с одинаковыми идентификаторами продуктов и скопируйте открытый ключ base64 вашего приложения из Play Console (Monetization setup).

Примеры кода

Четыре полных сценария из API, который работает в наших приложениях. Каждый вызов возвращается сразу; результаты приходят как события на InAppBilling.service. Полная документация →

1 · Подключение к магазину
Store.as
import com.klug.billing.*;
import com.klug.billing.events.*;

var store:InAppBillingService = InAppBilling.service;

if ( InAppBilling.isSupported )   // iOS, Android
{
    store.addEventListener( InAppBillingEvent.SETUP_SUCCESS, onSetup );
    store.addEventListener( InAppBillingEvent.SETUP_FAILURE, onSetupFailed );
    store.addEventListener( PurchaseEvent.PURCHASES_UPDATED, onPurchasesUpdated );   // see 3

    var service:BillingService = new BillingService();
    if ( store.platform == "android" )
        service.setServiceType( InAppBillingServiceTypes.GOOGLE_PLAY_INAPP_BILLING )
               .setGooglePlayPublicKey( "MIIBIjANBgkqh..." );   // from the Play Console, Android only
    else
        service.setServiceType( InAppBillingServiceTypes.APPLE_INAPP_PURCHASE );
    store.setup( service );
}

function onSetup( e:InAppBillingEvent ):void
{
    store.checkAvailability( function( result:String ):void {
        if ( result == InAppBillingAvailability.AVAILABLE ) loadProducts();   // see 2
        else hideShop();   // e.g. purchases disabled by Screen Time
    });
}
2 · Показ товаров с локализованными ценами
Products.as
function loadProducts():void
{
    store.addEventListener( ProductEvent.PRODUCTS_LOADED, onProducts );
    store.addEventListener( ProductEvent.PRODUCTS_FAILED, function( e:ProductEvent ):void {
        trace( "store not reachable: " + e.message );
    });
    // one-time products first, subscriptions second
    store.getProducts( [ "com.example.removeads" ],
                       [ "com.example.pro.monthly", "com.example.pro.yearly" ] );
}

function onProducts( e:ProductEvent ):void
{
    for each ( var p:Product in e.products )
    {
        // e.g. "Pro Yearly · 19,99 €" in the user's currency and language
        addShopButton( p.id, p.title + " · " + p.priceString );   // your app function
    }
}
3 · Покупка, предоставление, завершение
Purchase.as
function buy( productId:String ):void
{
    var request:PurchaseRequest = new PurchaseRequest().setProductId( productId );
    if ( store.checkPurchaseRequestValid( request ) ) store.makePurchase( request );
}

// every step of every transaction, also open ones from earlier sessions
function onPurchasesUpdated( e:PurchaseEvent ):void
{
    for each ( var p:Purchase in e.data )
    {
        switch ( p.transactionState )
        {
            case Purchase.STATE_PURCHASED:
            case Purchase.STATE_RESTORED:
                // iOS: p.transactionReceipt (app receipt)
                // Android: p.originalMessage + p.signature (Google's signed purchase data)
                verifyOnServer( p, function():void {   // your server call
                    unlock( p.productId );              // your app function
                    store.finishPurchase( p );          // close it, or the store sends it again
                });
                break;
            case Purchase.STATE_FAILED:
            case Purchase.STATE_CANCELLED:
                store.finishPurchase( p );
                break;
            case Purchase.STATE_DEFERRED:
                showHint( "Waiting for approval" );   // e.g. Ask to Buy
                break;
        }
    }
}
4 · Восстановление прежних покупок
Restore.as
function restore():void
{
    if ( store.isGetPurchasesSupported )   // Android: list what the Google account owns
    {
        store.addEventListener( PurchaseEvent.GET_PURCHASES_COMPLETE, function( e:PurchaseEvent ):void {
            for each ( var p:Purchase in e.data ) unlock( p.productId );
        });
        store.getPurchases();
    }
    else   // iOS: restored transactions arrive in onPurchasesUpdated with STATE_RESTORED
    {
        store.addEventListener( PurchaseEvent.RESTORE_PURCHASES_SUCCESS, function( e:PurchaseEvent ):void {
            showHint( "Purchases restored" );
        });
        store.restorePurchases();
    }
}

Обзор API

InAppBilling.isSupportedTrue на iOS и Android, false на остальных.
InAppBilling.serviceЕдинственный сервис магазина; через него идут все вызовы и события ниже.
setup(service)Подключается к магазину, описанному BillingService. Результат: SETUP_SUCCESS или SETUP_FAILURE.
checkAvailability(callback)AVAILABLE, NOT_AVAILABLE или STORE_UPGRADE_REQUIRED.
canMakePaymentsFalse, если покупки на устройстве отключены.
getProducts(productIds, subscriptionIds)Загружает данные магазина. Результат: PRODUCTS_LOADED, INVALID_PRODUCT или PRODUCTS_FAILED.
getProduct(id)Загруженный Product: title, description, price, priceString, currencyCode, subscriptionPeriod, subscriptionOffers.
makePurchase(request)Открывает окно покупки магазина для PurchaseRequest; предложение подписки необязательно.
finishPurchase(purchase)Закрывает транзакцию после предоставления товара. Результат: FINISH_SUCCESS или FINISH_FAILED.
getPendingPurchases()Транзакции, которые магазин ещё держит открытыми.
restorePurchases()iOS: восстанавливает прежние покупки Apple ID.
getPurchases()Android: перечисляет покупки аккаунта Google.
applicationReceiptiOS: чек приложения в base64 для вашего сервера, с refresh().
dispose()Отключается от магазина.

События

InAppBillingEventSETUP_SUCCESS, SETUP_FAILURE, RESTORE_PURCHASES_SUCCESS, RESTORE_PURCHASES_FAILED
ProductEventPRODUCTS_LOADED (products), INVALID_PRODUCT, PRODUCTS_FAILED
PurchaseEventPURCHASES_UPDATED (data = объекты Purchase), PURCHASE_FAILED, FINISH_SUCCESS, FINISH_FAILED, RESTORE_PURCHASES_SUCCESS, RESTORE_PURCHASES_FAILED, GET_PURCHASES_COMPLETE, GET_PURCHASES_FAILED
AvailabilityEventCOMPLETE с результатом проверки доступности
ApplicationReceiptEventREFRESH_SUCCESS, REFRESH_FAILED

Купить KlugBilling

Годовая лицензия на одно приложение AIR со всеми обновлениями в течение 12 месяцев. После оплаты вы получаете расширение, библиотеку ActionScript и документацию по e-mail, обычно в течение одного рабочего дня. Лицензия и условия

Базовый
€19 / год
  • Лицензия на одно приложение AIR
  • Все обновления в течение 12 месяцев
  • Без поддержки
Купить Базовый
Стандартный
€149 / год
  • Лицензия на одно приложение AIR
  • Все обновления в течение 12 месяцев
  • Ответ по e-mail в течение 7 дней
Купить Стандартный
Приоритетный
€299 / год
  • Лицензия на одно приложение AIR
  • Все обновления в течение 12 месяцев
  • Ответ по e-mail в течение 48 часов
Купить Приоритетный
Налоги рассчитываются при оформлении заказа через Link (Stripe). ID приложения вашего приложения AIR вы указываете при оформлении заказа.

Требования

AIR SDK51.x (HARMAN)
iOSiOS 13 или новее, товары в App Store Connect
AndroidAndroid 6.0 (API 23) или новее, товары в Google Play Console
Google PlayPlay Billing Library 8.3, добавляется при упаковке
Сервер (рекомендуется)Проверяет чек приложения iOS или подписанные данные покупки Google