Easy Checkout Library (Android In-App Billing v3 and v5)

API Build Status Bintray codecov License

Fast and easy checkout library (Android In-App Billing) for Android apps with RxJava support. For RxJava please check here.

Why you should use Easy-Checkout?

This library supports both non-consumable/consumable items and upgrading/downgrading of subscriptions.

NOTE: Upgrade/Downgrade of subscriptions are only available in the api version 5. You can still set the api version 3 for other actions in the library. The api version 5 automatically will be used only in this case.

It also solves common problems that developers face while working with In-App Billing, such as:

Test coverage 100%

Easy-Checkout has 100% test coverage and I will try to keep it at that level for stable releases.

coverage report

Let's get started

Installation

repositories {
    jcenter()
    mavenCentral()
}
dependencies {
    compile 'jp.alessandro.android:easy-checkout:vX.X.X'
}

where vX.X.X is the your preferred version. For the latest version, please see the project's Releases. You can also see more details on Bintray.

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

Creating a Billing Context

// Application context
Context context = getApplicationContext();

// Public key generated on the Google Play Console
String base64EncodedPublicKey = "YOUR_PUBLIC_KEY";

BillingContext.Builder builder = new BillingContext.Builder()
    .setContext(getApplicationContext()) // App context
    .setPublicKeyBase64(base64EncodedPublicKey) // Public key generated on the Google Play Console
    .setApiVersion(BillingApi.VERSION_3) // It also supports version 5
    .setLogger(new SystemLogger()) // This is optional

BillingContext context = builder.build();

Sample (Sample App coming soon)

public class SampleActivity extends Activity {

    private final PurchaseHandler mPurchaseHandler = new PurchaseHandler() {
      @Override
      public void call(PurchaseResponse response) {
          if (response.isSuccess()) {
              Purchase purchase = response.getPurchase();
              // Do your stuff with the purchased item
          } else {
              // Handle the error
          }
      }
    };
    private BillingProcessor mBillingProcessor;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);

      initBillingProcessor();
    }

    private void initBillingProcessor() {
      // Your public key
      String base64EncodedPublicKey = "YOUR_PUBLIC_KEY";

      BillingContext.Builder builder = new BillingContext.Builder()
        .setContext(getApplicationContext()) // App context
        .setPublicKeyBase64(base64EncodedPublicKey) // Public key generated on the Google Play Console
        .setApiVersion(BillingApi.VERSION_3) // It also supports version 5
        .setLogger(new SystemLogger()) // This is optional

      mBillingProcessor = new BillingProcessor(builder.build(), mPurchaseHandler);
    }

    @Override
    public void onDestroy() {
      super.onDestroy();
      mBillingProcessor.release();
    }
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  if (mBillingProcessor.onActivityResult(requestCode, resultCode, data)) {
      // The response will be sent through PurchaseHandler
      return;
  }
  super.onActivityResult(requestCode, resultCode, data);
}

Purchase Item

Activity activity = this;
int requestCode = 10; // YOUR REQUEST CODE
String itemId = "YOUR_ITEM_ID";
PurchaseType purchaseType = PurchaseType.IN_APP; // or PurchaseType.SUBSCRIPTION for subscriptions
String developerPayload = "YOUR_DEVELOPER_PAYLOAD";

mBillingProcessor.startPurchase(activity, requestCode, itemId, purchaseType, developerPayload,
        new StartActivityHandler() {
            @Override
            public void onSuccess() {
                // Billing activity started successfully
                // Do nothing
            }

            @Override
            public void onError(BillingException e) {
                // Handle the error
            }
        });

As a result you will get a Purchase object.

Consume Purchased Item

String itemId = "YOUR_ITEM_ID";

mBillingProcessor.consumePurchase(itemId, new ConsumeItemHandler() {
    @Override
    public void onSuccess() {
        // Item was consumed successfully
    }

    @Override
    public void onError(BillingException e) {
        // Handle the error
    }
});

Upgrade/Downgrade Subscription

This is only available in the api version 5. You can still set the api version 3 for other actions in the library. The api version 5 automatically will be used only in this case.

Activity activity = this;
int requestCode = 10; // YOUR REQUEST CODE
ArrayList<String> itemIdList = new ArrayList<>();
itemIdList.add("CURRENT_ITEM_ID");
String targetItemId = "TARGET_ITEM_ID";
String developerPayload = "YOUR_DEVELOPER_PAYLOAD";

mBillingProcessor.updateSubscription(activity, requestCode, itemIdList, targetItemId, developerPayload,
              new StartActivityHandler() {
                @Override
                public void onSuccess() {
                    // Billing activity started successfully
                    // Do nothing
                }

                @Override
                public void onError(BillingException e) {
                    // Handle the error
                }
              });

As a result you will get a Purchase object through of the PurchaseHandler set in the BillingProcessor's constructor.

Inventory of Purchases

PurchaseType purchaseType = PurchaseType.IN_APP; // PurchaseType.SUBSCRIPTIONS for subscriptions

mBillingProcessor.getPurchases(purchaseType, new PurchasesHandler() {
    @Override
    public void onSuccess(Purchases purchases) {
        // Do your stuff with the list of purchases
        List<Purchase> purchaseList = purchases.getAll();
    }

    @Override
    public void onError(BillingException e) {
        // Handle the error
    }
});

As a result you will get a list of Purchase objects.

List of Item details

PurchaseType purchaseType = PurchaseType.IN_APP; // PurchaseType.SUBSCRIPTIONS for subscriptions
ArrayList<String> itemIds = new ArrayList<>();
itemIds.add("item_id_2");
itemIds.add("item_id_1");

mBillingProcessor.getItemDetails(purchaseType, itemIds, new ItemDetailListHandler() {
    @Override
    public void onSuccess(ItemDetails itemDetails) {
        // Do your stuff with the list of item details
        List<Item> items = itemDetails.getAll();
    }

    @Override
    public void onError(BillingException e) {
        // Handle the error
    }
});

Cancel

mBillingProcessor.cancel();

Release

mBillingProcessor.release();

As a result you will get a list of Item detail objects.

Check In-App Billing service availability

boolean isAvailable = BillingProcessor.isServiceAvailable(getApplicationContext());
if (!isAvailable) {
    // Abort
}

Purchase Object

  public String getOriginalJson();
  public String getOrderId();
  public String getPackageName();
  public String getSku();
  public long getPurchaseTime();
  public int getPurchaseState();
  public String getDeveloperPayload();
  public String getToken();
  public boolean isAutoRenewing();
  public String getSignature();

Item Object

  public String getOriginalJson();
  public String getSku();
  public String getType();
  public String getTitle();
  public String getDescription();
  public String getCurrency();
  public String getPrice();
  public long getPriceMicros();
  public String getSubscriptionPeriod();
  public String getFreeTrialPeriod();
  public String getIntroductoryPrice();
  public long getIntroductoryPriceAmountMicros();
  public String getIntroductoryPricePeriod();
  public int getIntroductoryPriceCycles();