Платежный поток успешно запускается, и я получаю письмо с квитанцией о покупке. Однако фатальная ошибка возникает при вызове client.consumeAsync(consumeParams,consumeResponseListener);
.
Это проблематично c, поскольку это означает, что покупка не была израсходована и не может быть приобретена снова.
Нажатие кнопки:
public void onClick5Handler(View view) {
billingClient.launchBillingFlow(this, flowParams);
}
setupBillingClient () запускается из onCreate () и приводит к успешному соединению:
public void setupBillingClient() {
billingClient = BillingClient.newBuilder(this).setListener(this).enablePendingPurchases().setListener(this).build();
billingClient.startConnection(new BillingClientStateListener() {
@Override
public void onBillingSetupFinished(BillingResult billingResult) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
Toast.makeText(CoinsActivity.this, "success" + billingResult.getResponseCode(), Toast.LENGTH_SHORT).show();
queryProducts();
} else
Toast.makeText(CoinsActivity.this, "failed" + billingResult.getResponseCode(), Toast.LENGTH_SHORT).show();
}
@Override
public void onBillingServiceDisconnected() {
Toast.makeText(CoinsActivity.this, "you are disconnected from billing", Toast.LENGTH_SHORT).show();
// Try to restart the connection on the next request to
// Google Play by calling the startConnection() method.
}
});
}
public void queryProducts() {
List<String> skuList = new ArrayList<>();
skuList.add(COINS_5);
skuList.add(COINS_15);
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) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && skuDetailsList != null) {
for (SkuDetails skuDetails : skuDetailsList) {
String sku = skuDetails.getSku();
String price = skuDetails.getPrice();
flowParams = BillingFlowParams.newBuilder().setSkuDetails(skuDetailsList.get(0)).build();
if ("coins_5".equals(sku)) {
coins5Price = price;
} else if ("coins_15".equals(sku)) {
coins15Price = price;
}
}
}
}
});
}
@Override
public void onPurchasesUpdated(BillingResult billingResult, @Nullable List<Purchase> purchases) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && purchases != null) {
for (Purchase purchase : purchases) {
handlePurchase(purchase);
}
}
else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.USER_CANCELED) {
}
else {
}
}
void handlePurchase(Purchase purchase) {
if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
// Grant entitlement to the user.
ConsumeParams consumeParams = ConsumeParams.newBuilder()
.setPurchaseToken(purchase.getPurchaseToken())
.build();
billingClient.consumeAsync(consumeParams, consumeResponseListener);
}
}
java.lang.NullPointerException: Attempt to invoke virtual method 'void com.android.billingclient.api.BillingClient.consumeAsync(com.android.billingclient.api.ConsumeParams, com.android.billingclient.api.ConsumeResponseListener)' on a null object reference
at com.example.hundredriddles.CoinsActivity.handlePurchase(CoinsActivity.java:197)
at com.example.hundredriddles.CoinsActivity.onPurchasesUpdated(CoinsActivity.java:168)
Любые предложения будут оценены.