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

调用Google Play订阅API时用户姓名邮箱字段返回null问题求助

解决Google Play订阅API返回用户邮箱/姓名为null的问题

我来帮你分析下这个棘手的问题——你调用Google Play的Purchases.Subscriptions.Get接口时,EmailAddress、GivenName和FamilyName字段始终返回null,但其他购买信息(比如价格、国家代码)都显示正常,对吧?这其实是Google Play隐私机制导致的,咱们一步步来拆解解决:

问题背景

你的Android应用Akita Security(包名com.highiot.mob)提供订阅购买服务,用户完成购买后你拿到了purchase token,但调用API查询用户个人信息时,核心的身份字段全部为空。

相关代码片段

应用内购买代码(Xamarin)

private async void Purcase(string productId) { 
    try { 
        var connected = await CrossInAppBilling.Current.ConnectAsync(); 
        if (!connected) { 
            //Couldn't connect to billing, could be offline, alert user 
            return; 
        } 
        //try to purchase item 
        CrossInAppBilling.Current.InTestingMode = true; 
        var purchase = await CrossInAppBilling.Current.PurchaseAsync(productId, ItemType.Subscription, "apppayload"); 
        if (purchase == null) { 
            //Not purchased, alert the user 
        } else { 
            //Purchased, save this information 
            var id = purchase.Id; 
            var token = purchase.PurchaseToken; 
            var state = purchase.State; 
            bool status = false; 
            if (state == PurchaseState.PaymentPending) { 
                status = true; 
            } 
            ViewModel.SendSubscription(productId, token, "Google", status); 
        } 
    } catch (Exception ex) { 
        //Something bad has occurred, alert user 
    } finally { 
        //Disconnect, it is okay if we never connected 
        await CrossInAppBilling.Current.DisconnectAsync(); 
    } 
}

Google API调用代码

static async Task Main(string[] args) { 
    bool acknowledge = false; 
    string projectId = "robotic-circle-243009"; 
    string subscriptionId = "highiot-admin-api"; 
    var _credentialsJson = "HighIoT_key.json"; 
    Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", Path.Combine(AppDomain.CurrentDomain.BaseDirectory, _credentialsJson)); 
    SubscriptionName subscriptionName = new SubscriptionName(projectId, subscriptionId); 
    SubscriberClient subscriber = await SubscriberClient.CreateAsync(subscriptionName); 
    GoogleCredential credentialsPlay; 
    using (var key = new FileStream(_credentialsJson, FileMode.Open, FileAccess.Read)) 
        credentialsPlay = GoogleCredential.FromStream(key).CreateScoped(Scope.Androidpublisher); 
    var publisherService = new AndroidPublisherService(new BaseClientService.Initializer { 
        HttpClientInitializer = credentialsPlay 
    }); 
    var request1 = publisherService.Purchases.Subscriptions.Get(
        "com.highiot.mob", 
        "com.highiot.mob.test_subsription", 
        "nceeeoihojjngafdmfmahbii.AO-J1Ow8yISTj4C6MW4mKgXYp9Tizo7iZ8JP6PgIRenFLHj4xHaAuCxffDL5jaxEzq_t2IopZXXa4_uLyZYBsXMwk_wn3pwMXoL9rNDWJoZV8SCkVsXcAlaMJe0l2Mn_-OhhuHbjPVP8Tn0ruP4WUlxGPyxUjkNv_Q"
    ); 
    var response1 = request1.Execute(); 
}

服务账号凭证(HighIoT_key.json)

{ 
    "type": "service_account", 
    "project_id": "robotic-circle-243009", 
    "private_key_id": "cb017791695e97d8b2ab68ae94d940ba07def824", 
    "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDPJxCrGu1o1AdD\neiBtuxPS/0wdF4chN5KqK0hR8E6x7qfd30I9zI5k07msD3qEo2iuBWwohIeUCWLh\n5x0Xkkx8ADQqWh9Z0HlWcx8JEFIqeKGy+l7j8mnLtv71xxnUSZdPuE7VQhNt9U2F\ng/uCehcF5rRYKsb9m//uS1dzAFfPepnwgOyAbxL91EUX8TFpfjqonof+pV4N4kTd\nT+U6YcK9FEyQCBUIMW3SJRYQE3lVjxKOVI7osoh3ileMMyFmYhROkuHgL4dMijHa\nXtI6d+8ZkbBtmGy28yYFzMwFKdyb5r9locpcpfXRJnRFRgEHRkGBkvAjdQo/KeNp\nznDsEzKlAgMBAAECggEAMrYJ/xEm+EgbhRnDEYnAFyGXVPHbCzcrCMxytlhhM27M\nmmSatz05yJYKOIRLhmfoat159ktHU2ae1dV5ijkuzxZPruSEEz0VTyP8f4AG1U3V\nq9Zd32iLHKsuLCWy/YSMbaAdcFhuIDdyZFKEghL4SuII2SKTtyb21rOL82Osm2Yj\niiB+04huCKOXvau86284c6GuTtUCRRGPuT85LsV4gQvSLa9gSm9UrMonKktXjdRA\nZenOYtofc4gVjIFozHZwLWleSaM/9jaX0IJ7uct3G1DObqEptCfQnSRQsa1Mtv6e\nXSazGPYMAGW+XOF/yWwuM0zCyI3GyEbc989PI/4IuwKBgQD1Yz3qAeQGYMToLNb7\nUMd0OtWxJFHHa2J97Dwlv73/aGroByAkc4bmYo2ub1YW/JVcyu94IfNR0wHGiV07\ncwFOkYlEYDMWv11VMBeqhHrLmk242jM1ZxhIoNC59RcSBnQHnbvHCe2FugKH7s51\nSHV8EUWR+CkIpZRLNIJBEXv4BwKBgQDYHIMBJ0vYE0O+EvJHR3DQrOQN4xLb2GlI\nFvN1+6N2oox5yfXUlHLi9g138cJnqpayERGE9lZfphSoAtgcgidwJDx7VCkf5C+Q\n8P4wkgL24svZhcJJI2xmnTV8LrG6nU81bUu5dyGTnFeeVPQLcoscVKyII1NbXPBc\nIPbmTAoc8wKBgEl7K2osoMTMK4q/Cq19Ngz3JVCDaL3HyVmd6TEApvuZoBHVOGnR\n8n6A2p52lpgRkQSVfHpD6GIDRs/WCIYp3SVS7YD9Ma9JJMDCwwN74m2fylBlftoq\nAhqVlYtp+jualRpGwJlMvsTBu8pK16ZFSXEalvOsFVWSh8KxeaPUgYP3AoGAT0oe\nspSlWhCvYRR4ebh3ZsiYH5Q5fhmnfwCUsKvzrHo1ChYUMLuKb0URafl0dy56fbiP\ncfYjeJJpr77jZYpHR/izjBgzwnSpEweoa0+W8NgDLLrLrqPliLyTPA2xvaMrxZFl\nIBXaZtsMtpW6uFx9N5bFemljkvjFYzfg/lvVtgsCgYEAqMQ8CEjizn91k8ACK6Fs\nFQkCLjSl5h/lvES0+VZDlWMIwos0e6a7vsTVg0IoJ32hY2a7E6R37MbHP2o6lJiS\njJPzBd5pa803DYl8ehId0/8PAUsMscK6LKPblQW9QzoYk5yEjhU1bFLJQfLmmQsV\neRHZgYsNE/U60DnuZsv4wZg=\n-----END PRIVATE KEY-----\n", 
    "client_email": "highiot-server@robotic-circle-243009.iam.gserviceaccount.com", 
    "client_id": "110565816019675715733", 
    "auth_uri": "https://accounts.google.com/o/oauth2/auth", 
    "token_uri": "https://oauth2.googleapis.com/token", 
    "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", 
    "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/highiot-server%40robotic-circle-243009.iam.gserviceaccount.com" 
}

API返回结果

Name Value 
◢ response1 {Google.Apis.AndroidPublisher.v3.Data.SubscriptionPurchase} 
AcknowledgementState 1 
AutoRenewing false 
AutoResumeTimeMillis null 
CancelReason 0 
▶ CancelSurveyResult {Google.Apis.AndroidPublisher.v3.Data.SubscriptionCancelSurveyResult} 
CountryCode “UA” 
DeveloperPayload “apppayload” 
ETag “\"kLoaNGFQwzHXpxRSLTfX9req9yE/1xXhq0Lm_lUloQUDN3UhbVIoE08\"” 
EmailAddress null 
ExpiryTimeMillis 1568883651389 
FamilyName null 
GivenName null 
Kind “androidpublisher#subscriptionPurchase” 
LinkedPurchaseToken null 
OrderId “GPA.3309-8881-6545-64850” 
PaymentState 1 
PriceAmountMicros 21990000 
PriceChange null 
PriceCurrencyCode “UAH” 
ProfileId null 
ProfileName null 
PurchaseType null 
StartTimeMillis 1566205275451 
UserCancellationTimeMillis 1566209506502

当前配置情况

  • Google Play Console:已关联项目,添加了服务账号,服务账号已出现在用户菜单中
  • Google API开发者控制台:已为服务账号授权,启用了Google Play Android Developer API,并添加了查看用户信息的权限范围

核心原因与解决办法

为什么这些字段返回null?

Google Play不会默认返回用户的邮箱、姓名等敏感隐私信息,必须同时满足两个条件:

  1. 你的应用在发起购买时,主动请求获取用户个人信息的授权
  2. 用户在购买流程中明确同意授权你的应用获取这些信息

具体修复步骤

1. 修改内购代码,触发用户授权流程

你当前使用的是Xamarin的CrossInAppBilling第三方插件,需要确保插件支持请求用户账号信息。尝试在调用PurchaseAsync前添加以下代码(需确认插件版本是否支持该API):

// 请求获取用户账号信息
CrossInAppBilling.Current.SetObtainAccountDetails(true);

如果插件不支持,建议直接切换到官方Google Play Billing Library(Xamarin也有对应的绑定库),官方库提供了完整的AccountIdentifiers获取能力,能确保你正确触发授权流程。

2. 关闭测试模式测试

你代码中设置了CrossInAppBilling.Current.InTestingMode = true;,测试模式下Google Play会模拟购买流程,不会返回真实的用户个人信息。建议切换到内部测试渠道或正式环境,用真实账号完成购买测试。

3. 确认服务账号权限

虽然你已经添加了androidpublisher权限,仍需在Google Play Console的「用户和权限」-「服务账号」中,确认服务账号拥有**「查看订单和订阅数据」**的权限(通常是「订单管理」或「财务数据」相关权限)。

4. 检查用户授权状态

如果用户在购买时拒绝了授权请求,这些字段依然会返回null。你可以在购买成功后,先通过Billing API的AccountIdentifiers获取用户账号信息(如果授权成功),再调用Subscriptions.Get接口,此时个人信息字段才会被填充。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:26:31