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

Purchased items have incorrect information #89

Closed
EdwardCaulfield opened this issue Oct 22, 2017 · 7 comments
Closed

Purchased items have incorrect information #89

EdwardCaulfield opened this issue Oct 22, 2017 · 7 comments

Comments

@EdwardCaulfield
Copy link

EdwardCaulfield commented Oct 22, 2017

If you are creating an issue for a BUG please fill out this information. If you are asking a question or requesting a feature you can delete the sections below.

Failure to fill out this information will result in this issue being closed. If you post a full stack trace in a bug it will be closed, please post it to http://gist.github.com and then post the link here.

Bug Information

Version Number of Plugin: 1.2.3.107
Device Tested On: iPhone 5, iOS 11.0.3
Simulator Tested On:
Version of VS: 7.2 (build 636)
Version of Xamarin:
Versions of other things you are using:

SkiSharp 1.59.1
Xam.Plugins.Settings 3.1.1
Xamarin.Google.iOS.MobileAds 7.21.0

Steps to reproduce the Behavior

Purchase newly created subscription once

Expected Behavior

Call to GetPurchasesAsync returns only one purchase of subscription item with correct purchase date and time

Actual Behavior

Calls to GetPurchasesAsync return sometimes 6, sometimes 7 instances of purchase with the date September 12, 2017 at 6:09:17 PM. However, the item was created on October 22, 2017 and purchased once on October 22, 2017.

It is noteworthy that the date September 12, 2017 is the date that another subscription item, 005_Advanced_Features, was actually purchased. This item shows sometimes 51, sometimes 52 successful purchases with the date September 12, 2017 at 6:09:17 PM.

The product '005_Advanced_Features' has been bought 51 times
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
Purchased 005_Advanced_Features on 9/12/2017 6:09:17 PM
The product '00_Subscription_Testing' has been bought 6 times
Purchased 00_Subscription_Testing on 9/12/2017 6:09:17 PM
Purchased 00_Subscription_Testing on 9/12/2017 6:09:17 PM
Purchased 00_Subscription_Testing on 9/12/2017 6:09:17 PM
Purchased 00_Subscription_Testing on 9/12/2017 6:09:17 PM
Purchased 00_Subscription_Testing on 9/12/2017 6:09:17 PM
Purchased 00_Subscription_Testing on 9/12/2017 6:09:17 PM

I have rebooted my development system, removed the App and rebooted my iPhone, but always get the same results.

Code snippet

    public static async void Restore_Purchased_Items(bool pExecute_Quietly = false)
	{
        bool mLocal_Debug = true;

        if (Application_Parameters.Using_Simulator || !CrossInAppBilling.IsSupported)
            return;

        if(_Store_Is_Connected)
        {
            if (!pExecute_Quietly)
                HomePage.Display_Fatal_Error(String_Definitions.Error_Store_Already_Connected);

            return;
        }
        
		var mBilling = CrossInAppBilling.Current;

		int mRestore_Count = 0;
		try
		{
            _Store_Is_Connected = await mBilling.ConnectAsync();

            if (!_Store_Is_Connected)
			{
				Display_Connection_Failure();
                return;
			}

			//check purchases
			var purchases = await mBilling.GetPurchasesAsync(ItemType.InAppPurchase);

			for (int i = 0; i < String_Definitions.Purchaseable_Items.Length; i++)
			{

                var mPurchases = purchases.Where(p => (p.ProductId == String_Definitions.Purchaseable_Items[i]) && (p.State == PurchaseState.Purchased));

                Debug.WriteLineIf(mLocal_Debug, string.Format("The product '{0}' has been bought {1} times", mPurchases.First().ProductId, mPurchases.Count()));

                foreach ( InAppBillingPurchase purchase in mPurchases)
                    //     purchases.Where(
                    //p => (( p.ProductId == String_Definitions.Purchaseable_Items[i])) && ( p.State != PurchaseState.Failed) ))
                {
					mRestore_Count++;
					Enable_Function(i, purchase);
                    Debug.WriteLineIf(mLocal_Debug, string.Format("Purchased {0} on {1}", purchase.ProductId, purchase.TransactionDateUtc.ToLocalTime().ToString()));
					if (!pExecute_Quietly)
						HomePage.Display_Non_Fatal_Error(String_Definitions.Title_Store_Message,
													 string.Format(String_Definitions.Message_Product_Restored_1_Arg, String_Definitions.Purchaseable_Item_Names[i]),
													 String_Definitions.Response_Button_Text_Okay);

				}

			}
            if (!pExecute_Quietly)
            {
				if (mRestore_Count == 0)
					HomePage.Display_Non_Fatal_Error(String_Definitions.Title_Store_Message,
													  String_Definitions.Message_No_Products_Restored, String_Definitions.Response_Button_Text_Okay);
				else
					HomePage.Display_Non_Fatal_Error(String_Definitions.Title_Store_Message,
													  string.Format(String_Definitions.Message_Product_Restore_Summary_2_Args, mRestore_Count,
																	mRestore_Count == 1 ? "" : String_Definitions.Final_S), String_Definitions.Response_Button_Text_Okay);
			}

		}
		catch (InAppBillingPurchaseException pRestore_Exception)
		{
            //Billing Exception handle this based on the type
            if (!pExecute_Quietly)
                HomePage.Display_Non_Fatal_Error(String_Definitions.Title_Store_Error,
											 String_Definitions.Error_Restore_Failed + String_Definitions.Message_Prefix + pRestore_Exception.Message,
											 String_Definitions.Response_Button_Text_Cancel);
		}
		catch (Exception pRestore_Exception)
		{
            //Something has gone wrong
            if (!pExecute_Quietly)
				HomePage.Display_Non_Fatal_Error(String_Definitions.Title_Store_Error,
											 String_Definitions.Error_Restore_Failed + String_Definitions.Message_Prefix + pRestore_Exception.Message,
											 String_Definitions.Response_Button_Text_Cancel);
		}
		finally
		{
            if(mBilling != null)
            {
				await mBilling.DisconnectAsync();
                _Store_Is_Connected = false;
				//CrossInAppBilling.Dispose();

			}
		}


        return ;
	}
	public static async Task<bool> Buy_Feature(int pFeature_ID)
	{
        if (Application_Parameters.Using_Simulator || !CrossInAppBilling.IsSupported)
            return false;

        if (_Store_Is_Connected)
        {
            HomePage.Display_Fatal_Error(String_Definitions.Error_Store_Already_Connected);
            return false;

        }

		try
		{

            _Store_Is_Connected = await CrossInAppBilling.Current.ConnectAsync();

            if (!_Store_Is_Connected)
			{
                //Couldn't connect to billing, could be offline, alert user
				Display_Connection_Failure();

				return false;
			}

			//try to purchase item
			var purchase = await CrossInAppBilling.Current.PurchaseAsync(String_Definitions.Purchaseable_Items[pFeature_ID], ItemType.InAppPurchase, String_Definitions.App_Payload);
			if (purchase == null)
			{
				HomePage.Display_Non_Fatal_Error(String_Definitions.Title_Store_Error,
												  String_Definitions.Error_Purchase_Failed,
												  String_Definitions.Response_Button_Text_Cancel);

				return false;
			}
			else
			{
				//Purchased, save this information
				//string id = purchase.Id;
				//string token = purchase.PurchaseToken;
				//var state = purchase.State;

                Enable_Function(pFeature_ID, purchase);

				return true;
			}

		}
		catch (InAppBillingPurchaseException pPurchase_Exception)
		{
			Global_Functions.Display_Purchase_Exception(pPurchase_Exception);
			return false;
		}
		catch (Exception ex)
		{
            //Something else has gone wrong, log it
            Debug.WriteLine("Issue connecting: " + ex.Message);

			return false;
		}
		finally
		{
			//Disconnect, it is okay if we never connected
			await CrossInAppBilling.Current.DisconnectAsync();
            _Store_Is_Connected = false;

			CrossInAppBilling.Dispose();
		}

	}

Screenshots

@EdwardCaulfield
Copy link
Author

I moved the plugin into my project and debugged the code. In the function ToIABPurchase you have the statement

		var p = transaction?.OriginalTransaction ?? transaction;

For whatever odd reason, the OriginalTransaction.TransactionDate is always returning the same date of 9/12/2017 6:09:17 PM. However, if I don't go to the original transaction, but stay with the root transaction, the correct date and time are stored. In ToIABPurchase I changed the line:

           TransactionDateUtc = NSDateToDateTimeUtc(p.TransactionDate),

to:
TransactionDateUtc = NSDateToDateTimeUtc(transaction.TransactionDate),

and it now works correctly. Because you already return prior to this assignment if p is null, then this should work fine.

Intuitively, I would have thought that the date held in the OriginalTransaction structure would be the date the transaction originally occurred, but unfortunately it is not.

Curious to hear your thoughts on the matter.

Best Regards,

Edward

@jamesmontemagno
Copy link
Owner

If you send a PR down that will help me debug it.

@EdwardCaulfield
Copy link
Author

EdwardCaulfield commented Dec 9, 2017 via email

@EdwardCaulfield
Copy link
Author

Downloaded code and fixed issue.

@prashantvc
Copy link
Collaborator

prashantvc commented Dec 19, 2017

@EdwardCaulfield You can find the instructions to send a pull request here https://help.github.com/articles/creating-a-pull-request/ :)

@EdwardCaulfield
Copy link
Author

EdwardCaulfield commented Dec 20, 2017 via email

@jamesmontemagno
Copy link
Owner

I integrated into latest

@ghost ghost removed the triaged label Jan 6, 2018
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

3 participants