This document describes how you can integrate your app with the multi-product feature of Play Billing Library (PBL).

The multi-product for one-time product (OTP) feature lets you combine several one-time products into a single unit. These bundled products can then be purchased, billed, and managed collectively. You can also create[discount offers](https://developer.android.com/google/play/billing/one-time-product-multi-purchase-options-offers#discount-offers.)for these bundled OTPs to incentivize product purchases.

## Considerations

When you create one-time product bundles, note the following considerations:

- You can't have subscriptions in a one-time product bundle.
- You can't have a combination of digital content and service in the same one-time product bundle.
- The bundled one-time products must be available for immediate download. For example, a one-time product bundle can't have a pre-order purchase because it's not available for immediate download.
- The multi-product for one-time products doesn't support the[rent purchase option](https://developer.android.com/google/play/billing/one-time-product-multi-purchase-options-offers#rent-option).

## Integrate with Play Billing Library

This section assumes that you are familiar with the initial PBL integration steps such as,[adding the PBL dependency to your app](https://developer.android.com/google/play/billing/integrate#dependency), initializing the[BillingClient](https://developer.android.com/google/play/billing/integrate#initialize), and[connecting to Google Play](https://developer.android.com/google/play/billing/integrate#connect_to_google_play). This section focuses on the PBL integration aspects that are specific to the multi-product OTP purchases.

### Launch a purchase flow

To launch a purchase flow for multi-product one-time products, do the following steps:

1. Create a product list having all the one-time products by using the[QueryProductDetailsParams.Builder.setProductList](https://developer.android.com/reference/com/android/billingclient/api/QueryProductDetailsParams.Builder#setProductList(java.util.List%3Ccom.android.billingclient.api.QueryProductDetailsParams.Product%3E))method.

2. Fetch all your one-time products by using the[`BillingClient.queryProductDetailsAsync`](https://developer.android.com/reference/com/android/billingclient/api/BillingClient#queryProductDetailsAsync(com.android.billingclient.api.QueryProductDetailsParams,com.android.billingclient.api.ProductDetailsResponseListener))method.

   The following sample shows how to fetch all your one-time products:  

   #### Java

   ```java
   billingClient.queryProductDetailsAsync(
   queryProductDetailsParams,
   new ProductDetailsResponseListener() {
     public void onProductDetailsResponse(
         BillingResult billingResult, QueryProductDetailsResult productDetailsResult) {
       // check billingResult
       // ...
       // process productDetailsList returned by QueryProductDetailsResult
       ImmutableList productDetailsList = productDetailsResult.getProductDetailsList();
       for (ProductDetails productDetails : productDetailsList) {
         for (OneTimePurchaseOfferDetails oneTimePurchaseOfferDetails :
             productDetails.getOneTimePurchaseOfferDetailsList()) {
                // ...
         }
       }
     }
   });
   ```
3. Set the[`ProductDetails`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.ProductDetailsParams.Builder#setProductDetails(com.android.billingclient.api.ProductDetails))object for each one-time product.

   | **Note:** All one-time products in the`ProductDetails`must be from the same app.
4. Specify the one-time product details in the[`BillingFlowParams.Builder.setProductDetailsParamsList`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.Builder#setProductDetailsParamsList(java.util.List%3Ccom.android.billingclient.api.BillingFlowParams.ProductDetailsParams%3E))method. The[`BillingFlowParams`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams)class specifies the details of a purchase flow.

   The following sample shows how to launch the billing flow for a multi-product OTP purchase:  

   #### Java

   ```java
   BillingClient billingClient =
      BillingClient.newBuilder()
       // set other options
       .build();
   // ProductDetails obtained from queryProductDetailsAsync().
   ProductDetails productDetails1 = ...;
   ProductDetails productDetails2 = ...;
   ArrayList productDetailsList = new ArrayList<>();
   productDetailsList.add(productDetails1);
   productDetailsList.add(productDetails2);
   BillingFlowParams billingFlowParams =
   BillingFlowParams.newBuilder()
       .setProductDetailsParamsList(productDetailsList)
       .build();
   billingClient.launchBillingFlow(billingFlowParams);
   ```
   | **Note:** An in-app purchase will still be represented by the[`Purchase`](https://developer.android.com/reference/com/android/billingclient/api/Purchase)object, but this object will also be associated with all the products acquired in the transaction.

## Process purchases

Processing multi-product OTP purchases is the same as for existing single-item purchases as described in[Integrate the Google Play Billing Library into your app](https://developer.android.com/google/play/billing/integrate#launch). The only difference is that you need to grant entitlement for all products instead of only one for multi-product OTP purchases so that the user can receive multiple entitlements with a single purchase. A multi-product OTP purchase returns multiple items which can be retrieved by using[`Purchase.getProducts()`](https://developer.android.com/reference/com/android/billingclient/api/Purchase#getProducts())in the Google Play Billing Library, and then the`lineItems`list in[`purchases.products.get`](https://developers.google.com/android-publisher/api-ref/rest/v3/purchases.subscriptionsv2)of the[Google Play Developer API](https://developers.google.com/android-publisher/api-ref/rest/v3/purchases.subscriptionsv2).

## Real-time developer notifications

The`sku`field isn't provided in[RTDN](https://developer.android.com/google/play/billing/rtdn-reference)for multi-product OTP purchases. The multi-product OTP purchases represent more than one product. Therefore, you can use the Play Developer APIs to get the purchase data, and see all the items in it.

## Refunds

In a multi-product OTP purchase, users can't request refunds for individual items, and you too can't issue refunds for individual items. However, request and issue of refunds for the entire multi-product OTP purchase is permitted. If you are cancelling a multi-product OTP purchase for a user, all the entitlements associated with the purchase are cancelled.
| **Note:** Refunded multi-product OTP orders will be available in the[Voided Purchases API](https://developer.android.com/android-publisher/voided-purchases)and RTDN.

## Financial reporting and reconciliation

Use the[Earnings report](https://support.google.com/googleplay/android-developer/answer/6135870)to reconcile your active multi-product OTP purchases with Google Payoffs and transactions on Play. Each transaction line item has an Order ID. For a multi-product OTP purchase, the[Earnings and Estimated sales reports](https://support.google.com/googleplay/android-developer/answer/2482017)will include separate rows (with the same Order ID) for each transaction such as charge, fee, tax, and refund, for each item involved.

For dashboards in the Play Console:

- The revenue statistics presented in the**Financial reporting**section of the console are broken down by individual products.

- Order management reflects multi-product OTP purchases, and show itemized lists of what was purchased. From order management, you may revoke, cancel or fully refund a user's purchase.