Пример #1
0
  /**
   * Verifies that the data was signed with the given signature, and returns the list of verified
   * purchases. The data is in JSON format and contains a nonce (number used once) that we generated
   * and that was signed (as part of the whole data string) with a private key. The data also
   * contains the {@link PurchaseState} and product ID of the purchase. In the general case, there
   * can be an array of purchase transactions because there may be delays in processing the purchase
   * on the backend and then several purchases can be batched together.
   *
   * @param signedData the signed JSON string (signed, not encrypted)
   * @param signature the signature for the data, signed with the private key
   */
  public static ArrayList<VerifiedPurchase> verifyPurchase(String signedData, String signature) {
    if (signedData == null) {
      Log.e(TAG, "data is null");
      return null;
    } else if (StoreConfig.debug) {
      Log.d(TAG, "signedData: " + signedData);
    }

    boolean verified = false;
    // TODO: check this out... we might not want to verify when debugging.
    //        if (!StoreConfig.debug) {
    if (TextUtils.isEmpty(signature)) {
      Log.w(TAG, "Empty signature. Stopping verification.");
      return null;
    }
    PublicKey key = Security.generatePublicKey(StoreConfig.publicKey);
    verified = Security.verify(key, signedData, signature);
    if (!verified) {
      Log.w(TAG, "signature does not match data.");
      return null;
    }
    //        }

    JSONObject jObject;
    JSONArray jTransactionsArray = null;
    int numTransactions = 0;
    long nonce = 0L;
    try {
      jObject = new JSONObject(signedData);

      // The nonce might be null if the user backed out of the buy page.
      nonce = jObject.optLong("nonce");
      jTransactionsArray = jObject.optJSONArray("orders");
      if (jTransactionsArray != null) {
        numTransactions = jTransactionsArray.length();
      }
    } catch (JSONException e) {
      return null;
    }

    if (!Security.isNonceKnown(nonce)) {
      Log.w(TAG, "Nonce not found: " + nonce);
      return null;
    }

    ArrayList<VerifiedPurchase> purchases = new ArrayList<VerifiedPurchase>();
    try {
      for (int i = 0; i < numTransactions; i++) {
        JSONObject jElement = jTransactionsArray.getJSONObject(i);
        int response = jElement.getInt("purchaseState");
        PurchaseState purchaseState = PurchaseState.valueOf(response);
        String productId = jElement.getString("productId");
        String packageName = jElement.getString("packageName");
        long purchaseTime = jElement.getLong("purchaseTime");
        String orderId = jElement.optString("orderId", "");
        String notifyId = null;
        if (jElement.has("notificationId")) {
          notifyId = jElement.getString("notificationId");
        }
        String developerPayload = jElement.optString("developerPayload", null);

        // If the purchase state is PURCHASED, then we require a
        // verified nonce.
        if (purchaseState == PurchaseState.PURCHASED && !verified) {
          continue;
        }
        purchases.add(
            new VerifiedPurchase(
                purchaseState, notifyId, productId, orderId, purchaseTime, developerPayload));
      }
    } catch (JSONException e) {
      Log.e(TAG, "JSON exception: ", e);
      return null;
    }
    removeNonce(nonce);
    return purchases;
  }