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
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 :
<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 →
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 }); }
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 } }
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; } } }
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.isSupported | Vrai sur iOS et Android, faux ailleurs. |
| InAppBilling.service | L’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. |
| canMakePayments | Faux 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. |
| applicationReceipt | iOS : le reçu d’application en base64 pour votre serveur, avec refresh(). |
| dispose() | Se déconnecte de la boutique. |
Événements
| InAppBillingEvent | SETUP_SUCCESS, SETUP_FAILURE, RESTORE_PURCHASES_SUCCESS, RESTORE_PURCHASES_FAILED |
| ProductEvent | PRODUCTS_LOADED (products), INVALID_PRODUCT, PRODUCTS_FAILED |
| PurchaseEvent | PURCHASES_UPDATED (data = objets Purchase), PURCHASE_FAILED, FINISH_SUCCESS, FINISH_FAILED, RESTORE_PURCHASES_SUCCESS, RESTORE_PURCHASES_FAILED, GET_PURCHASES_COMPLETE, GET_PURCHASES_FAILED |
| AvailabilityEvent | COMPLETE avec le résultat de disponibilité |
| ApplicationReceiptEvent | REFRESH_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
- Licence pour une application AIR
- Toutes les mises à jour pendant 12 mois
- Sans support
- Licence pour une application AIR
- Toutes les mises à jour pendant 12 mois
- Réponse par e-mail sous 7 jours
- Licence pour une application AIR
- Toutes les mises à jour pendant 12 mois
- Réponse par e-mail sous 48 heures
Prérequis
| SDK AIR | 51.x (HARMAN) |
| iOS | iOS 13 ou version ultérieure, produits dans App Store Connect |
| Android | Android 6.0 (API 23) ou version ultérieure, produits dans la Google Play Console |
| Google Play | Play 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 |