我正在创建一个应用程序,我几乎完成了应用程序开发,只剩下应用程序内订阅。
我也做了一些工作,但无法处理下面列出的一些场景:
1-如果用户在iPhone中登录的苹果id还没有订阅,那么流程就可以正常工作,购买就会发生,升级api也会命中。
现在,假设我已经在我的一个帐户上购买了订阅,然后我注销并创建一个新帐户,然后用相同的苹果id为我的第二个帐户购买订阅,下面列出了情况:
1-ios弹出窗口显示您已经拥有此项目,当我单击“确定”按钮时,升级api仍然会在没有购买的情况下命中。
我想处理这个senario,并向用户显示这个苹果id已经订阅了,也许还有其他senario需要配置,直到我还没有面对
截止日期太近了,我是第一次与IAP打交道
任何需要拯救的人都将不胜感激。
这是我的代码:
@override
void initState() {
final Stream<List<PurchaseDetails>> purchaseUpdated = _iap.purchaseStream;
_subscription =
purchaseUpdated.listen((List<PurchaseDetails> purchaseDetailsList) {
for (PurchaseDetails purchaseDetails in purchaseDetailsList) {
_iap.completePurchase(purchaseDetails);
}
_listenToPurchaseUpdated(purchaseDetailsList);
}, onDone: () {
_subscription.cancel();
}, onError: (Object error) {});
AddProvider addProvider = Provider.of<AddProvider>(context, listen: false);
addProvider.initializeStatisticsPageInterstitialAd();
handlePurchase();
super.initState();
}
late StreamSubscription<List<PurchaseDetails>> _subscription;
final List<PurchaseDetails> _purchases = [];
// Inside your _listenToPurchaseUpdated method:
void _listenToPurchaseUpdated(
List<PurchaseDetails> purchaseDetailsList) async {
for (PurchaseDetails purchaseDetails in purchaseDetailsList) {
if (purchaseDetails.pendingCompletePurchase) {
await _iap.completePurchase(purchaseDetails);
}
if (purchaseDetails.status == PurchaseStatus.pending) {
CommonData.showCustomSnackbar(
context, 'Please wait while fetching details..');
} else {
if (purchaseDetails.status == PurchaseStatus.error) {
CommonData.showCustomSnackbar(context, 'Error');
} else if (purchaseDetails.status == PurchaseStatus.canceled) {
CommonData.showCustomSnackbar(context, 'Subscription is cancelled');
_purchases.removeWhere(
(element) => element.productID == purchaseDetails.productID);
} else if (purchaseDetails.status == PurchaseStatus.purchased) {
bool valid = await _verifyPurchase(purchaseDetails);
if (valid) {
await _verifyPurchase(purchaseDetails);
await hitUpgradeApi(
pri, pdi, pdi == "monthly_subscription" ? "monthly" : "yearly");
upgradeToPro(purchaseDetails);
} else {
if (context.mounted) {
CommonData.showCustomSnackbar(context,
'This apple id have already active subcription,change the id or logged in with relative subscribed account');
}
return;
}
}
}
}
}
Future<bool> _verifyPurchase(PurchaseDetails purchaseDetails) async {
if (purchaseDetails.status == PurchaseStatus.purchased) {
st = purchaseDetails.status.toString();
pdi = purchaseDetails.productID.toString();
pri = purchaseDetails.purchaseID.toString();
td = purchaseDetails.transactionDate.toString();
if (st.isNotEmpty && pdi.isNotEmpty && pri.isNotEmpty && td.isNotEmpty) {
return Future<bool>.value(true);
}
}
CommonData.showCustomSnackbar(context, "Transaction failed");
return Future<bool>.value(false);
}
Future<void> hitUpgradeApi(
String purchaseTocken, String purchaseId, String plan) async {
try {
Map<String, dynamic> data = {
"purchase_token": purchaseTocken,
"purchase_id": purchaseId,
"plan": plan
};
Dio dio = await CommonData.createDioWithAuthHeader();
Response response = await dio.post(CommonData.subcriptionApi, data: data);
if (response.statusCode == 200) {
if (mounted) {
CommonData.showCustomSnackbar(context, "Upgraded to pro");
Navigator.of(context).pop();
}
}
} on DioException catch (e) {
if (e.type == DioExceptionType.unknown ||
e.type == DioExceptionType.connectionError ||
e.type == DioExceptionType.connectionTimeout) {
if (mounted) {
CommonData.showCustomSnackbar(context, "No internet connection");
}
} else {
if (mounted) {
CommonData.sshowDialog('Error', e.response!.data['message'], context);
}
}
}
}
bool _isPurchased(String productId) {
return _purchases.any((purchase) => purchase.productID == productId);
}
Future<void> handlePurchase() async {
monthlyProductDetailsResponse = await _iap.queryProductDetails({
'monthly_subscription',
});
yearlyProductDetailsResponse =
await _iap.queryProductDetails({'yearly_subscription'});
}
Future<void> purchaseProduct(ProductDetails productDetails) async {
try {
final PurchaseParam purchaseParam =
PurchaseParam(productDetails: productDetails);
final purchaseDetailss = await _iap.buyNonConsumable(
purchaseParam: purchaseParam,
);
// _verifyPurchase(purchaseDetails);
if (!purchaseDetailss) {
if (context.mounted) {
CommonData.showCustomSnackbar(context, "Some error occurred..");
}
} else {
if (context.mounted) {
CommonData.showCustomSnackbar(context, "Transaction failed");
}
}
} catch (e) {
print(e.toString());
// completePurchase(productDetails.id);
}
}
Future<void> upgradeToPro(PurchaseDetails purchaseDetails) async {
_purchases.add(purchaseDetails);
}