bounty将在6天后过期。回答此问题可获得+50声望奖励。JBTG希望引起更多人关注此问题。
我正在努力在iOS上的应用程序支付.当我尝试启动应用程序,我恢复过去的购买,有时我得到代码0 SKError(未知错误).我无法获得可用的产品,和购买列表.不知道是什么原因导致错误,我挣扎了几天.
重要的是,有时它工作正常,有时它只是不. Android版本是完美的工作.
Xcode:14.2 Flutter版本:3.7.6 Dart版本:2.19.3我使用的包和版本:in_app_purchase:第三年第一年第五次
出现问题的设备:iPhone Xs MAX,iOS 16.3.1 iPhone 6s,iOS 15.7.3 iPad Air 2,iOS 15.7.3
下面是我在Cubit中的代码:
import 'dart:async';
import 'dart:io';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:in_app_purchase/in_app_purchase.dart';
part 'payments_state.dart';
class PaymentsCubit extends Cubit<PaymentsState> {
PaymentsCubit()
: super(PaymentsState(
isPremium: null,
avaliable: false,
products: [],
purchases: [],
));
late StreamSubscription subscription;
late InAppPurchase iap;
void start() async {
iap = InAppPurchase.instance;
state.avaliable = await iap.isAvailable();
if (state.avaliable) {
//listener must be declared before get products and purchases calls
subscription = iap.purchaseStream.listen(
(purchaseDetailsList) {
listenToPurchaseUpdated(purchaseDetailsList);
},
onDone: () => subscription.cancel(),
onError: (error) => print(error),
);
await getProducts();
await getPastPurchases();
//it's listening to every changes in purchases e.g. buy new product, restore old products.
//everytime when change will occur, then function is triggered
//remember to always cancel listeners to avoid memmory leaks
}
emit(state);
}
Future<void> getProducts() async {
Set<String> ids = Platform.isAndroid
? {
'com.example.example.example',
'com.example.example.exampleNew'
}
: {
'com.example.example.exampleNew',
};
ProductDetailsResponse response = await iap.queryProductDetails(ids);
state.products = response.productDetails;
}
Future<void> getPastPurchases() async {
//this will trigger listener if user made purchases in the past
await iap.restorePurchases();
}
void buyProduct() async {
state.avaliable = await iap.isAvailable();
if (state.avaliable) {
final PurchaseParam purchaseParam = PurchaseParam(
productDetails: state.products.firstWhere(
(element) =>
element.id ==
(Platform.isAndroid
? 'com.example.example.example'
: 'com.example.example.exampleNew'),
),
);
await InAppPurchase.instance
.buyNonConsumable(purchaseParam: purchaseParam);
}
}
void listenToPurchaseUpdated(List<PurchaseDetails> purchaseDetailsList) {
purchaseDetailsList.forEach((element) {
if (element.status == PurchaseStatus.pending) {
//handle situation when user pressed button to start purchase, (on iOS it takes more time, android have almost immediately response) maybe show some loading spinners
} else if (element.status == PurchaseStatus.error) {
} else if (element.status == PurchaseStatus.canceled) {
} else if (element.status == PurchaseStatus.purchased ||
element.status == PurchaseStatus.restored) {
state.purchases.add(element);
emit(state.copyWith(
isPremium: true,
));
iap.completePurchase(element);
}
});
if (state.isPremium == null) {
emit(state.copyWith(isPremium: false));
}
}
}
Start方法在MyApp中的块声明后调用,如下所示:
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider(create: (context) => PaymentsCubit()..start()),
],
child: MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
fontFamily: 'Rubik',
primarySwatch: Colors.blue,
),
home: const FakeSplashscreen()),
);
}
}
1条答案
按热度按时间m0rkklqb1#
代码看起来很好。
发生SKError Code 0时,您可能需要检查错误对象的localizedDescription属性。
当测试过程中出现此错误时,通常可以通过注销iTunes和/或App Store并在App Store Connect中创建新的测试用户帐户来解决。这种方法仅在设备上运行应用时有效,而不是模拟器。
当生产中出现此错误时,可能表示用户的iTunes帐户有问题。