React-native-iap: getAvailablePurchases каждый раз возвращает разные массивы

Созданный на 9 авг. 2019  ·  13Комментарии  ·  Источник: dooboolab/react-native-iap

Версия react-native-iap

3.3.9 (но также встречается в 3.0.0 и ранее)

Версия react-native

0,59,9

Платформы, на которых вы столкнулись с ошибкой (IOS или Android или оба?)

iOS (не тестировалось на Android)

Ожидаемое поведение

Один и тот же массив каждый раз, когда я вызываю getAvailablePurchases
Одинаковая длина массива каждый раз

Фактическое поведение

Разный массив каждый раз, когда я вызываю getAvailablePurchases
Разная длина массива каждый раз, когда я вызываю getAvailablePurchases

Протестированная среда (Эмулятор? Настоящее устройство?)

Настоящее устройство

Шаги по воспроизведению поведения

Я думаю, что это видно только при большом количестве транзакций, но не могу это подтвердить. В моей учетной записи Sandbox 50+ транзакций.

handleOnPressRestore = async () => {
  return this.setState({ isLoadingRestorePurchases: true }, async () => {
    try {

      // Get the previous purchases of the current user
      const purchases = await RNIap.getAvailablePurchases();

      // Get the latest receipt from the purchases to validate
      const { transactionReceipt, productId, transactionDate } = this.getLatestPurchase(purchases);

      console.log(purchases.length, productId, transactionDate);

      // Validate the receipt on our server
      await this.props.validateSubscriptionReceipt(productId, transactionReceipt);

      // The validation result is handled in componentDidUpdate
    } catch (err) {
      throw err;
    } finally {
      this.setState({ isLoadingRestorePurchases: false });
    }
  });
}

getLatestPurchase = (purchases: RNIap.ProductPurchase[]): RNIap.ProductPurchase => {
  // First, sort the array, so the latest purchase is on top
  // https://github.com/dooboolab/react-native-iap/issues/532#issuecomment-503174711
  const sortedPurchases = purchases.sort((a, b) => b.transactionDate - a.transactionDate);

  const purchase = sortedPurchases[0];

  return purchase;
}

С помощью приведенного выше кода, когда я нажимаю «Восстановить покупку», я каждый раз получаю разные журналы:

Нажатие 6 раз "Восстановить покупку" с промежуточным ожиданием результатов:

// purchases.length, productId, transactionDate
9 "com.app.sub" 1565182529000
21 "com.app.sub" 1565181329000
22 "com.app.sub" 1565183001000
42 "com.app.sub" 1565183001000
53 "com.app.sub" 1565182529000
55 "com.app.sub" 1565183001000
15 "com.app.sub" 1565182529000

Я ожидал, что массив всегда будет одинаковым, верно? Что тут происходит?

Результат getAvailablePurchases() меняется каждый раз, когда я запускаю его

📱 iOS 🙏 help wanted 🚶🏻 stale

Самый полезный комментарий

Я также запустил цикл для всех транзакций и не смог удалить их с помощью finishTransactionIOS. Мои транзакции - это подписки с автоматическим продлением.

Все 13 Комментарий

Я тоже это вижу. На самом деле опасно то, что есть шанс, что самый последний действительный чек может не оказаться в результатах.

Глядя на код этого модуля, он честно выглядит как проблема со стороны Apple, поскольку этот модуль фактически просто передает все, что restoreCompletedTransactions() возвращает

Интересно, является ли getPurchaseHistory() хорошей альтернативой для подписок. В настоящее время я использую это как альтернативу, так как это дает мне надежные результаты. В моем приложении нет других покупок, только подписки.

Как указано в документации iap по этому пакету, getAvailablePurchases() говорит о расходных материалах. Подписка не является «расходным» или «нерасходуемым» продуктом. Это «автоматически возобновляемая подписка». Так что getPurchaseHistory() подойдут?

Screenshot 2019-08-16 at 18 11 13

Я обнаружил, что getPurchaseHistory () также дает разную длину массива. Казалось бы, на это повлияла частота запросов. В конце концов выяснилось, что для нас это не имело большого значения, поскольку после того, как какая-либо из квитанций о транзакциях была отправлена ​​на проверку, все квитанции были возвращены Apple в массиве latest_receipt_info любом случае, и это все, что имело для нас значение.

У меня такая же проблема (не знаю, ошибка ли это режима песочницы). Кроме того, когда я переключаю идентификатор Apple на реальном устройстве, возвращается покупка, сделанная с другой учетной записью.

Пример:
1 - Я совершил покупку через аккаунт [email protected]
2 - Идентификатор Apple изменен на
3 - getAvailablePurchases возвращает transactionId покупки, совершенной с помощью аккаунта [email protected]

Еще одна проблема, которую я обнаружил, заключается в том, что если я восстановлю устройство (сброс к заводским настройкам), оба метода getPurchaseHistory() и getAvailablePurchases дают случайные результаты.

Ответ Apple по поводу восстановления покупки:

"Users restore transactions to maintain access to content they've already purchased. For example, when they upgrade to a new phone, they don't lose all of the items they purchased on the old phone. Include some mechanism in your app to let the user restore their purchases, such as a Restore Purchases button."

Нашел тему на форумах разработчиков Apple о различных результатах restoreCompletedTransactions как было сказано ранее @ ssg-luke.

https://forums.developer.apple.com/thread/115242

Может быть, это связано:

Похоже, вы имеете в виду одного пользователя, имеющего много транзакций, для которых приложение еще не вызвало finishTransaction.
https://forums.developer.apple.com/thread/115242#thread -post-355444

У меня были другие учетные записи песочницы на том же устройстве. Так может быть, транзакции разных учетных записей на одном устройстве просто испорчены и вообще не «завершены»?

Однако я выполнил цикл для всех транзакций и вызвал finishTransactionIOS для всех из них. Но это не заставило их исчезнуть и не привело к надежному выводу getAvailablePurchases() ... Может быть, потому, что я уже использую новую учетную запись песочницы, а транзакции происходят из старой учетной записи песочницы?

Также можно объяснить, что испытывает @fcandiani .

Я обнаружил, что getPurchaseHistory () также дает разную длину массива. Казалось бы, на это повлияла частота запросов. В конце концов выяснилось, что для нас это не имеет особого значения: как только какие-либо квитанции о транзакциях были отправлены на проверку, все квитанции в любом случае возвращались Apple в массиве latest_receipt_info, а это все, что имело для нас значение.

Спасибо за информацию @ ssg-luke, я сделаю то же самое.

Я также запустил цикл для всех транзакций и не смог удалить их с помощью finishTransactionIOS. Мои транзакции - это подписки с автоматическим продлением.

Облицовка почти такая же. Я создавал проблему, но решил поместить здесь всю информацию, чтобы помочь другим найти проблему и решение.

Версия react-native-iap

3.5.9

Версия react-native

0,60,5

Платформы, на которых вы столкнулись с ошибкой (IOS или Android или оба?)

iOS

  • Тот же код отлично работает на Android, уже в производстве

Ожидаемое поведение

Пользователь подписался один раз , getAvailablePurchases должен вернуть только одну покупку

Фактическое поведение

getAvailablePurchases возвращает более одной покупки,

Протестированная среда (Эмулятор? Настоящее устройство?)

Настоящее устройство со свежей учетной записью в песочнице.

Шаги по воспроизведению поведения

  • Создайте тестового пользователя песочницы на https://appstoreconnect.apple.com/access/testers
  • Сборка и запуск проекта на xcode
  • Позвоните getAvailablePurchases , покупок не будет (как и ожидалось)
  • Подпишитесь на какой-нибудь продукт
  • вызывается мой purchaseUpdatedListener , и я вызываю RNIap.finishTransactionIOS(subscription.transactionId); который возвращает только undefined (как и ожидалось, я думаю)
  • Позвоните по getAvailablePurchases , вернет одну покупку (как и ожидалось)
  • Перезагрузить приложение
  • Вызов getAvailablePurchases возвращает две покупки , каждая с разными transactionId :
{
   originalTransactionDateIOS: 1571144840000
   originalTransactionIdentifierIOS: "1000000579413333"
   productId: "io.appmasters.lowcarb.development"
   transactionDate: 1571145019000
   transactionId: "1000000579415509"
   transactionReceipt: "MIIVnQYJKoZIhvcN..."
},
{
   originalTransactionDateIOS: 1571144840000
   originalTransactionIdentifierIOS: "1000000579413333"
   productId: "io.appmasters.lowcarb.development"
   transactionDate: 1571144839000
   transactionId: "1000000579416705"
   transactionReceipt: "MIIVnQYJKoZIhvcN...."
}
  • Перезагрузите приложение еще раз
  • Вызов getAvailablePurchases возвращает три покупки , каждая с разными transactionId (не совпадает с предыдущим результатом):
{
   originalTransactionDateIOS: 1571144840000
   originalTransactionIdentifierIOS: "1000000579413333"
   productId: "io.appmasters.lowcarb.development"
   transactionDate: 1571145739000
   transactionId: "1000000579423546"
   transactionReceipt: "MIIb1AYJKoZIhvcN..."
},{
   originalTransactionDateIOS: 1571144840000
   originalTransactionIdentifierIOS: "1000000579413333"
   productId: "io.appmasters.lowcarb.development"
   transactionDate: 1571145019000
   transactionId: "1000000579426352"
   transactionReceipt: "MIIb1AYJKoZI..."
},{
   originalTransactionDateIOS: 1571144840000
   originalTransactionIdentifierIOS: "1000000579413333"
   productId: "io.appmasters.lowcarb.development"
   transactionDate: 1571144839000
   transactionId: "1000000579426353"
   transactionReceipt: "MIIb1AYJKoZIhvcN..."
}
  • Перезагрузите приложение снова
  • Вызов getAvailablePurchases , возврат четырех покупок , каждая с разными transactionId (не совпадает с предыдущим результатом) ...

Это не кажется правильным поведением, исходя из того, что я читал в документации, и из того, что происходит на Android.

Я ценю любую помощь.

getAvaialblePurchases () возвращает 150+ результатов в моей тестовой учетной записи песочницы. Я решил вообще не использовать getAvailablePurchases () и просто сохранить последнюю покупку на устройстве, а также на сервере. Если приложение удалено или пользователь перешел на новый телефон, у нас все еще будет последняя покупка на нашем сервере, привязанная к идентификатору пользователя и платформе нашей компании (iOS или Android). Вызов getAvailablePurchases () занимает около минуты, а иногда вызывает этот запускающий слушатель покупок, обновленный, пытаясь восстановить несколько покупок. Мы изменили наш поток следующим образом:
1) Когда пользователь входит в систему:
а) посмотреть, есть ли на нашем сервере действительная последняя покупка для пользователя и платформы.
б) Если на сервере нет записи, посмотрите, есть ли локально сохраненная покупка в БД
c) Если их нет или истек срок действия, отобразить представление подписок.
Сначала мы вызывали getAvailablePurchases () и пытались узнать, действительна ли последняя покупка. Не уверен, что это помогает другим, но у нас больше нет проблем с этим. Мы реагируем 59, и это еще одна проблема, с которой нам приходится иметь дело.

@ramakula, а что если пользователь откажется от подписки?

Как вы сказали, вы сохраните подписку в своей базе данных до даты окончания и «увидите», что покупка больше не доступна.

Привет, похоже, в последнее время по этой проблеме не было никакой активности. Проблема устранена или все еще требует внимания сообщества? Эта проблема может быть закрыта, если больше не будет активности. Вы также можете пометить этот вопрос как «Для обсуждения» или «Хороший первый выпуск», и я оставлю его открытым. Спасибо за ваш вклад.

Закрытие этого вопроса после длительного периода бездействия. Если эта проблема все еще присутствует в последней версии, пожалуйста, создайте новую проблему с актуальной информацией.

getAvaialblePurchases () возвращает 150+ результатов в моей тестовой учетной записи песочницы. Я решил вообще не использовать getAvailablePurchases () и просто сохранить последнюю покупку на устройстве, а также на сервере. Если приложение удалено или пользователь перешел на новый телефон, у нас все еще будет последняя покупка на нашем сервере, привязанная к идентификатору пользователя и платформе нашей компании (iOS или Android). Вызов getAvailablePurchases () занимает около минуты, а иногда вызывает этот запускающий слушатель покупок, обновленный, пытаясь восстановить несколько покупок. Мы изменили наш поток следующим образом:

  1. Когда пользователь входит в систему:
    а) посмотреть, есть ли на нашем сервере действительная последняя покупка для пользователя и платформы.
    б) Если на сервере нет записи, посмотрите, есть ли локально сохраненная покупка в БД
    c) Если их нет или истек срок действия, отобразить представление подписок.
    Сначала мы вызывали getAvailablePurchases () и пытались узнать, действительна ли последняя покупка. Не уверен, что это помогает другим, но у нас больше нет проблем с этим. Мы реагируем 59, и это еще одна проблема, с которой нам приходится иметь дело.

Я считаю, что мы можем узнать последние покупки по квитанции. Проверяя получение пользователя с помощью exclude-old-transaction: true, мы можем получить последнюю информацию о подписке (только для типа с автоматическим продлением). Я считаю, что мы можем использовать этот метод для восстановления покупок автоматически возобновляемых подписок. Я не уверен, что это идеальный метод.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги