title: How to confirm android billing notifications?
body: <p>I am trying to implement in-app purchase staring with the sample app.
  I am verifying the purchase by using a web server and doing the verification there. The problem is that the purchase state change notifications never stop, no matter the result of the transaction.
  That is, I receive purchase state change notifications every minute untill i close the app regardless of the purchase that i made was succesfull, unsuccesfull or canceld by the user.</p>
  
  <p>Here is some sample code that I am using:</p>
  
  <pre><code>public class BillingReceiver extends BroadcastReceiver 
  {
  @Override
  public void onReceive(Context context, Intent intent) {
      String action = intent.getAction();
      Log.i(TAG, "Received action: " + action);
      if (ACTION_PURCHASE_STATE_CHANGED.equals(action)) {
          String signedData = intent.getStringExtra(INAPP_SIGNED_DATA);
          String signature = intent.getStringExtra(INAPP_SIGNATURE);
          purchaseStateChanged(context, signedData, signature);
      } else if (ACTION_NOTIFY.equals(action)) {
          String notifyId = intent.getStringExtra(NOTIFICATION_ID);
          notify(context, notifyId);
      } else if (ACTION_RESPONSE_CODE.equals(action)) {
          long requestId = intent.getLongExtra(INAPP_REQUEST_ID, -1);
          int responseCodeIndex = intent.getIntExtra(INAPP_RESPONSE_CODE, C.ResponseCode.RESULT_ERROR.ordinal());
          checkResponseCode(context, requestId, responseCodeIndex);
      } else {
         Log.e(TAG, "unexpected action: " + action);
      }
  }
  
  private void purchaseStateChanged(Context context, String signedData, String signature) {
      Log.i(TAG, "purchaseStateChanged got signedData: " + signedData);
      Log.i(TAG, "purchaseStateChanged got signature: " + signature);
      BillingHelper.verifyPurchase(signedData, signature);
  }
  }
  </code></pre>
  
  <p>BillingHelper:</p>
  
  <pre><code>ArrayList&lt;VerifiedPurchase&gt; purchases = BillingSecurity.verifyPurchase(mApp, signedData, signature);
  
      if(purchases != null &amp;&amp; purchases.size() &gt; 0)
      {
          latestPurchase = purchases.get(0);
          confirmTransaction(new String[]{latestPurchase.notificationId});
      }
      if(mCompletedHandler != null){
          mCompletedHandler.sendEmptyMessage(0);
      } else {
          Log.e(TAG, "verifyPurchase error. Handler not instantiated. Have you called setCompletedHandler()?");
      }
  </code></pre>
  
  <p>BillingSecurity:</p>
  
  <pre><code>public static ArrayList&lt;VerifiedPurchase&gt; verifyPurchase(Context context, String signedData, String signature) {
      if (signedData == null) {
          Log.e(TAG, "data is null");
      }
      Log.i(TAG, "signedData: " + signedData);
      boolean verified = false;
      if (!TextUtils.isEmpty(signature)) {
  
          try
          {
              boolean result = Server.verifyAndroidPurchase( signedData, signature);
              if(!result)
              {
                  Log.d("VERIFY RESULT", "verification failed");
                                                 return null;
              }               
              verified = true;
          }
  
      }
  
      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) {
      }
  
      if (!BillingSecurity.isNonceKnown(nonce)) {
          Log.w(TAG, "Nonce not found: " + nonce);
          return null;
      }
  
      ArrayList&lt;VerifiedPurchase&gt; purchases = new ArrayList&lt;VerifiedPurchase&gt;();
      try {
          for (int i = 0; i &lt; 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 &amp;&amp; !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;
  }
  </code></pre>