EconomyAppleAppStorePurchaseFailedException: Purchase receipt invalid

My code goes along those lines

public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
{
    [...]
        var realMoneyPurchaseId = (await EconomyService.Instance.Configuration.GetRealMoneyPurchasesAsync()).Find(def => def.StoreIdentifiers.AppleAppStore == purchaseId).Id;
        var receipt = args.purchasedProduct.receipt;
        var price = Mathf.RoundToInt((float)args.purchasedProduct.metadata.localizedPrice * 100);
        var currencyCode = args.purchasedProduct.metadata.isoCurrencyCode;
        var result = await EconomyService.Instance.Purchases.RedeemAppleAppStorePurchaseAsync(new RedeemAppleAppStorePurchaseArgs(realMoneyPurchaseId, receipt, price, currencyCode));
    [...]
        return PurchaseProcessingResult.Complete;
}

And I’m receiving an this error. The documentation clearly said that the receipt should be exactly what comes from the store, and it is. Am I missing something, or is it really a bug?

I’m using version 2.0.4 as recommended, so I could use GetRealMoneyPurchasesAsync.

Some prints from the editor. The JSON printed before the error is what receipt have. The behavior on the native app is the same, showing the editor for convenience.

Hi @Hiago_AD

You will need to send the payload as opposed to the entire receipt to the Redeem method. You should also take a look at the method you are using to calculate the price, not all currencies have 2 minor currency units, so it isn’t safe to assume you can multiply by 100.

These code snippets should give you some pointers.

    public class AppleReceipt
    {
        public string payload;
    }
  AppleReceipt ar = JsonConvert.DeserializeObject<AppleReceipt>(product.receipt);
               
  // Convert decimal currency value to int, to correctly handle currencies with <> 2 minor currecy units
  int localCurrencyInt = (int)AnalyticsService.Instance.ConvertCurrencyToMinorUnits(
      product.metadata.isoCurrencyCode,
      (double)product.metadata.localizedPrice);              

  // Redeem IAP
  RedeemAppleAppStorePurchaseArgs args = new RedeemAppleAppStorePurchaseArgs(
      ecomomyRealMoneyPurchase.Id,
      ar.payload,                   
      localCurrencyInt,
      product.metadata.isoCurrencyCode);

   RedeemAppleAppStorePurchaseResult result = await EconomyService.Instance.Purchases.RedeemAppleAppStorePurchaseAsync(args);

    // Player's currency balance updated on server if receipt valid
    Debug.Log($"IAP Purchase Success :: {result.Verification.Status}");

I hope that helps.

1 Like

This code helps a lot, but when I’m testing on native, the payload is a empty string. Is this because I’m on sandbox mode, or is it for some other reason?

If it is so, what’s the best way to test it? On the editor says that the item was already redeemed, and on the native app, the payload comes empty

OK, I’ve found the answer in the IAP forum. Thanks!

Hi @Hiago_AD

I’m glad you found the answer to your problem, can you perhaps share a link to it here?

It was this thread , basically I need to have the IAP published with an app update in iOS to have a valid receipt

awesome thanks for the help!