4

我正在尝试使用 Google APIs .NET 客户端库从我的 ASP.NET Web 服务器访问购买状态 API,这是使用Purchase API v1.1的推荐方式。但是,此 API 的授权页面建议将 Web 请求直接发送到 Google 的 OAuth2 页面,而不是使用相应的客户端库。

好的,我用我能想象到的所有变体尝试了这两种方法,它们都导致“远程服务器返回错误:(400)错误请求。”。

现在我做了什么来达到我的目的。首先,我在授权页面的创建 API 控制台项目下完成了所有步骤 1-8 。接下来,我按照那里的描述生成了一个刷新令牌。在刷新令牌生成期间,我选择了与发布我的 Android 应用程序(现在处于发布的 beta 状态)相同的 Google 帐户。

接下来,我在 Visual Studio 中创建了一个用于测试目的的控制台 C# 应用程序(可能是控制台应用程序有问题?)并尝试使用此代码(在一些 Google API 示例中找到)调用购买 API:

    private static void Main(string[] args)
    {
        var provider =
            new WebServerClient(GoogleAuthenticationServer.Description)
                {
                    ClientIdentifier = "91....751.apps.googleusercontent.com",
                    ClientSecret = "wRT0Kf_b....ow"
                };
        var auth = new OAuth2Authenticator<WebServerClient>(
            provider, GetAuthorization);

        var service = new AndroidPublisherService(
            new BaseClientService.Initializer()
                {
                    Authenticator = auth,
                    ApplicationName = APP_NAME
                });

        var request = service.Inapppurchases.Get(
            PACKAGE_NAME, PRODUCT_ID, PURCHASE_TOKEN);
        var purchaseState = request.Execute();

        Console.WriteLine(JsonConvert.SerializeObject(purchaseState));
    }

    private static IAuthorizationState GetAuthorization(WebServerClient client)
    {
        IAuthorizationState state =
            new AuthorizationState(
                new[] {"https://www.googleapis.com/auth/androidpublisher"})
                {
                    RefreshToken = "4/lWX1B3nU0_Ya....gAI"
                };

        // below is my redirect URI which I used to get a refresh token
        // I tried with and without this statement
        state.Callback = new Uri("https://XXXXX.com/oauth2callback/");

        client.RefreshToken(state); // <-- Here we have (400) Bad request
        return state;
    }

然后我尝试了这段代码来获取访问令牌(我在这里找到了它:Google Calendar API - Bad Request (400) Trying To Swap Code For Access Token):

    public static string GetAccessToken()
    {
        var request = WebRequest.Create(
            "https://accounts.google.com/o/oauth2/token");
        request.Method = "POST";
        var postData =
            string.Format(
                @"code={0}&client_id={1}&client_secret={2}&redirect_uri={3}&grant_type=authorization_code",
            // refresh token I got from browser
            // also tried with Url encoded value
            // 4%2FlWX1B3nU0_Yax....gAI
                "4/lWX1B3nU0_Yax....gAI",
            // ClientID from Google APIs Console
                "919....1.apps.googleusercontent.com",
            // Client secret from Google APIs Console
                "wRT0Kf_bE....w",
            // redirect URI from Google APIs Console
            // also tried Url encoded value
            // https%3A%2F%2FXXXXX.com%2Foauth2callback%2F
                "https://XXXXX.com/oauth2callback/");

        byte[] byteArray = Encoding.UTF8.GetBytes(postData);
        request.ContentType = "application/x-www-form-urlencoded";
        request.ContentLength = byteArray.Length;
        using (var dataStream = request.GetRequestStream())
        {
            dataStream.Write(byteArray, 0, byteArray.Length);
            dataStream.Close();
        }
        try
        {
            // request.GetResponse() --> (400) Bad request again!
            using (var response = request.GetResponse())
            {
                using (var dataStream = response.GetResponseStream())
                {
                    using (var reader = new StreamReader(dataStream))
                    {
                        var responseFromServer = reader.ReadToEnd();
                        var jsonResponse = JsonConvert.DeserializeObject<OAuth2Response>(responseFromServer);
                        return jsonResponse.access_token;
                    }
                }
            }
        }
        catch (Exception ex) { var x = ex; }
        return null;
    }

所以,总结一下我所有的长篇故事:

  1. 是否可以使用上述任何一种方法从 C# 控制台应用程序(无需用户交互)通过 OAuth2 授权?
  2. 我已经仔细检查了重定向 URI(因为我在 stackoverflow 上看到了很多讨论的问题)和其他参数,如 ClientID 和 ClientSecret。在上面的代码中我还能做错什么?
  3. 我是否需要在刷新令牌中对斜杠进行 URL 编码(我看到使用客户端库的第一种方法可以做到)?
  4. 实现我的最终目标(从 ASP.NET Web 服务器购买 API 访问)的推荐方法是什么?
4

2 回答 2

14

我会尽力回答你的最后一个问题。如果您访问自己的数据帐户,则不需要在 oAuth2 中使用客户端 ID。让我们使用服务帐户来访问 Google Play API。

  1. Google Developer Console在> Your project> APIs and auth> Credentials>中创建服务帐户Create a new key。您将下载 p12 密钥。
  2. 创建一个 C# 项目。您可以选择控制台应用程序。
  3. 从Google.Apis.androidpublisher安装 google play api 库。努吉特您可以在Google APIs Client Library for .NET中找到其他 dotnet库
  4. 在 API 访问中将 google api 项目与您的 google play 帐户关联

  5. 验证并尝试查询信息。我会尝试列出所有应用内项目。您可以更改以获取购买状态

    String serviceAccountEmail = "your-mail-in-developer-console@developer.gserviceaccount.com";
    
        var certificate = new X509Certificate2(@"physical-path-to-your-key\key.p12", "notasecret", X509KeyStorageFlags.Exportable);
    
        ServiceAccountCredential credential = new ServiceAccountCredential(
           new ServiceAccountCredential.Initializer(serviceAccountEmail)
           {
               Scopes = new[] { "https://www.googleapis.com/auth/androidpublisher" }
           }.FromCertificate(certificate));
    
    
        var service = new AndroidPublisherService(
       new BaseClientService.Initializer()
       {
           HttpClientInitializer = credential,
           ApplicationName = "GooglePlay API Sample",
       });
    // try catch this function because if you input wrong params ( wrong token) google will return error.
        var request = service.Inappproducts.List("your-package-name");
        var purchaseState = request.Execute();
    
       // var request = service.Purchases.Products.Get(
       //"your-package-name", "your-inapp-item-id", "purchase-token"); get purchase'status
    
    
    
        Console.WriteLine(JsonConvert.SerializeObject(purchaseState));
    
于 2014-12-27T15:58:55.970 回答
-1

您应该在您的私有静态 IAuthorizationState GetAuthorization(WebServerClient client) 方法中执行以下操作:

        private IAuthorizationState GetAuthorization(WebServerClient client)
        {
            IAuthorizationState state = AuthState;
            if (state != null)
            {
                return state;
            }

            state = new AuthorizationState()
            {
                RefreshToken = "4/lWX1B3nU0_Ya....gAI",
                Callback = new Uri(@"https://XXXXX.com/oauth2callback/")
            };
            client.RefreshToken(state);

            // Store and return the credentials.
            HttpContext.Current.Session["AUTH_STATE"] = _state = state;
            return state;
        }
  1. 请让我知道这对你有没有用。
  2. 请注意,我们知道今天整个 OAuth2 流程很尴尬,我们正在努力改进它。
于 2013-08-09T14:38:24.093 回答