应用内结算 (Android) 中的恢复交易如何工作?

发布于 2024-12-12 19:37:57 字数 300 浏览 0 评论 0原文

我试图搜索这个问题,但没有得到很多信息。我只知道:
- 在用户首次安装应用程序时或用户卸载/擦除数据时重新安装时恢复。
- 恢复事务仅适用于托管产品。
我尝试阅读 Dungeon 示例,有几行关于恢复事务的代码,例如:何时调用恢复请求,何时获得恢复响应...但我不知道:
- 如何获取退货信息? (例如您购买的商品 ID)

请有人再解释一下应用内计费中恢复交易的流程。

非常感谢你!!!

编辑:很抱歉,我很长时间没有在 Android 中工作了,现在我不知道这个问题的正确答案是什么,所以我无法标记答案:P

I tried to search about that problem, but didnt get many information. I just know that:

- Restore in the first time user install app or when user reinstall when they uninstall/wipe data.

- Restore transaction just apply for managed-product.

I tried to read Dungeon Example, there are few line of code about restore transaction like: when to call restore request, when to get restore respone... but i dont know:

- How to get return information? (like item id that you have bought)

Someone please explain once again about Process of Restore Transaction in In-App billing.

Thanks you so much!!!

Edited: so sorry, I did not work in Android from long time, and right now I dont know what is right answer for this question, so I cant mark answer :P

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

涫野音 2024-12-19 19:37:57

典型流程如下:

  1. 用户安装您的应用。

  2. 首次加载应用程序时,您检查是否需要恢复
    购买。

  3. 如果您这样做,请向 Google 发送 RESTORE_TRANSACTION 同步请求。

  4. Google 将通过确认回复来回复您的
    RESTORE_TRANSACTION 请求。 (这只是一个确认
    他们收到了您的请求。)

  5. 此时,您应该标记您已向 Google 发送了恢复请求,并且不需要从应用发送进一步的恢复。

  6. 现在,对于用户之前购买的每项应用内购买,Google 将开始异步向您的应用发送“PURCHASE_STATE_CHANGED”事件。此调用与用户首次购买时 Google 发送的调用相同

  7. 由于这是同一个调用,因此您的应用程序将接收该事件并正常处理它,就像用户刚刚购买了应用内产品一样(从而“恢复”购买的功能)。

关于步骤 2 和 5,我为应用程序所做的就是保留一个名为“APP_INITIALISED”的 SharedPreference 值,该值默认为 false。每次我的应用程序启动时,如果“APP_INITIALISED”为 false,我会告诉 Google RESTORE_TRANSACTION(步骤 2),然后将 APP_INITIALISED 设置为 true(步骤 5)。

The typical flow is as follows:

  1. User installs your app.

  2. On first load of your app, you check if you need to restore
    purchases.

  3. If you do, send a RESTORE_TRANSACTION synchronous request to Google.

  4. Google will respond with a acknowlegment response to your
    RESTORE_TRANSACTION request. (This is only an acknowlegement that
    they received your request.)

  5. At this point, you should mark that you had already sent a restore request to Google and no further restores needs to be sent from the app.

  6. Now asynchronously Google will start sending a 'PURCHASE_STATE_CHANGED' event to your app for each in-app purchase the user has previously purchased. This call is the same as what Google would had sent if the user had made that purchase for the first time.

  7. Since it's the same call, your app would pick up the event and handled it normally as if the user has just purchased the in-app product (thereby "restoring" the purchased feature).

In regard to steps 2 and 5, what I've done for my app is to keep a SharedPreference value called 'APP_INITIALISED' that defaults to false. Everytime my app starts up, if 'APP_INITIALISED' is false, I tell Google to RESTORE_TRANSACTION (step 2) then I set APP_INITIALISED to true (step 5).

櫻之舞 2024-12-19 19:37:57

我不确定,但我认为,在调用restoreTransactions()之后,将使用已购买物品的id调用onPurchaseStateChange。

I'm not sure, but i think, after call restoreTransactions() will be call onPurchaseStateChange with ids of purchaised items.

筱果果 2024-12-19 19:37:57

我使用了这个方法:

public static void restoreTransactionInformation(Long nonce){
    if (amIDead()) 
    {
        return;
    }
    Log.i(TAG, "confirmTransaction()");
    Bundle request = makeRequestBundle("RESTORE_TRANSACTIONS");
    // The REQUEST_NONCE key contains a cryptographically secure nonce (number used once) that you must generate
    request.putLong("NONCE", nonce);
    try 
    {
        Bundle response = mService.sendBillingRequest(request);

        //The REQUEST_ID key provides you with a unique request identifier for the request
        Long requestIndentifier     = (Long) response.get("REQUEST_ID");
        Log.i(TAG, "current request is:" + requestIndentifier);

        //The RESPONSE_CODE key provides you with the status of the request
        Integer responseCodeIndex   = (Integer) response.get("RESPONSE_CODE");
        C.ResponseCode responseCode = C.ResponseCode.valueOf(responseCodeIndex);
        Log.i(TAG, "RESTORE_TRANSACTIONS Sync Response code: "+responseCode.toString());
    } 
    catch (RemoteException e) 
    {
        Log.e(TAG, "Failed, internet error maybe", e);
        Log.e(TAG, "Billing supported: " + isBillingSupported());
    }
}

通过使用调用它

BillingHelper.restoreTransactionInformation(BillingSecurity.generateNonce());

I used this method:

public static void restoreTransactionInformation(Long nonce){
    if (amIDead()) 
    {
        return;
    }
    Log.i(TAG, "confirmTransaction()");
    Bundle request = makeRequestBundle("RESTORE_TRANSACTIONS");
    // The REQUEST_NONCE key contains a cryptographically secure nonce (number used once) that you must generate
    request.putLong("NONCE", nonce);
    try 
    {
        Bundle response = mService.sendBillingRequest(request);

        //The REQUEST_ID key provides you with a unique request identifier for the request
        Long requestIndentifier     = (Long) response.get("REQUEST_ID");
        Log.i(TAG, "current request is:" + requestIndentifier);

        //The RESPONSE_CODE key provides you with the status of the request
        Integer responseCodeIndex   = (Integer) response.get("RESPONSE_CODE");
        C.ResponseCode responseCode = C.ResponseCode.valueOf(responseCodeIndex);
        Log.i(TAG, "RESTORE_TRANSACTIONS Sync Response code: "+responseCode.toString());
    } 
    catch (RemoteException e) 
    {
        Log.e(TAG, "Failed, internet error maybe", e);
        Log.e(TAG, "Billing supported: " + isBillingSupported());
    }
}

Call this by using

BillingHelper.restoreTransactionInformation(BillingSecurity.generateNonce());
尘曦 2024-12-19 19:37:57

我会证明 @Frank Leigh 的答案,并修改为所有购买都在一个 PURCHASE_STATE_CHANGED,签名数据如下

signedData:{

    "nonce":1234*,
    "orders":[
         {
         "orderId":"1234*.1234*",
         "packageName":"com.*",
         "productId":"**p1**",
         "purchaseTime":time,
         "purchaseState":0,
         "purchaseToken":"*"
        },
        {
         "orderId":"1234*.1234*",
         "packageName":"com.*",
         "productId":"**p2**",
         "purchaseTime":time,
         "purchaseState":0,
         "purchaseToken":"*"
        },
        {
         "orderId":"1234*.1234*",
         "packageName":"com.*",
         "productId":"**p3**",
         "purchaseTime":time,
         "purchaseState":0,
         "purchaseToken":"*"
        }
    ]
}

I would attest @Frank Leigh's answer with an edit that all the purchases come in one PURCHASE_STATE_CHANGED, with signed data as follows

signedData:{

    "nonce":1234*,
    "orders":[
         {
         "orderId":"1234*.1234*",
         "packageName":"com.*",
         "productId":"**p1**",
         "purchaseTime":time,
         "purchaseState":0,
         "purchaseToken":"*"
        },
        {
         "orderId":"1234*.1234*",
         "packageName":"com.*",
         "productId":"**p2**",
         "purchaseTime":time,
         "purchaseState":0,
         "purchaseToken":"*"
        },
        {
         "orderId":"1234*.1234*",
         "packageName":"com.*",
         "productId":"**p3**",
         "purchaseTime":time,
         "purchaseState":0,
         "purchaseToken":"*"
        }
    ]
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文