Ton*_*oni 34 security android in-app-purchase
我正处于完成我的第一个应用程序的边缘,剩下的最后一件事就是实现IAP计费,这就是为什么我目前正在阅读相关主题(包括加密,混淆和东西等安全问题).
我的应用程序是免费版本,能够通过IAP升级到完整版本,因此只有一个托管购买项目"溢价".我有几个问题:
在Google IAP API示例(trivialdrivesample)中,总是在MainActivity中检查IAP以查看用户是否购买了高级版本,通过
mHelper.queryInventoryAsync(mGotInventoryListener);
我的第一个问题:这是否意味着用户始终需要在应用启动时拥有互联网/数据连接,才能切换到高级版本?如果用户没有互联网连接怎么办?他会选择我猜的精简版,我觉得这很烦人.
所以我想到了如何在SharedPrefs或app数据库中本地保存isPremium状态.现在,我知道你无法阻止黑客对应用程序进行逆向工程,无论如何,即便如此,因为我没有服务器来进行服务器端验证.
然而,一个人根本无法在某处保存"isPremium"标志,因为这太容易被发现.
所以我在考虑这样的事情:
- 用户购买Premium
- 应用程序获取IMEI/Device-ID,XOR使用硬编码的String键对其进行编码,并将其保存在应用程序数据库中.
现在,当用户再次启动应用程序时:
- App从数据库中获取编码的String,对其进行解码并检查decodeString == IMEI.如果是 - >溢价
- 如果不是,则将调用正常的queryInventoryAsync以查看用户是否购买了premium.
您如何看待这种方法?我知道这不是超级固定,但对我而言,更重要的是用户不会烦恼(比如强制性的互联网连接),而不是应用程序将无法解决(无论如何这是不可能的).你有其他一些提示吗?
另一件事,我目前还不知道,是当用户卸载/重新安装应用程序时如何恢复事务状态.我知道API有一些机制,并且我的数据库可以通过应用程序导出和导入(因此编码的isPremium标志也可以导出/导入).好吧,我猜这将是另一个问题,当时机成熟时;-)
对这种方法的任何想法和评论都是受欢迎的,您认为这是一个很好的解决方案吗?或者我错过了什么/朝着错误的方向前进?
Ne0*_*Ne0 17
我也在做同样的调查,但是在我的测试中我发现你不需要存储它,因为谷歌会做你需要的所有缓存,我怀疑(虽然我没有调查过)他们这样做是安全的尽可能(看到他们感兴趣的!)
所以这就是我的所作所为
// 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 + ").");
}
}
};
Run Code Online (Sandbox Code Playgroud)
那么这里发生了什么?
startSetup成功完成IAB设置和呼叫(只要它已经通过互联网连接运行一次,并且设置正确,它将始终成功)我们打电话queryInventoryAsync找出已经购买的东西(如果已经购买的话)在线时调用它总是在离线时工作).
因此,如果购买成功完成(只能在网上完成),我们会打电话queryInventoryAsync确保在线时调用.
现在没有必要存储与购买有关的任何内容,并且使您的应用程序不那么容易破解.
我已经测试了很多方法,飞行模式,再次打开设备,唯一令人困惑的是清除手机上某些Google应用程序中的数据(不太可能发生!).
如果您有不同的经历,请为此做出贡献,我的应用程序仍处于早期测试阶段.
我将ne0的答案重构为静态方法,包括来自snark的评论.
我的应用程序启动时会调用此方法 - 您需要启用此功能 TODO
/**
* This is how you check with Google if the user previously purchased a non-consumable IAP
* @param context App Context
*/
public static void queryPlayStoreForPurchases(Context context)
{
final IabHelper helper = new IabHelper(context, getPublicKey());
helper.startSetup(new IabHelper.OnIabSetupFinishedListener()
{
public void onIabSetupFinished(IabResult result)
{
if (!result.isSuccess())
{
Log.d("InApp", "In-app Billing setup failed: " + result);
}
else
{
helper.queryInventoryAsync(false, new IabHelper.QueryInventoryFinishedListener()
{
public void onQueryInventoryFinished(IabResult result, Inventory inventory)
{
// If the user has IAP'd the Pro version, let 'em have it.
if (inventory.hasPurchase(PRO_VERSION_SKU))
{
//TODO: ENABLE YOUR PRO FEATURES!!
Log.d("IAP Check", "IAP Feature enabled!");
}
else
{
Log.d("IAP Check", "User has not purchased Pro version, not enabling features.");
}
}
});
}
}
});
}
Run Code Online (Sandbox Code Playgroud)
如果用户购买了该项目,这将在重新启动和没有网络连接的情况下工作.
由于您已经知道使用该系统不可能使其无法被黑客攻击,因此我建议不要尝试阻止黑客攻击。您提出的建议被称为“通过默默无闻实现安全”,通常是一个坏主意。
我的建议是queryInventoryAsync()首先尝试,并且仅在没有互联网连接的情况下检查您的“isPremium”标志。
还有一些潜在的其他方法可以解决此问题,例如拥有单独的免费和付费应用程序,而不是应用程序内购买。其他人如何处理这个问题以及谷歌提供的工具可能值得调查。
queryInventoryAsync将自动考虑卸载和重新安装,因为它会跟踪登录用户的购买情况。
| 归档时间: |
|
| 查看次数: |
6392 次 |
| 最近记录: |