Oversigt
KlugBilling sælger engangsprodukter og abonnementer fra din AIR-app. På iPhone og iPad taler den med App Store, på Android med Google Play, og din ActionScript-kode forbliver den samme for begge.
Den indlæser dine produkter med lokaliserede titler og priser, åbner butikkens købsdialog, rapporterer hvert trin i en transaktion og afslutter den, når du har leveret produktet. Gendannelse af tidligere køb, iOS-appkvitteringen og Google Plays signerede købsdata er inkluderet, så din server kan verificere hvert salg.
På Android bruger KlugBilling det aktuelle Google Play Billing Library 8. Det tilføjes automatisk, når appen pakkes, og opfylder Google Plays krav til nye apps og opdateringer.
KlugBilling sælger abonnementerne i vores apps på iOS og Android, vores proof of concept.
Funktioner
- Selvstændig: én ANE, intet kernebibliotek eller afhængige ANE'er at tilføje
- Én API til App Store og Google Play
- Engangsprodukter og automatisk fornyede abonnementer
- Lokaliserede titler, beskrivelser og priser direkte fra butikken
- Abonnementsperioder, tilbud og prisfaser
- Hver transaktionstilstand som en hændelse: køber, købt, mislykket, annulleret, gendannet, udskudt
- Gendan køb (iOS) og vis ejede køb (Android)
- Data til kontrol på serversiden: iOS-appkvitteringen, Googles signerede købsdata og signatur
- Android: køb kontrolleres mod din offentlige Play-nøgle
Understøttede platforme
På andre platforme returnerer InAppBilling.isSupported false, så den samme kode kan blive i en cross-platform-app.
Kom i gang
Tilføj udvidelsen til din applikationsdescriptor:
<extensions>
<extensionID>com.klug.billing</extensionID>
</extensions>
Der kræves ingen manifest-poster og ingen activities. Opret dine produkter i App Store Connect og i Google Play Console med de samme produkt-ID'er, og kopiér din apps offentlige base64-nøgle fra Play Console (Monetization setup).
Kodeeksempler
Fire komplette flows, taget fra den API, der kører i vores apps. Hvert kald vender straks tilbage; resultater ankommer som hændelser på InAppBilling.service. Fuld dokumentation →
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(); } }
API-oversigt
| InAppBilling.isSupported | Sand på iOS og Android, falsk andre steder. |
| InAppBilling.service | Den eneste butikstjeneste; alle kald og hændelser nedenfor. |
| setup(service) | Forbinder til den butik, der er beskrevet af en BillingService. Resultat: SETUP_SUCCESS eller SETUP_FAILURE. |
| checkAvailability(callback) | AVAILABLE, NOT_AVAILABLE eller STORE_UPGRADE_REQUIRED. |
| canMakePayments | Falsk, når køb er deaktiveret på enheden. |
| getProducts(productIds, subscriptionIds) | Indlæser butiksdata. Resultat: PRODUCTS_LOADED, INVALID_PRODUCT eller PRODUCTS_FAILED. |
| getProduct(id) | Et indlæst Product: title, description, price, priceString, currencyCode, subscriptionPeriod, subscriptionOffers. |
| makePurchase(request) | Åbner butikkens købsdialog for en PurchaseRequest; valgfrit abonnementstilbud. |
| finishPurchase(purchase) | Afslutter en transaktion efter levering. Resultat: FINISH_SUCCESS eller FINISH_FAILED. |
| getPendingPurchases() | Transaktioner, som butikken stadig holder åbne. |
| restorePurchases() | iOS: gendanner tidligere køb på Apple-id'et. |
| getPurchases() | Android: viser Google-kontoens køb. |
| applicationReceipt | iOS: appkvitteringen som base64 til din server, med refresh(). |
| dispose() | Afbryder forbindelsen til butikken. |
Events
| InAppBillingEvent | SETUP_SUCCESS, SETUP_FAILURE, RESTORE_PURCHASES_SUCCESS, RESTORE_PURCHASES_FAILED |
| ProductEvent | PRODUCTS_LOADED (products), INVALID_PRODUCT, PRODUCTS_FAILED |
| PurchaseEvent | PURCHASES_UPDATED (data = Purchase-objekter), PURCHASE_FAILED, FINISH_SUCCESS, FINISH_FAILED, RESTORE_PURCHASES_SUCCESS, RESTORE_PURCHASES_FAILED, GET_PURCHASES_COMPLETE, GET_PURCHASES_FAILED |
| AvailabilityEvent | COMPLETE med tilgængelighedsresultatet |
| ApplicationReceiptEvent | REFRESH_SUCCESS, REFRESH_FAILED |
Køb KlugBilling
En årlig licens til én AIR-applikation, med alle opdateringer i 12 måneder. Efter betaling modtager du udvidelsen, ActionScript-biblioteket og dokumentationen pr. e-mail, normalt inden for én hverdag. Licens og vilkår
- Licens til én AIR-applikation
- Alle opdateringer i 12 måneder
- Svar pr. e-mail inden for 7 dage
- Licens til én AIR-applikation
- Alle opdateringer i 12 måneder
- Svar pr. e-mail inden for 48 timer
Krav
| AIR SDK | 51.x (HARMAN) |
| iOS | iOS 13 eller nyere, produkter i App Store Connect |
| Android | Android 6.0 (API 23) eller nyere, produkter i Google Play Console |
| Google Play | Play Billing Library 8.3, tilføjes ved pakningen |
| Server (anbefales) | Verificerer iOS-appkvitteringen eller Googles signerede købsdata |