如何最好地保存InApp购买本地状态? [英] How to best save InApp purchase status locally?

查看:189
本文介绍了如何最好地保存InApp购买本地状态?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在完成我的第一个应用程序的边缘,最后剩下的事情就是实现IAP计费,所以这就是为什么我现在读了很多有关的话题(包括例如加密,模糊处理和材料的安全问题)

I'm on the edge of finishing my first app, and one last remaining thing is to implement IAP billing, so that's why I am currently reading quite a lot about the topic (including security concerns like encryption, obfuscation and stuff).

我的应用程序是一个免费的版本,通过IAP升级到完整的verison的能力,所以就只是一个管理采购项目premium。我有这几个问题:

My app is a free version, with the ability to upgrade to full verison via IAP, so there would be just one managed purchase item "premium". I have a few questions about this:

在谷歌IAP API示例(trivialdrivesample),总是有IAP入住MainActivity看到,如果用户购买了premium版本,通过

In the Google IAP API example (trivialdrivesample), there's always the IAP check in MainActivity to see if the user bought the premium version, done via

mHelper.queryInventoryAsync(mGotInventoryListener);

mHelper.queryInventoryAsync(mGotInventoryListener);

我的第一个担忧: 这并不意味着用户总是需要有在应用程序,启动互联网/数据连接,才能够切换到premium版本吧?如果用户没有什么可以上网吗?他会去的是精简版的版本,我想,我会觉得很烦。

My first concern: This does mean that the user always needs to have an internet/data connection at app-startup, to be able switch to the premium version right? What if the user doesn't have an internet connection? He would go with the lite version I guess, which I would find annoying.

所以,我想过如何保存到本地IS premium地位,无论是在共享preFS或应用程序的数据库。现在,我知道你不能阻止黑客逆向工程的应用程序,不管是什么,即使是这样,因为我没有自己的服务器上做一些服务器端验证。

So I thought about how to save the isPremium status locally, either in the SharedPrefs or in the app database. Now, I know you can't stop a hacker to reverse engineer the app, no matter what, even so because I don't own a server to do some server-side validation.

然而,人们根本无法保存是premium标志的地方,因为这将是太容易被发现。

Nevertheless, one simply can't save an "isPremium" flag somewhere, since that would be too easy to spot.

所以,我在想是这样的:

So I was thinking about something like this:

      
  • 在用户购买premium
  •   
  • 应用获​​取IMEI /设备ID和XOR EN codeS用硬codeD串键,将最大限度地保留在本地应用程序数据库中。
  •   

现在,当用户再次启动该应用程序:

Now when the user starts the app again:

      
  • 应用获​​得EN codeD字符串从数据库中,德codeS,并检查是否去codedString == IMEI。如果是的话 - > premium
  •   
  • 如果没有,那么正常queryInventoryAsync将被调用来看看,如果用户购买了premium。
  •   

那你想想办法?我知道这不是supersecure,但对我来说更重要的是,用户不恼火(如强制性的互联网连接),比该应用程序将是牢不可破的(这是不可能的反正)。 你有一些其他的建议吗?

What do you think about that approach? I know it's not supersecure, but for me it's more important that the user isn't annoyed (like with mandatory internet connection), than that the app will be unhackable (which is impossible anyway). Do you have some other tips?

另一件事,这是我目前还没有一个有关的线索,是如何当用户卸载/重新安装应用程序恢复交易状态。我知道API有一定的机制是什么,以及方法,另外我的数据库可以通过应用程序(使EN codeD为premium标志将导出/导入的为好)导出和导入。好吧,我想这会是另外一个问题,当时间是正确的; - )

Another thing, which I currently don't have a clue about, is how to restore the transaction status when the user uninstalls/reinstalls the app. I know the API has some mechanism for that, and aditionally my database can be exported and imported through the app (so the encoded isPremium flag would be exportable/importable as well). Ok, I guess that would be another question, when the time is right ;-)

有什么想法和意见,这种做法是值得欢迎的,你认为这是一个很好的解决方案?还是我失去了一些东西/标题进入一些错误的方向?

Any thoughts and comments to this approach are welcome, do you think that's a good solution? Or am I missing something/heading into some wrong direction?

推荐答案

我也被做了同样的调查,但我的测试中我想通了,你不需要保存它,因为谷歌做所有你需要的缓存和我怀疑(虽然我还没有调查的话),他们这样做是尽可能安全(看到它在自己的利益呢!)

I too was making the same investigations, but during my testing I figured out that you do not need to store it, as Google do all the caching you need and I suspect (though I have not investigated it) that they are doing so as securely as possible (seeing as it in their interest too!)

因此​​,这里是我做什么

So here is what i do

// Done in onCreate
mHelper = new IabHelper(this, getPublicKey());

mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result) {
      if (!result.isSuccess()) {
         // Oh noes, there was a problem.
         Log("Problem setting up In-app Billing: " + result);
      } else {
         Log("onIabSetupFinished " + result.getResponse());
         mHelper.queryInventoryAsync(mGotInventoryListener);
     }
    }
});

// Called by button press
private void buyProUpgrade() {
    mHelper.launchPurchaseFlow(this, "android.test.purchased", 10001,   
           mPurchaseFinishedListener, ((TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE)).getDeviceId());
}

// Get purchase response
private IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {
    public void onIabPurchaseFinished(IabResult result, Purchase purchase) 
    {
       if (result.isFailure()) {
          Log("Error purchasing: " + result);
          return;
       }      
       else if (purchase.getSku().equals("android.test.purchased")) {
      Log("onIabPurchaseFinished GOT A RESPONSE.");
              mHelper.queryInventoryAsync(mGotInventoryListener);
      }
    }
};

// Get already purchased response
private IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() {
    public void onQueryInventoryFinished(IabResult result,
       Inventory inventory) {

       if (result.isFailure()) {
         // handle error here
           Log("Error checking inventory: " + result); 
       }
       else {
         // does the user have the premium upgrade?        
         mIsPremium = inventory.hasPurchase("android.test.purchased");        
         setTheme();

         Log("onQueryInventoryFinished GOT A RESPONSE (" + mIsPremium + ").");
       }
    }
};

那么这里会发生什么?

So what happens here?

IAB的设置和调用 startSetup ,在成功完成(只要它已经与互联网连接运行一次,并正确设置它总会成功),我们称之为 queryInventoryAsync 来找出哪些是已经购买(同样,如果这被称为同时在线人数始终工作在脱机状态下)。

The IAB is set up and calls startSetup, on a successful completion (as long as it has been run once with an internet connection and is set up correctly it will always succeed) we call queryInventoryAsync to find out what is already purchased (again if this has been called while online it always works while offline).

因此​​,如果购买成功完成(如只能同时在线进行),我们称之为 queryInventoryAsync ,以确保它被称为同时在线。

So if a purchase is completed successfully (as can only be done while online) we call queryInventoryAsync to ensure that it has been called while online.

现在有没有必要存储任何与收购,使您的应用程序少了很多容易被破解。

Now there is no need to store anything to do with purchases and makes your app a lot less hackable.

我已经测试了这个方法很多,飞行模式,在再次打开设备关闭,并且打乱它的唯一事情是清除手机(不太可能发生!)在一些谷歌应用程序的数据。

I have tested this many ways, flight mode, turning the devices off an on again and the only thing that messes it up is clearing data in some of the Google apps on the phone (Not likely to happen!).

请有助于这个,如果你有不同的经历,我的应用还处于早期测试阶段。

Please contribute to this if you have different experiences, my app is still in early testing stage.

这篇关于如何最好地保存InApp购买本地状态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆