Git Product home page Git Product logo

google-inapp-billing's Introduction

Google In-App Billing Library v6+ API JitCI JitPack

A simple implementation of the Android In-App Billing API.

It supports: in-app purchases (both consumable and non-consumable) and subscriptions with a base plan or multiple offers.

image preview video example

Getting Started

  • You project should build against Android 4.1.x (minSdkVersion 16).

  • Add the JitPack repository to your project's build.gradle file:

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}
  • Add the dependency in your app's build.gradle file:
dependencies {
    implementation 'com.github.moisoni97:google-inapp-billing:1.1.3'
}
  • Open the AndroidManifest.xml of your application and add this permission:
  <uses-permission android:name="com.android.vending.BILLING" />

Important Notice

  • For builds that use minSdkVersion lower than 24 it is very important to include the following in your app's build.gradle file:
android {
  compileOptions {
    coreLibraryDesugaringEnabled true

    sourceCompatibility JavaVersion.VERSION_17
    targetCompatibility JavaVersion.VERSION_17
  }
}

dependencies {
  coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
}
  • For builds that use minSdkVersion lower than 21 add the above and also this:
android {
    defaultConfig {
        multiDexEnabled true
    }
}

This step is required to enable support for some APIs on lower SDK versions that aren't available natively only starting from minSdkVersion 24.

Usage

  • Create an instance of BillingConnector class. Constructor will take 2 parameters:
    • Context
    • License key from Play Console
billingConnector = new BillingConnector(this, "license_key")
                .setConsumableIds(consumableIds)
                .setNonConsumableIds(nonConsumableIds)
                .setSubscriptionIds(subscriptionIds)
                .autoAcknowledge()
                .autoConsume()
                .enableLogging()
                .connect();
  • Implement the listener to handle event results and errors:
billingConnector.setBillingEventListener(new BillingEventListener() {
            @Override
            public void onProductsFetched(@NonNull List<ProductInfo> productDetails) {
                /*Provides a list with fetched products*/
            }

            @Override
            public void onPurchasedProductsFetched(@NonNull ProductType productType, @NonNull List<PurchaseInfo> purchases) {
                /*Provides a list with fetched purchased products*/
                
                /*
                 * This will be called even when no purchased products are returned by the API
                 * */
            }

            @Override
            public void onProductsPurchased(@NonNull List<PurchaseInfo> purchases) {
                /*Callback after a product is purchased*/
            }

            @Override
            public void onPurchaseAcknowledged(@NonNull PurchaseInfo purchase) {
                /*Callback after a purchase is acknowledged*/
                
                /*
                 * Grant user entitlement for NON-CONSUMABLE products and SUBSCRIPTIONS here
                 *
                 * Even though onProductsPurchased is triggered when a purchase is successfully made
                 * there might be a problem along the way with the payment and the purchase won't be acknowledged
                 *
                 * Google will refund users purchases that aren't acknowledged in 3 days
                 *
                 * To ensure that all valid purchases are acknowledged the library will automatically
                 * check and acknowledge all unacknowledged products at the startup
                 * */
            }

            @Override
            public void onPurchaseConsumed(@NonNull PurchaseInfo purchase) {
                /*Callback after a purchase is consumed*/
                
                /*
                 * Grant user entitlement for CONSUMABLE products here
                 *
                 * Even though onProductsPurchased is triggered when a purchase is successfully made
                 * there might be a problem along the way with the payment and the user will be able consume the product
                 * without actually paying
                 * */
            }

            @Override
            public void onBillingError(@NonNull BillingConnector billingConnector, @NonNull BillingResponse response) {
                /*Callback after an error occurs*/
                
                switch (response.getErrorType()) {
                    case CLIENT_NOT_READY:
                        //TODO - client is not ready yet
                        break;
                    case CLIENT_DISCONNECTED:
                        //TODO - client has disconnected
                        break;
                    case PRODUCT_NOT_EXIST:
                        //TODO - product does not exist
                        break;
                    case CONSUME_ERROR:
                        //TODO - error during consumption
                        break;
                    case CONSUME_WARNING:
                        /*
                         * This will be triggered when a consumable purchase has a PENDING state
                         * User entitlement must be granted when the state is PURCHASED
                         *
                         * PENDING transactions usually occur when users choose cash as their form of payment
                         *
                         * Here users can be informed that it may take a while until the purchase complete
                         * and to come back later to receive their purchase
                         * */
                        //TODO - warning during consumption
                        break;
                    case ACKNOWLEDGE_ERROR:
                        //TODO - error during acknowledgment
                        break;
                    case ACKNOWLEDGE_WARNING:
                        /*
                         * This will be triggered when a purchase can not be acknowledged because the state is PENDING
                         * A purchase can be acknowledged only when the state is PURCHASED
                         *
                         * PENDING transactions usually occur when users choose cash as their form of payment
                         *
                         * Here users can be informed that it may take a while until the purchase complete
                         * and to come back later to receive their purchase
                         * */
                        //TODO - warning during acknowledgment
                        break;
                    case FETCH_PURCHASED_PRODUCTS_ERROR:
                        //TODO - error occurred while querying purchased products
                        break;
                    case BILLING_ERROR:
                        //TODO - error occurred during initialization / querying product details
                        break;
                    case USER_CANCELED:
                        //TODO - user pressed back or canceled a dialog
                        break;
                    case SERVICE_UNAVAILABLE:
                        //TODO - network connection is down
                        break;
                    case BILLING_UNAVAILABLE:
                        //TODO - billing API version is not supported for the type requested
                        break;
                    case ITEM_UNAVAILABLE:
                        //TODO - requested product is not available for purchase
                        break;
                    case DEVELOPER_ERROR:
                        //TODO - invalid arguments provided to the API
                        break;
                    case ERROR:
                        //TODO - fatal error during the API action
                        break;
                    case ITEM_ALREADY_OWNED:
                        //TODO - failure to purchase since item is already owned
                        break;
                    case ITEM_NOT_OWNED:
                        //TODO - failure to consume since item is not owned
                        break;
                }
            }
        });

Initiate a purchase

  • Purchase a non-consumable/consumable product:
billingConnector.purchase(this, "product_id");
  • Purchase a subscription with a base plan:
billingConnector.subscribe(this, "product_id");
  • Purchase a subscription with multiple offers:
billingConnector.subscribe(this, "product_id", 0);
billingConnector.subscribe(this, "product_id", 1);
  • Cancel a subscription:
billingConnector.unsubscribe(this, "product_id");

Release instance

  • To avoid memory leaks don't forget to release the BillingConnector instance when it's no longer needed.
@Override
    protected void onDestroy() {
        super.onDestroy();
        if (billingConnector != null) {
            billingConnector.release();
        }
    }

Kotlin

Kotlin is interoperable with Java and vice versa. This library works without any issues in Kotlin projects.

The sample app provides an example for Kotlin users.

Sample App

Go through the sample app to see a more advanced integration of the library.

It also shows how to implement some useful public methods.

Credits

This is an open-source project meant to help developers to fastly and easily implement the Google Billing API.

The library uses a code base from a fork created by @Mustafa Rasheed and was heavily modified by me and later by other contributors.

google-inapp-billing's People

Contributors

andresesfm avatar moisoni97 avatar tandohanthonynwiackah avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

google-inapp-billing's Issues

This purchase is not restored.

I'm testing the library 1.06 with an app installed on a device where the user has a non-consumable purchase already made in the past.
This purchase is not restored. Restored purchase 1 out of 50 attempts

What the hell?

What is the use of

com.android.tools:desugar_jdk_libs:1.1.5

library i am using Sketchware pro 6.4 beta 5 i can't add that can you guys tell me how can i use this cool library with out that pointless library?

onPurchasedProductsFetched is always called twice

onPurchasedProductsFetched is called twice on connect().
One time with purchases empty and once with purchases as expected (in case the user purchased).
The worst thing is that there's a race condition so you can't even write a logic based on skipping the first time as sometimes this is the correct data, followed by the false data.

It doesn't help to connect before setting the listener or after.

Granting title to the product to the user before the purchase is confirmed.

First of all, I'm new to the subject of programming, I managed to implement in-app-purchase almost successfully, but I'm facing some problems:

I have a problem that when I make a test purchase that will be denied after a few minutes, it already calls the OnProductPurchase event and gives the user the title of the product. How to solve?
I would like to verify that the user has actually purchased by validating the purchase information before granting entitlement.

mobizen_20210815_222231_001.mp4

Also would you like to implement queryPurchasesAsync() is the library compatible? I didn't find any information in the README

Oh, one more thing, Lucky Patcher makes the purchase easily with just one click, does anyone have an efficient system against that?

Thank you very much in advance.

Cannot Initiate Purchase or Subscription

I came across your library the other day because I need to update my billing library and yours seemed to be straight forward. I'm able to receive callbacks with product info ie. pricing and product ids, but when I initiate billingConnector.purchase or .subscribe neither go anywhere. Checked all cases as well, even copied your logic to a T & the only thing I can seem to get working is getting the info.

Hope to get some help, thank you.

Need example to get Subscriptions price

Hi, can anyone help me with how to implement the get the price for subscriptions? I tried looking into the library but there's no method to directly call the price (in respected currency) like the example

price = productInfo.getOneTimePurchaseOfferFormattedPrice();

Did this library test in real app?

Dear moison97,
Sorry for my question, I'm new to Google IAP. I recently just include other IAP library. And all my orders are auto refund after 3 days. So I want to know if you already used this library in your app?
Thank you very much (Sorry that Github does not have message function to me to ask directly)

(Java 8) BillingConnector.java - java.lang.NoSuchMethodError

En BillingConnector.java en la linea 277 se utiliza un método creado en Java 8 para comprobar duplicados en las IDs del SKU, el cual no es compatible con dispositivos que no cuenten con esta versión en su sistema, recomendaría usar otro método sin depender de Java 8.

Este error se produce en gran medida en dispositivos huawei, y celulares Android 6 e inferiores.

Fatal Exception: java.lang.NoSuchMethodError: No interface method stream()Ljava/util/stream/Stream; in class Ljava/util/List; or its super classes (declaration of 'java.util.List' appears in /system/framework/core-libart.jar) at games.moisoni.google_iab.BillingConnector.connect(BillingConnector.java:277) at AppBilling.<init>(AppBilling.java:30) at MainActivity.onCreate(MainActivity.java:39) at android.app.Activity.performCreate(Activity.java:6279) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1108) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2393) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2500) at android.app.ActivityThread.access$900(ActivityThread.java:163) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1362) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5585) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)

Error retriving information from server

Hello,
I have added your library in my application but while subscribe I am getting an error like DF-DFERH-01

I have also tried to clear data/cache in playstore as well

please let me know if you have an any idea about that
device-2021-07-28-085646

No billing events triggered if one of the sku Id lists are empty

Hi,

Thank you for this easy to use and updated library.
I followed implementation guide. Billing service is connected but I did not receive any events like "onProductsFetched" if one of the provide sku Id lists is empty.

Use case:

  • App query SKU ID List (Consumable, Non-Consumbable and Subscription) automatically from a web service.
  • App sets SUK ID lists during connecting to billing service, see below code.
  • Later, developer decided to drop one kind of subsriptions, for example Consumable. So, App will not receive this list, it will be empty.

I think above scenarion should be considered since some developers doesn't like to hardcode SKU ID's as it subject to change. Hardcoding SKU ID means new App releasing on every change.

Below are some code snapshots:

        billingConnector = BillingConnector(this, licenseKey)
            .setNonConsumableIds(nonConsumableIds)
            .setConsumableIds(consumableIds)
            .setSubscriptionIds(subscriptionIds)
            .autoAcknowledge()
            .autoConsume()
            .enableLogging()
            .connect()

In my case:
nonConsumableIds, subscriptionIds have some items but consumableIds is empty list.

        billingConnector.setBillingEventListener(object : BillingEventListener {
            override fun onProductsFetched(skuDetails: MutableList<SkuInfo>) {

                skuDetailsList.addAll(skuDetails)
                adapter.notifyDataSetChanged()
                
                progress.visibility = View.GONE
            }

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

Below are the only billing logs received:

D/BillingConnector: Billing service: connecting...
D/BillingConnector: Billing service: connected

Thanks,

How to get sku's prices?

Hi.
How to get sku's price from Google Play?

And after purchase, how to get order id and purchase token?

How to start subscription? Like this?; billingConnector.purchase(this, "skuId");

I hope you'll answer it soon.

License confirmation

As this is your code, your library and you have used Google official IAP, still we need to show a license inside our application for your Github project. Please mention your license or do we need to use it as it is without worrying about you will change the license in the future?

purchase cancelled because it was not acknowledged

First time using this library, I try to implement it as it says in README. but when I purchase onProductsPurchased was called with empty purchases, this is the only callback I got back.

I setup the billingConnector like this.

billingConnector = BillingConnector(this, base64Key)
            .setConsumableIds(listOf(id1))
            .autoAcknowledge()
            .autoConsume()
            .enableLogging()
            .connect()

what am I missing here?

Card is declined

In the case the card is declined we are not able to handle the error

Crash while calling connect()

Hi, I got this error while trying to integrate your library.

java.lang.NoSuchMethodError: No interface method stream()Ljava/util/stream/Stream; in class Ljava/util/List; or its super classes (declaration of 'java.util.List' appears in /system/framework/core-libart.jar) at games.moisoni.google_iab.BillingConnector.connect(BillingConnector.java:228)

Can you help me?

call onPurchasedProductsFetched if no have purchased products

Hello.
Thanks for your work!
I ask you to call the onPurchasedProductsFetched event with an empty list if the user hasn't bought anything or the subscription has ended.
This will greatly simplify the work, as well as reduce the amount of code, as it will make it possible to check the purchase correctly.

@Override
public void onPurchasedProductsFetched(@NonNull List<PurchaseInfo> purchases) {
    //   not called if there are no purchases
    boolean subscribedPremium = purchases.stream().anyMatch(a -> a.getSku().equals(InAppConstants.SKU_SUBSCRIBE_PREMIUM_ONE_YEAR));
}

The current implementation results in a double check.

@Override
public void onProductsFetched(@NonNull List<SkuInfo> skuDetails) {
    for(SkuInfo skuInfo : skuDetails) {
        if (skuInfo.getSku().equals(InAppConstants.SKU_SUBSCRIBE_PREMIUM_ONE_YEAR)) {
            // mBillingConnector.isPurchased(skuInfo) return PURCHASED_PRODUCTS_NOT_FETCHED_YET 
            // because purchases have not been synced yet
            // We cannot know for sure whether a purchase was made, 
            // so the subscribedPremium value will be false regardless of whether something was purchased or not.
            // If not, then everything is fine, but if yes, then we will disable the user's purchase 
            // and will wait for the onPurchasedProductsFetched event
            boolean subscribedPremium = mBillingConnector.isPurchased(skuInfo) == PurchasedResult.YES;

            // subscribedPremium == false
            // We cannot assign a value other than false, 
            // because we are not sure that the onPurchasedProductsFetched event will fire
        }
    }
}
@Override
public void onPurchasedProductsFetched(@NonNull List<PurchaseInfo> purchases) {
    // Reassigning a value to the subscribedPremium variable
    boolean subscribedPremium = purchases.stream().anyMatch(a -> a.getSku().equals(InAppConstants.SKU_SUBSCRIBE_PREMIUM_ONE_YEAR));
}

Is it possible to do this?

Having problem fetching product price at onProductsFetched

Hi,

I'm having an "Attempt to invoke interface method 'java.lang.Object java.util.List.get(int)' on a null object reference" on onProductsFetched while trying to fetch prices for both IAPP and SUBS. The pricePro is a non-consumable IAPP and both subs doesn't have multiple offers.

Below is the code snipped:

'public void onProductsFetched(@nonnull List productDetails) {

String product, pricePro, priceSubMontly, priceSubYearly;

           for (ProductInfo productInfo : productDetails) {
                product = productInfo.getProduct();
                pricePro = productInfo.getOneTimePurchaseOfferPrice();
                priceSubMontly = productInfo.getSubscriptionOfferPrice(0,0);
                priceSubYearly = productInfo.getSubscriptionOfferPrice(0,0);

                if (product.equalsIgnoreCase(purchasePro)) {
                    Log.d("BillingConnector", "Product fetched: " + product);
                    Log.d("BillingConnector", "Product price: " + pricePro);
                    purchasePrice = pricePro;
                }
                if (product.equalsIgnoreCase(subMonthly)) {
                    Log.d("BillingConnector", "Product fetched: " + product);
                    Log.d("BillingConnector", "Product price: " + priceSubMontly);
                    monthlyPrice = priceSubMontly;
                }
                if (product.equalsIgnoreCase(subYearly)) {
                    Log.d("BillingConnector", "Product fetched: " + product);
                    Log.d("BillingConnector", "Product price: " + priceSubYearly);
                    yearlyPrice = priceSubYearly;
                }

}`

bad class

bad class file: /private/var/root/.gradle/caches/transforms-2/files-2.1/df4279a49e79bf63c6c455bff6f5285e/jetified-google-inapp-billing-1.0.6-api.jar(games/moisoni/google_iab/BillingConnector.class)
class file has wrong version 55.0, should be 52.0
Please remove or make sure it appears in the correct subdirectory of the classpath.

Subscriptions Not Loading

So I've successfully loaded all other items but when I activate & load a Subscription it doesn't load. When I try to subscribe it also says it doesn't exist. Do apps that have Subscriptions need to be on the PlayStore to work I've followed all the steps & nothing.

Billing V5.0 increases apk size by 8MB compared to V4

Hey thanks for the update to billing V5, it works perfectly!

Just a small issue i noticed that when i use billing V5 compared to the previous V4 the size of the compiled apk is increased by approx 8mb

is anyone else having the same effect? Thanks

Caching purchases

I am using the latest version of the library. Everything works as it should. But there is one thing: when I turn off the Internet connection, there must be a connection error. But the library takes purchases from somewhere. I understand that from the cache. How can I turn off the caching of purchases?

java.lang.NoClassDefFoundError V1.1.1

In Version 1.1.1 i've upgraded the billibg lib to V5 & the app worked but when i click on item & call the function billingConnector.purchase(payment.this, itemID)
the app crashes,

this is the error log:

java.lang.NoClassDefFoundError: Failed resolution of: Lcom/google/common/collect/ImmutableList;
        at games.moisoni.google_iab.BillingConnector.purchase(BillingConnector.java:653)
        at games.moisoni.google_iab.BillingConnector.purchase(BillingConnector.java:628)

        at com.app.paym.payment$Gridview1Adapter.lambda$getView$0$com-app-paym-payment$Gridview1Adapter(payment.java:685)
        at com.app.paym.payment$Gridview1Adapter$$ExternalSyntheticLambda0.onClick(Unknown Source:4)
        at android.view.View.performClick(View.java:7498)
        at android.view.View.performClickInternal(View.java:7471)
        at android.view.View.access$3700(View.java:843)
        at android.view.View$PerformClick.run(View.java:29098)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loopOnce(Looper.java:233)
        at android.os.Looper.loop(Looper.java:344)
        at android.app.ActivityThread.main(ActivityThread.java:8248)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:589)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1071)

        Caused by: java.lang.ClassNotFoundException: Didn&#39;t find class &#34;com.google.common.collect.ImmutableList&#34; on path: DexPathList[[zip file &#34;/data/app/~~k-5sJaEvztbKcFitQEr0IA==/com.app.paym-w23RSv1-LySXb-MoSjy6fg==/base.apk&#34;],nativeLibraryDirectories=[/data/app/~~k-5sJaEvztbKcFitQEr0IA==/com.app.paym-w23RSv1-LySXb-MoSjy6fg==/lib/arm64, /system/lib64, /system_ext/lib64]]

        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:259)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
        ... 16 more

Please build release lastest code

Thanks for your work

I see your commit lastest a2e27e5 but still does not release in jitpack

Could you please build lastest jitpack ?

onNoPurchasedProductsFetched listener is great listener, I want using this callback to trigger data

Please build jitpack help me.

billingConnector.isPurchased(productInfo) == PurchasedResult.YES does not work

I am struggling to get this library to work, the only callback method that gives any data on app startup is onProductsFetched() and it gives no data as to what products are purchased or not, how are we supposed to know if the user cancelled or even bought a subscription or made a purchase?

I think the purpose of a library is supposed to be to simplify the complicated Google Play In App Billing process but this is just as bad in my opinion because it is impossible to get any useful information as to the state of a purchase and the method billingConnector.isPurchased(productInfo) == PurchasedResult.YES does not work whatsoever, I am not sure why this was even included in the example app if does nothing, I have spent days trying to figure this out and I feel more lost now than I started, highly frustrating and demoralizing.....

onPurchasedProductsFetched onClick

Hello,

Is there any way I can use onPurchasedProductsFetched on a button click, such as "Restore purchases"? Or do I have to launch the entire BIllingConnector on the activity I want to restore purchases to?

ImmutableList Error

The error below keeps occurring I've searched online for a solution but nothing is working.

java.lang.NoClassDefFoundError: Failed resolution of: Lcom/google/common/collect/ImmutableList;
at games.moisoni.google_iab.BillingConnector.purchase(BillingConnector.java:653)

Error in classes_proguard.jar

I recently updated the lib to version 1.0.6 and I am getting an error building with proguard, the error is as follows: Compilation failed to complete, origin: /storage/emulated/0/.sketchware/mysc/601/bin/classes_proguard.jar

In version 1.0.5, proguard worked normally.

What could be happening?

can not restore purchase

// if (billingConnector.isPurchased(skuInfo) == PurchasedResult.YES) {
// //TODO - do something Not Work
// Log.d("BillingConnector", "The SKU: " + skuInfo.getSku() + " is purchased");
// } else if (billingConnector.isPurchased(skuInfo) == PurchasedResult.NO) {
// //TODO - do something
// Log.d("BillingConnector", "The SKU: " + skuInfo.getSku() + " is not purchased");

is purchased >>> not work,always goto >>> is not purchased。

Only way is call billingConnector.purchase(this, "sku_name");
then get error code ( ITEM_ALREADY_OWNED ) know to restore.

Do anyone have any suggestions?

Thanks。

Billing API version is not supported for the type requested

Hello, I recently tried using this library and am having some issues using it. I have one in-app purchase that I want to use your library with. The in-app is a remove ads non-consumable that would only ever be purchased once by the user (If bought in the past then I'd want the purchase to be verified and handled instead of purchased again).

Whenever I try to make a purchase I see this:

Screenshot_20221113-194441_Google Play Store

I filtered Android Studio to show me only BillingConnector:

? D/BillingConnector: Billing service: connecting...
? D/BillingConnector: Billing service: connected
? D/BillingConnector: Query Product Details: data found
? D/BillingConnector: Subscriptions support check: success
? D/BillingConnector: Query SUBS Purchases: the list is empty
? D/BillingConnector: Query IN-APP Purchases: the list is empty
? D/BillingConnector: Billing API version is not supported for the type requested. Response code: 3 <-- after billingConnector.purchase

I followed the instruction in the readme for setting everything up.

implementation 'com.android.billingclient:billing:5.0.0'
implementation 'com.github.moisoni97:google-inapp-billing:1.1.1'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
billingConnector = new BillingConnector(activity, LICENSE)
					.setNonConsumableIds(Collections.singletonList(SKU))
					.autoAcknowledge()
					.autoConsume()
					.enableLogging()
					.connect();
...

billingConnector.setBillingEventListener(new BillingEventListener() {
			@Override public void onProductsFetched(@NonNull List<ProductInfo> productDetails) {
				for (ProductInfo pinfo : productDetails)
				{
					Logd("Fetched product " + pinfo.getProductDetails().getProductId());

					...
				}
			}
			@Override public void onPurchasedProductsFetched(@NonNull ProductType productType, @NonNull List<PurchaseInfo> purchases) {
				for (PurchaseInfo pinfo : purchases)
				{
					Logd("Fetched purchased product " + pinfo.getPurchase().toString());

					...
				}
			}
			@Override public void onPurchaseConsumed(@NonNull PurchaseInfo purchase) {}

			@Override
			public void onProductsPurchased(@NonNull List<PurchaseInfo> purchases) {
				for (PurchaseInfo pinfo : purchases)
				{
					verifyPayload(pinfo.getPurchase(), new Runnable() {
						@Override
						public void run() {
							Logd("Handling purchase payload");
							
							...
						}
					});
				}
			}

			@Override
			public void onPurchaseAcknowledged(@NonNull PurchaseInfo purchase) {
				/*Callback after a purchase is acknowledged*/

				verifyPayload(purchase.getPurchase(), new Runnable() {
					@Override
					public void run() {
						Logd("Acknowledge purchase payload");
	
						...
					}
				});
			}

			@Override
			public void onBillingError(@NonNull BillingConnector billingConnector, @NonNull BillingResponse response) {

				Logd(response.toString());
			}
		});

...

billingConnector.purchase(activity, SKU); // I have this elsewhere in my code

I also tried updating to com.android.billingclient:billing:5.1.0 and that didn't change anything.

Do you have any ideas why this issue is happening?

Edit:
My minSdkVersion is 23 if that helps

Correct purchase flow to handle Cash payments for consumables?

Thanks for creating this wrapper, it looks very useful.
One question I have, is how can I use this library to correctly handle those new Cash payments that are now happening in Indonesia, Malaysia, etc? In those cases the user makes the purchase, then later goes to a convenience store to make the actual payment. Google recommends using the PurchaseToken to store information about a consumable on our own servers, which can then be granted later when the cash payment is made.
It would be super helpful if you could add some sample code that correctly handles this type of situation.
Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.