← Toutes les extensions

Extension native

KlugBilling

com.klug.billing

AUCUN APM NÉCESSAIRE. Téléchargez et profitez-en. Impossible de faire plus simple. Mettez simplement à jour l’Adobe AIR SDK. Si vous avez besoin d’aide, nous sommes là.

Achats intégrés et abonnements pour les applications AIR sur l’App Store et Google Play, avec une seule API ActionScript pour les deux boutiques.

iOS Android En production À partir de €19 / an · Acheter

Vue d’ensemble

KlugBilling vend des produits ponctuels et des abonnements depuis votre application AIR. Sur iPhone et iPad, l’extension communique avec l’App Store, sur Android avec Google Play, et votre code ActionScript reste le même pour les deux.

L’extension charge vos produits avec des titres et des prix localisés, ouvre la feuille d’achat de la boutique, signale chaque étape d’une transaction et la clôture une fois le produit livré. La restauration des achats antérieurs, le reçu d’application iOS et les données d’achat signées de Google Play sont inclus, afin que votre serveur puisse vérifier chaque vente.

Sur Android, KlugBilling utilise la version actuelle de Google Play Billing Library 8. Elle est ajoutée automatiquement lors de l’empaquetage de l’application et répond aux exigences de Google Play pour les nouvelles applications et les mises à jour.

KlugBilling vend les abonnements de nos applications sur iOS et Android, notre preuve de concept.

Fonctionnalités

  • Autonome : une seule ANE, sans bibliothèque centrale ni ANE de dépendance à ajouter
  • Une seule API pour l’App Store et Google Play
  • Produits ponctuels et abonnements à renouvellement automatique
  • Titres, descriptions et prix localisés, directement depuis la boutique
  • Périodes d’abonnement, offres et phases tarifaires
  • Chaque état de transaction sous forme d’événement : achat en cours, acheté, échoué, annulé, restauré, différé
  • Restauration des achats (iOS) et liste des achats possédés (Android)
  • Données pour les vérifications côté serveur : le reçu d’application iOS, les données d’achat signées de Google et leur signature
  • Android : les achats sont vérifiés avec votre clé publique Play

Plateformes prises en charge

iOS iPhone · iPad · App Store
Android téléphones · tablettes · appareils pliables · Google Play Billing Library 8

Sur les autres plateformes, InAppBilling.isSupported renvoie false : le même code peut donc rester dans une application multiplateforme.

Prise en main

Ajoutez l’extension au descripteur de votre application :

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

Aucune entrée de manifeste ni aucune activité n’est nécessaire. Créez vos produits dans App Store Connect et dans la Google Play Console avec les mêmes identifiants de produit, puis copiez la clé publique base64 de votre application depuis la Play Console (Monetization setup).

Exemples de code

Quatre flux complets, tirés de l’API qui tourne dans nos applications. Chaque appel retourne immédiatement ; les résultats arrivent sous forme d’événements sur InAppBilling.service. Documentation complète →

1 · Se connecter à la boutique
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 · Afficher les produits avec des prix localisés
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 · Acheter, livrer, clôturer
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 · Restaurer les achats antérieurs
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();
    }
}

Aperçu de l’API

InAppBilling.isSupportedVrai sur iOS et Android, faux ailleurs.
InAppBilling.serviceL’unique service de boutique, qui porte tous les appels et événements ci-dessous.
setup(service)Se connecte à la boutique décrite par un BillingService. Résultat : SETUP_SUCCESS ou SETUP_FAILURE.
checkAvailability(callback)AVAILABLE, NOT_AVAILABLE ou STORE_UPGRADE_REQUIRED.
canMakePaymentsFaux lorsque les achats sont désactivés sur l’appareil.
getProducts(productIds, subscriptionIds)Charge les données de la boutique. Résultat : PRODUCTS_LOADED, INVALID_PRODUCT ou PRODUCTS_FAILED.
getProduct(id)Un Product chargé : title, description, price, priceString, currencyCode, subscriptionPeriod, subscriptionOffers.
makePurchase(request)Ouvre la feuille d’achat de la boutique pour une PurchaseRequest ; offre d’abonnement facultative.
finishPurchase(purchase)Clôture une transaction après la livraison. Résultat : FINISH_SUCCESS ou FINISH_FAILED.
getPendingPurchases()Transactions que la boutique maintient encore ouvertes.
restorePurchases()iOS : restaure les achats antérieurs de l’identifiant Apple.
getPurchases()Android : liste les achats du compte Google.
applicationReceiptiOS : le reçu d’application en base64 pour votre serveur, avec refresh().
dispose()Se déconnecte de la boutique.

Événements

InAppBillingEventSETUP_SUCCESS, SETUP_FAILURE, RESTORE_PURCHASES_SUCCESS, RESTORE_PURCHASES_FAILED
ProductEventPRODUCTS_LOADED (products), INVALID_PRODUCT, PRODUCTS_FAILED
PurchaseEventPURCHASES_UPDATED (data = objets Purchase), PURCHASE_FAILED, FINISH_SUCCESS, FINISH_FAILED, RESTORE_PURCHASES_SUCCESS, RESTORE_PURCHASES_FAILED, GET_PURCHASES_COMPLETE, GET_PURCHASES_FAILED
AvailabilityEventCOMPLETE avec le résultat de disponibilité
ApplicationReceiptEventREFRESH_SUCCESS, REFRESH_FAILED

Acheter KlugBilling

Une licence annuelle pour une application AIR, avec toutes les mises à jour pendant 12 mois. Après le paiement, vous recevez l’extension, la bibliothèque ActionScript et la documentation par e-mail, généralement sous un jour ouvré. Licence et conditions

Simple
€19 / an
  • Licence pour une application AIR
  • Toutes les mises à jour pendant 12 mois
  • Sans support
Acheter Simple
Standard
€149 / an
  • Licence pour une application AIR
  • Toutes les mises à jour pendant 12 mois
  • Réponse par e-mail sous 7 jours
Acheter Standard
Priority
€299 / an
  • Licence pour une application AIR
  • Toutes les mises à jour pendant 12 mois
  • Réponse par e-mail sous 48 heures
Acheter Priority
Les taxes sont calculées lors du paiement par Link (Stripe). Vous saisissez l’identifiant d’application de votre app AIR pendant le paiement.

Prérequis

SDK AIR51.x (HARMAN)
iOSiOS 13 ou version ultérieure, produits dans App Store Connect
AndroidAndroid 6.0 (API 23) ou version ultérieure, produits dans la Google Play Console
Google PlayPlay Billing Library 8.3, ajoutée à l’empaquetage
Serveur (recommandé)Vérifie le reçu d’application iOS ou les données d’achat signées de Google