React-native-iap: Ошибка покупки в приложении iOS при добавлении способа оплаты в реальном времени, когда способ оплаты еще не указан

Созданный на 31 окт. 2018  ·  27Комментарии  ·  Источник: dooboolab/react-native-iap

Версия react-native-iap

react-native-iap": "^2.3.17

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

iOS

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

Платеж должен проходить только тогда, когда вызывается finishTransaction

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

Сумма определяется после добавления способа оплаты, например кредитной карты.
Но до метода RNIap.buyProductWithoutFinishTransaction(sku) дошло.

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

Настоящее устройство - iPhone 6s

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

  • Убедитесь, что для учетной записи Apple на устройстве выбран метод оплаты «Нет» или указаны недопустимые платежные реквизиты.
  • Совершайте покупки в приложении через приложение
  • Пользователь попадает на страницу настроек учетной записи, чтобы добавить действующий способ оплаты.
  • Способ оплаты взимается, но квитанция о транзакции не получена с указанным ниже кодом
ComponentDidMount(){
     await RNIap.initConnection();
     await RNIap.consumeAllItems();
     const prod = await RNIap.getProducts(product);

} 

  async componentWillUnmount() {
       RNIap.endConnection()
}

buyProduct(sku){
await RNIap.clearTransaction();

RNIap.buyProductWithoutFinishTransaction(sku)
.then(purchase => {
  // not reached
 if(calltoserverisSuccess){
    RNIap.finishTransaction();
 }
})
.catch(error => {
 // code enters catch case if ever
}}
📱 iOS 🙏 help wanted

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

Я думаю, нам нужно связаться с apple для этого, и это выглядит ужасно из-за того, что существует другой тестовый пример, который не воспроизводится в среде sandbox . Для тех, кто хочет разобраться в проблеме, я записал экран, и вы можете посмотреть ролик здесь . @anandwahed Не могли бы вы также связаться с Apple по этому

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

К сожалению, в вашем коде много синтаксических ошибок. Пожалуйста, обратитесь к нашему примеру проекта в нашем репо и сначала сравните с вашим кодом.

@dooboolab
Спасибо за ответ, размещенный здесь код приведен только для примера, это не совсем то, что используется в реальном приложении.
я постараюсь объяснить, в чем проблема

  1. componentDidMount

    • соединение инициировано вызовом RNIap.initConnection();

    • затем продукты выбираются и сохраняются в состоянии, вызывая RNIap.getProducts(product)

  1. когда пользователь нажимает кнопку покупки

    • RNIap.clearTransaction(); вызывается только для того, чтобы убедиться, что не осталось незавершенных транзакций.
    • RNIap.buyProductWithoutFinishTransaction(sku) вызывается в случае успешного вызова сервера приложений, если сервер дает успешное значение true, тогда вызывается RNIap.finishTransaction(); для завершения платежа.
  2. componentWillUnmount ()

    • RNIap.endConnection() для завершения соединения.

Этот процесс работает нормально, если пользователь уже добавил способ оплаты. Если у пользователя нет добавленного способа оплаты, требуется страница добавления способа оплаты, и сумма списывается до достижения RNIap.finishTransaction();

Спасибо за подробности. Теперь ваша проблема ясна. cc @JJMoon

@JJMoon

@ zohaibahmed-22 Это тестовый пример в песочнице?

@JJMoon Нет, это реальный случай окружающей среды.

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

@dooboolab и @JJMoon также я думаю, что обнаружил проблему при просмотре нашего кода iOS. В методе updatedTransactions, когда мы получаем сообщение об SKPaymentTransactionStateDeferred или SKPaymentTransactionStateFailed мы не предполагаем, что finishTransaction .

Поскольку во многих случаях за результатом SKPaymentTransactionStateFailed следует SKPaymentTransactionStatePurchased как указано в приведенном выше потоке 6431 . Я не уверен в коде Objective-C, поэтому проверьте и подтвердите, очищаем ли мы транзакцию в случае сбоя.

@anandwahed Я согласен с тобой. Это моя вина. Простите за это.
Я просмотрю ветку Apple и позабочусь о проблеме.

@anandwahed Я думаю, это правильный способ finish transaction когда он потерпел неудачу. Пожалуйста, посмотрите эту ветку. https://stackoverflow.com/questions/11008636/inapp-purchase-skpaymentqueue-finish-transaction-doesnt-work
В случае неудачи квитанции не будет, поэтому вы не применяете приобретенный продукт. И завершающая сделка не всегда означает «покупку».
А пока я исследую ветку 6431.

Я только что прочитал ветку 6431 (https://forums.developer.apple.com/thread/6431#14562)
Суть. Проблема не решается с 2015 года. Вау ..
Есть два разных способа справиться с этим эффектом «потока комплектов».

  1. Не показывать никаких предупреждений пользователя.
  2. Покажи результат.

И я узнал две вещи.
A. Мы должны finishTransaction когда это не удалось. (Я думаю, с опцией или без, всегда)
B. Поток Storekit делает неудачный и успешный с получением обоих. (это плохо)

Я предлагаю вам всем прочитать эту ветку и вернуться к этому вопросу.

Думаю, какой путь вы выберете (1 или 2), все зависит от вас.
В случае отказа нам может потребоваться обратный звонок.

@JJMoon означает ли это, что мы не должны использовать buyProductWithoutFinishTransaction?

@ maxs15 Я не это имел в виду. Извините за запутанность.
Поток StoreKit может произойти при любой покупке. Это проблема iOS, а не этого модуля.
На данный момент я тоже ничего не понимаю. Это происходит в любых нативных приложениях iOS. Правильно?
В свободное время будем копать еще.

Сегодня я попытался отладить эту проблему, потому что создал эту проблему. Платеж finishTransanction и завершен, но не получает callback при изменении метода payMethod. Я попытался отладить запись некоторых console.log но не смог проверить реальный биллинг в среде dev . Может ли кто-нибудь предложить мне, как отладить этот процесс, чтобы я мог debug это за real purchase ? Должен ли я использовать это в режиме sandbox ? Он отлично работает в песочнице, поэтому я не знаю, как это отладить. Это очень неохотно.

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

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

@hyochan Если вы подключаете реальный сервер (ваш), не имеет значения, находитесь ли вы в режиме отладки или в режиме выпуска. Думаю, у вас есть 2 варианта.

  1. Вы работаете на реальном устройстве в режиме отладки в Xcode. Используйте журнал консоли JS.
  2. Вы работаете на реальном устройстве в режиме выпуска в Xcode. Используйте NSLog в коде objective-c.
    Оба метода должны работать.

@JJMoon Да, я уже понял это, но все же я не мог провести тестирование покупок в реальном времени на ios. Это правда stackoverflow ? Тогда как мне решить эту проблему? Мы должны протестировать живую покупку.

Любой, кто сталкивается с этой проблемой, я уверен, что все они, пожалуйста, дайте нам представление о том, как столкнуться с этой проблемой. in-app purchase fail when payment method added live как описано в заголовке проблемы. Как я мог это отладить? @anandwahed Вы когда-нибудь связывались с Apple по поводу этой проблемы?

@hyochan Нет, мы не

Я думаю, нам нужно связаться с apple для этого, и это выглядит ужасно из-за того, что существует другой тестовый пример, который не воспроизводится в среде sandbox . Для тех, кто хочет разобраться в проблеме, я записал экран, и вы можете посмотреть ролик здесь . @anandwahed Не могли бы вы также связаться с Apple по этому

Сегодня мы получили ответ от Apple. Обратный вызов может быть возвращен снова после failure . Мы работаем над решением проблемы # 348, но я боюсь, что это может быть очень неприятно.

Я выполнил 2.4.0-beta1 , пытаясь найти обходной путь для этой проблемы. В эту версию добавлен PR # 348, и вы также можете увидеть файл readme для этой функции . Обратите внимание, что это тестируется.

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

Ребята, спасибо что потратили время на эту проблему! 🙏

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

Но я также думаю, что это оставляет место для улучшения API. Не могли бы вы, ребята, обсудить изменение в API, которое может лучше приспособиться к так называемому «потоку комплектов магазина»? Что-то может быть с использованием RxJS, например:

const observable = RNIap.buyProduct('com.example.coins100')
                        .subscribe(
                            purchase => console.log(purchase), // successful payment
                            err => console.log(err) // err.code and err.message are available
                        )

Или что-то другое, что лучше скрывает дополнительную подписку для iOS?

@Edgpaez Это здорово, но это изменит поведение покупки, совершаемой в android . Я надеюсь, что смогу исследовать version 3 этого модуля в 2019 .

привет @hyochan , AFAICT, нам не нужно изменять внутреннее поведение пакета, только общедоступный интерфейс. Мы можем оставить метод buyItemByType, разрешающий обещания, и просто добавить немного Rx поверх этого в index.js .

например, у нас было бы это в index.js:

export const buyProduct = (sku) => Platform.select({
  android: () => Observable.of(RNIapModule.buyItemByType(ANDROID_ITEM_TYPE_IAP, sku, null, 0)), // returns an observable that emits when the RNIapModule.buyItemByType promise resolves
  ios: ... // ios would do the same but taking into account the usage of addAdditionalSuccessPurchaseListenerIOS
})();

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

@Edgpaez Хорошо. Теперь я понимаю детали. Однако мне кажется, что добавление RxJS слишком много для реализации feature поскольку я думаю, что это можно решить без него.

Кроме того, я чувствую, что ниже будет что-то другое.

RNIap.buyProduct('com.example.coins100')
                        .subscribe(
                            purchase => console.log(purchase), // successful payment
                            err => console.log(err) // err.code and err.message are available
                        )

Если вы вызываете buyProduct для двух пунктов, как показано ниже,

RNIap.buyProduct('com.example.coins100');
RNIap.buyProduct('com.example.coins200');

Мы не можем гарантировать, какой из них завершится первым, поэтому я думаю, что мы должны справиться с этим в нативном режиме до sendEvent до JS .

Мне кажется, реализация должна выглядеть так

RNIap.buyProduct('com.example.coins100');
RNIap.buyProduct('com.example.coins200');

// receiving events
const subs =  RNIap.purchaseUpdateListener(purchase => {
  ...
});

Скажите, пожалуйста, если я что-то пропустил.

Давайте займемся дальнейшим disccustin в # 423

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