Google Android应用内购买“内容投放”如何正确投放内容?

我目前正在尝试编写应用内购买代码。 我正在寻找有关谷歌无法处理的一些东西的最佳实践的文档,信息和教程。

到目前为止我做了什么:

我有一个运行结算服务来处理与Google Play的通话。 此服务可以完成“示例”事务,我的应用程序会收到消息。

我现在要将内容传送到设备。 我认为接下来需要发生的事情:

  1. 我的应用程序需要联系我的服务器并显示成功交易的一些证据。 做一些Cert手抖或一些这样的废话。

  2. 然后我将下载内容并将该内容放入数据库。 我应该使用某种设备唯一加密来加密数据库。

我正在寻找如何做以上两件事和其他任何需要做的事情。 我想要一个合理数量的安全/加密。 任何文档/教程/示例项目都会很棒,我已经尝试过搜索这些东西并且找不到我想要的东西。

您必须从示例中对计费服务客户端代码进行一些更改。

首先,您应该调用您的服务器以获取将用于RestoreTransactions或进行购买的nonce,以使事情尽可能安全。

让我们来看看会发生什么。 以下是Google Play调用的BillingReceiver:

/** * This is called when Android Market sends information about a purchase state * change. The signedData parameter is a plaintext JSON string that is * signed by the server with the developer's private key. The signature * for the signed data is passed in the signature parameter. * @param context the context * @param signedData the (unencrypted) JSON string * @param signature the signature for the signedData */ private void purchaseStateChanged(Context context, String signedData, String signature) { Intent intent = new Intent(Consts.ACTION_PURCHASE_STATE_CHANGED); intent.setClass(context, BillingService.class); intent.putExtra(Consts.INAPP_SIGNED_DATA, signedData); intent.putExtra(Consts.INAPP_SIGNATURE, signature); context.startService(intent); } 

如果你看看BillingService.java中的handleCommand,它会处理这个意图:

 /** * The {@link BillingReceiver} sends messages to this service using intents. * Each intent has an action and some extra arguments specific to that action. * @param intent the intent containing one of the supported actions * @param startId an identifier for the invocation instance of this service */ public void handleCommand(Intent intent, int startId) { String action = intent.getAction(); if (Consts.DEBUG) { Log.i(TAG, "handleCommand() action: " + action); } if (Consts.ACTION_CONFIRM_NOTIFICATION.equals(action)) { String[] notifyIds = intent.getStringArrayExtra(Consts.NOTIFICATION_ID); confirmNotifications(startId, notifyIds); } else if (Consts.ACTION_GET_PURCHASE_INFORMATION.equals(action)) { String notifyId = intent.getStringExtra(Consts.NOTIFICATION_ID); getPurchaseInformation(startId, new String[] { notifyId }); } else if (Consts.ACTION_PURCHASE_STATE_CHANGED.equals(action)) { String signedData = intent.getStringExtra(Consts.INAPP_SIGNED_DATA); String signature = intent.getStringExtra(Consts.INAPP_SIGNATURE); purchaseStateChanged(startId, signedData, signature); } else if (Consts.ACTION_RESPONSE_CODE.equals(action)) { long requestId = intent.getLongExtra(Consts.INAPP_REQUEST_ID, -1); int responseCodeIndex = intent.getIntExtra(Consts.INAPP_RESPONSE_CODE, ResponseCode.RESULT_ERROR.ordinal()); ResponseCode responseCode = ResponseCode.valueOf(responseCodeIndex); checkResponseCode(requestId, responseCode); } } 

然后调用thePurchaseStateChanged函数。 应该通过调用服务器来替换此function,以便为内容交付创建会话。 应将Security.java中的代码移植到服务器端以validation云中的事务。

 /** * Verifies that the data was signed with the given signature, and calls * {@link ResponseHandler#purchaseResponse(Context, PurchaseState, String, String, long)} * for each verified purchase. * @param startId an identifier for the invocation instance of this service * @param signedData the signed JSON string (signed, not encrypted) * @param signature the signature for the data, signed with the private key */ private void purchaseStateChanged(int startId, String signedData, String signature) { ArrayList purchases; purchases = Security.verifyPurchase(signedData, signature); if (purchases == null) { return; } ArrayList notifyList = new ArrayList(); 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); } } 

确保将公钥放在已移植的Security.java文件中的服务器端。