int queryPurchases(Inventory inv, String itemType) throws JSONException, RemoteException {
    // Query purchases
    logDebug("Querying owned items, item type: " + itemType);
    logDebug("Package name: " + mContext.getPackageName());
    boolean verificationFailed = false;
    String continueToken = null;

    do {
      logDebug("Calling getPurchases with continuation token: " + continueToken);
      Bundle ownedItems =
          mService.getPurchases(3, mContext.getPackageName(), itemType, continueToken);

      int response = getResponseCodeFromBundle(ownedItems);
      logDebug("Owned items response: " + String.valueOf(response));
      if (response != BILLING_RESPONSE_RESULT_OK) {
        logDebug("getPurchases() failed: " + getResponseDesc(response));
        return response;
      }
      if (!ownedItems.containsKey(RESPONSE_INAPP_ITEM_LIST)
          || !ownedItems.containsKey(RESPONSE_INAPP_PURCHASE_DATA_LIST)
          || !ownedItems.containsKey(RESPONSE_INAPP_SIGNATURE_LIST)) {
        logError("Bundle returned from getPurchases() doesn't contain required fields.");
        return IABHELPER_BAD_RESPONSE;
      }

      ArrayList<String> ownedSkus = ownedItems.getStringArrayList(RESPONSE_INAPP_ITEM_LIST);
      ArrayList<String> purchaseDataList =
          ownedItems.getStringArrayList(RESPONSE_INAPP_PURCHASE_DATA_LIST);
      ArrayList<String> signatureList =
          ownedItems.getStringArrayList(RESPONSE_INAPP_SIGNATURE_LIST);

      for (int i = 0; i < purchaseDataList.size(); ++i) {
        String purchaseData = purchaseDataList.get(i);
        String signature = signatureList.get(i);
        String sku = ownedSkus.get(i);
        if (Security.verifyPurchase(mSignatureBase64, purchaseData, signature)) {
          logDebug("Sku is owned: " + sku);
          Purchase purchase = new Purchase(itemType, purchaseData, signature);

          if (TextUtils.isEmpty(purchase.getToken())) {
            logWarn("BUG: empty/null token!");
            logDebug("Purchase data: " + purchaseData);
          }

          // Record ownership and token
          inv.addPurchase(purchase);
        } else {
          logWarn("Purchase signature verification **FAILED**. Not adding item.");
          logDebug("   Purchase data: " + purchaseData);
          logDebug("   Signature: " + signature);
          verificationFailed = true;
        }
      }

      continueToken = ownedItems.getString(INAPP_CONTINUATION_TOKEN);
      logDebug("Continuation token: " + continueToken);
    } while (!TextUtils.isEmpty(continueToken));

    return verificationFailed ? IABHELPER_VERIFICATION_FAILED : BILLING_RESPONSE_RESULT_OK;
  }
Exemple #2
0
  /**
   * Consumes a given in-app product. Consuming can only be done on an item that's owned, and as a
   * result of consumption, the user will no longer own it. This method may block or take long to
   * return. Do not call from the UI thread. For that, see {@link #consumeAsync}.
   *
   * @param itemInfo The PurchaseInfo that represents the item to consume.
   * @throws IabException if there is a problem during consumption.
   */
  void consume(Purchase itemInfo) throws IabException {
    checkSetupDone("consume");
    try {
      String token = itemInfo.getToken();
      String sku = itemInfo.getSku();
      if (token == null || token.equals("")) {
        logError("Can't consume " + sku + ". No token.");
        throw new IabException(
            IABHELPER_MISSING_TOKEN,
            "PurchaseInfo is missing token for sku: " + sku + " " + itemInfo);
      }

      logDebug("Consuming sku: " + sku + ", token: " + token);
      int response =
          mService.consumePurchase(BILLING_API_VERSION, mContext.getPackageName(), token);
      if (response == BILLING_RESPONSE_RESULT_OK) {
        logDebug("Successfully consumed sku: " + sku);
      } else {
        logDebug("Error consuming consuming sku " + sku + ". " + getResponseDesc(response));
        throw new IabException(response, "Error consuming sku " + sku);
      }
    } catch (RemoteException e) {
      throw new IabException(
          IABHELPER_REMOTE_EXCEPTION,
          "Remote exception while consuming. PurchaseInfo: " + itemInfo,
          e);
    }
  }
 /**
  * Serialize purchase data to json
  *
  * @param purchase purchase data
  * @return json string
  * @throws JSONException
  */
 private String purchaseToJson(Purchase purchase) throws JSONException {
   return new JSONStringer()
       .object()
       .key("itemType")
       .value(purchase.getItemType())
       .key("orderId")
       .value(purchase.getOrderId())
       .key("packageName")
       .value(purchase.getPackageName())
       .key("sku")
       .value(purchase.getSku())
       .key("purchaseTime")
       .value(purchase.getPurchaseTime())
       .key("purchaseState")
       .value(purchase.getPurchaseState())
       .key("developerPayload")
       .value(purchase.getDeveloperPayload())
       .key("token")
       .value(purchase.getToken())
       .key("originalJson")
       .value(purchase.getOriginalJson())
       .key("signature")
       .value(purchase.getSignature())
       .key("appstoreName")
       .value(purchase.getAppstoreName())
       .endObject()
       .toString();
 }