Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to do Buy+Consume #1

Open
HelmuthWcs opened this issue Apr 5, 2013 · 9 comments
Open

How to do Buy+Consume #1

HelmuthWcs opened this issue Apr 5, 2013 · 9 comments

Comments

@HelmuthWcs
Copy link

Hi, I'm heaving troubling implementing a consumable IAP. Your sample shows how to do a purchase and a "consume" on two different events. I'm trying to chain a buy request with a consume request, but I'm getting errors saying that the product has not been bought even if that product was purchased successfully.

Even your demo doesn't work if I "buy Item_2" and then "consume item 2". I have to "query purchases" before consuming to make it work.

I'm also having trouble releasing the BillingService. If I call m_service.Dispose(); in Activity.Destroy I get an Java.Lang.IllegalArgumentException: Service not registered: play.billing.v3.BillingService@4052d918. I'm trying to do this because after leaving the store activity I'm getting leak warning messages.

Thanks,
Helmuth

@ddebilt
Copy link
Owner

ddebilt commented Apr 5, 2013

Hi @HelmuthWcs

I haven't fully tested the consume functionality yet, as I have just needed to use the regular purchase functionality in other apps that I am working on. I will take a look into it this weekend, as well as the disposal issue.

ddebilit

@onomasticon
Copy link

Did this ever get resolved? I've run into the same issue as the OP.

@karios
Copy link

karios commented Jul 8, 2013

Same issue here. I would love to know everybody's thoughts on that. I was thinking about setting a timed event to try and consume possible purchases by querying them at specific intervals, since chaining a purchase and consume has proven to be tricky. Any ideas?

@ddebilt
Copy link
Owner

ddebilt commented Jul 8, 2013

Sorry, I haven't been able to spend any time on this, but I will take a look at this issue by the end of this week, since I will need this for an upcoming project. I will re-post with any additional findings.

@ddebilt
Copy link
Owner

ddebilt commented Jul 10, 2013

The "Buy Item" code was not adding the purchased item to the inventory on success. Fixing that allows the chaining to work. I also changed the "Get Purchases" code to split up what is valid and what is not valid, rather than failing the entire request if something was not valid (didn't pass signature).

The service leak is also fixed. I was trying to unbind the play billing service from the MainActivity, rather than the BillingService object (IServiceConnection implementation).

Give it a try and let me know if I can close this out.

@karios
Copy link

karios commented Jul 10, 2013

I still have an issues with chaining the thing. When I use:

var req = new Buy(sku, m_requestId++);
m_service.SendRequest(req).ContinueWith(t => gameActivity.RunOnUiThread(() =>
{
if (t.Result.Success)
{

and the SendRequest is successful, the ContinueWith never runs (so it never goes to if (t.Result.Success). If it fails (for example, the item is already owned) it does run. This essentially means that the user has to click the "buy" button once to buy the item and then click it again, to make the task fail (because the item is already owned) and consume the item (since the ContinueWith works in that case).

@ddebilt
Copy link
Owner

ddebilt commented Jul 10, 2013

@karios Are you able to confirm that OnActivityResult is getting invoked after you successfully purchase the item through the intent GUI? (perhaps put in a Toast or Log that can be seen).

Specifically, once OnActivityResult is invoked on your activity, the BillingService's HandleActivityResult method will get invoked, and the previously requested Buy's task will get its result set, which then should trigger the ContinueWith.

I won't be able to try this out again until later today, tomorrow at the latest, but will try as I suggested as well. I was able to do a sequential Buy - Consume - Buy - Consume, but it was not based on the Buy success tasks (rather it was just checking current inventory), so I will try your route as well.

@HelmuthWcs
Copy link
Author

To successfully consume a purchase I was able to implement it into BillingService.cs in the HandleActivityResult method passing in my store activity to handle the successful purchase and consume it:

public bool HandleActivityResult(int requestCode, int resultCode, Intent data, Store store)
{
...
try
{
var item = new Purchase(buyReq.ItemType, purchaseData, dataSignature);
string sku = item.Sku;

    // Verify signature
    if (!Security.VerifyPurchase(this.AppKey, purchaseData, dataSignature))
    {
        Utils.LogError("Purchase signature verification failed. SKU: " + sku);
        return true;
    }
    Utils.LogDebug("Purchase signature verification passed. SKU: " + sku);

            store.HandlePurchase(item);
}

...
In Store.cs (Activity):
public void HandlePurchase(Purchase purchaseID)
{
switch (purchaseID.Sku)
{
case "android.test.purchased":
ConsumeProduct(purchaseID);
...
private void ConsumeProduct(Purchase p)
{
System.Diagnostics.Debug.WriteLine("Attemping to consume: " + p.Sku);
m_service.SendRequest(new ConsumePurchase(p, m_requestId++)).ContinueWith(t => this.RunOnUiThread(() =>
{
if (t.Result.Success)
{
//p.Token?
m_service.CurrentInventory.ErasePurchase(p.Sku);
_status.Text = "Consume complete.";
System.Diagnostics.Debug.WriteLine("Consume OK");
}
else
{
System.Diagnostics.Debug.WriteLine("Consume failure. Error: " + t.Result.Message);
_status.Text = "Consume failure. Error: " + t.Result.Message;
}
}));
}

I hope this helps

@karios
Copy link

karios commented Jul 11, 2013

I think I got it in the end. I had a huge problem when I was calling m_service.SendRequest, with the OnActivityResult being called immediately with USER_CANCELLED. I think I fixed this by using LaunchMode = LaunchMode.SingleTask on the game Activity. Previously I was using LaunchMode = LaunchMode.SingleInstance and it seemed like it was causing this issue.
Seems to work now. I am trying to buy and it waits until I complete or cancel the action before proceeding. The function that works for me (and launches a boolean Action if the purchase was successful) is the following:

public static void SendBuyRequest(string sku, bool consumable, Action result)
{
var req = new Buy(sku, m_requestId++);
m_service.SendRequest(req).ContinueWith(t =>
{
mainGameActivity.RunOnUiThread(() =>
{
if (t.Result.Success)
{
System.Diagnostics.Debug.WriteLine("Purchase complete. Item: " + req.Sku);
if (consumable)
{
consume(sku);
}
}
else
{
System.Diagnostics.Debug.WriteLine("Purchase failure. Error: " + t.Result.Message);
}
result(t.Result.Success);
});
});
}

I set the mainGameActivity at IAP initialization.
The way I call it is like this:

SendBuyRequest(sku, consumable, success =>
{
if (success)
{

}
});

I hope this helps someone.
A big thanx to ddebilt for their efforts:)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants