【问题标题】:Restore purchases in In-app Billing (IAB Version 3) android在应用内结算(IAB 版本 3)android 中恢复购买
【发布时间】:2012-12-03 02:57:24
【问题描述】:

Google 已升级到 IAB3(应用内结算版本 3)。 首先是示例代码中的问题。super.onDestroy() 遗漏了。

我在http://developer.android.com/google/play/billing/billing_integrate.html的帮助下实现了v3

在手机上测试过,在模拟器上不行,卡在模拟器上。

我的问题是,我没有看到用于恢复交易的 API。如何使用 IAB3 恢复购买?是mService.getPurchases(apiVersion, packageName, type, continuationToken)。有人测试过这个吗??这会从本地存储的物品中返回购买的物品还是恢复购买的物品? 卸载应用程序没有continuationToken。应该是null吗?

那么当购买状态发生变化时呢?

请帮忙!

提前致谢。

编辑:

Google 已更新应用内计费库并解决了 super.onDestroy() 问题。 他们还添加了一些附加功能。

【问题讨论】:

  • 设置后立即发生的查询购买就是这样做的。我正在尝试相同的方法,但我有另一个问题是在我得到结果“ITEM 已经拥有并且我再次尝试调用launchPurchaseFlow。它放弃异常”java.lang.IllegalStateException:无法启动异步操作( launchPurchaseFlow),因为另一个异步操作(launchPurchaseFlow)正在进行中。 “。我不知道如何通过它。
  • 为了测试,我应该发布应用程序还是使用草稿?.. 我的应用程序没有在 play 上发布(不是单个版本)。
  • 您只需要发布您的应用内产品而不是应用。

标签: java android in-app-purchase in-app-billing


【解决方案1】:

要使物品可消耗,您必须发送消耗请求,并且必须在单独的线程中执行此操作。

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == 1111) {
        int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
        String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
        String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
        Logger.printMessage(TAG, "on activity result reponse"
                + responseCode, Logger.DEBUG);
        if (resultCode == RESULT_OK && responseCode == 0) {
            try {
                JSONObject jo = new JSONObject(purchaseData);
                String sku = jo.getString("productId");
                String title = jo.getString("title");
                addChipsToBalance(sku);
                final String token = jo.getString("purchaseToken");
                Toast.makeText(BuyChipsActivity.this,
                        "You have bought " + title + ". Enjoy the game!",
                        Toast.LENGTH_SHORT).show();

                new Thread(new Runnable() {

                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        Logger.printMessage(TAG, "inside run", Logger.DEBUG);
                        try {
                            int response = mService.consumePurchase(3,
                                    getPackageName(), token);
                            Logger.printMessage(TAG, "inside run response"
                                    + response, Logger.DEBUG);
                        } catch (RemoteException e) {
                            // TODO Auto-generated catch block
                            Logger.printMessage(TAG, "exception here 1",
                                    Logger.DEBUG);
                            e.printStackTrace();
                        }
                    }
                }).start();
                // alert("You have bought the " + sku +
                // ". Excellent choice,  adventurer!");
            } catch (JSONException e) {
                // alert("Failed to parse purchase data.");
                e.printStackTrace();
            }
        }
    }

但有时谷歌端没有完成消费请求,所以你可能想查询购买的物品列表并使用购买令牌消费它。我确实喜欢这个

   private void showPreviousPurchases() {
    Logger.printMessage(TAG, "previous purchases", Logger.DEBUG);
    if (mService == null) {
        Toast.makeText(this, "Something Went Wrong. Try later",
                Toast.LENGTH_LONG).show();
        return;
    }
    Bundle ownedItems = null;
    ;
    try {
        ownedItems = mService.getPurchases(3, getPackageName(), "inapp",
                null);
    } catch (RemoteException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    if (ownedItems == null) {
        Logger.printMessage(TAG, "criical error ", Logger.DEBUG);
        return;
    }
    int response = ownedItems.getInt("RESPONSE_CODE");
    if (response == 0) {
        ArrayList<String> ownedSkus = ownedItems
                .getStringArrayList("INAPP_PURCHASE_ITEM_LIST");
        ArrayList<String> purchaseDataList = ownedItems
                .getStringArrayList("INAPP_PURCHASE_DATA_LIST");
    /*  ArrayList<String> signatureList = ownedItems
                .getStringArrayList("INAPP_DATA_SIGNATURE");
        String continuationToken = ownedItems
                .getString("INAPP_CONTINUATION_TOKEN");*/

        for (int i = 0; i < purchaseDataList.size(); ++i) {
            String purchaseData = purchaseDataList.get(i);
            Logger.printMessage(TAG, "json  = " + purchaseData,
                    Logger.DEBUG);
            // String signature = signatureList.get(i);
            String sku = ownedSkus.get(i);

            addChipsAndMakeItConsumable(purchaseData);
            // do something with this purchase information
            // e.g. display the updated list of products owned by user
        }

        // if continuationToken != null, call getPurchases again
        // and pass in the token to retrieve more items
    }

}

private void addChipsAndMakeItConsumable(String purchaseData) {

    try {
        JSONObject jo = new JSONObject(purchaseData);
        String sku = jo.getString("productId");
        // String title = jo.getString("title");
        addChipsToBalance(sku);
        final String token = jo.getString("purchaseToken");
        Logger.printMessage(TAG, "id  = " + sku, Logger.DEBUG);

        Logger.printMessage(TAG, "inside run", Logger.DEBUG);
        try {
            int response = mService.consumePurchase(3, getPackageName(),
                    token);
            Logger.printMessage(TAG, "inside run response" + response,
                    Logger.DEBUG);
        } catch (RemoteException e) {
            // TODO Auto-generated catch block
            Logger.printMessage(TAG, "exception here 1", Logger.DEBUG);
            e.printStackTrace();
        }

        // alert("You have bought the " + sku +
        // ". Excellent choice,  adventurer!");
    } catch (JSONException e) {
        // alert("Failed to parse purchase data.");
        e.printStackTrace();
    }
}

【讨论】:

  • consume 表示可以再次购买该物品。是这样吗???...我想一次性购买,一次用户购买。他/她可以使用专业功能终身。如果应用程序将被卸载,那么我想恢复该特定用户的购买。所以让我知道如何恢复交易/购买。如果我退款项目,那么用户如何得到通知??
  • 嘿 user1194037,我第一次尝试了您获取最新购买信息的功能,但如果我在卸载我的应用程序后再次尝试,则它什么也不做。如果 Google 为我们提供了一个产品 ID,可以在整个应用程序中购买一次,否则恢复交易是没有意义的。您对此有任何想法吗?好吧,我使用“android.test.purchase”作为产品 ID。请在卸载您的应用程序后尝试此操作,并请让我知道它是否可以在您的最后使用谢谢..kabir :)
  • 如果用户是第一次运行你的应用程序,那么你可以检查应用程序产品中是否有任何二手产品,如果有则恢复该特定功能。
  • 好的,所以 getPurchase 退回购买的物品。我将恢复交易。现在,如果应用程序所有者退款,那么用户如何在 IBV3 中得到通知。在旧版本 od Inapp Billing 中。 OnpurchaseStateChanged 监听器就在那里。谢谢..
【解决方案2】:

在您的 /android-sdk/extras/google/play_billing/samples/ 中的示例 IabHelper.java 中,放置此代码以获取用户已购买的所有项目。这将返回一个购买数据的 JSON 数组。您还可以使用 Purchase.java 进行解析,在示例文件夹中也有。

     public ArrayList<String> getAllPurchases() throws RemoteException{
     Bundle ownedItems = mService.getPurchases(3, mContext.getPackageName(),"inapp", null);

     int response = getResponseCodeFromBundle(ownedItems);
     logDebug("Owned items response: " + String.valueOf(response));
     if (response != BILLING_RESPONSE_RESULT_OK) {
         logDebug("getPurchases() failed: " + getResponseDesc(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.");
     }

     ArrayList<String> purchaseDataList = ownedItems.getStringArrayList(RESPONSE_INAPP_PURCHASE_DATA_LIST);
     return purchaseDataList;
}

进入你的主要活动

 public class MainActivity extends Activity{
  private IabHelper mHelper;
      private String arrayString;
      public void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);

    mHelper = new IabHelper(this,"YOUR PUBLIC KEY" );
      mHelper.enableDebugLogging(true);
      mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {

        public void onIabSetupFinished(IabResult result) {

        if (!result.isSuccess()) { // Oh noes, there was a problem.
            Toast.makeText(this,"Problem setting up in-app billing: " + result,Toast.LENGTH_LONG).show();
              return;
          }

        arrayString=mHelper.getAllPurchases().toString();

        Log.d("Purchases: ",""+arrayString);


        array = new JSONArray(arrayString);

        for (int i = 0; i < array.length(); i++) {
            JSONObject row = array.getJSONObject(i);    
            productId=row.getString("productId");  //this will get the product id's that has been purchased.

            Log.e("To be restored:", " PRODUCT ID's "+productId);
        }

      });         
    }
}

我希望这会对你有所帮助。 ^_^ 谢谢。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-17
    • 1970-01-01
    • 1970-01-01
    • 2012-06-21
    • 1970-01-01
    相关资源
    最近更新 更多