使用应用商店服务访问分析数据

使用 Microsoft Store 分析 API,针对已注册到你的或组织的 Windows 合作伙伴中心帐户的应用以编程方式检索分析数据。 通过此 API,可以检索应用和加载项(也称为应用内产品或 IAP)购置、错误、应用分级和评论的数据。 此 API 使用 Microsoft Entra 对来自应用或服务的调用进行身份验证。

以下步骤介绍端到端过程:

  1. 确保已完成所有先决条件
  2. 在 Microsoft Store 分析 API 中调用方法之前, 请获取Microsoft Entra 访问令牌。 获取令牌后,在令牌过期之前,在调用 Microsoft Store 分析 API 时,需要 60 分钟才能使用此令牌。 该令牌到期后,可以重新生成一个。
  3. 调用Microsoft应用商店分析 API

步骤 1:完成使用 Microsoft 应用商店分析 API 的先决条件

在开始编写代码以调用Microsoft应用商店分析 API 之前,请确保已完成以下先决条件。

  • (或组织)必须具有Microsoft Entra 目录,并且必须具有 目录的全局管理员 权限。 如果已在 Microsoft 中使用 Microsoft 365 或其他业务服务,则已有Microsoft Entra 目录。 否则,可以在 合作伙伴中心创建新的合作伙伴中心 ,无需额外付费。

  • 必须将 Microsoft Entra 应用程序与合作伙伴中心帐户相关联,检索应用程序的租户 ID 和客户端 ID 并生成密钥。 Microsoft Entra 应用程序表示要从中调用 Microsoft 应用商店分析 API 的应用或服务。 需要租户 ID、客户端 ID 和密钥才能获取传递给 API 的 Microsoft Entra 访问令牌。

    注意

    你只需执行一次此任务。 拥有租户 ID、客户端 ID 和密钥后,可以随时重复使用它们,以创建新的Microsoft Entra 访问令牌。

若要将 Microsoft Entra 应用程序与合作伙伴中心帐户相关联,并检索所需的值:

  1. 在合作伙伴中心, 将组织的合作伙伴中心帐户与组织的Microsoft Entra 目录相关联。
  2. 接下来,从合作伙伴中心的“帐户设置”部分中的“用户添加表示将用于访问合作伙伴中心帐户分析数据的应用或服务的 Microsoft Entra 应用程序。 确保为此应用程序分配“管理者”角色。 如果Microsoft Entra 目录中尚不存在该应用程序,则可以 在合作伙伴中心创建新的 Microsoft Entra 应用程序。
  3. 返回到 “用户管理 ”页并导航到 “Microsoft Entra 应用程序 ”选项卡,单击Microsoft Entra 应用程序的名称转到应用程序设置,并复制 租户 ID客户端 ID 值。
  4. 单击“添加新密钥”。 在下一个屏幕上,复制“密钥”值。 离开此页后,不再可以访问此信息。 有关详细信息,请参阅 管理Microsoft Entra 应用程序的密钥。

步骤 2:获取Microsoft Entra 访问令牌

在调用 Microsoft Store Analytics API 中的任何方法之前,必须先获取传递给 API 中每个方法的 Authorization 标头的 Microsoft Entra 访问令牌。 获取访问令牌后,你有 60 分钟的时间来使用它,60 分钟后它将过期。 该令牌到期后,可以对它进行刷新,以便可以在之后调用该 API 时继续使用。

若要获取访问令牌,请按照 使用客户端凭据的服务到服务调用 中的说明将 HTTP POST 发送到 https://login.microsoftonline.com/<tenant_id>/oauth2/token 终结点。 示例请求如下所示。

POST https://login.microsoftonline.com/<tenant_id>/oauth2/token HTTP/1.1
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded; charset=utf-8

grant_type=client_credentials
&client_id=<your_client_id>
&client_secret=<your_client_secret>
&resource=https://manage.devcenter.microsoft.com

对于 POST URI 中的 tenant_id 值以及 client_idclient_secret 参数,请指定在上一部分中从合作伙伴中心中为应用程序检索的租户 ID、客户端 ID 和密钥。 对于 resource 参数,必须指定 https://manage.devcenter.microsoft.com

在你的访问令牌到期后,你可按照此处的说明刷新令牌。

注意

ResourceType=Graph.windows.net 于 2023 年 9 月弃用。 请迁移到 ResourceType =Graph.microsoft.com

步骤 3:调用Microsoft应用商店分析 API

获得Microsoft Entra 访问令牌后,即可调用 Microsoft Store 分析 API。 你必须将访问令牌传递到每个方法的 Authorization 标头。

UWP 应用和游戏的方法

以下方法可用于应用、游戏购置和附加购置:

UWP 应用的方法

在合作伙伴中心,UWP 应用可以使用以下分析方法。

场景 方法
购置、转换、安装和使用
应用错误
Insights
评分和评价
应用内广告和广告市场活动

桌面应用程序的方法

以下分析方法可供属于 Windows 桌面应用程序的开发人员帐户使用。

场景 方法
安装
应用程序错误
Insights

Xbox Live 服务的方法

对于使用 Xbox Live 服务的游戏,开发人员帐户可以使用以下其他方法。 适用于 Xbox 的 Microsoft Store Analytics API 不再可用。 gaming/xbox-live/get-started/join-dev-program/join-dev-program_nav

场景 方法
常规分析

硬件和驱动程序的方法

属于 Windows 硬件仪表板程序的开发人员帐户可以访问一组额外的方法来检索硬件和驱动程序的分析数据。 有关详细信息,请参阅硬件仪表板 API

代码示例

下面的代码示例演示如何获取 Microsoft Entra 访问令牌,以及如何从 C# 控制台应用调用 Microsoft Store Analytics API。 若要使用此代码示例,请将 tenantIdclientIdclientSecretappID 变量分配给你的方案的相应值。 此示例要求 Newtonsoft 的 Json.NET 包 反序列化 Microsoft Store 分析 API 返回的 JSON 数据。

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

namespace TestAnalyticsAPI
{
    class Program
    {
        static void Main(string[] args)
        {
            string tenantId = "<your tenant ID>";
            string clientId = "<your client ID>";
            string clientSecret = "<your secret>";

            string scope = "https://manage.devcenter.microsoft.com";

            // Retrieve an Azure AD access token
            string accessToken = GetClientCredentialAccessToken(
                    tenantId,
                    clientId,
                    clientSecret,
                    scope).Result;

            // This is your app's Store ID. This ID is available on
            // the App identity page of the Dev Center dashboard.
            string appID = "<your app's Store ID>";

            DateTime startDate = DateTime.Parse("08-01-2015");
            DateTime endDate = DateTime.Parse("11-01-2015");
            int pageSize = 1000;
            int startPageIndex = 0;

            // Call the Windows Store analytics API
            CallAnalyticsAPI(accessToken, appID, startDate, endDate, pageSize, startPageIndex);

            Console.Read();
        }

        private static void CallAnalyticsAPI(string accessToken, string appID, DateTime startDate, DateTime endDate, int top, int skip)
        {
            string requestURI;

            // Get app acquisitions
            requestURI = string.Format(
                "https://manage.devcenter.microsoft.com/v1.0/my/analytics/appacquisitions?applicationId={0}&startDate={1}&endDate={2}&top={3}&skip={4}",
                appID, startDate, endDate, top, skip);

            //// Get add-on acquisitions
            //requestURI = string.Format(
            //    "https://manage.devcenter.microsoft.com/v1.0/my/analytics/inappacquisitions?applicationId={0}&startDate={1}&endDate={2}&top={3}&skip={4}",
            //    appID, startDate, endDate, top, skip);

            //// Get app failures
            //requestURI = string.Format(
            //    "https://manage.devcenter.microsoft.com/v1.0/my/analytics/failurehits?applicationId={0}&startDate={1}&endDate={2}&top={3}&skip={4}",
            //    appID, startDate, endDate, top, skip);

            //// Get app ratings
            //requestURI = string.Format(
            //    "https://manage.devcenter.microsoft.com/v1.0/my/analytics/ratings?applicationId={0}&startDate={1}&endDate={2}top={3}&skip={4}",
            //    appID, startDate, endDate, top, skip);

            //// Get app reviews
            //requestURI = string.Format(
            //    "https://manage.devcenter.microsoft.com/v1.0/my/analytics/reviews?applicationId={0}&startDate={1}&endDate={2}&top={3}&skip={4}",
            //    appID, startDate, endDate, top, skip);

            HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, requestURI);
            requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

            WebRequestHandler handler = new WebRequestHandler();
            HttpClient httpClient = new HttpClient(handler);

            HttpResponseMessage response = httpClient.SendAsync(requestMessage).Result;

            Console.WriteLine(response);
            Console.WriteLine(response.Content.ReadAsStringAsync().Result);

            response.Dispose();
        }

        public static async Task<string> GetClientCredentialAccessToken(string tenantId, string clientId, string clientSecret, string scope)
        {
            string tokenEndpointFormat = "https://login.microsoftonline.com/{0}/oauth2/token";
            string tokenEndpoint = string.Format(tokenEndpointFormat, tenantId);

            dynamic result;
            using (HttpClient client = new HttpClient())
            {
                string tokenUrl = tokenEndpoint;
                using (
                    HttpRequestMessage request = new HttpRequestMessage(
                        HttpMethod.Post,
                        tokenUrl))
                {
                    string content =
                        string.Format(
                            "grant_type=client_credentials&client_id={0}&client_secret={1}&resource={2}",
                            clientId,
                            clientSecret,
                            scope);

                    request.Content = new StringContent(content, Encoding.UTF8, "application/x-www-form-urlencoded");

                    using (HttpResponseMessage response = await client.SendAsync(request))
                    {
                        string responseContent = await response.Content.ReadAsStringAsync();
                        result = JsonConvert.DeserializeObject(responseContent);
                    }
                }
            }

            return result.access_token;
        }
    }
}

错误响应

Microsoft存储分析 API 在包含错误代码和消息的 JSON 对象中返回错误响应。 下面的示例演示了由无效参数引起的错误响应。

{
    "code":"BadRequest",
    "data":[],
    "details":[],
    "innererror":{
        "code":"InvalidQueryParameters",
        "data":[
            "top parameter cannot be more than 10000"
        ],
        "details":[],
        "message":"One or More Query Parameters has invalid values.",
        "source":"AnalyticsAPI"
    },
    "message":"The calling client sent a bad request to the service.",
    "source":"AnalyticsAPI"
}