Почему предыдущие покупки запускают прослушиватель покупок в приложении во время инициализации во Flutter (iOS)?IOS

Программируем под IOS
Ответить Пред. темаСлед. тема
Anonymous
 Почему предыдущие покупки запускают прослушиватель покупок в приложении во время инициализации во Flutter (iOS)?

Сообщение Anonymous »

Flutter iOS: прослушиватель покупок в приложении, отражающий старые покупки при инициализации
Привет всем!
Я интегрирую покупки в приложении в свое приложение Flutter с помощью пакета in_app_purchase . Я успешно настроил все как для Google Play Store, так и для Apple App Store в тестовой среде.
Текущая настройка
Покупки работают нормально на обеих платформах. Я могу совершить покупку по подписке, и это правильно отображается в Google Play и в песочнице iOS.
Я создал контроллер Getx, в котором инициализирую прослушиватель покупок и информацию о магазине. Ниже приведен соответствующий код:

Код: Выделить всё

 Listener Initialization in onInit:
late InAppPurchasePlatform _inAppPurchasePlatform;

@override
Future onInit() async {
_inAppPurchasePlatform = InAppPurchasePlatform.instance;

final Stream purchaseUpdated =
_inAppPurchasePlatform.purchaseStream;

_subscription0 =
purchaseUpdated.listen((List purchaseDetailsList) {
_handlePurchaseUpdates(purchaseDetailsList);

}, onDone: () {
_subscription0.cancel();
print("purchase listener onDone :");
}, onError: (Object error) {
print("purchase listener erro :" + error.toString());
});

initStoreInfo();

super.onInit();
}
Реализация initStoreInfo:

Код: Выделить всё

   Future initStoreInfo() async {
print("initStoreInfo called:");

try {
final bool isAvailable = await _inAppPurchasePlatform.isAvailable();
if (!isAvailable) {
error.value = 'Store is unavailable.  Please try again later.';
return;
}

print("Store is available.");
final List fetchedPlans = await fetchIAPPlanModel();
plans.addAll(fetchedPlans);

_kProductIds.addAll(fetchedPlans
.map((plan) => plan.productId ?? '')
.where((id) => id.isNotEmpty));

final ProductDetailsResponse productDetailResponse =
await _inAppPurchasePlatform
.queryProductDetails(_kProductIds.toSet());

if (productDetailResponse.error != null) {
error.value = productDetailResponse.error!.message!;
return;
}

if (productDetailResponse.productDetails.isEmpty) {
error.value = 'No products available at the moment.';
return;
}

// print(
//     "Product Details Fetched: ${productDetailResponse.productDetails.map((e) =>
e.rawPrice).toList()}");

_linkPlansWithProductDetails(productDetailResponse.productDetails);

if (GetPlatform.isAndroid) {
// Set user choice billing
final InAppPurchaseAndroidPlatformAddition addition =
InAppPurchasePlatformAddition.instance!
as InAppPurchaseAndroidPlatformAddition;
unawaited(
addition.setBillingChoice(BillingChoiceMode.userChoiceBilling));
} else if (Platform.isIOS) {
//write code for ios
}
} catch (e) {
print("Error initializing store: $e");
error.value = "Error initializing store: $e";
isLoading.value = false;
return;
}
}
< /code>
Функция _handlepurchaseupdates < /p>
void _handlePurchaseUpdates(List
 purchaseDetailsList) async {
print("purchaseDetailsList : " + purchaseDetailsList.length.toString());

final list = _plansController.subscriptionsList
.map((e) => e.transactionIds)
.toList();
list.map((e) => print("listitems : " + e.toString()));

print("list : " + list.toString());
print("list : " + list.length.toString());

for (final PurchaseDetails details in purchaseDetailsList) {
purchases[details.productID] = details;

var purchaseID = details.purchaseID;
print(" purchaseID:" + purchaseID.toString());

print("PurchaseDetails.status :" + details.status.toString());

if (details.pendingCompletePurchase) {
try {
await _inAppPurchasePlatform.completePurchase(details);
} catch (e) {
print("Error completing purchase: $e");
}
}

if (details.status == PurchaseStatus.canceled) {
purchasePending.value = false;
isLoading.value = false;
isButtonClicked.value = false;
return;
}

// Print error details if the purchase failed
if (details.status == PurchaseStatus.error) {
error.value = details.error?.message ?? "Unknown error occurred.";
purchasePending.value = false;
isLoading.value = false;
isButtonClicked.value = false;
Get.snackbar(
'Purchase Error',
'',
backgroundColor: Colors.red,
snackPosition: SnackPosition.BOTTOM,
duration: const Duration(seconds: 3),
);
// Check if the error is due to "itemAlreadyOwned"
if (details.error?.message == "BillingResponse.itemAlreadyOwned") {
// Show dialog to the user
_showAlreadyOwnedDialog();
}
print("PurchaseStatus.error "  + details.error!.message.toString());
return;
}
isLoading.value = true;

if (details.status == PurchaseStatus.pending) {
purchasePending.value = true;
return;
} else if (details.status == PurchaseStatus.error) {
error.value = details.error?.message ?? "Unknown error occurred.";
purchasePending.value = false;
await _sendPurchaseToBackend(details, false);
} else if (details.status == PurchaseStatus.restored) {
error.value = details.error?.message ?? "Subscription restored";
isButtonClicked.value = false;
return;
} else if (details.status == PurchaseStatus.purchased) {
// final bool isValid = await _verifyPurchase(details);
activePlanId.value = details.productID;
purchasePending.value = true;
// Notify backend about the successful transaction
await _sendPurchaseToBackend(details, true);
_processedPurchases.add(details.productID);
}

if (details.pendingCompletePurchase) {
await _inAppPurchasePlatform.completePurchase(details);
await fetchUserActivePlan();
}
}
< /code>
} < /p>
Проблема
на iOS, как только приложение запускается, и контроллер Getx инициализируется, покупка в приложении Слушатель (BoickAseStream) также инициализируется. Тем не менее, слушатель сразу же предоставляет купленный detailslist, содержащий предыдущие покупки, даже несмотря на то, что новая плата не произведена. < /P>
>  bookasestatus. Приобретенен
Это поведение проблематично, потому что я не могу различать старые покупки (из предыдущих сессий) и новых покупок. < /p>
То, что я пробовал
Я запускаю всплывающее окно счета через кнопку после запуска, которая работает нормально. Но эта проблема возникает до того, как будет совершена какая -либо новая покупка.  < /P>
Мой вопрос
Почему слушатель Boickestream возвращает предыдущие покупки на iOS во время инициализации? < /P>
< P> Как я могу различить старые покупки и новые? P> Любая помощь или альтернативные идеи реализации будут высоко оценены! < /p>
Результат для < /p>
   print("old originalT :" +

details.skPaymentTransaction.originalTransaction!.toString());

flutter: old originalT : {transactionState: 1, payment: {productIdentifier: spindle_plus_30_days, applicationUsername: null, requestData: null, quantity: 1, simulatesAskToBuyInSandbox: false
}, originalTransaction: null, transactionTimeStamp: 1737634871.0, transactionIdentifier: 2000000838444102, error: null
}
flutter: old originalT : {transactionState: 1, payment: {productIdentifier: spindle_plus_30_days, applicationUsername: null, requestData: null, quantity: 1, simulatesAskToBuyInSandbox: false
}, originalTransaction: null, transactionTimeStamp: 1737634871.0, transactionIdentifier: 2000000838444102, error: null
}
flutter: old originalT : {transactionState: 1, payment: {productIdentifier: spindle_plus_30_days, applicationUsername: null, requestData: null, quantity: 1, simulatesAskToBuyInSandbox: false
}, originalTransaction: null, transactionTimeStamp: 1737634871.0, transactionIdentifier: 2000000838444102, error: null
}
flutter: old originalT : {transactionState: 1, payment: {productIdentifier: spindle_plus_30_days, applicationUsername: null, requestData: null, quantity: 1, simulatesAskToBuyInSandbox: false
}, originalTransaction: null, transactionTimeStamp: 1737634871.0, transactionIdentifier: 2000000838444102, error: null
}
flutter: old originalT : {transactionState: 1, payment: {productIdentifier: spindle_plus_30_days, applicationUsername: null, requestData: null, quantity: 1, simulatesAskToBuyInSandbox: false
}, originalTransaction: null, transactionTimeStamp: 1737634871.0, transactionIdentifier: 2000000838444102, error: null
}
flutter: old originalT : {transactionState: 1, payment: {productIdentifier: spindle_plus_30_days, applicationUsername: null, requestData: null, quantity: 1, simulatesAskToBuyInSandbox: false
}, originalTransaction: null, transactionTimeStamp: 1737634871.0, transactionIdentifier: 2000000838444102, error: null
}
flutter: old originalT : {transactionState: 1, payment: {productIdentifier: spindle_plus_30_days, applicationUsername: null, requestData: null, quantity: 1, simulatesAskToBuyInSandbox: false
}, originalTransaction: null, transactionTimeStamp: 1737634871.0, transactionIdentifier: 2000000838444102, error: null
}
flutter: old originalT : {transactionState: 1, payment: {productIdentifier: spindle_plus_30_days, applicationUsername: null, requestData: null, quantity: 1, simulatesAskToBuyInSandbox: false
}, originalTransaction: null, transactionTimeStamp: 1737634871.0, transactionIdentifier: 2000000838444102, error: null
}
flutter: old originalT : {transactionState: 1, payment: {productIdentifier: spindle_plus_30_days, applicationUsername: null, requestData: null, quantity: 1, simulatesAskToBuyInSandbox: false
}, originalTransaction: null, transactionTimeStamp: 1737634871.0, transactionIdentifier: 2000000838444102, error: null
}
flutter: old originalT : {transactionState: 1, payment: {productIdentifier: spindle_plus_30_days, applicationUsername: null, requestData: null, quantity: 1, simulatesAskToBuyInSandbox: false
}, originalTransaction: null, transactionTimeStamp: 1737634871.0, transactionIdentifier: 2000000838444102, error: null
}
см. полный ответ


Подробнее здесь: https://stackoverflow.com/questions/793 ... initializa
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «IOS»