You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Flutter应用因内购问题遭App Store拒审,如何添加iOS恢复购买按钮?

Hey,我之前刚用in_app_purchase 0.3.0+2解决过一模一样的App Store拒审问题,给你一步一步讲怎么实现,完全符合苹果的要求:

一、先在UI中添加“Restore Purchases”按钮

首先得在用户能方便找到的地方加个按钮——比如内购页面底部、设置页面里,苹果要求必须是用户主动触发,不能自动恢复。用Flutter的话,代码大概是这样:

ElevatedButton(
  onPressed: _restorePurchases,
  child: const Text('Restore Purchases'), // 中文场景可以用“恢复购买”
)
二、实现恢复购买的核心逻辑

接下来就是写_restorePurchases方法,调用in_app_purchase库的恢复接口,同时处理基础的可用性判断:

import 'package:in_app_purchase/in_app_purchase.dart';

void _restorePurchases() async {
  // 先检查内购服务是否可用
  final bool isAvailable = await InAppPurchase.instance.isAvailable();
  if (!isAvailable) {
    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(content: Text('内购服务不可用,请检查网络或Apple ID设置')),
    );
    return;
  }

  // 发起恢复购买请求
  await InAppPurchase.instance.restorePurchases();
}
三、处理恢复后的交易回调

要在页面初始化时就订阅PurchaseUpdatedStream,这样才能收到恢复后的交易数据,然后给用户解锁对应的内容:

StreamSubscription<List<PurchaseDetails>>? _subscription;

@override
void initState() {
  super.initState();
  // 订阅购买/恢复的回调流
  _subscription = InAppPurchase.instance.purchaseUpdatedStream.listen((purchaseDetailsList) {
    _handlePurchaseUpdates(purchaseDetailsList);
  });
}

void _handlePurchaseUpdates(List<PurchaseDetails> purchaseDetailsList) {
  for (var purchaseDetails in purchaseDetailsList) {
    if (purchaseDetails.status == PurchaseStatus.restored) {
      // 恢复成功,解锁用户已购买的内容
      _unlockPurchasedContent(purchaseDetails.productID);
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('购买内容已恢复')),
      );
    } else if (purchaseDetails.status == PurchaseStatus.error) {
      // 恢复失败,给用户明确提示
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('恢复失败:${purchaseDetails.error?.message}')),
      );
    }
    // 必须完成交易,避免后续异常
    if (purchaseDetails.pendingCompletePurchase) {
      await InAppPurchase.instance.completePurchase(purchaseDetails);
    }
  }
}

// 自定义业务方法:根据产品ID解锁对应内容
void _unlockPurchasedContent(String productId) {
  // 这里写你的逻辑,比如存SharedPreferences、更新页面状态等
}

@override
void dispose() {
  _subscription?.cancel();
  super.dispose();
}
四、关键注意事项(必看!)
  • 绝对不能在App启动时自动触发恢复,必须是用户点击按钮主动触发——这是苹果明确要求的,自动恢复会再次被拒
  • 按钮的文案要清晰,就用“Restore Purchases”或者“恢复购买”,别用模糊的表述
  • 恢复成功后一定要遍历所有恢复的交易,不要漏解锁用户已购买的内容
  • 要处理各种异常情况:比如内购不可用、网络错误、用户未登录Apple ID等,给用户明确的提示

苹果官方拒审理由如下:我们发现您的应用提供可恢复的内购项目,但未包含“Restore Purchases”功能以允许用户恢复已购买的内购项目,这不符合《In-App Purchase Programming Guide》中“Restoring Purchase Products”章节的规定:用户恢复交易是为了继续访问已购买的内容,例如更换新手机时不会丢失旧设备上购买的所有项目。应用需提供恢复购买的机制,比如“Restore Purchases”按钮。下一步建议:需提供“Restore Purchases”按钮,在用户点击时触发恢复流程,注意应用启动时自动恢复购买无法解决此问题。

内容的提问来源于stack exchange,提问作者dijkstra

火山引擎 最新活动