【问题标题】:Android in app billing - How to know which users have bought a productAndroid in app billing - 如何知道哪些用户购买了产品
【发布时间】:2017-09-29 16:53:46
【问题描述】:

我有一个带有捐赠系统的安卓应用,这些捐赠是自动消费的集成产品,让用户可以多次捐赠。

我需要知道是否有某种方法可以找出哪些用户至少捐赠过一次。

感谢您的帮助。

编辑:

除了 Dima Kozhevin 的回答...我在startSetup() 方法中的onServiceConnected() 事件中使用了此代码,来自我的IabHelper.

Bundle purchaseHistoryBundle = mService.getPurchaseHistory(6,BuildConfig.APPLICATION_ID, "inapp", null, new Bundle());
ArrayList<String> mListItems = purchaseHistoryBundle.getStringArrayList("INAPP_PURCHASE_ITEM_LIST");
if (mListItems != null){
    if (mListItems.size()>0){
        //User have donated at least once
    }else{
        //User never donated
    }
}

【问题讨论】:

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


    【解决方案1】:

    您应该使用getPurchaseHistory() 方法。 Signature的方法:

    Bundle getPurchaseHistory(int apiVersion,
                              String packageName,
                              String type,
                              String continuationToken,
                              Bundle extraParams);
    

    您的代码将如下所示:

    Bundle purchaseHistoryBundle = service.getPurchaseHistory(6, BuildConfig.APPLICATION_ID, "subs", null, new Bundle());
    

    另外,guy from Google建议在that example使用queryPurchaseHistoryAsync方法:

    这个库还允许获取购买历史记录,即使它不是 在样品中演示。请使用this method获取所有 购买历史记录(每个 SKU 最多 1 条记录)。

    【讨论】:

      【解决方案2】:

      我假设您已经为 IabHelper 等集成了 AIDL 文件和应用内计费代码文件。按照 Android 说明进行基本计费处理。

      一旦您已经在处理帐单,您只需查询库存以查看他们是否已购买。我倾向于在一个名为 PurchaseManager 的单例类中执行此操作。

      我将在下面与您分享该课程。但是,我只有一个包,所以我在我购买的 pro 支票中硬编码了该包,为了更加动态,您可能希望在调用类或循环中进行这些检查。

      /**
       * Created by App Studio 35 on 9/28/17.
       */
      public class PurchaseManager {
      
          /*///////////////////////////////////////////////////////////////
          // MEMBERS
          *////////////////////////////////////////////////////////////////
          private static PurchaseManager mInstance;
          private static final String TAG = Globals.SEARCH_STRING + PurchaseManager.class.getSimpleName();
          private static String PUBLIC_LICENSING_KEY = "<YOUR PUBLIC KEY HERE>";
          private static final String PRO_PACKAGE_SKU = "pro_package_level_1";
          public static final int RESULT_KEY_PURCHASE = 9876;
          private IabHelper mHelper;
          private Boolean mIABServiceIsAvailable = false;
          private static String mAndroidId;
      
      
          /*///////////////////////////////////////////////////////////////
          // CONSTRUCTOR
          *////////////////////////////////////////////////////////////////
          private PurchaseManager(){}
          public static synchronized PurchaseManager getInstance(){
              if(mInstance == null){
                  mInstance = new PurchaseManager();
      
              }
      
              return mInstance;
          }
      
      
          /*///////////////////////////////////////////////////////////////
          // EXTERNAL METHODS
          *////////////////////////////////////////////////////////////////
          public boolean getIsIABServiceAvailable(){
              return mIABServiceIsAvailable;
          }
          public void checkForPurchasesOrTrials(final Context context, final IPurchaseSyncListener listener) {
              mHelper = new IabHelper(context, PUBLIC_LICENSING_KEY);
      
              if(!BuildConfig.DEBUG) {
                  mHelper.enableDebugLogging(true, TAG);
      
              }
      
              //Setup Purchase Processor
              mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
                  @Override
                  public void onIabSetupFinished(IabResult result) {
                      mIABServiceIsAvailable = result.isSuccess();
                      if (!result.isSuccess()) {
                          String error = "Problem setting up In-app Billing: " + result;
                          A35Log.d(TAG, error);
                          notifyUserOfError(listener, error);
                          return;
      
                      }
      
                      ArrayList<String> skus = new ArrayList<String>();
                      skus.add(PRO_PACKAGE_SKU);
                      checkExistingPurchasesForSkus(context, listener, skus);
      
                  }
      
              });
      
          }
          public void attemptPurchaseOfPro(Activity activity, final IPurchaseConsumeListener listener){
              mHelper.launchPurchaseFlow(activity, PRO_PACKAGE_SKU, RESULT_KEY_PURCHASE, new IabHelper.OnIabPurchaseFinishedListener() {
                  @Override
                  public void onIabPurchaseFinished(IabResult result, Purchase info) {
                      if (result.isSuccess()) {
                          mHelper.consumeAsync(info, new IabHelper.OnConsumeFinishedListener() {
                              @Override
                              public void onConsumeFinished(Purchase purchase, IabResult result) {
                                  if (result.isSuccess()) {
                                      Log.d(TAG, "Successfully synced purchases" + result);
                                      notifyUserOfPurchaseSuccess(listener, purchase, result, PRO_PACKAGE_SKU);
      
                                  } else {
                                      String error = "Could not sync purchases. Error: " + result;
                                      Log.d(TAG, error);
                                      notifyUserOfPurchaseError(listener, error, result, PRO_PACKAGE_SKU);
      
                                  }
                              }
      
                          });
                      }else{
                          notifyUserOfPurchaseError(listener, "Purchase Incomplete", result, PRO_PACKAGE_SKU);
      
                      }
                  }
              });
      
      
      
          }
      
      
          /*///////////////////////////////////////////////////////////////
          // INTERNAL METHODS
          *////////////////////////////////////////////////////////////////
          private void checkExistingPurchasesForSkus(final Context context, final IPurchaseSyncListener listener, final ArrayList<String> skus) {
              mHelper.queryInventoryAsync(true, skus, new IabHelper.QueryInventoryFinishedListener() {
                  @Override
                  public void onQueryInventoryFinished(IabResult result, Inventory inv) {
                      if (!result.isSuccess()) {
                          String error = "Unable to query inventory. Error: " + result;
                          A35Log.d(TAG, error);
                          notifyUserOfError(listener, error);
                          return;
      
                      }
      
                      ArrayList<Purchase> purchaseList = new ArrayList<Purchase>();
                      if (inv.getPurchase(PRO_PACKAGE_SKU) != null) {
                          purchaseList.add(inv.getPurchase(PRO_PACKAGE_SKU));
      
                      }
      
                      if (!purchaseList.isEmpty()) {
                          A35Log.d(TAG, "Attempting to sync purchases" + result);
                          attemptToSyncPurchases(context, listener, purchaseList);
      
                      } else {
                          A35Log.d(TAG, "We didn't see any purchases, attempting to check for Trials");
                          if(mAndroidId == null) {
                              getAdvertiserIDThenCheckTrialsForDevice(context, listener, skus);
      
                          }else{
                              checkTrialsForDeviceID(context, listener, skus);
      
                          }
      
                      }
      
                  }
      
              });
      
          }
          private void attemptToSyncPurchases(final Context context, final IPurchaseSyncListener listener, final ArrayList<Purchase> purchaseList) {
              for(Purchase purchase : purchaseList) {
                  mHelper.consumeAsync(purchase, new IabHelper.OnConsumeFinishedListener() {
                      @Override
                      public void onConsumeFinished(Purchase purchase, IabResult result) {
                          if (result.isSuccess()) {
                              Log.d(TAG, "Successfully synced purchases" + result);
                              notifyUserOfPurchasedPackages(listener, purchaseList);
      
                          } else {
                              String error = "Could not sync purchases. Error: " + result;
                              Log.d(TAG, error);
                              notifyUserOfError(listener, error);
      
                          }
                      }
      
                  });
      
              }
      
          }
          private void getAdvertiserIDThenCheckTrialsForDevice(final Context context, final IPurchaseSyncListener listener, final ArrayList<String> skus){
              //If no purchases then check for trial times for skus get Advertiser ID for identifying device
              new GetAdvertiserIDAsyncTask(context){
                  @Override
                  protected void onPostExecute(String advertisementID) {
                      mAndroidId = (advertisementID == null ? "unknownID" : advertisementID);
                      checkTrialsForDeviceID(context, listener, skus);
      
                  }
      
              }.execute();
      
          }
          private void checkTrialsForDeviceID(final Context context, final IPurchaseSyncListener listener, final ArrayList<String> skus){
              //Use device ID to check for Trials
              new GetTrialTimeAsyncTask(context, mAndroidId){
                  @Override
                  protected void onPostExecute(ActiveTrialsListResponseModel activeTrialsListResponseModel) {
                      super.onPostExecute(activeTrialsListResponseModel);
                      A35Log.v(TAG, "onPostExecute");
      
                      if(activeTrialsListResponseModel.getErrorMessage() != null) {
                          String error = "Error getting trial time: " + activeTrialsListResponseModel.getErrorMessage();
                          A35Log.e(TAG, error);
                          notifyUserOfError(listener, error);
                          return;
                      }
      
                      notifyUserOfTrialCheckCompleteForPackages(listener, activeTrialsListResponseModel);
      
                  }
              }.execute();
          }
      
      
          /*///////////////////////////////////////////////////////////////
          // NOTIFY USER CALLBACKS
          *////////////////////////////////////////////////////////////////
          private void notifyUserOfError(IPurchaseSyncListener listener, String message){
              if(listener != null){
                  listener.onPurchaseManagerError(message);
              }
          }
          private void notifyUserOfPurchasedPackages(IPurchaseSyncListener listener, ArrayList<Purchase> purchasedSkus){
              if(listener != null){
                  listener.onPackagePurchased(purchasedSkus);
              }
          }
          private void notifyUserOfTrialCheckCompleteForPackages(IPurchaseSyncListener listener, ActiveTrialsListResponseModel activeTrialsListResponseModel){
              if(listener != null){
                  listener.onTrialRetrievalComplete(activeTrialsListResponseModel);
              }
          }
          private void notifyUserOfPurchaseSuccess(IPurchaseConsumeListener listener, Purchase purchase, IabResult result, String sku){
              if(listener != null){
                  listener.onPurchaseSuccessful(purchase, result, sku);
              }
          }
          private void notifyUserOfPurchaseError(IPurchaseConsumeListener listener, String message, IabResult result, String sku){
              if(listener != null){
                  listener.onPurchaseFailure(message, result, sku);
              }
          }
      
          /*///////////////////////////////////////////////////////////////
          // INTERFACE
          *////////////////////////////////////////////////////////////////
          public interface IPurchaseSyncListener {
              void onPackagePurchased(ArrayList<Purchase> sku);
              void onTrialRetrievalComplete(ActiveTrialsListResponseModel activeTrialsListResponseModel);
              void onPurchaseManagerError(String message);
          }
          public interface IPurchaseConsumeListener {
              void onPurchaseSuccessful(Purchase purchase, IabResult result, String sku);
              void onPurchaseFailure(String message, IabResult result, String sku);
          }
      
      }
      

      关于我的共享代码也需要注意三件事。

      1. 我正在为我的 pro 软件包使用试用版,因此这是我的异步任务,以确认它们不在任何软件包的试用版中,您不会这样做。
      2. 我没有经过身份验证的用户,我依靠设备广告商 ID 来了解他们是否有试用版,这对你来说无关紧要。此外,如果用户足够狡猾,他们可以在谷歌设置中重置广告客户 ID,他们可以弄清楚如何获得另一个免费试用版,但我并不担心高级用户为了节省一美元而走那么远哈哈。李>
      3. 我在 checkfor purchase 方法中进行了启动,因为它只在应用启动时被调用一次,而且是第一次调用。如果 helper 为 null,则更通用的方法可能是在第一个 getInstance 中执行。

      祝你好运。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-12-10
        • 2014-06-06
        • 2013-11-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-10-17
        • 1970-01-01
        相关资源
        最近更新 更多