我正在使用In App Billing示例应用将此功能添加到我的应用中。 在我将其添加到我的应用程序并测试完所有工作后,我注意到此Security class中的评论:
与安全相关的方法。为了安全实施,全部 此代码应在与之通信的服务器上实现 设备上的应用程序。为了简单起见 此示例的清晰度,此代码包含在此处并执行 在设备上。如果您必须在手机上验证购买,那么您 应该混淆这段代码,使攻击者更难 将代码替换为将所有购买视为已验证的存根。
正如谷歌建议的那样,我在服务器端进行购买验证,所以我真的不需要我项目中的安全类。 问题是,我无法弄清楚如何删除Security类中的BillingService类依赖项。
我首先删除了安全类并关注了BillingService中的错误,并且在大多数地方使用它我可以轻松删除,除了在一个地方:
private void purchaseStateChanged(int startId, String signedData, String signature) {
ArrayList<Security.VerifiedPurchase> purchases;
purchases = Security.verifyPurchase(signedData, signature);
if (purchases == null) {
return;
}
ArrayList<String> notifyList = new ArrayList<String>();
for (VerifiedPurchase vp : purchases) {
if (vp.notificationId != null) {
notifyList.add(vp.notificationId);
}
ResponseHandler.purchaseResponse(this, vp.purchaseState, vp.productId,
vp.orderId, vp.purchaseTime, vp.developerPayload);
}
if (!notifyList.isEmpty()) {
String[] notifyIds = notifyList.toArray(new String[notifyList.size()]);
confirmNotifications(startId, notifyIds);
}
}
如果有人可以在不使用安全类的情况下分享他/她的purchaseStateChanged方法(基于应用内结算示例应用),那就太喜欢了。
答案 0 :(得分:1)
所以这就是我所做的。首先,对BillingService的调用发生在应用程序主线程上,因此您需要在后台线程中发出服务器调用。我选择在主线程上完成处理,因为我不确定在后台线程上调用像'confirmNotifications'这样的方法有什么影响。
我创建了一个回调接口VerifyTransactionCompletion,可以在远程调用完成后将其调度回主线程。
我保留了Security类,并让它现在管理对服务器的调用,而不是它最初在示例中执行的操作。因此,当您看到对安全性的调用时,我就会调用我的服务器并执行签名验证。
/**
* Callback interface to <em>finish</em> processing a transaction once the remote
* servers have processed it.
*/
public interface VerifyTransactionCompletion {
public void transactionVerified(List<Security.VerifiedPurchase> purchases);
}
private void purchaseStateChanged(final int startId, String signedData, String signature) {
// verifyPurchase issues remote call to server (in a background thread), then
// calls transactionVerified on the main thread to continue processing.
Security.verifyPurchase(signedData, signature, new VerifyTransactionCompletion() {
@Override
public void transactionVerified(List<VerifiedPurchase> purchases) {
if (purchases == null) {
return;
}
ArrayList<String> notifyList = new ArrayList<String>();
for (VerifiedPurchase vp : purchases) {
if (vp.notificationId != null) {
notifyList.add(vp.notificationId);
}
ResponseHandler.purchaseResponse(BillingService.this, vp.purchaseState, vp.productId,
vp.orderId, vp.purchaseTime, vp.developerPayload);
}
if (!notifyList.isEmpty()) {
String[] notifyIds = notifyList.toArray(new String[notifyList.size()]);
confirmNotifications(startId, notifyIds);
}
}
});
}