React-native-iap: finishTransactionIOS / finishTransaction ничего не делает для iOS

Созданный на 19 февр. 2020  ·  34Комментарии  ·  Источник: dooboolab/react-native-iap

Версия react-native-iap

4.4.1

Версия react-native

0,60,4

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

iOS

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

После вызова finishTransactionIOS (PurchaId) или finishTransaction (покупка) для подписки транзакция должна быть завершена и больше не отправляться в приложение при следующем запуске. Если бы с этим возникла проблема, я бы ожидал, что что-то будет возвращено либо в прослушиватель ошибок, либо в обещании от одной из функций finishTransaction, ничего не произойдет.

Андроид вроде нормально работает.

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

Транзакция отправляется при каждом запуске, если не вызывается clearTransactionIOS, что, похоже, имеет другие побочные эффекты.

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

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

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

  • Создайте продукт подписки.
  • Купить подписку
  • Имитация бэкэнд-валидации
  • Вызовите finishTransactionIOS или finishTransaction для этой подписки. Не действует.

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

ℹ needs more info 📱 iOS 🙏 help wanted 🚶🏻 stale

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

@hyochan есть

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

У меня такая же проблема.

Можете ли вы поделиться ackResult ?

          try {
            const ackResult = await finishTransaction(purchase);
            console.log('ackResult', ackResult);
          } catch (ackErr) {
            console.warn('ackErr', ackErr);
          }

@hyochan
В моем случае:
ackResult undefined

@hyochan
В моем случае:
ackResult undefined

Тоже самое

Также в моем случае возвращаемое значение не определено (реальное устройство с пользователем песочницы).

Похоже, это связано с № 366. Также для ios finishTransaction ничего не вернет.
Можете ли вы все сосредоточиться на # 366 и вернуться за обновлением?

Похоже, это связано с № 366. Также для ios finishTransaction ничего не вернет.
Можете ли вы все сосредоточиться на # 366 и вернуться за обновлением?

Просто чтобы прояснить - поскольку № 366 касается тестирования, вы предлагаете, чтобы это работало нормально в производственной среде без необходимости clearTransactionIOS?

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

`` tsx
useEffect (() => {
PurchaseUpdateSubscription.current = PurchaseUpdatedListener (
async (покупка: InAppPurchase | SubscriptionPurchase) => {
const Receipt = Purchase.transactionReceipt;
if (получение) {
пытаться {
await myBackendHandler ({
Пользователь,
покупка,
});
const result = await RNIap.finishTransaction (покупка, ложь);
console.log ('результат', результат);
} catch (e) {
// СДЕЛАТЬ
}
}
}
);
return () => {
if (buyUpdateSubscription.current) {
buyUpdateSubscription.current.remove ();
PurchaseUpdateSubscription.current = null;
}
};
}, []);
`` ''

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

Мой вариант использования

  1. Пользователь 1 совершает покупку и применяет премию к своей учетной записи.
  2. Пользователь 1 выходит из системы
  3. Пользователь 2 входит в систему

Ожидаемый результат:

  • Транзакции от пользователя 1 не отправляются через слушателя покупок

Фактический результат

  • Транзакции от пользователя 1 НЕ очищаются и отправляются снова. Даже если новый пользователь вошел в систему, что привело к неверным данным.

Это всего лишь пример того, почему важно сделать этот вопрос приоритетным. Спасибо, что прочитали этот длинный комментарий ...

то же самое

точно такая же проблема, как и выше, похоже, что стек вообще не очищен, даже после отключения учетной записи песочницы / itunes, перезагрузки устройства, переустановки приложения ..: /

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

Пожалуйста, проверьте метод clearTransaction или finishTransactionWithIdentifier и попробуйте поместить туда любые журналы. Попробуйте найти ниже коды.

RCT_EXPORT_METHOD(clearTransaction) {
    NSArray *pendingTrans = [[SKPaymentQueue defaultQueue] transactions];
    NSLog(@"\n\n\n  ***  clear remaining Transactions. Call this before make a new transaction   \n\n.");
    for (int k = 0; k < pendingTrans.count; k++) {
        [[SKPaymentQueue defaultQueue] finishTransaction:pendingTrans[k]];
    }
-(void)finishTransactionWithIdentifier:(NSString *)transactionIdentifier {
    SKPaymentQueue *queue = [SKPaymentQueue defaultQueue];
    for(SKPaymentTransaction *transaction in queue.transactions) {
        if([transaction.transactionIdentifier isEqualToString:transactionIdentifier]) {
            [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
        }
    }
}

Я не могу продвигать этот вопрос вперед, потому что не понимаю, что происходит. Я надеюсь, что кто-нибудь сможет отладить что-то в своей среде и поделиться

есть новости по этой проблеме?

вверх, я тоже испытываю эту проблему.

То же самое здесь finishTransactionIOS / finishTransaction это не работает в IOS

Кажется, я испытываю то же самое.
Покупка IAP завершается успешно, но последний вызов finishTransaction возвращает undefined .

// Finish transaction
const ackResult = await finishTransaction(purchase);
console.log("Ack result: ", ackResult); // Ack result: undefined

_Реальное устройство «iPhone 6s» в среде App Store Sandbox._

Каков ожидаемый результат от finishTransaction? undefined - это хороший результат или мне следует ожидать чего-то другого?

Я также испытываю эту проблему на iOS, где ни finishTransactionIOS ни finishTransaction на самом деле не удаляют эти транзакции, что мешает мне выпустить приложение. Есть обновления?

@hyochan Хотя я определенно не finishTransaction и finishTransactionWithIdentifier и кажется, что они работают правильно (идентификатор передается и сопоставляется). Единственное, о чем я могу думать, это то, что [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; самом деле не подключается к StoreKit и не завершает транзакцию? Я действительно не знаю, куда идти, но, надеюсь, это поможет при отладке

Вы также обрабатываете уведомления о статусе подписки из App Store? В моем случае у меня была эта проблема, пока я не убедился, что мой сервер правильно обрабатывает все события уведомлений и не ответил 200.

@espenjanson Интересно. Нет, не был. Но на самом деле я только что переключился на модуль Expo InAppPurchases вчера, и теперь он отлично работает.

@lachlanglen Nevermind. Это была всего лишь одна удача (?) Или что-то еще. Создал другую версию приложения, и проблема снова здесь. Думаю сделать то же самое, но немного обеспокоен тем, что репо на выставках не очень хорошо поддерживается.

Я изучал это, и это правильно, что он возвращает undefined, поскольку вызов finishTransactions не предназначен для возврата чего-либо в obj-c.
Я провел несколько тестов, и в моем случае он, кажется, завершил их правильно (простой тест, pull pendingTransactions, если ничего нет, он работает хорошо)

@espenjanson Я не знаю, почему вы думаете, что пакеты Expo не содержатся в хорошем состоянии. Я думаю, что Expo выпустила свой модуль iap совсем недавно. Если бы я знал, что у expo есть модуль iap в то время, когда я внедрял iap, я бы выбрал expo, не задумываясь.

Есть ли способ решить эту проблему?
Я протестировал это на TestFlight даже с новым пользователем песочницы, и это все еще происходит.

Мой purchaseUpdateListener продолжает получать "старые" транзакции.
Я звоню по номеру finishTransaction(purchase,false) как использую автопродление подписок.
Результат вызова: undefined .

Может ли кто-нибудь предложить обходной путь или объяснение, почему это происходит?

@zatloeri Очевидно, это желаемое поведение. Мне потребовалось время, чтобы осознать это. App Store будет помещать новую квитанцию ​​для продления в StoreKit, которая запускает наблюдателя. Вы должны обработать этот чек и завершить транзакцию.

https://developer.apple.com/videos/play/wwdc2018/705/
https://developer.apple.com/videos/play/wwdc2020/10671

(смотрите в Safari для качества HD)

@ziyoshams Спасибо за быстрый ответ и за ресурсы, которые я немного рассмотрю.

Но сначала я просто хочу указать на одну вещь, потому что не думаю, что я сделал это привлекательным.
То, что вы описываете, кажется мне логичным, и я ожидал, что это произойдет, но меня озадачивает следующее:

Срок действия продукта A истек, что подтверждается receipt validation .
Я получаю одну старую (с предыдущего дня) транзакцию для продукта A, когда я запускаю или передаю приложение.
Затем в следующий раз, когда я снова буду выводить приложение на передний план, я получаю еще одну старую (может быть, немного новее, чем предыдущая, не уверенная) транзакция для продукта A.
На другом переднем плане, возможно, на другом и так далее.

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

@zatloeri Каждая

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

я упомянул несколько фрагментов моего кода ниже ...

``
import RNIap, {
Покупки в приложении,
Товар,
PurchaseError,
Подписка,
ПодпискаПокупка,
finishTransaction,
finishTransactionIOS,
PurchaseErrorListener,
buyUpdatedListener,
clearTransactionIOS,
} от 'react-native-iap';

async componentDidMount () {
const result = ждать RNIap.initConnection ();
const itemSubs = Platform.select ({
android: [
получить (this.props, 'subscriptionStore.subscription.android_product_id', null)
],
ios: [
получить (this.props, 'subscriptionStore.subscription.ios_product_id', null)
]
});

const subscriptions = ждать RNIap.getSubscriptions (itemSubs);
PurchaseUpdateSubscription = PurchaseUpdatedListener (
async (покупка) => {
const Receipt = Purchase.transactionReceipt;
let subscription = {
ID подписки: get (this.props, 'subscriptionStore.subscription.id', null)
};
if (Platform.OS === 'ios') {
подписка = {
...подписка,
order_id: get (покупка, 'transactionId', null),
Purchase_token: get (покупка, 'originalTransactionIdentifierIOS', null),
квитанция: get (покупка, 'transactionReceipt', null), // (сохранить в ТЕКСТЕ)
os: 'IOS'
}
} else if (Platform.OS === 'android') {
const data = JSON.parse (квитанция);
подписка = {
...подписка,
order_id: получить (данные, 'orderId', null),
Purchase_token: get (data, 'PurchaseToken', null),
os: 'ANDROID'
}
}
пытаться {
finishTransaction (покупка, ложь); // это здесь для temp, позже он будет помещен на успех.
this.props.notificationStore.showToast («Подписка успешно выполнена. Подождите ...», «Успешно», 5000);
const resp = await this.props.subscriptionStore.onPurchase (подписка); // проверка транзакций на стороне сервера.
if (соотв. успех) {// успешный ответ
this.props.userStore.setUser ({is_premium: 1});
this.props.navigation.replace ('FixFooter');
}
} catch (ошибка) {
console.log ("ОШИБКА API onPurchase:", ошибка);
}
}
)

PurchaseErrorSubscription = PurchaseErrorListener (
async (ошибка) => {
console.log ('ошибка покупки:', ошибка);
}
)
}

/ * кнопка onPurchase * /
async onPurchase () {
пытаться {
const request = await RNIap.requestSubscription (Platform.OS === 'android'?
get (this.props, 'subscriptionStore.subscription.android_product_id', null):
получить (this.props, 'subscriptionStore.subscription.ios_product_id', null))
} catch (ошибка) {
console.log ('ошибка:', ошибка)
}
}

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

@ziyoshams Получаете ли вы null также с помощью метода finishTransaction модуля expo iap?

@bcbcbcbcbcl Я не использую модуль expo.

+1 мне он возвращает undefined

@hyochan есть

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

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