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

Flutter中无transaction_id时关联App Store服务器通知与用户的方案咨询

解决方案:Flutter内购订阅的用户关联与收据验证

一、交易与用户映射的可靠方案

核心思路:基于originalTransactionId建立持久映射

Apple订阅的originalTransactionId是订阅生命周期内的唯一标识——首次订阅生成后,后续续订、恢复、取消等操作都会沿用这个ID。服务器端只需在用户首次购买成功时,将originalTransactionId与用户UUID绑定存储,后续所有Apple服务器通知(续订、取消、过期等)都会携带这个ID,直接通过它即可关联到对应用户。

操作步骤:

  • 用户购买成功后,Flutter端将purchaseID(即transactionId)、originalTransactionId、user_id同步到服务器;
  • 服务器存储映射关系:originalTransactionId → user_id,可额外存储transactionId → user_id作为冗余;
  • 收到Apple服务器通知时,解析通知的signedPayload,提取originalTransactionId,直接查询映射表获取用户。

fallback方案:通过API从收据中提取applicationUserName

若因特殊情况未存储originalTransactionId,可通过通知中的transactionId调用App Store Server API获取交易详情,从返回的收据数据中提取applicationUsername字段(即你传入的用户UUID),再关联到用户。

二、替代废弃verifyReceipt的收据验证方案

Apple官方推荐App Store Server API作为verifyReceipt的替代方案,该API支持服务器到服务器的安全通信,提供订阅状态查询、交易详情获取等功能,同时能直接验证数据真实性。

1. 核心验证方式:解析服务器通知的signedPayload

Apple服务器通知的signedPayload是Apple私钥签名的JWT令牌,只需用Apple公钥验证签名,即可确保通知内容未被篡改,无需额外调用验证API。

Node.js实现示例(使用官方库@apple/app-store-server-library):

const { AppStoreServerAPIClient, Environment } = require('@apple/app-store-server-library');

// 初始化客户端,使用你的App Store Connect密钥信息
const client = new AppStoreServerAPIClient({
  issuerId: '你的Issuer ID',
  privateKey: '你的私钥内容',
  privateKeyId: '你的私钥ID',
  environment: Environment.PRODUCTION // 测试环境用Environment.SANDBOX
});

// 解析并验证Apple服务器通知
async function processAppleNotification(signedPayload) {
  try {
    const notification = await client.parseAndValidateNotification(signedPayload);
    // 提取关键交易信息
    const originalTransactionId = notification.data.originalTransactionId;
    const subscriptionStatus = notification.data.subscriptionStatus;
    
    // 通过originalTransactionId查询关联用户
    const user = await yourDatabase.query('SELECT * FROM user_subscriptions WHERE original_transaction_id = ?', [originalTransactionId]);
    
    // 处理订阅状态更新逻辑(如续订、取消、过期)
    updateUserSubscriptionStatus(user.id, subscriptionStatus);
  } catch (error) {
    console.error('通知验证失败:', error);
  }
}

2. 主动查询订阅状态:使用Get Subscription Status API

如果需要主动验证用户订阅状态(比如用户打开APP时),可调用Get Subscription Status API,传入originalTransactionId或transactionId,获取最新订阅信息,同时可从返回的latestReceipt中提取applicationUsername关联用户。

Node.js示例:

async function getSubscriptionStatus(originalTransactionId) {
  try {
    const statusResponse = await client.getSubscriptionStatus(originalTransactionId);
    const latestTransaction = statusResponse.data[0].latestTransaction;
    const applicationUsername = latestTransaction.receipt.applicationUsername;
    
    // 通过applicationUsername查询用户
    const user = await yourDatabase.query('SELECT * FROM users WHERE uuid = ?', [applicationUsername]);
    return { user, subscriptionStatus: statusResponse.data[0].status };
  } catch (error) {
    console.error('订阅状态查询失败:', error);
  }
}

关键注意事项

  • 确保每次发起购买时,applicationUserName参数都传入正确的用户UUID,Apple会将其存入交易收据;
  • 服务器需妥善存储App Store Connect的密钥信息(Issuer ID、私钥、私钥ID),避免泄露;
  • 开发测试时使用沙盒环境API,上线切换为生产环境。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 18:23:15