Xamarin.Android付费应用开发:Play Store订阅状态验证与功能解锁指引
嘿,我来帮你搞定Xamarin.Android里的Google Play订阅状态验证和功能解锁的事儿!这活儿我之前做过好几个项目,流程门儿清,一步步给你说清楚。
第一步:给你的Xamarin.Android项目配置Google Play Billing库
首先得把Google Play的计费库集成到项目里,Xamarin这边直接用NuGet包就行:
- 打开Visual Studio的NuGet包管理器,搜索
Xamarin.GooglePlay.Billing,安装最新稳定版 - 或者在Package Manager Console里跑命令:
Install-Package Xamarin.GooglePlay.Billing
接下来初始化BillingClient,这是和Google Play通信的核心对象,建议在你的主Activity或者Application类里初始化:
private BillingClient _billingClient; protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); // 初始化BillingClient _billingClient = BillingClient.NewBuilder(this) .SetListener(PurchaseUpdatedListener) .EnablePendingPurchases() // 处理待支付的订单 .Build(); // 连接到Google Play服务 _billingClient.StartConnection(new BillingClientStateListener() { public void OnBillingSetupFinished(BillingResult billingResult) { if (billingResult.ResponseCode == BillingClient.BillingResponseCode.Ok) { // 连接成功,接下来可以查询订阅状态了 QueryUserSubscriptions(); } } public void OnBillingServiceDisconnected() { // 连接断开,这里可以实现重连逻辑 _billingClient.StartConnection(this); } }); }
第二步:查询用户的订阅状态
连接成功后,就可以查询用户已经购买的订阅了,重点是过滤出有效的、未过期的订阅:
private async void QueryUserSubscriptions() { if (!_billingClient.IsReady) { // 确保BillingClient已经连接好 return; } var purchasesResult = await _billingClient.QueryPurchasesAsync(BillingClient.SkuType.Subscription); if (purchasesResult.ResponseCode == BillingClient.BillingResponseCode.Ok) { foreach (var purchase in purchasesResult.PurchasesList) { // 先验证订阅签名(本地校验) if (!VerifyPurchase(purchase.OriginalJson, purchase.Signature)) { Log.Error("Subscription", "订阅签名验证失败,可能被篡改"); continue; } // 检查订阅是否有效(已购买且未过期) if (purchase.PurchaseState == Purchase.PurchaseState.Purchased && IsSubscriptionActive(purchase)) { // 这里标记用户有有效订阅 SaveSubscriptionStatus(true, purchase.ExpirationTimeMillis); UnlockPremiumFeatures(); } else { // 订阅过期或已取消,锁定功能 SaveSubscriptionStatus(false, 0); LockPremiumFeatures(); } } } } // 判断订阅是否处于有效期内 private bool IsSubscriptionActive(Purchase purchase) { var currentTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); // 过期时间大于当前时间,说明订阅还在有效期 return purchase.ExpirationTimeMillis > currentTime; }
第三步:验证订阅的有效性(本地+服务器端,双重保障)
本地验证是基础,但绝对不能只依赖本地验证,因为容易被篡改,必须配合服务器端验证:
本地验证(快速校验)
用Google Play提供的公钥验证订阅的签名,公钥可以在Google Play控制台的应用详情里找到:
private bool VerifyPurchase(string signedData, string signature) { const string publicKey = "你的Google Play公钥"; // 从控制台复制过来,建议存到安全配置里,不要硬编码 try { var security = new Security(); return security.VerifyPurchase(publicKey, signedData, signature); } catch (Exception e) { // 验证失败,日志记录一下 Log.Error("SubscriptionVerify", $"验证失败: {e.Message}"); return false; } }
服务器端验证(安全保障)
这一步是必须的,要在你的后端服务里做:
- 先在Google Cloud Console创建服务账号,下载JSON密钥,给这个账号授予Google Play Developer API的权限
- 后端代码调用Google Play Developer API的
Purchases.Subscriptions:Get接口,传入应用包名、订阅ID、购买token(即purchase.PurchaseToken) - 根据API返回的
expiryTimeMillis、autoRenewing、cancelReason等字段判断订阅是否有效 - 把验证结果返回给Xamarin应用,应用再根据结果处理功能解锁
第四步:根据订阅状态解锁/锁定功能
最后一步就是把状态和功能关联起来,比如:
private void UnlockPremiumFeatures() { // 比如显示付费功能的按钮,隐藏付费提示 premiumFeatureButton.Visibility = ViewStates.Visible; paywallLayout.Visibility = ViewStates.Gone; } private void LockPremiumFeatures() { premiumFeatureButton.Visibility = ViewStates.Gone; paywallLayout.Visibility = ViewStates.Visible; } // 把订阅状态保存到本地,比如SharedPreferences private void SaveSubscriptionStatus(bool isActive, long expiryTime) { var prefs = GetSharedPreferences("AppPrefs", FileCreationMode.Private); var editor = prefs.Edit(); editor.PutBoolean("IsSubscriptionActive", isActive); editor.PutLong("SubscriptionExpiry", expiryTime); editor.Apply(); }
额外注意事项
- 实时通知:配置Google Play的Real-Time Developer Notifications,这样当用户订阅续订、取消、退款时,你的服务器能收到实时通知,及时更新用户状态,不用等用户打开应用才检查
- 测试订阅:用Google Play控制台的测试账号和测试订阅进行测试,不要用真实账号产生费用
- 处理待支付订单:在
PurchaseUpdatedListener里处理Purchase.PurchaseState.Pending的情况,等支付完成后再解锁功能
内容的提问来源于stack exchange,提问作者Amit
相关产品推荐
相关产品推荐

