Comment mettre en œuvre la facturation dans l'application dans l'application Android?

Il semble qu'il soit assez difficile de mettre en œuvre la facturation à l'intérieur de l'application dans l'application Android. Comment pourrais-je le faire? Un exemple d'application est SDK Il n'a qu'une seule action qui la simplifie un peu pour une telle application, comme la mienne qui a plusieurs actions.
Invité:

Agathe

Confirmation de:

Eh bien, je vais essayer d'expliquer ce que j'ai vécu. Je ne me considère pas comme un expert en la matière, mais quelques jours me brisaient la tête.

Premièrement, j'ai eu un très mauvais temps d'essayer de comprendre le flux de travail de l'exemple et de l'application. Je pensais qu'il était préférable de commencer par un exemple simple, mais il est très difficile de diviser le code en petits morceaux et de ne pas savoir si vous violez quoi que ce soit. Je vais vous dire que j'ai et ce que j'ai changé de l'exemple pour le faire fonctionner.

J'ai un type d'activité, d'où vient tous mes achats. On l'appelle "Pro".

Tout d'abord, vous devez mettre à jour la variable base64EncodedPublicKey Dans sa classe de sécurité utilisant la clé de développeur public Market, Sinon, vous verrez une exception agréable.

Eh bien, j'associe mes activités avec mon BillingService comme ça:


public class Pro extends TrackedActivity implements OnItemClickListener {

private BillingService mBillingService;
private BillingPurchaseObserver mBillingPurchaseObserver;
private Handler mHandler;

@Override
protected void onCreate/Bundle savedInstanceState/ {
super.onCreate/savedInstanceState/;
setContentView/R.layout.pro/;


//Do my stuff

mBillingService = new BillingService//;
mBillingService.setContext/getApplicationContext///;

mHandler = new Handler//;
mBillingPurchaseObserver = new BillingPurchaseObserver/mHandler/;

}

}



@Override
protected void onStart// {
//Register the observer to the service
super.onStart//;
ResponseHandler.register/mBillingPurchaseObserver/;
}


@Override
protected void onStop// {
//Unregister the observer since you dont need anymore
super.onStop//;
ResponseHandler.unregister/mBillingPurchaseObserver/;
}

@Override
protected void onDestroy// {
//Unbind the service
super.onDestroy//;
mBillingService.unbind//;
}


Ainsi, tous les achats parlent avec ce service, qui enverront ensuite des demandes JSON Au marché. Vous pourriez penser que les achats sont faits au même moment, mais non. Vous envoyez une demande et l'achat peut venir dans quelques minutes ou quelques heures. Je pense que c'est principalement dû à l'approbation de la surcharge de serveurs et de la carte de crédit.

Ensuite j'ai ListView avec mes articles et j'ouvre AlertDialog Sur chacun d'eux, les invitant à acheter cet article. Quand ils cliquent sur l'article, je le fais:


private class BuyButton implements DialogInterface.OnClickListener {

private BillingItem item = null;
private String developerPayload;

public BuyButton/BillingItem item, String developerPayload/ {
this.item = item;
this.developerPayload = developerPayload;
}

@Override
public void onClick/DialogInterface dialog, int which/ {

if /GeneralHelper.isOnline/getApplicationContext////{
//I track the buy here with GA SDK.

mBillingService.requestPurchase/this.item.getSku//, this.developerPayload/;
} else {
Toast.makeText/getApplicationContext//, R.string.msg_not_online, Toast.LENGTH_SHORT/.show//;
}

}

}


Eh bien, vous devez voir que le marché s'ouvre et l'utilisateur se termine ou annule l'achat.

Que alors important est mon PurChaseObserver, qui traite tous les événements que le marché envoie. Ceci est une version trimérique, mais vous devez comprendre l'essence /Voir mes commentaires autour du code/:


private class BillingPurchaseObserver extends PurchaseObserver {
public BillingPurchaseObserver/Handler handler/ {
super/Pro.this, handler/;
}

@Override
public void onBillingSupported/boolean supported/ {

if /supported/ {
//Enable buy functions. Not required, but you can do stuff here. The market first checks if billing is supported. Maybe your country is not supported, for example.
} else {
Toast.makeText/getApplicationContext//, R.string.billing_not_supported, Toast.LENGTH_LONG/.show//;
}
}

@Override
public void onPurchaseStateChange/PurchaseState purchaseState, String itemId,
int quantity, long purchaseTime, String developerPayload/ {

//This is the method that is called when the buy is completed or refunded I believe.
// Here you can do something with the developerPayload. Its basically a Tag you can use to follow your transactions. i dont use it.

BillingItem item = BillingItem.getBySku/getApplicationContext//, itemId/;

if /purchaseState == PurchaseState.PURCHASED/ {
if /item != null/{
//This is my own implementation that sets the item purchased in my database. BillingHelper is a class with methods I use to check if the user bought an option and update the UI. You should also check for refunded. You can see the Consts class to find what you need to check for.

boolean resu = item.makePurchased/getApplicationContext///;
if /resu/{
Toast.makeText/getApplicationContext//, R.string.billing_item_purchased, Toast.LENGTH_LONG/.show//;
}
}
}
}

private void trackPurchase/BillingItem item, long purchaseTime/ {
//My code to track the purchase in GA
}

@Override
public void onRequestPurchaseResponse/RequestPurchase request,
ResponseCode responseCode/ {

//This is the callback that happens when you sent the request. It doesnt mean you bought something. Just that the Market received it.

if /responseCode == ResponseCode.RESULT_OK/ {

Toast.makeText/getApplicationContext//, R.string.billing_item_request_sent, Toast.LENGTH_SHORT/.show//;

} else if /responseCode == ResponseCode.RESULT_USER_CANCELED/ {
//The user canceled the item.
} else {
//If it got here, the Market had an unexpected problem.
}
}

@Override
public void onRestoreTransactionsResponse/RestoreTransactions request,
ResponseCode responseCode/ {
if /responseCode == ResponseCode.RESULT_OK/ {
//Restore transactions should only be run once in the lifecycle of your application unless you reinstalled the app or wipe the data.

SharedPreferences.Editor edit = PreferencesHelper.getInstance//.getDefaultSettings/getApplicationContext///.edit//;
edit.putBoolean/Consts.DB_INITIALIZED, true/;
edit.commit//;

} else {
//Something went wrong
}
}
}


Et je pense que vous n'avez pas besoin de modifier autre chose. rest Coda "works".
Vous pouvez essayer d'abord utiliser l'échantillon SKU Dans vos propres éléments "android.test.purchased". Jusqu'à présent, je l'ai vérifié, et cela fonctionne, mais j'ai toujours besoin de tout couvrir comme l'état retourné. Dans ce cas, je permet à l'utilisateur de sauvegarder des fonctions, mais je veux m'assurer qu'ils fonctionnent parfaitement avant de les changer.

J'espère que cela vous aidera et d'autres.

Blanche

Confirmation de:

V3:

Voici un manuel pour un démarrage rapide. Il utilise des classes auxiliaires de l'exemple google /Trivial Drive/ ... bon comme le premier "Hello Billing" ..

http://www.techotopia.com/inde ... orial

Giselle

Confirmation de:

Exemple

Android In-App Billing v3

Un pas à pas est donné ici avec une capture d'écran. S'il vous plaît vérifier le tutoriel:
https://inducesmile.com/androi ... rial/
ServiceConnection

J'espère que cela aidera.

Pour plus de clarification, lisez ce tutoriel:
https://developer.android.com/ ... .html
Étapes à effectuer pour intégrer la bibliothèque de facturation dans l'application à notre projet

Mettez à jour votre fichier AndroidManifest.xml.

Créer ServiceConnection et l'attache à IInAppBillingService.

Envoyer des demandes de factures dans l'application à partir de votre candidature à l'adresse IInAppBillingService.

Réponses de facturation de processus dans l'application de Google Play.

Mettre à jour AndroidManifest.xml


<uses-permission android:name="com.android.vending.BILLING"></uses-permission>


Ajouter des autorisations au fichier Manifest.xml

Ajouter un fichier. AIDL Dans votre projet

Créez votre application. Vous devez voir le fichier généré nommé IInAppBillingService.java dans le catalogue /gen Votre projet.

Mise à jour de dépendance de fichier build.gradle


apply plugin: 'com.android.application'
android {
compileSdkVersion 24
buildToolsVersion "24.0.0"
defaultConfig {
applicationId "com.inducesmile.androidinapppurchase"
minSdkVersion 14
targetSdkVersion 24
versionCode 2
versionName "1.1"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile/'proguard-android.txt'/, 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree/dir: 'libs', include: ['*.jar']/
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:24.1.1'
compile 'com.intuit.sdp:sdp-android:1.0.3'
compile 'com.android.support:support-annotations:24.1.1'
compile 'org.jetbrains:annotations-java5:15.0'
}


InAppPurchaseActivity.java et activity_in_app_purchase.xml

C'est ici que nous offrirons à nos utilisateurs de l'application la possibilité de faire un achat dans l'annexe. Dans le fichier de mise en page, nous donnerons à l'utilisateur la possibilité de faire des achats de différents nominaux.

InAppPurchaseActivity.java

Remarque: méthodes getAllUserPurchase// et itemPurchaseAvailability// Doit être appelé dans un flux sans interface utilisateur pour éviter la défaillance de l'application.


public class InAppPurchaseActivity extends AppCompatActivity {
private static final String TAG = InAppPurchaseActivity.class.getSimpleName//;
private IInAppBillingService mService;
private CustomSharedPreference customSharedPreference;
String[] productIds = new String[]{Helper.ITEM_ONE_ID, Helper.ITEM_TWO_ID, Helper.ITEM_THREE_ID};
private ImageView buyOneButton, buyTwoButton, buyThreeButton;
private static final char[] symbols = new char[36];
static {
for /int idx = 0; idx < 10; ++idx/
symbols[idx] = /char/ /'0' + idx/;
for /int idx = 10; idx < 36; ++idx/
symbols[idx] = /char/ /'a' + idx - 10/;
}
private String appPackageName;
@Override
protected void onCreate/Bundle savedInstanceState/ {
super.onCreate/savedInstanceState/;
setContentView/R.layout.activity_in_app_purchase/;
appPackageName = this.getPackageName//;
Intent serviceIntent = new Intent/"com.android.vending.billing.InAppBillingService.BIND"/;
serviceIntent.setPackage/"com.android.vending"/;
bindService/serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE/;
customSharedPreference = new CustomSharedPreference/InAppPurchaseActivity.this/;
buyOneButton = /ImageView/findViewById/R.id.buy_one/;
buyOneButton.setVisibility/View.GONE/;
assert buyOneButton != null;
buyOneButton.setOnClickListener/new View.OnClickListener// {
@Override
public void onClick/View view/ {
if/!isBillingSupported///{
Helper.displayMessage/InAppPurchaseActivity.this, getString/R.string.in_app_support//;
return;
}
purchaseItem/Helper.ITEM_ONE_ID/;
}
}/;
buyTwoButton = /ImageView/findViewById/R.id.buy_two/;
buyTwoButton.setVisibility/View.GONE/;
assert buyTwoButton != null;
buyTwoButton.setOnClickListener/new View.OnClickListener// {
@Override
public void onClick/View view/ {
if/!isBillingSupported///{
Helper.displayMessage/InAppPurchaseActivity.this, getString/R.string.in_app_support//;
return;
}
purchaseItem/Helper.ITEM_TWO_ID/;
}
}/;
buyThreeButton = /ImageView/findViewById/R.id.buy_three/;
buyThreeButton.setVisibility/View.GONE/;
assert buyThreeButton != null;
buyThreeButton.setOnClickListener/new View.OnClickListener// {
@Override
public void onClick/View view/ {
if/!isBillingSupported///{
Helper.displayMessage/InAppPurchaseActivity.this, getString/R.string.in_app_support//;
return;
}
purchaseItem/Helper.ITEM_THREE_ID/;
}
}/;
}
ServiceConnection mServiceConn = new ServiceConnection// {
@Override
public void onServiceDisconnected/ComponentName name/ {
mService = null;
}
@Override
public void onServiceConnected/ComponentName name, IBinder service/ {
mService = IInAppBillingService.Stub.asInterface/service/;
AvailablePurchaseAsyncTask mAsyncTask = new AvailablePurchaseAsyncTask/appPackageName/;
mAsyncTask.execute//;
}
};
private void purchaseItem/String sku/{
String generatedPayload = getPayLoad//;
customSharedPreference.setDeveloperPayLoad/generatedPayload/;
try {
Bundle buyIntentBundle = mService.getBuyIntent/3, getPackageName//, sku, "inapp", generatedPayload/;
PendingIntent pendingIntent = buyIntentBundle.getParcelable/"BUY_INTENT"/;
try {
startIntentSenderForResult/pendingIntent.getIntentSender//, Helper.RESPONSE_CODE, new Intent//, Integer.valueOf/0/, Integer.valueOf/0/, Integer.valueOf/0//;
} catch /IntentSender.SendIntentException e/ {
e.printStackTrace//;
}
} catch /RemoteException e/ {
e.printStackTrace//;
}
}
@Override
protected void onActivityResult/int requestCode, int resultCode, Intent data/ {
if /requestCode == Helper.RESPONSE_CODE/ {
int responseCode = data.getIntExtra/"RESPONSE_CODE", 0/;
String purchaseData = data.getStringExtra/"INAPP_PURCHASE_DATA"/;
String dataSignature = data.getStringExtra/"INAPP_DATA_SIGNATURE"/;
if /resultCode == RESULT_OK/ {
try {
JSONObject purchaseJsonObject = new JSONObject/purchaseData/;
String sku = purchaseJsonObject.getString/"productId"/;
String developerPayload = purchaseJsonObject.getString/"developerPayload"/;
String purchaseToken = purchaseJsonObject.getString/"purchaseToken"/;
//the developerPayload value is better stored in remote database but in this tutorial
//we will use a shared preference
for/int i = 0; i < productIds.length; i++/{
if/productIds[i].equals/sku/ && developerPayload.equals/customSharedPreference.getDeveloperPayload////{
customSharedPreference.setPurchaseToken/purchaseToken/;
//access to private content
Intent contentIntent = new Intent/InAppPurchaseActivity.this, PrivateContentActivity.class/;
startActivity/contentIntent/;
}
}
}
catch /JSONException e/ {
e.printStackTrace//;
}
}
}
}
private String getPayLoad//{
RandomString randomString = new RandomString/36/;
String payload = randomString.nextString//;
return payload;
}
public class RandomString {
private final Random random = new Random//;
private final char[] buf;
public RandomString/int length/ {
if /length < 1/
throw new IllegalArgumentException/"length < 1: " + length/;
buf = new char[length];
}
public String nextString// {
for /int idx = 0; idx < buf.length; ++idx/
buf[idx] = symbols[random.nextInt/symbols.length/];
return new String/buf/;
}
}
public final class SessionIdentifierGenerator {
private SecureRandom random = new SecureRandom//;
public String nextSessionId// {
return new BigInteger/130, random/.toString/32/;
}
}
private class AvailablePurchaseAsyncTask extends AsyncTask<void, bundle="" void,=""> {
String packageName;
public AvailablePurchaseAsyncTask/String packageName/{
this.packageName = packageName;
}
@Override
protected Bundle doInBackground/Void... voids/ {
ArrayList<string> skuList = new ArrayList<string>//;
skuList.add/Helper.ITEM_ONE_ID/;
skuList.add/Helper.ITEM_TWO_ID/;
skuList.add/Helper.ITEM_THREE_ID/;
Bundle query = new Bundle//;
query.putStringArrayList/Helper.ITEM_ID_LIST, skuList/;
Bundle skuDetails = null;
try {
skuDetails = mService.getSkuDetails/3, packageName, "inapp", query/;
} catch /RemoteException e/ {
e.printStackTrace//;
}
return skuDetails;
}
@Override
protected void onPostExecute/Bundle skuDetails/ {
List<availablepurchase> canPurchase = new ArrayList<availablepurchase>//;
int response = skuDetails.getInt/"RESPONSE_CODE"/;
if /response == 0/ {
ArrayList<string> responseList = skuDetails.getStringArrayList/"DETAILS_LIST"/;
if/responseList != null/{
for /String thisResponse : responseList/ {
JSONObject object = null;
try {
object = new JSONObject/thisResponse/;
String sku = object.getString/"productId"/;
String price = object.getString/"price"/;
canPurchase.add/new AvailablePurchase/sku, price//;
} catch /JSONException e/ {
e.printStackTrace//;
}
}
}
}
if/checkIfPurchaseIsAvailable/canPurchase, productIds[0]//{
buyOneButton.setVisibility/View.VISIBLE/;
}else{
buyOneButton.setVisibility/View.GONE/;
}
if/checkIfPurchaseIsAvailable/canPurchase, productIds[1]//{
buyTwoButton.setVisibility/View.VISIBLE/;
}else{
buyTwoButton.setVisibility/View.GONE/;
}
if/checkIfPurchaseIsAvailable/canPurchase, productIds[2]//{
buyThreeButton.setVisibility/View.VISIBLE/;
}else{
buyThreeButton.setVisibility/View.GONE/;
}
}
}
@org.jetbrains.annotations.Contract/"null, _ -&gt; false"/
private boolean checkIfPurchaseIsAvailable/List<availablepurchase> all, String productId/{
if/all == null/{ return false;}
for/int i = 0; i &lt; all.size//; i++/{
if/all.get/i/.getSku//.equals/productId//{
return true;
}
}
return false;
}
public boolean isBillingSupported//{
int response = 1;
try {
response = mService.isBillingSupported/3, getPackageName//, "inapp"/;
} catch /RemoteException e/ {
e.printStackTrace//;
}
if/response &gt; 0/{
return false;
}
return true;
}
public void consumePurchaseItem/String purchaseToken/{
try {
int response = mService.consumePurchase/3, getPackageName//, purchaseToken/;
if/response != 0/{
return;
}
} catch /RemoteException e/ {
e.printStackTrace//;
}
}
public Bundle getAllUserPurchase//{
Bundle ownedItems = null;
try {
ownedItems = mService.getPurchases/3, getPackageName//, "inapp", null/;
} catch /RemoteException e/ {
e.printStackTrace//;
}
return ownedItems;
}
public List<userpurchaseitems> extractAllUserPurchase/Bundle ownedItems/{
List<userpurchaseitems> mUserItems = new ArrayList<userpurchaseitems>//;
int response = ownedItems.getInt/"RESPONSE_CODE"/;
if /response == 0/ {
ArrayList<string> ownedSkus = ownedItems.getStringArrayList/"INAPP_PURCHASE_ITEM_LIST"/;
ArrayList<string> purchaseDataList = ownedItems.getStringArrayList/"INAPP_PURCHASE_DATA_LIST"/;
ArrayList<string> signatureList = ownedItems.getStringArrayList/"INAPP_DATA_SIGNATURE_LIST"/;
String continuationToken = ownedItems.getString/"INAPP_CONTINUATION_TOKEN"/;
if/purchaseDataList != null/{
for /int i = 0; i &lt; purchaseDataList.size//; ++i/ {
String purchaseData = purchaseDataList.get/i/;
assert signatureList != null;
String signature = signatureList.get/i/;
assert ownedSkus != null;
String sku = ownedSkus.get/i/;
UserPurchaseItems allItems = new UserPurchaseItems/sku, purchaseData, signature/;
mUserItems.add/allItems/;
}
}
}
return mUserItems;
}
@Override
public void onDestroy// {
super.onDestroy//;
if /mService != null/ {
unbindService/mServiceConn/;
}
}
}


Créer un catalogue d'emballages auxiliaires

Créez un nouveau dossier de colis et nommez-le. helpers. Créez un nouveau fichier à l'intérieur du package java Helper.java.

Helper.java


public class Helper {
public static final String ITEM_ID_LIST = "ITEM_ID_LIST";
public static final String ITEM_ONE_ID = "productone";
public static final String ITEM_TWO_ID = "producttwo";
public static final String ITEM_THREE_ID = "productthree";
public static final int RESPONSE_CODE = 1001;
public static final String SHARED_PREF = "shared_pref";
public static final String DEVELOPER_PAYLOAD = "developer_payload";
public static final String PURCHASE_TOKEN = "purchase_token";
public static void displayMessage/Context context, String message/{
Toast.makeText/context.getApplicationContext//, message, Toast.LENGTH_LONG/.show//;
}
}


Test d'achat de facturation dans l'application

Créer un compte Google+ /N'utilisez pas le compte principal/

Ajoutez des utilisateurs à tester l'application dans votre groupe ou votre communauté.

Erreurs avec lesquelles vous pouvez rencontrer lors de l'achat de tests dans l'application

Vous avez demandé des biens indisponibles d'acheter

Décision –
https://coderoad.ru/13117081/
,

Tout le mérite appartient

pour ça
https://inducesmile.com/androi ... rial/
Android Le blog du développeur recommande également une formation pour la vente de produits dans la demande. Pour voir la mise en œuvre complète et apprendre à tester la demande, veuillez lire ce tutoriel:
https://developer.android.com/ ... .html
</string></string></string></userpurchaseitems></userpurchaseitems></userpurchaseitems></availablepurchase></string></availablepurchase></availablepurchase></string></string></void,>

Agathe

Confirmation de:

Si vous souhaitez utiliser une bibliothèque simple pour publication dans Google Play et Appstore Amazon, vous pouvez utiliser
https://github.com/christopher ... brary
. Il résume les détails des deux en un simple à utiliser la bibliothèque. Des instructions détaillées sont affichées sur la page. Github.

Dominique

Confirmation de:

Eh bien, c'est l'une de ces choses qui ont beaucoup de documents disponibles sur Internet. Je ferai de mon mieux pour expliquer tout pas à pas. Pris de mon message dans un blog, une version plus détaillée de cette /avec captures d'écran/,
http://themillibit.com/2018/07 ... -app/
. Sans plusieurs mots,

La première étape:

Autorisation
C'est la dernière étape. Aller au fichier manifest.xml Et ajoutez la chaîne suivante sous la balise:


<uses-permission android:name="com.android.vending.BILLING"></uses-permission>


Cela donnera à vos autorisations de votre application pour accéder à la facturation de la demande. Si vous êtes concentré sur la version ci-dessus API 22, Vous devrez vous assurer que cette autorisation est accordée lors de l'exécution.

Deuxième étape:

Console de jeu
Maintenant, vous devez télécharger votre application sur la console. Google Play. Nous ne publions pas notre candidature pour le grand public. /ne t'inquiète pas/, Nous le téléchargons simplement dans la section bêta, ce qui nous permettra de tester des achats dans l'application. La raison pour laquelle nous devrions faire cela est que Google Doit avoir une version de votre APK, Téléchargé pour les processus de facturation a vraiment fonctionné.

Basculer vers
https://play.google.com/apps/publish/
/

Créer une application

Suivez ces étapes pour configurer votre application.

Aller aux applications

Aller à bêta

Créer APK Votre demande B. Android studio et téléchargez-le à la version bêta dans Play Console

/Avant la libération, assurez-vous d'avoir déjà rempli la liste des magasins, la note de contenu, les prix et la distribution./

Appuyez sur le bouton MAGIC /Publier!/

Troisième étape:

Configuration du projet
D'accord, c'est la partie où vous devez copier et insérer un tas de fichiers.

Première prise
https://github.com/googlesampl ... .aidl
fichier, téléchargez-le et placez-le sous
src/main

Il doit être intégré au dossier
Puis prendre
https://github.com/googlesampl ... /util
dossier util Et insérez-le dans
src/java folder.

, Puis ajustez votre projet pour éliminer les erreurs.
Dossier Util Contient les classes suivantes:

IabBroadcastReceiver

IabException

IabHelper

IabResult

Inventaire

Acheter

Sécurité

SkuDetails

Étape quatre:

Création de produits

Créer un produit géré

Cliquez sur Enregistrer et faire “pricing template”

Ici vous choisirez le prix de ce produit. Vous pouvez choisir le prix pour différents pays ou le personnaliser automatiquement, si vous choisissez simplement tous les pays à votre prix:

Assurez-vous que le produit intégré est activé et est associé à l'application correcte dans la console pour la dernière fois.

Enfin, faites attention à ID Ton produit. Nous allons utiliser ceci ID Dans les prochaines étapes.

Obtenir votre Base64EncodedString

Aller à la section "Prestations de service & APIs" Et prenez votre Base64EncodedString. Copiez-le et collez-le dans un ordinateur portable quelque part afin que vous ayez accès à celui-ci. Ne partagez-la avec personne, ils pourront faire des choses perverses avec lui.

Pitch cinquième:

Pour terminer! Nous pouvons commencer à coder:
D'abord, nous contacterons la bibliothèque de facturation dans la demande et demanderons d'acheter un utilisateur has/hasn’t. Ensuite, nous achetons un produit qui a créé plus tôt.

Tout d'abord, importez tout ce que nous avons mis en place plus tôt:


import util.*;


Maintenant, nous allons utiliser l'objet IabHelper intitulé mHelper, Et nous ferons tout avec ça.


base64EncodedPublicKey = ""; //PUT YOUR BASE64KEY HERE

mHelper = new IabHelper/this, base64EncodedPublicKey/;
mHelper.enableDebugLogging/false/; //set to false in real app


mHelper.startSetup/new IabHelper.OnIabSetupFinishedListener// {
public void onIabSetupFinished/IabResult result/ {
if /!result.isSuccess/// {
// Oh no, there was a problem.

if /result.getResponse// == 3/ {
new AlertDialog.Builder/MainActivity.this/
.setTitle/"In app billing"/
.setMessage/"This device is not compatible with In App Billing, so" +
" you may not be able to buy the premium version on your phone. "/
.setPositiveButton/"Okay", null/
.show//;
}

Log.v/TAG, "Problem setting up In-app Billing: " + result/;
} else {
Log.v/TAG, "YAY, in app billing set up! " + result/;
try {
mHelper.queryInventoryAsync/mGotInventoryListener/; //Getting inventory of purchases and assigning listener
} catch /IabHelper.IabAsyncInProgressException e/ {
e.printStackTrace//;
}
}
}
}/;


Eh bien, laissez-moi vous expliquer ce qui se passe ici. En substance, nous appelons “startSetup” Pour notre initialisation “IabHelper”. Si le réglage est passé avec succès, nous demandons quels achats ont déjà un utilisateur et nous enregistrons les réponses à
mGotInventoryListener

, Ce que nous allons coder plus loin:


IabHelper.QueryInventoryFinishedListener mGotInventoryListener
= new IabHelper.QueryInventoryFinishedListener// {
public void onQueryInventoryFinished/IabResult result,
Inventory inventory/ {

i = inventory;

if /result.isFailure/// {
// handle error here

Log.v/TAG, "failure in checking if user has purchases"/;
} else {
// does the user have the premium upgrade?
if /inventory.hasPurchase/"premium_version"// {

premiumEditor.putBoolean/"hasPremium", true/;
premiumEditor.commit//;

Log.v/TAG, "Has purchase, saving in storage"/;

} else {

premiumEditor.putBoolean/"hasPremium", false/;
premiumEditor.commit//;

Log.v/TAG, "Doesn't have purchase, saving in storage"/;

}
}
}
};


Le code ci-dessus est tout à fait compréhensible. En substance, il vérifie simplement les achats de l'utilisateur existant déjà. Maintenant, lorsque nous savons si l'utilisateur a déjà acheté notre produit, nous savons s'il faut lui demander d'acheter nos biens! S'ils n'ont jamais acheté notre produit avant, commençons à acheter un achat:


public void buyPremium// {
try {

mHelper.flagEndAsync//;//If any async is going, make sure we have it stop eventually
mHelper.launchPurchaseFlow/this, "premium_version", 9, mPurchaseFinishedListener, "SECURITYSTRING"/; //Making purchase request and attaching listener
} catch /Exception e/ {
e.printStackTrace//;

mHelper.flagEndAsync//;//If any async is going, make sure we have it stop eventually




new AlertDialog.Builder/MainActivity.this/
.setTitle/"Error"/
.setMessage/"An error occurred in buying the premium version. Please try again."/
.setPositiveButton/"Okay", null/
.show//;
}
}


@Override

protected void onActivityResult/int requestCode, int resultCode, Intent data/ {

Log.d/TAG, "onActivityResult/" + requestCode + "," + resultCode + "," + data/;

// Pass on the activity result to the helper for handling

if /!mHelper.handleActivityResult/requestCode, resultCode, data// {

}

else
Log.d/TAG, "onActivityResult handled by IABUtil."/;
}

}

IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener
= new IabHelper.OnIabPurchaseFinishedListener// {
public void onIabPurchaseFinished/IabResult result, Purchase purchase/ {

Log.v/TAG, "purchase finished"/;

if /purchase != null/ {

if /purchase.getSku//.equals/"premium_version"// {

Toast.makeText/MainActivity.this, "Purchase successful!", Toast.LENGTH_SHORT/.show//;

premiumEditor.putBoolean/"hasPremium", true/;
premiumEditor.commit//;
}
} else {
return;
}
if /result.isFailure/// {
return;
}
}
};


Ici nous achetons le sujet /de ID, que nous avons généré dans play console Plus tôt/ Avec ce qui suit:


mHelper.launchPurchaseFlow/this, "premium_version", 9, mPurchaseFinishedListener, "SECURITYSTRING"/; //Making purchase request and attaching listener


Notez que nous avons passé
mPurchaseFinishedListener

dans les paramètres. Cela signifie que le résultat d'achat sera renvoyé à cet auditeur. Ensuite, nous vérifions simplement si l'achat est null, Et sinon, nous récompensons l'utilisateur par n'importe quelle fonction qu'il a achetée.

Ne laissez pas les auditeurs se pencher! Nous devons les détruire lorsque l'application détruira.


@Override
public void onDestroy// {
super.onDestroy//;
if /mHelper != null/
try {
mHelper.dispose//;
mHelper = null;

} catch /IabHelper.IabAsyncInProgressException e/ {
e.printStackTrace//;
}
}


Enfin, si vous voulez consommer votre achat en le faisant un nouvellement disponible à l'achat, vous pouvez le faire facilement. Par exemple, si l'utilisateur a acheté de l'essence pour une machine virtuelle et que cela s'est terminé. Ils ont besoin d'acheter le même produit à nouveau et vous pouvez le rendre accessible au deuxième achat, pour le consommer:


public void consume//{

//MAKING A QUERY TO GET AN ACCURATE INVENTORY
try {
mHelper.flagEndAsync//; //If any async is going, make sure we have it stop eventually

mHelper.queryInventoryAsync/mGotInventoryListener/; //Getting inventory of purchases and assigning listener

if/i.getPurchase/"gas"/==null/{
Toast.makeText/this, "Already consumed!", Toast.LENGTH_SHORT/.show//;
}
} catch /IabHelper.IabAsyncInProgressException e/ {
e.printStackTrace//;

Toast.makeText/this, "Error, try again", Toast.LENGTH_SHORT/.show//;
mHelper.flagEndAsync//;//If any async is going, make sure we have it stop eventually
}

//ACTUALLY CONSUMING
try {
mHelper.flagEndAsync//;//If any async is going, make sure we have it stop eventually

this.mHelper.consumeAsync/this.i.getPurchase/"gas"/, new IabHelper.OnConsumeFinishedListener// {
public void onConsumeFinished/Purchase paramAnonymousPurchase, IabResult paramAnonymousIabResult/ {
//resell the gas to them
}
}/;

return;
} catch /IabHelper.IabAsyncInProgressException localIabAsyncInProgressException/ {
localIabAsyncInProgressException.printStackTrace//;
Toast.makeText/this, "ASYNC IN PROGRESS ALREADY!!!!" +localIabAsyncInProgressException, Toast.LENGTH_LONG/.show//;
Log.v/"myTag", "ASYNC IN PROGRESS ALREADY!!!"/;

mHelper.flagEndAsync//;
}
}


C'est ici! Maintenant, vous pouvez commencer à gagner de l'argent. C'est vraiment aussi simple!

Encore une fois, si vous voulez avoir une version plus détaillée de cette leçon avec des captures d'écran et des images, visitez
http://themillibit.com/2018/07 ... -app/
. Faites-moi savoir dans les commentaires si vous avez d'autres questions.

Blanche

Confirmation de:

Pour une meilleure compréhension de la facturation fonctionne dans l'application à l'aide de la bibliothèque de facturation google play, Reportez-vous au diagramme de bloc ci-dessous:

https://i.stack.imgur.com/wvt5s.png
Vous pouvez suivre l'étape d'intégration que j'ai expliquée dans cet article. :

https://medium.com/%40surabhic ... 9a78e
Si vous avez besoin d'une version de démonstration à ce sujet, voici un lien vers le projet:
https://github.com/surabhi6/InAppPurchaseDemo

Dominique

Confirmation de:

j'ai développé Android Dans la bibliothèque d'applications de facturation qui utilise "com.android.billingclient: Facturation: 2.1.0"

Voici ses propriétés:

La bibliothèque est prise en charge pour "INAPP"

L'abonnement sera pris en charge plus tard!

Utilise la bibliothèque Roomdb Pour vos produits, vous n'avez pas besoin d'une implémentation pour vérifier le statut de vos produits.

La bibliothèque utilise une dépendance générale. Votre application sera de plus petite taille et ne nécessitera pas de multiplex

La bibliothèque vérifie l'état de vos produits chaque fois que l'application est lancée. Vous pouvez obtenir le statut /Acheté ou non/!

Chaque produit acheté par le client devrait être "confirmé" Dans une condition réussie. La bibliothèque le fait pour vous!

Bibliothèque de soutien /Achat immédiat, la réponse est en retard pour acheter une baie, la réponse est tardive pour rejeter, l'utilisateur a annulé l'achat./

https://github.com/Ucdemir/Ucd ... se_v2

Pour répondre aux questions, connectez-vous ou registre