Este tópico descreve como migrar de uma integração de faturamento que usa a Linguagem de definição de interface do Android (AIDL). O acesso ao sistema de faturamento do Google Play por meio da AIDL está suspenso. Todas as integrações passarão a usar a Biblioteca Play Faturamento no futuro.
Etapas da migração
Importar a Biblioteca do Google Play Faturamento
Primeiro, adicione uma dependência à Biblioteca do Google Play Faturamento. Se você estiver usando
o Gradle, poderá adicionar o seguinte ao arquivo build.gradle
do seu app:
Groovy
dependencies { def billing_version = "5.1.0" implementation "com.android.billingclient:billing:$billing_version" }
Kotlin
dependencies { val billing_version = "5.1.0" implementation("com.android.billingclient:billing:$billing_version") }
Você pode excluir qualquer código "agrupador", como
IabHelper
,
que pode ter sido copiado do código de referência anterior. A funcionalidade oferecida pelo IabHelper
agora faz parte da Biblioteca do Google Play Faturamento.
Remover a permissão com.android.vending.BILLING
A Biblioteca do Google Play Faturamento inclui a permissão com.android.vending.BILLING
no manifesto. Não é mais necessário adicionar essa permissão explicitamente no manifesto do seu app.
Conectar-se ao Google Play Faturamento
O método
BillingClient
da Biblioteca Google Play Faturamento processa o gerenciamento de conexão para você. Para migrar, faça as seguintes
mudanças no app:
- Crie uma instância de
BillingClient
. - Implemente um
BillingClientStateListener
para receber callbacks sobre o status do serviço. - Chame
startConnection()
na instância do seuBillingClient
. - Remova o código
onActivityResult()
relacionado a compras no aplicativo e mova paraPurchasesUpdatedListener
.
Os exemplos a seguir mostram a possível aparência do app antes e depois dessas mudanças:
Antes
mServiceConn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
...
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
...
}
};
Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
serviceIntent.setPackage("com.android.vending");
List<ResolveInfo> intentServices = mContext.getPackageManager()
.queryIntentServices(serviceIntent, 0);
if (intentServices != null && !intentServices.isEmpty()) {
mContext.bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);
} else {
// Handle errors.
...
}
...
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
IabResult result;
if (requestCode != mRequestCode || data == null) {
// Handle errors.
...
}
int responseCode = getResponseCodeFromIntent(data);
String purchaseData = data.getStringExtra(RESPONSE_INAPP_PURCHASE_DATA);
String dataSignature = data.getStringExtra(RESPONSE_INAPP_SIGNATURE);
if (resultCode != Activity.RESULT_OK || responseCode != BILLING_RESPONSE_RESULT_OK) {
// Handle errors.
...
}
// Process successful purchase.
...
return true;
}
Depois
Kotlin
class MyBillingImpl(private var billingClient: BillingClient) : PurchasesUpdatedListener { init { billingClient = BillingClient.newBuilder(activity).setListener(this).build() billingClient.startConnection(object : BillingClientStateListener { override fun onBillingSetupFinished(billingResult: BillingResult?) { // Logic from ServiceConnection.onServiceConnected should be moved here. } override fun onBillingServiceDisconnected() { // Logic from ServiceConnection.onServiceDisconnected should be moved here. } }) } override fun onPurchasesUpdated( billingResult: BillingResult?, purchases: MutableList<Purchase>? ) { // Logic from onActivityResult should be moved here. } }
Java
public class MyBillingImpl implements PurchasesUpdatedListener { private BillingClient billingClient; ... public void initialize() { billingClient = BillingClient.newBuilder(activity).setListener(this).build(); billingClient.startConnection(new BillingClientStateListener() { @Override public void onBillingSetupFinished(BillingResult billingResult) { // Logic from ServiceConnection.onServiceConnected should be moved here. } @Override public void onBillingServiceDisconnected() { // Logic from ServiceConnection.onServiceDisconnected should be moved here. } }); } @Override public void onPurchasesUpdated( @BillingResponse int responseCode, @Nullable List<Purchase> purchases) { // Logic from onActivityResult should be moved here. } }
Fazer uma compra
Para iniciar a caixa de diálogo de compras, faça o seguinte:
- Converta os detalhes
Bundle
da sua SKU paraSkuDetailsParams
. - Deixe de
chamar
mService.getSkuDetails()
e chameBillingClient.querySkuDetailsAsync()
. - Converta a intent de compra
Bundle
para um objetoBillingFlowParams
. - Deixe de
chamar
mService.getBuyIntent()
e chameBillingClient.launchBillingFlow()
. - Remova todo o código relacionado a compras no aplicativo de
onActivityResult()
e mova esse código paraPurchasesUpdatedListener
.
Os exemplos a seguir mostram a possível aparência do app antes e depois dessas mudanças:
Antes
// Query Skus
String skuToSell = "premium_upgrade";
ArrayList<String> skus = new Arraylist<>();
skus.add(skuToSell);
Bundle querySkus = new Bundle();
querySkus.putStringArrayList(GET_SKU_DETAILS_ITEM_LIST, skus);
Bundle skuDetails = mService.getSkuDetails(3,
mContext.getPackageName(),
itemType,
querySkus);
if (!skuDetails.containsKey(RESPONSE_GET_SKU_DETAILS_LIST)) {
// Handle errors.
...
}
// Launch Buy Flow
Bundle buyIntentBundle = mService.getBuyIntent(3,
mContext.getPackageName(),
skuToSell,
"Inapp",
"");
int response = getResponseCodeFromBundle(buyIntentBundle);
if (response != BILLING_RESPONSE_RESULT_OK) {
// Handle errors.
...
}
PendingIntent pendingIntent = buyIntentBundle.getParcelable(RESPONSE_BUY_INTENT);
act.startIntentSenderForResult(pendingIntent.getIntentSender(),
requestCode,
new Intent(),
Integer.valueOf(0),
Integer.valueOf(0),
Integer.valueOf(0));
// Purchase is handled in onActivityResult illustrated in the previous section.
Depois
Kotlin
val skuToSell = "premium_upgrade" val skuList = mutableListOf<String>() skuList.add(skuToSell) val params = SkuDetailsParams.newBuilder() params.setSkusList(skuList).setType(BillingClient.SkuType.INAPP) billingClient.querySkuDetailsAsync(params.build(), object : SkuDetailsResponseListener { override fun onSkuDetailsResponse( billingResult: BillingResult?, skuDetailsList: MutableList<SkuDetails>?) { // Process the result. } }) // SkuDetails object obtained above. val skuDetails = ... val purchaseParams = BillingFlowParams.newBuilder() .setSkuDetails(skuDetails) .build() billingClient.launchBillingFlow(activity, purchaseParams) // Purchase is handled in onPurchasesUpdated illustrated in the previous section
Java
String skuToSell = "premium_upgrade"; List<String> skuList = new ArrayList<> (); skuList.add(skuToSell); SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder(); params.setSkusList(skuList).setType(SkuType.INAPP); billingClient.querySkuDetailsAsync(params.build(), new SkuDetailsResponseListener() { @Override public void onSkuDetailsResponse(BillingResult billingResult, List<SkuDetails> skuDetailsList) { // Process the result. ... } }); // SkuDetails object obtained above. SkuDetails skuDetails = ...; BillingFlowParams purchaseParams = BillingFlowParams.newBuilder() .setSkuDetails(skuDetails) .build(); mBillingClient.launchBillingFlow(mActivity, purchaseParams); // Purchase is handled in onPurchasesUpdated illustrated in the previous section.
Consumir compras
Para consumir compras usando a Biblioteca Play Faturamento, faça o seguinte:
- Em vez de chamar
consumePurchase()
, chameBillingClient.consumeAsync()
. - Implemente
ConsumeResponseListener
.
Os exemplos a seguir mostram a possível aparência do app antes e depois dessas mudanças:
Antes
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
int responseCode = data.getIntExtra(RESPONSE_CODE);
JSONObject purchaseData =
new JSONObject(data.getStringExtra("INAPP_PURCHASE_DATA"));
String token = purchaseData.get("purchaseToken");
...
// Consume purchase
int response = mService.consumePurchase(3, mContext.getPackageName(), token);
if (response != BILLING_RESPONSE_RESULT_OK) {
// Handle errors.
...
}
// Handle successful consumption.
}
Depois
Kotlin
class MyBillingImpl(private val billingClient: BillingClient) : ... , ConsumeResponseListener { fun consumePurchase(purchaseToken: String) { val consumeParams = ConsumeParams .newBuilder() .setPurchaseToken(purchaseToken) .build() } override fun onConsumeResponse( billingResult: BillingResult?, purchaseToken: String?) { // Handle consumption } }
Java
public class MyBillingImpl implements ..., ConsumeResponseListener { private BillingClient billingClient; ... public void consumePurchase(String purchaseToken) { ConsumeParams consumeParams = ConsumeParams.newBuilder() .setPurchaseToken(purchaseToken) .build(); } @Override void onConsumeResponse(BillingResult billingResult, String purchaseToken) { // Handle consumption. ... } }
Confirmar compras
A partir da versão 2.0 da Biblioteca Play Faturamento, o app precisa consumir ou confirmar todas as compras.
Se você não consumir ou confirmar uma compra em até três dias, o Google revogará a compra automaticamente e reembolsará o usuário. Para ver mais informações, consulte Confirmar uma compra.
Reconhecer compras fora do aplicativo
Para migrar o gerenciamento de compras fora do aplicativo para a Biblioteca Play Faturamento, faça o seguinte:
- Verifique se o app chama
BillingClient.queryPurchasesAsync()
no callbackonResume()
. - Remova o broadcast receiver para
com.android.vending.billing.PURCHASES_UPDATED
e mova o código de callback correspondente para seuPurchasesUpdatedListener
.
Antes, ao integrar o Google Play Faturamento com a AIDL, o app
precisava registrar um listener para receber a
intent com.android.vending.billing.PURCHASES_UPDATED
para gerenciar
compras feitas fora do app.
Com a Biblioteca Google Play Faturamento, o primeiro passo para
garantir que
todas
as compras feitas fora
do app (com ele aberto) sejam reconhecidas é sempre chamar queryPurchasesAsync()
no callback onResume()
. Enquanto seu app está em execução, a
Biblioteca Google Play Faturamento
detecta automaticamente as compras feitas fora dele e envia uma notificação pelo
PurchasesUpdatedListener
.
Como processar transações pendentes
A partir da versão 2.0 da Biblioteca Play Faturamento, o app precisa processar transações pendentes que exigem outras ações após a compra antes de conceder titularidade. Por exemplo, um usuário pode escolher comprar seu produto em uma loja física com dinheiro. Isso significa que a transação será concluída fora do seu app. Em casos como esse, a titularidade só pode ser concedida após o usuário ter concluído a transação.
Para ver mais informações, consulte Compatibilidade com transações pendentes.
Payload do desenvolvedor
Historicamente, o payload do desenvolvedor tem sido usado para várias finalidades, incluindo a prevenção de fraudes e a atribuição de compras ao usuário correto. Considerando que agora a Biblioteca Google Play Faturamento tem suporte a esses casos de uso, o payload do desenvolvedor foi descontinuado na versão 2.2 e mais recentes dessa biblioteca. Para ver mais informações, consulte payload do desenvolvedor.
Mensagens de erro detalhadas
A partir da versão 2.0 da Biblioteca Play Faturamento, todos os erros
têm mensagens correspondentes relacionadas à depuração. Você pode ver essas mensagens chamando BillingResult.getDebugMessage()
.