La version de la bibliothèque est passée de 1.0 à 2.0, j'ai donc réécrit le contenu. Vous trouverez ci-dessous le code de l'essai d'essai.
Je vais vous montrer un exemple de code qui fonctionne d'une manière ou d'une autre, mais à vos risques et périls. C'est une histoire qui implique de l'argent, il est donc fortement recommandé de vérifier les informations du chef de famille. https://developer.android.com/google/play/billing/billing_library_overview?hl=ja
À la recherche d'échantillons de traitement des achats via une application sur Android, beaucoup étaient anciens et complexes. Avec la nouvelle bibliothèque de facturation Google Play, c'était relativement facile à réaliser, donc je m'en souviendrai.
Cette procédure ne nécessite pas de paramètres tels que «IInAppBillingService.aidl» ou «AndroidManifest.xml». Vous pouvez également le tester avant de télécharger l'application sur Google Play.
Ici, j'ai sélectionné une simple "Activité Employeur" comme activité et j'ai écrit tout le code dans MainActivity. Le nom du projet était "Exemple de facturation".
build.gradle
dependencies {
....
implementation 'com.android.billingclient:billing:2.0.1'
}
MainActivity.java
package xx.xx.xx.xx.billingsample;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import com.android.billingclient.api.AcknowledgePurchaseParams;
import com.android.billingclient.api.AcknowledgePurchaseResponseListener;
import com.android.billingclient.api.BillingClient;
import com.android.billingclient.api.BillingClientStateListener;
import com.android.billingclient.api.BillingFlowParams;
import com.android.billingclient.api.BillingResult;
import com.android.billingclient.api.Purchase;
import com.android.billingclient.api.PurchaseHistoryRecord;
import com.android.billingclient.api.PurchaseHistoryResponseListener;
import com.android.billingclient.api.PurchasesUpdatedListener;
import com.android.billingclient.api.SkuDetails;
import com.android.billingclient.api.SkuDetailsParams;
import com.android.billingclient.api.SkuDetailsResponseListener;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity
implements View.OnClickListener, PurchasesUpdatedListener, AcknowledgePurchaseResponseListener {
TextView textView1;
private BillingClient billingClient;
List<SkuDetails> mySkuDetailsList;
//Appelé au démarrage de l'application
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Préparer les boutons de commande et le champ de sortie des résultats
textView1 = findViewById(R.id.text_view1);
findViewById(R.id.button_get_skus).setOnClickListener(this);
findViewById(R.id.button_query_owned).setOnClickListener(this);
findViewById(R.id.button_purchase).setOnClickListener(this);
findViewById(R.id.button_purchase_history).setOnClickListener(this);
//Préparer le client de facturation
billingClient = BillingClient.newBuilder(this)
.setListener(this).enablePendingPurchases().build();
billingClient.startConnection(new BillingClientStateListener() {
@Override
public void onBillingSetupFinished(BillingResult billingResult) {
int responseCode = billingResult.getResponseCode();
if (responseCode == BillingClient.BillingResponseCode.OK) {
// The BillingClient is ready. You can query purchases here.
textView1.setText("Billing Setup OK");
} else {
showResponseCode(responseCode);
}
}
@Override
public void onBillingServiceDisconnected() {
// Try to restart the connection on the next request to
// Google Play by calling the startConnection() method.
textView1.setText("Billing Servise Disconnected. Retry");
}
});
}
//Appelé lorsque le bouton est cliqué
@Override
public void onClick(View v) {
if (v != null) {
switch (v.getId()) {
case R.id.button_get_skus:
querySkuList();
break;
case R.id.button_query_owned:
queryOwned();
break;
case R.id.button_purchase:
startPurchase("android.test.purchased");
break;
case R.id.button_purchase_history:
queryPurchaseHistory();
break;
default:
break;
}
}
}
//Appelé lorsque l'application est fermée
@Override
protected void onDestroy() {
billingClient.endConnection();
super.onDestroy();
}
//Renseignez-vous sur l'article que vous souhaitez acheter
void querySkuList() {
List skuList = new ArrayList<>();
skuList.add("android.test.purchased"); // prepared by Google
skuList.add("android.test.canceled");
skuList.add("android.test.refunded");
skuList.add("android.test.item_unavailable");
SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
params.setSkusList(skuList).setType(BillingClient.SkuType.INAPP);
billingClient.querySkuDetailsAsync(params.build(),
new SkuDetailsResponseListener() {
@Override
public void onSkuDetailsResponse(BillingResult billingResult,
List<SkuDetails> skuDetailsList) {
// Process the result.
StringBuffer resultStr = new StringBuffer("");
int responseCode = billingResult.getResponseCode();
if (responseCode == BillingClient.BillingResponseCode.OK) {
//Conservez les détails du Sku pour le processus d'achat ultérieur
mySkuDetailsList = skuDetailsList;
//Afficher la liste
if (skuDetailsList != null) {
for (Object item : skuDetailsList) {
SkuDetails skuDetails = (SkuDetails) item;
String sku = skuDetails.getSku();
String price = skuDetails.getPrice();
resultStr.append("Sku=" + sku + " Price=" + price + "\n");
}
} else {
resultStr.append("No Sku");
}
textView1.setText(resultStr);
} else {
showResponseCode(responseCode);
}
}
});
}
//Lancer le processus d'achat
void startPurchase(String sku) {
SkuDetails skuDetails = getSkuDetails(sku);
if (skuDetails != null) {
BillingFlowParams params = BillingFlowParams.newBuilder()
.setSkuDetails(skuDetails)
.build();
BillingResult billingResult = billingClient.launchBillingFlow(this, params);
showResponseCode(billingResult.getResponseCode());
}
}
//Obtenir les détails de la référence SKU spécifiée dans la liste
SkuDetails getSkuDetails(String sku) {
SkuDetails skuDetails = null;
if(mySkuDetailsList==null){
textView1.setText("Exec [Get Skus] first");
}else {
for (SkuDetails sd : mySkuDetailsList) {
if (sd.getSku().equals(sku)) skuDetails = sd;
}
if (skuDetails == null) {
textView1.setText(sku + " is not found");
}
}
return skuDetails;
}
//Appelé lors de la mise à jour des résultats d'achat
@Override
public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
StringBuffer resultStr = new StringBuffer("");
int billingResultCode = billingResult.getResponseCode();
if (billingResultCode == BillingClient.BillingResponseCode.OK
&& purchases != null) {
for (Purchase purchase : purchases) {
//Approuver l'achat
String state = handlePurchase(purchase);
//Afficher la chaîne Sku achetée et le résultat d'approbation
String sku = purchase.getSku();
resultStr.append(sku).append("\n");
resultStr.append(" State=").append(state).append("\n");
}
textView1.setText(resultStr);
} else {
// Handle error codes.
showResponseCode(billingResultCode);
}
}
//Approuver l'achat
String handlePurchase(Purchase purchase) {
String stateStr = "error";
int purchaseState = purchase.getPurchaseState();
if (purchaseState == Purchase.PurchaseState.PURCHASED) {
// Grant entitlement to the user.
stateStr = "purchased";
// Acknowledge the purchase if it hasn't already been acknowledged.
if (!purchase.isAcknowledged()) {
AcknowledgePurchaseParams acknowledgePurchaseParams =
AcknowledgePurchaseParams.newBuilder()
.setPurchaseToken(purchase.getPurchaseToken())
.build();
billingClient.acknowledgePurchase(acknowledgePurchaseParams, this);
}
}else if(purchaseState == Purchase.PurchaseState.PENDING){
stateStr = "pending";
}else if(purchaseState == Purchase.PurchaseState.UNSPECIFIED_STATE){
stateStr = "unspecified state";
}
return stateStr;
}
//Résultats d'approbation d'achat renvoyés
@Override
public void onAcknowledgePurchaseResponse(BillingResult billingResult) {
int responseCode = billingResult.getResponseCode();
if(responseCode != BillingClient.BillingResponseCode.OK) {
showResponseCode(responseCode);
}
}
//Renseignez-vous sur les articles achetés (traitement des espèces)
void queryOwned(){
StringBuffer resultStr = new StringBuffer("");
Purchase.PurchasesResult purchasesResult
= billingClient.queryPurchases(BillingClient.SkuType.INAPP);
int responseCode = purchasesResult.getResponseCode ();
if(responseCode== BillingClient.BillingResponseCode.OK){
resultStr.append("Query Success\n");
List<Purchase> purchases = purchasesResult.getPurchasesList();
if(purchases.isEmpty()){
resultStr.append("Owned Nothing");
} else {
for (Purchase purchase : purchases) {
resultStr.append(purchase.getSku()).append("\n");
}
}
textView1.setText(resultStr);
}else{
showResponseCode(responseCode);
}
}
//Demander l'historique des achats (traitement de l'accès au réseau)
void queryPurchaseHistory() {
billingClient.queryPurchaseHistoryAsync(BillingClient.SkuType.INAPP,
new PurchaseHistoryResponseListener() {
@Override
public void onPurchaseHistoryResponse(BillingResult billingResult,
List<PurchaseHistoryRecord> purchasesList) {
int responseCode = billingResult.getResponseCode();
if (responseCode == BillingClient.BillingResponseCode.OK) {
if (purchasesList == null || purchasesList.size() == 0) {
textView1.setText("No History");
} else {
for (PurchaseHistoryRecord purchase : purchasesList) {
// Process the result.
textView1.setText("Purchase History="
+ purchase.toString() + "\n");
}
}
} else {
showResponseCode(responseCode);
}
}
});
}
//Afficher la réponse du serveur
void showResponseCode(int responseCode){
switch(responseCode){
case BillingClient.BillingResponseCode.OK:
textView1.setText("OK");break;
case BillingClient.BillingResponseCode.USER_CANCELED:
textView1.setText("USER_CANCELED");break;
case BillingClient.BillingResponseCode.SERVICE_UNAVAILABLE:
textView1.setText("SERVICE_UNAVAILABLE");break;
case BillingClient.BillingResponseCode.BILLING_UNAVAILABLE:
textView1.setText("BILLING_UNAVAILABLE");break;
case BillingClient.BillingResponseCode.ITEM_UNAVAILABLE:
textView1.setText("ITEM_UNAVAILABLE");break;
case BillingClient.BillingResponseCode.DEVELOPER_ERROR:
textView1.setText("DEVELOPER_ERROR");break;
case BillingClient.BillingResponseCode.ERROR:
textView1.setText("ERROR");break;
case BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED:
textView1.setText("ITEM_ALREADY_OWNED");break;
case BillingClient.BillingResponseCode.ITEM_NOT_OWNED:
textView1.setText("ITEM_NOT_OWNED");break;
case BillingClient.BillingResponseCode.SERVICE_DISCONNECTED:
textView1.setText("SERVICE_DISCONNECTED");break;
case BillingClient.BillingResponseCode.FEATURE_NOT_SUPPORTED:
textView1.setText("FEATURE_NOT_SUPPORTED");break;
}
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<Button
android:id="@+id/button_get_skus"
android:text="Get Skus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/button_query_owned"
android:text="Query Owned"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/button_purchase"
android:text="Purchase"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/button_purchase_history"
android:text="Purchase History"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/text_view1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</android.support.constraint.ConstraintLayout>
Ouvrez Build Valiants dans l'onglet le plus à gauche d'Android Studio et remplacez Build Valiant de Debug en Release.
Error: The apk for your currently selected variant (app-release-unsigned.apk) is not signed.
Cliquez sur "Corriger" affiché sur le côté droit de l'affichage des erreurs et entrez la clé enregistrée dans Google Play. Si vous n'êtes pas inscrit, vous devez vous inscrire. La procédure de saisie par clé est la suivante.