You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS React Native订阅验证返回21002状态及沙箱登录问题求助

iOS React Native 订阅问题解决方案

问题1:沙箱测试用户登录提示不弹出

排查与修复步骤

  • 退出设备真实Apple ID:前往「设置」→「App Store」退出当前登录的真实账号,触发订阅时系统会自动弹出沙箱用户登录界面,输入你的沙箱测试账号即可。
  • 匹配地区设置:确保沙箱测试用户的地区,与App Store Connect中订阅产品的可用地区完全一致。
  • 验证应用权限与签名:
    1. 在Xcode项目的「Signing & Capabilities」中确认「In-App Purchase」已开启。
    2. 检查entitlements文件是否包含com.apple.developer.in-app-purchase权限。
  • 确认网络环境:沙箱验证需连接Apple测试服务器,确保设备可正常访问境外网络(可尝试切换境外网络测试)。
  • 核对产品ID:代码中subscriptionSkus的['Monthly', 'Yearly']必须与App Store Connect中创建的订阅产品ID完全匹配(包括大小写、前缀,比如com.yourapp.Monthly)。

问题2:verifyReceipt返回21002状态码(收据格式错误)

Apple官方定义21002为「提供的收据数据格式不正确」,以下是具体修复方案:

排查与修复步骤

  • 校验收据数据有效性:
    验证前打印收据内容,确认transactionReceipt不为空且是有效Base64字符串:
    console.log('Receipt Data:', receipt);
    
    若存在换行符,可清理后再使用:
    const cleanedReceipt = receipt.replace(/\n/g, '');
    
  • 确认共享密钥正确性:
    确保IOS_SHARED_SECRET是从App Store Connect「用户和访问」→「密钥」中生成的共享密钥,完全复制无多余空格或换行。
  • 匹配验证环境:
    代码中isTestEnvironment = __DEV__的逻辑正确,但需注意:
    • 开发环境(__DEV__为true)使用沙箱验证服务器
    • 生产环境或TestFlight测试时,需将第二个参数改为false,使用生产服务器
  • 补全交易流程:
    验证成功后必须调用finishTransaction,否则会导致重复验证或状态异常。修改checkCurrentPurchase函数:
    const checkCurrentPurchase = async purchase => {
      if (purchase) {
        try {
          const receipt = purchase.transactionReceipt;
          if (receipt && Platform.OS === 'ios') {
            const isTestEnvironment = __DEV__;
            const cleanedReceipt = receipt.replace(/\n/g, '');
            const appleReceiptResponse = await validateReceiptIos(
              {
                'receipt-data': cleanedReceipt,
                password: IOS_SHARED_SECRET,
              },
              isTestEnvironment,
            );
    
            if (appleReceiptResponse) {
              const { status } = appleReceiptResponse;
              if (status === 0) { // 0表示验证成功
                await finishTransaction(purchase); // 完成交易
                // 此处处理订阅成功后的业务逻辑
                // navigation.navigate('Home');
              } else {
                console.log('Receipt validation failed with status:', status);
              }
            }
          }
        } catch (error) {
          console.log('Validation error:', error);
        }
      }
    };
    
  • 避免使用历史收据:
    不要用getPurchaseHistory返回的历史收据验证,应使用当前购买产生的currentPurchase中的transactionReceipt,历史收据可能已失效或格式不符。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 16:34:55