web-dev-qa-db-fra.com

Mettre en œuvre la bibliothèque de facturation Google Play version 2

Google a publié une toute nouvelle version pour gérer les paiements dans Android mais après une recherche assez longue, je ne trouve pas un seul exemple ou tutoriel de quelqu'un qui a réussi à l'implémenter.

La documentation est très courte et ne fournit qu'une partie du code nécessaire: https://developer.Android.com/google/play/billing/billing_library_overview

Le seul exemple fourni est réalisé avec Kotlin: https://github.com/Android/play-billing-samples

On dirait qu'ils ont oublié Java développeurs ...

Quelqu'un connaît-il un tutoriel en ligne ou a-t-il réussi à le mettre en œuvre? Mon code actuel est loin de fonctionner pour être publié.

4
Yoann Hercouet

Je débute sur Android Studio et j'implémente la bibliothèque de facturation 2.1.0. Après une semaine de lecture de Android et de nombreux tutoriels sur bibliothèque de facturation J'ai créé cette classe Java classe, mais je pense que ce n'est pas assez bon, au moins il fait ce qu'il doit faire. Si vous trouvez un moyen de l'améliorer, commentez-le. Merci:

1.- Classe Pago.Java:

package com.example.billing;

import Android.app.Activity;
import Android.content.Context;
import Android.util.Log;
import Android.widget.Toast;

import androidx.annotation.Nullable;

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.ConsumeParams;
import com.Android.billingclient.api.ConsumeResponseListener;
import com.Android.billingclient.api.Purchase;
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 com.example.R;

import static com.Android.billingclient.api.BillingClient.BillingResponseCode.SERVICE_TIMEOUT;
import static com.Android.billingclient.api.BillingClient.BillingResponseCode.OK;
import static com.Android.billingclient.api.BillingClient.BillingResponseCode.USER_CANCELED;
import static com.Android.billingclient.api.BillingClient.BillingResponseCode.BILLING_UNAVAILABLE;
import static com.Android.billingclient.api.BillingClient.BillingResponseCode.ITEM_UNAVAILABLE;
import static com.Android.billingclient.api.BillingClient.BillingResponseCode.ERROR;
import static com.Android.billingclient.api.BillingClient.SkuType.INAPP;

import Java.util.ArrayList;
import Java.util.List;


public class Pagos implements PurchasesUpdatedListener, BillingClientStateListener, SkuDetailsResponseListener, ConsumeResponseListener {


    private BillingClient billingClient;
    private Context contextPago;
    private String skuId;
    private List<SkuDetails> misProductos;


    // Constructor de la clase Pagos
    public Pagos(Context context) {

        contextPago = context;

    }


    // Asigna el sku del producto que se quiere comprar
    public void comprar(String skuId) {

        this.skuId = skuId;
        configurarBillingClient();

    }


    // Configura el Billing Client para iniciar la conexión con Google Play Console
    private void configurarBillingClient() {

        //  1. Configura el Billing Client
        billingClient = BillingClient.newBuilder(contextPago)
                .enablePendingPurchases()
                .setListener(this)
                .build();

        // 2. Inicia la conexión y asigna los Listener
        billingClient.startConnection(this);

    }


    @Override
    // Evento salta al llamar billingClient.startConnection()
    public void onBillingSetupFinished(BillingResult billingResult) {

        // Busca compras en el Servidor de Google y las marca como consumidas
        consumeCompras();

        // Verifica que la versión de Play Store sea compatible con INAPP
        if (!billingClient.isReady()) {
            String mensaje = contextPago.getString(R.string.PAGOS_MENSAJE_VERSIÓN_NO_COMPATIBLE);
            Toast.makeText(contextPago, mensaje, Toast.LENGTH_LONG).show();
            return;
        }

        // Verifica que la versión de Play Store sea compatible con Suscripciones
        // if (billingClient.isFeatureSupported(SUBSCRIPTIONS).getResponseCode() != OK) {
        //     String mensaje = contextPago.getString(R.string.PAGOS_MENSAJE_VERSIÓN_NO_COMPATIBLE);
        //     Toast.makeText(contextPago, mensaje, Toast.LENGTH_LONG).show();
        //     return; //GooglePlayNoSoportaComprasDeSuscripciones
        // }

        // Verifica que la Configuración se haya hecho bien, sino muestra mensaje de error
        if (verificaResponseCode(billingResult.getResponseCode()) == OK) {
            consultaProductos();
        }

    }


    // Asigna los elemento que se consultarán a Google y los envía con querySkuDetailsAsync
    private void consultaProductos() {

        // Inicializa constantes
        String ITEM_SKU_1 = "Android.test.item_unavailable";
        String ITEM_SKU_2 = "Android.test.canceled";
        String ITEM_SKU_3 = "Android.test.purchased";
        String ITEM_SKU_4 = "donar";
        String ITEM_SKU_5 = "prueba.1";

        // Agrega los productos que se consultarán a Google
        List<String> skuList = new ArrayList<>();
        skuList.add(ITEM_SKU_1);
        skuList.add(ITEM_SKU_2);
        skuList.add(ITEM_SKU_3);
        skuList.add(ITEM_SKU_4);
        skuList.add(ITEM_SKU_5);
        // TODO Cambiar el ingreso manual de items por una consulta a servidor propio de backend seguro.

        SkuDetailsParams.Builder skuDetailsParams = SkuDetailsParams
                .newBuilder()
                .setSkusList(skuList)
                .setType(INAPP);

        // Envía consulta a Google y devuelve el listado de productos mediante onSkuDetailsResponse
        billingClient.querySkuDetailsAsync(skuDetailsParams.build(), this);

    }


    @Override
    // Evento salta cuando Google envía los detalles de los Productos en Venta
    public void onSkuDetailsResponse(BillingResult billingResult, List<SkuDetails> skuDetailsList) {

        if (verificaResponseCode(billingResult.getResponseCode()) == OK) {
            if (skuDetailsList != null) {
                misProductos = skuDetailsList;
                muestraDialogoCompra();
            } else {
                String mensaje = contextPago.getString(R.string.PAGOS_MENSAJE_NO_SKUDETAILSLIST);
                Toast.makeText(contextPago, mensaje, Toast.LENGTH_LONG).show();
            }
        }

    }


    // Lanza el dialogo de compra de Google
    private void muestraDialogoCompra() {

        BillingFlowParams flowParams = BillingFlowParams.newBuilder()
                .setSkuDetails(getSkuIdDetails())
                .build();
        billingClient.launchBillingFlow((Activity) contextPago, flowParams);

    }


    // Obtiene el Producto que se comprará según el Sku ingresado mediante comprar(sku);
    private SkuDetails getSkuIdDetails() {

        if (misProductos == null) return null;
        for (SkuDetails skuProducto : misProductos) {
            if (skuId.equals(skuProducto.getSku())) return skuProducto;
        }
        return null;

    }


    @Override
    // Evento salta cuando se finaliza el Proceso de compra
    public void onPurchasesUpdated(BillingResult billingResult, @Nullable List<Purchase> list) {

        if (verificaResponseCode(billingResult.getResponseCode()) == OK) {
            // Validar compra con consulta a Google para evitar ingeniería inversa de hackers
            if (validaCompra()) {
                // Compra confirmada
                Log.i("Pagos", "Compra encontrada en servidor");
            } else {
                // Compra no encontrada: Mensaje de error - Revocar privilegios
                Log.i("Pagos", "Compra no encontrada posible hacker");
            }
            consumeCompras();
        }

    }


    // Valida la compra y Devuelve True si encuentra la compra del usuario en el Servidor de Google
    private boolean validaCompra() {

        List<Purchase> purchasesList = billingClient.queryPurchases(INAPP).getPurchasesList();
        if (purchasesList != null && !purchasesList.isEmpty()) {
            for (Purchase purchase : purchasesList) {
                if (purchase.getSku().equals(skuId)) {
                    return true;
                }
            }
        }
        return false;

    }


    // Busca compras en el Servidor de Google y las marca como consumidas
    private void consumeCompras() {

        Purchase.PurchasesResult queryPurchases = billingClient.queryPurchases(INAPP);
        if (queryPurchases.getResponseCode() == OK) {
            List<Purchase> purchasesList = queryPurchases.getPurchasesList();
            if (purchasesList != null && !purchasesList.isEmpty()) {
                for (Purchase purchase : purchasesList) {
                    ConsumeParams params = ConsumeParams.newBuilder()
                            .setPurchaseToken(purchase.getPurchaseToken())
                            .build();
                    billingClient.consumeAsync(params, this);
                }
            }
        }

    }


    @Override
    // Evento salta cuando se ha consumido un producto, Si responseCode = 0, ya se puede volver a comprar
    public void onConsumeResponse(BillingResult billingResult, String purchaseToken) {
        if (billingResult.getResponseCode() == OK) {
            Log.i("Pagos", "Token de Compra: " + purchaseToken + " consumida");
        } else {
            Log.i("Pagos", "Error al consumir compra, responseCode: " + billingResult.getResponseCode());
        }
    }


    @Override
    // Evento salta cuando se pierde la conexión durante una compra
    public void onBillingServiceDisconnected() {
        billingClient.startConnection(this);
    }


    // Verifica que el estado del responseCode sea OK, si no muestra mensaje de Error
    private int verificaResponseCode(int responseCode) {

        if (responseCode == OK) return OK;
        if (responseCode == USER_CANCELED) return USER_CANCELED;

        String mensaje = "";
        switch (responseCode) {
            case SERVICE_TIMEOUT:
                mensaje = contextPago.getString(R.string.PAGOS_MENSAJE_SERVICE_TIMEOUT);
                break;
            case BILLING_UNAVAILABLE:
                mensaje = contextPago.getString(R.string.PAGOS_MENSAJE_BILLING_UNAVAILABLE);
                break;
            case ITEM_UNAVAILABLE:
                mensaje = contextPago.getString(R.string.PAGOS_MENSAJE_ITEM_UNAVAILABLE);
                break;
            case ERROR:
                mensaje = contextPago.getString(R.string.PAGOS_MENSAJE_ERROR);
                break;
            default:
                mensaje = contextPago.getString(R.string.PAGOS_MENSAJE_ERROR) + " código: " + responseCode;
                break;
        }
        Toast.makeText(contextPago, mensaje, Toast.LENGTH_LONG).show();
        return responseCode;

    }


}

3.- Manifeste

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

4.- build.gradle

// Google Play Billing Library
implementation 'com.Android.billingclient:billing:2.1.0'

5.- Utilisation, placez ce code là où vous souhaitez afficher le composant de facturation:

private final String SKU_UNAVAILABLE = "Android.test.item_unavailable";
private final String SKU_CANCELED = "Android.test.canceled";
private final String SKU_PURCHASED = "Android.test.purchased";
private final String SKU_DONAR = "donar";


private void donar() {
    Pagos pagos = new Pagos(this);
    pagos.comprar(SKU_DONAR);
    cargandoDialogoCompra(true);
}

Vous pouvez changer SKU_DONAR, en SKU_UNAVAILABLE, SKU_CANCELED, SKU_PURCHASED car ce sont des éléments à des fins de test et comme je l'ai lu, il n'est pas nécessaire de les ajouter à la console de lecture

6.- Console Google Play

Presencia en Google Play Store -> Productos integrados en la aplicación -> Productos administrados:

Donación (donar) PEN 9.99

C'est tout, merci d'améliorer mon code, merci à tous.

0
Angel

Voici un exemple d'application pour Google Play Billing version 2 en Java:

Taxi chic à Java

0
Dyadee