如何通过PHP后端检查Flutter内购用户的自动续费订阅状态
自动续费订阅状态后端(PHP)检查最优实现方案
一、苹果App Store订阅状态验证
- 核心方案:使用App Store Server API
这是苹果官方推荐的后端验证方案,专为订阅场景设计,比旧版收据验证更可靠且功能更全面。- 前端传参:Flutter端完成订阅后,将
originalTransactionId(订阅的原始交易ID,续费后不会变更,适合长期跟踪用户订阅)传给PHP后端。 - 后端API调用流程:
- 生成JWT令牌:在App Store Connect创建开发者密钥后,使用PHP的
firebase/php-jwt库,结合开发者ID、密钥ID和私钥生成签名JWT,作为API请求的身份凭证。 - 调用订阅查询接口:请求
GET /v1/subscriptions/{originalTransactionId},获取订阅的最新状态数据。 - 解析状态:通过返回数据中的
status字段判断订阅状态(0=有效,2=过期但处于宽限期,3=已取消等)。
- 生成JWT令牌:在App Store Connect创建开发者密钥后,使用PHP的
- 优化策略:根据订阅到期时间缓存状态,减少API调用次数,避免触发苹果的限流规则。
- 前端传参:Flutter端完成订阅后,将
二、谷歌Play订阅状态验证
- 核心方案:使用Google Play Developer API的Subscriptions端点
- 前端传参:Flutter端将订阅的
subscriptionId和purchaseToken(唯一标识用户订阅的令牌)传给PHP后端。 - 后端身份配置:
- 在Google Cloud Console创建服务账号,下载JSON密钥文件,并为其分配"Google Play Developer API"访问权限。
- 使用PHP的
google/apiclient库加载密钥,初始化API客户端。
- 后端API调用流程:
- 调用
purchases.subscriptions.get接口,传入应用包名、订阅ID和purchaseToken,获取订阅详情。 - 解析状态:通过
autoRenewing判断是否开启自动续费,expiryTimeMillis判断订阅是否过期,paymentState确认支付状态。
- 调用
- 优化策略:基于订阅过期时间缓存状态,降低API调用频率。
- 前端传参:Flutter端将订阅的
三、通用注意事项
- 字段选择:优先使用
originalTransactionId(苹果)或purchaseToken(谷歌)跟踪订阅,这些字段在续费周期内保持稳定,避免因交易ID变更导致的状态查询错误。 - 异常处理:处理API调用失败场景(如网络波动、令牌过期、权限不足),可设置有限次数的重试逻辑,但需遵守平台限流规则。
- 用户关联:将订阅信息与后端用户ID绑定,确保每个用户的订阅状态对应关系准确。
- 实时性平衡:若需实时判断订阅状态(如解锁功能),可结合前端本地缓存和后端定期验证,在实时性与API调用成本间取得平衡。
苹果API调用示例(PHP)
use Firebase\JWT\JWT; // 生成JWT令牌 $privateKey = file_get_contents('path/to/your/private-key.p8'); $payload = [ 'iss' => '你的开发者ID', 'iat' => time(), 'exp' => time() + 3600, // 令牌有效期1小时 'aud' => 'appstoreconnect-v1' ]; $jwt = JWT::encode($payload, $privateKey, 'ES256', '你的密钥ID'); // 调用App Store Server API查询订阅 $originalTransactionId = '用户的原始交易ID'; $url = "https://api.storekit.itunes.apple.com/v1/subscriptions/{$originalTransactionId}"; $ch = curl_init($url); curl_setopt($ch, CURLOPT_HTTPHEADER, [ "Authorization: Bearer {$jwt}", "Content-Type: application/json" ]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); curl_close($ch); $subscriptionData = json_decode($response, true); $status = $subscriptionData['data'][0]['attributes']['status']; if ($status === 0) { // 订阅有效 } elseif ($status === 2) { // 订阅过期但处于宽限期 }
谷歌Play API调用示例(PHP)
require __DIR__ . '/vendor/autoload.php'; $client = new Google\Client(); $client->setAuthConfig('path/to/your/service-account-key.json'); $client->addScope('https://www.googleapis.com/auth/androidpublisher'); $service = new Google\Service\AndroidPublisher($client); $packageName = '你的应用包名'; $subscriptionId = '订阅ID'; $purchaseToken = '用户的purchaseToken'; try { $subscription = $service->purchases_subscriptions->get($packageName, $subscriptionId, $purchaseToken); $autoRenewing = $subscription->getAutoRenewing(); $expiryTime = $subscription->getExpiryTimeMillis(); $currentTime = time() * 1000; if ($autoRenewing && $expiryTime > $currentTime) { // 订阅有效且自动续费开启 } else { // 订阅已过期或已取消 } } catch (Exception $e) { // 处理异常(如token无效、权限不足等) echo 'Error: ' . $e->getMessage(); }
内容的提问来源于stack exchange,提问作者Khyati Modi
相关产品推荐
相关产品推荐

