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

buySubscription returns E_UNKNOWN despite successful purchase #287

Closed
Gaia-Nutrition opened this issue Oct 13, 2018 · 30 comments
Closed

buySubscription returns E_UNKNOWN despite successful purchase #287

Gaia-Nutrition opened this issue Oct 13, 2018 · 30 comments
Labels
🐛 bug Something isn't working 📱 iOS Related to iOS

Comments

@Gaia-Nutrition
Copy link

Version of react-native-iap

2.2.2 (because any newer version fails on iOS due to #279)

Platforms you faced the error (IOS or Android or both?)

iOS

Expected behavior

No error should be thrown. Purchase was successful (live and in production)

Actual behavior

E_UNKNOWN error is returned from Promise
Our Sentry.io error tracking reports this:

{"framesToPop":1,"code":"E_UNKNOWN","nativeStackIOS":["0   LuCoaching                          0x000000010062f6fc LuCoaching + 1996540","1   LuCoaching                          0x000000010060aa98 LuCoaching + 1845912","2   LuCoaching                          0x00000001007cad98 __cxa_throw + 438380","3   LuCoaching                          0x00000001007cc62c __cxa_throw + 444672","4   libdispatch.dylib                   0x000000019d078484 <redacted> + 16","5   libdispatch.dylib                   0x000000019d025610 <redacted> + 56","6   LuCoaching                          0x00000001007cc46c __cxa_throw + 444224","7   libdispatch.dylib                   0x000000019d0776c8 <redacted> + 24","8   libdispatch.dylib                   0x000000019d078484 <redacted> + 16","9   libdispatch.dylib                   0x000000019d0249ec <redacted> + 1068","10  CoreFoundation                      0x000000019d5ce1bc <redacted> + 12","11  CoreFoundation                      0x000000019d5c9084 <redacted> + 1964","12  CoreFoundation                      0x000000019d5c85b8 CFRunLoopRunSpecific + 436","13  GraphicsServices                    0x000000019f83c584 GSEventRunModal + 100","14  UIKitCore                           0x00000001ca444bc8 UIApplicationMain + 212","15  LuCoaching                          0x000000010044d110 LuCoaching + 20752","16  libdyld.dylib                       0x000000019d088b94 <redacted> + 4"],"userInfo":{"NSLocalizedDescription":"Verbindung mit iTunes Store nicht möglich"},"domain":"SKErrorDomain","line":26,"column":1877,"sourceURL":"/var/containers/Bundle/Application/818C8439-E250-42E8-AD57-EC4FB5FE5547/LuCoaching.app/main.jsbundle"}

Tested environment (Emulator? Real Device?)

Real Device. Live customers. Very consistenlty fails

Steps to reproduce the behavior

When testing the procedure with Sandbox users the error cannot be reproduced.

@JJMoon JJMoon added 📱 iOS Related to iOS 🐛 bug Something isn't working labels Oct 14, 2018
@JJMoon
Copy link
Contributor

JJMoon commented Oct 15, 2018

@Gaia-Nutrition Would you check this old-issue? It' might be same cause.
#201

@Gaia-Nutrition
Copy link
Author

Gaia-Nutrition commented Oct 15, 2018

@JJMoon in #201 the error was E_DEVELOPER_ERROR and was caused by not populating the validProducts list using getSubscriptions().
However, I am calling the function before trying to perform the checkout and I also get a different error.
But now that I think about it. It could happen that there is quite some time delay between the getSubscriptions() and buySubscription() call caused by the user reconsidering if he/she wants to perform the purchase. Could this be an issue? The app might have been backgrounded in the meantime.
EDIT: But then again the purchase is executed successfully so the issue must be where the app store response is being processed

@Jerome91410
Copy link

Hello,

Same issue behavior with "buyProductWithoutFinishTransaction" or "buyProduct".

Version 2.2.1

the return stored is
{ "framesToPop": 1, "code": "E_UNKNOWN", "nativeStackIOS": [...], "userInfo": { "NSLocalizedDescription": "Connexion à l’iTunes Store impossible" }, "domain": "SKErrorDomain", "line": 16, "column": 1599, "sourceURL": "..." }

We updated the module because we reproduce this bug on production with previous versions .

@fierysolid
Copy link
Contributor

fierysolid commented Oct 16, 2018

The interesting part is that the restore purchase also fails for my users when this happens. It only happens to about 1% of our iOS users.

@Jerome91410
Copy link

@fierysolid Same case , we are around 5% of purchases on iOS who failed. When the customer try to buy again, he has a restore purchase pop up.

@hyochan
Copy link
Member

hyochan commented Oct 24, 2018

Hi everyone. I hope it is fixed in our new version today which is 2.3.15. I've have noticed that using NSDictionaryin ios purely is not safe to use and may cause unexpected behavior. I've fixed this and hope now it works ok in every device. Please test this out.

@hyochan
Copy link
Member

hyochan commented Oct 24, 2018

Please reopen when still facing the problem.

@hyochan hyochan closed this as completed Oct 24, 2018
@danrevah
Copy link

danrevah commented Oct 26, 2018

@dooboolab
I still get this issue while using buySubscription() with a sandbox tester user with iPhone 6S.

{"userInfo":{"NSLocalizedDescription":"Cannot connect to iTunes Store"}}

@hyochan
Copy link
Member

hyochan commented Oct 26, 2018

@danrevah So you've tried our new version which is 2.3.15? @JJMoon Can you please test this one more time?

@danrevah
Copy link

@dooboolab yes Im using that version.

@hyochan
Copy link
Member

hyochan commented Oct 26, 2018

@danrevah Please try 2.3.16.

@danrevah
Copy link

danrevah commented Oct 27, 2018

@dooboolab it worked once, but while I tried again I kept getting this errors. (used v 2.3.17)

@hyochan
Copy link
Member

hyochan commented Oct 27, 2018

@JJMoon Do you have any clue on this? he is using iPhone6S

@hyochan hyochan reopened this Oct 28, 2018
@hyochan
Copy link
Member

hyochan commented Oct 28, 2018

I've reopened the issue. cc @JJMoon

If more people votes to this issue, we will try harder to dig this more deeply.

@JJMoon
Copy link
Contributor

JJMoon commented Oct 28, 2018

@danrevah I hope you to refer to this document.
https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/StoreKitGuide/Chapters/Subscriptions.html#//apple_ref/doc/uid/TP40008267-CH7-SW6
To test subscription in sandbox mode, you need to re-purchase subscription after some time.
And you might need to cancel it to purchase again.
And there are some weird reactions from Apple sandbox server, which makes the test more difficult.

@hyochan
Copy link
Member

hyochan commented Oct 28, 2018

If @JJMoon case is the problem we may close this again. Please reopen if you still needs help on this one. @danrevah

@yasirsalim22
Copy link

yasirsalim22 commented Dec 13, 2018

@JJMoon I have faced the same issue. any solution? buySubscription throws exception and yet payment is deducted. I need to have results data to store and validate them.
@hyochans

@cbfranca
Copy link

cbfranca commented Feb 7, 2019

+1 I've the same problem

@hyochan
Copy link
Member

hyochan commented Feb 7, 2019

Try using addAdditionalSuccessPurchaseListenerIOS in buySubscription also. This is same issue as in #307.

@cbfranca
Copy link

cbfranca commented Feb 8, 2019

Try using addAdditionalSuccessPurchaseListenerIOS in buySubscription also. This is same issue as in #307.

Has someone already using in production ?

@cbfranca
Copy link

cbfranca commented Feb 11, 2019

@hyochan , I've tried to do that but without success.

if (subscription && subscription.success) {
      this.props.subscribe(subscription.result);
    } else {
      if (Platform.OS === 'ios') {
        const sub = RNIap.addAdditionalSuccessPurchaseListenerIOS(async (purchase) => {
          this.props.subscribe(purchase); // -> This code is never fired
          sub.remove();
        });
      }
    }

@hyochan
Copy link
Member

hyochan commented Feb 11, 2019

@cbfranca Please follow the actual code. You are not even using promises. You should listen to addAdditionalSuccessPurchaseListenerIOS after the promise rejection.

Also you do not need extra Platform.OS === 'ios'.

@cbfranca
Copy link

cbfranca commented Feb 11, 2019

@hyochan
Sorry for my ignorance, but I do not think I understood correctly. I followed the same bases of the example, suiting my scenario. I created an abstraction that treats this promise using async / await. This subscription object is returned by my abstraction.

static purchaseSubscription(newSubscriptionID, currentSubscriptionID) {
    if (Platform.OS === 'ios') {
      const purchaseResult = KinvoBilling.purchaseSubscriptionIOS(newSubscriptionID);
      return purchaseResult;
    }

    const purchaseResult = KinvoBilling.purchaseSubscriptionANDROID(newSubscriptionID, currentSubscriptionID);
    return purchaseResult;
  }

  static purchaseSubscriptionANDROID = async (newSubscriptionID, currentSubscriptionID) => {
    const hasCurrentSubscription = currentSubscriptionID !== null;

    if (hasCurrentSubscription) {
      const purchaseResult = KinvoBilling.updateSubscription(newSubscriptionID, currentSubscriptionID);
      return purchaseResult;
    }
    const purchaseResult = KinvoBilling.buySubscription(newSubscriptionID);
    return purchaseResult;
  }

  static purchaseSubscriptionIOS = async (subscriptionID) => {
    await KinvoBilling.getSubscriptions();
    const purchaseResult = await KinvoBilling.buySubscription(subscriptionID);

    return purchaseResult;
}

@hyochan
Copy link
Member

hyochan commented Feb 12, 2019

@cbfranca

static purchaseSubscriptionIOS = async (subscriptionID) => {
    await KinvoBilling.getSubscriptions();
    try {
      const purchaseResult = await KinvoBilling.buySubscription(subscriptionID);
    } catch (err) {
     const subscription = RNIap.addAdditionalSuccessPurchaseListenerIOS(async (purchase) => {
        // dooboolab => check the call here.
        this.setState({ receipt: purchase.transactionReceipt }, () => this.goToNext());
        subscription.remove();
     }
    }
    return purchaseResult;
}

Check above code. I think you need to refactor your code to fit its lifecycle.

@cbfranca
Copy link

@hyochan Not works for me.

My test cenario is:

  • Purchase the monthly subscription plan - Ok
  • Upgrade to annual subscription plan - Fails and listener not working

Another doubt: Do I have to use finishTransaction() in subscriptions too ?

@gerbus
Copy link
Contributor

gerbus commented Mar 17, 2019

I'm seeing this error too. And I think I know one way to reproduce it.

Version of react-native-iap

^2.4.1

Version of react-native

https://github.com/expo/react-native/archive/sdk-32.0.0.tar.gz

Platform

iOS, when testing in TestFlight on a real device.

Observations

I noticed that when any RNIap functions were called in my app, iOS would ask me to enter a password for a previous iTunes/App Store user (which I have since logged out and replaced via iOS Settings). I read somewhere online that this is an issue that dogs iPhone users from time to time: sometimes an app is bought with one iTunes account, then the phone is switched to a new iTunes account, but the app continues to ask for the password for the old iTunes account.

I tried to delete my app (and TestFlight) and reinstall with the new App Store user, to no avail. The only way I could get rid of this behavior was to wipe the device. Once I did this, I could no longer reproduce this error.

Actual Behavior

  1. buySubscription()
  2. Select Continue when presented with iOS modal "Subscription Terms"
  3. Select OK when presented with iOS modal "Confirm Subscription"
  4. Error thrown by buySubscription():
{
   code: E_UNKNOWN, 
   column: 1565, 
   domain: NSURLErrorDomain, 
   framesToPop: 1, 
   line: 20, 
   nativeStackIOS: [...],
   sourceURL: ...,
   userInfo: {
      _kCFStreamErrorCodeKey: -4, 
      _kCFStreamErrorDomainKey: 4, 
      NSErrorFailingURLKey: None, 
      NSErrorFailingURLStringKey: https://p100-sandbox.itunes.apple.com/WebObjects/MZFinance.woa/wa/inAppBuy, 
      NSLocalizedDescription: Cannot connect to iTunes Store, 
      NSUnderlyingError: {
         code: "-1005", 
         domain: "kCFErrorDomainCFNetwork", 
         message: "underlying error", 
         nativeStackIOS: [...],
         userInfo:{"NSErrorPeerAddressKey":null,"_kCFStreamErrorCodeKey":-4,"_kCFStreamErrorDomainKey":4}
      }
   }
}

Steps to reproduce the behavior

  1. Create a test user in App Store Connect
  2. Install app from App Store (or invite test user to TestFlight and install TestFlight and then app through TestFlight)
  3. Purchase a subscription in app
  4. Let the subscription expire
  5. Logout iOS Apple ID (Settings > Apple ID, Sign Out)
  6. Login new Apple ID
  7. Purchase a subscription in app

Hope this helps someone!

@cbfranca
Copy link

cbfranca commented Apr 23, 2019

@hyochan

After trying many things I'm still with the same problem and more. At code bellow, the RNIap.buySubscription(sku) returns undefined. Please, did someone solve it?

static purchaseSubscriptionIOS = async (subscriptionID) => {
  await KinvoBilling.getSubscriptions();

  try {
    const purchaseResult = await RNIap.buySubscription(subscriptionID);
    return createResponse(true, purchaseResult);
  } catch (error) {
    const subscription = RNIap.addAdditionalSuccessPurchaseListenerIOS(async (purchase) => {
      // dooboolab => check the call here.
      console.tron.log('--- ERROR ----');
      console.tron.log(error);
      console.tron.log('--- PURCHASE ----');
      console.tron.log(purchase);
      const result = purchase;
      subscription.remove();
      console.tron.log(result);

      if (result) {
        return createResponse(true, result);
      }
      return createResponse(false, result);
    });
  }
};

@dphaener
Copy link

dphaener commented Sep 9, 2019

👍 We are experiencing this issue was well. It seems to be happening to about 10% of our users currently. We're going to try adding this listener, but I don't think that ultimately this is a great solution. @hyochan Is there any way we can get more detailed information in the cases where this throws, or is that a standard response from the StoreKit APIs? In every error case the message seems to be "Cannot connect to iTunes Store", even when the purchase is successful.

@drbarto
Copy link

drbarto commented Sep 14, 2019

We have a very similar problem with 3.4.6: 1st purchase attempt fails with E_UNKOWN, retrying succeeds. However, for us this happens with buyProduct, not with buySubscription. @hyochan could this still be the same root cause?

@agusvazquez
Copy link

agusvazquez commented Nov 15, 2019

Hello! I'm experiencing the same issue after calling RNIap.requestSubscription() I get an undefined result but the payment succeeds, the credit card is charged.

The only way of that user to get it past is by restoring the purchase.

Did anyone got a fix for this? I'm using version 3.5.9

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🐛 bug Something isn't working 📱 iOS Related to iOS
Projects
None yet
Development

No branches or pull requests