Google Apps Marketplace UpgradeableApp API获取"代码":500,"消息":"后端错误"

时间:2014-09-12 05:54:29

标签: oauth google-apps-marketplace

我们正在使用UpgradeableApp API资源迁移Google Apps Marketplace列表,但在调用时 PUT https://www.googleapis.com/appsmarket/v2/upgradableApp/listingID/cwsID/domain 签名请求收到错误:

81 {"error":{"errors":[{"domain":"global","reason":"backendError","message":"Backend Error"}],"code":500,"message":"Backend Error"}} 0

我做错了什么......

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OAuth.Net.Common;

using OAuth.Net.Components;
using System.IO;
using System.Net;
using System.Security.Cryptography;

namespace Google_UpgradeableApi_Console
{
    class Program
    {
        private static readonly ISigningProvider SigningProvider = new HmacSha1SigningProvider();

        static void Main(string[] args)
        {
            // Setup the variables necessary to create the OAuth 1.0 signature and make the request   
            string httpMethod = "PUT";
            string listingID = "xxxx+23453809800066606066";
            string cwsID = "bbmagicjcjeblpadhhnnjahfbbbbhjk";
            string domain = "xyz.com";


            Uri url = new Uri(String.Format("{0}/{1}/{2}/{3}", "https://www.googleapis.com/appsmarket/v2/upgradableApp", listingID, cwsID, domain));


            string consumerKey = "xyz.apps.googleusercontent.com";
            string secret = "gt2sj34656U687f8qj677+GK";

            string body = "";

            MemoryStream requestBody = null;

            string signatureMethod = SigningProvider.SignatureMethod;


            HttpWebResponse response = null;

            // Set the Nonce and Timestamp parameters
            string nonce = getNonce();
            string timestamp = getTimestamp();

            // Set the request body if making a POST or PUT request
            if (httpMethod == "POST" || httpMethod == "PUT")
            {
                requestBody = new MemoryStream(Encoding.UTF8.GetBytes(body));
            }


            // Create the OAuth parameter name/value pair dictionary
            Dictionary<string, string> oauthParams = new Dictionary<string, string>
                {
                    { "oauth_consumer_key", consumerKey },
                    { "oauth_signature_method", signatureMethod },
                    { "oauth_timestamp", timestamp },
                    { "oauth_nonce", nonce },
                };






            // Get the OAuth 1.0 Signature
            string signature = generateSignature(httpMethod, url, oauthParams, requestBody, secret);
            Console.WriteLine("OAuth 1.0 Signature = " + signature + "\r\n\r\n");

            // Add the oauth_signature parameter to the set of OAuth Parameters
            IEnumerable<KeyValuePair<string, string>> allParams = oauthParams.Union(new[]
            {
                new KeyValuePair<string, string>("oauth_signature", signature)
            });

            // Defines a query that produces a set of: keyname="URL-encoded(value)"
            IEnumerable<string> encodedParams = from param in allParams
                                                select param.Key + "=\"" + Uri.EscapeDataString(param.Value) + "\"";

            // Join all encoded parameters with a comma delimiter and convert to a string
            string stringParams = String.Join(",", encodedParams);

            // Build the X-Authorization request header
            string xauth = String.Format("X-Authorization: OAuth realm=\"{0}\",{1}", url, stringParams);
            Console.WriteLine("X-Authorization request header: \r\n" + xauth + "\r\n\r\n");

            try
            {
                // Setup the Request
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                request.Method = httpMethod;
                request.Headers.Add(xauth);

                // Set the request body if making a POST or PUT request
                if (httpMethod == "POST" || httpMethod == "PUT")
                {
                    byte[] dataArray = Encoding.UTF8.GetBytes(body);
                    request.ContentLength = dataArray.Length;

                    Stream requestStream = request.GetRequestStream();
                    requestStream.Write(dataArray, 0, dataArray.Length);
                    requestStream.Close();
                }

                // Send Request & Get Response
                response = (HttpWebResponse)request.GetResponse();

                using (StreamReader reader = new StreamReader(response.GetResponseStream()))
                {
                    // Get the response stream and write to console
                    string json = reader.ReadToEnd();
                    Console.WriteLine("Successful Response: \r\n" + json);
                }
            }
            catch (WebException e)
            {
                // This exception will be raised if the server didn't return 200 - OK
                // Retrieve more information about the error
                if (e.Response != null)
                {
                    using (HttpWebResponse err = (HttpWebResponse)e.Response)
                    {
                        Console.WriteLine("The server returned '{0}' with the status code '{1} ({2:d})'.",
                          err.StatusDescription, err.StatusCode, err.StatusCode);
                    }
                }
            }
            finally
            {
                if (response != null) { response.Close(); }
            }

            Console.ReadLine();
        }


        #region Helper Functions

        /// <summary>
        /// Generates a random nonce.
        /// </summary>
        /// <returns>A unique identifier for the request.</returns>
        private static string getNonce()
        {
            string rtn = Path.GetRandomFileName() + Path.GetRandomFileName() + Path.GetRandomFileName();
            rtn = rtn.Replace(".", "");
            if (rtn.Length > 32)
                return rtn.Substring(0, 32);
            else
                return rtn;
        }

        /// <summary>
        /// Generates an integer representing the number of seconds since the unix epoch using the 
        /// UTC date/time of the request.
        /// </summary>
        /// <returns>A timestamp for the request.</returns>
        private static string getTimestamp()
        {
            return ((int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds).ToString();
        }

        /// <summary>
        /// Generates an OAuth 1.0 signature.
        /// </summary>
        /// <param name="httpMethod">The HTTP method of the request.</param>
        /// <param name="url">The URI of the request.</param>
        /// <param name="oauthParams">The associative set of signable oauth parameters.</param>
        /// <param name="requestBody">A stream containing the serialized message body.</param>
        /// <param name="secret">Alphanumeric string used to validate the identity of the education partner (Private Key).</param>
        /// <returns>A string containing the BASE64-encoded signature digest.</returns>
        private static string generateSignature(
          string httpMethod,
          Uri url,
          IDictionary<string, string> oauthParams,
          Stream requestBody,
          string secret
        )
        {
            // Ensure the HTTP Method is upper-cased
            httpMethod = httpMethod.ToUpper();

            // Construct the URL-encoded OAuth parameter portion of the signature base string
            string encodedParams = normalizeParams(httpMethod, url, oauthParams, requestBody);

            // URL-encode the relative URL
            string encodedUri = Uri.EscapeDataString(url.AbsolutePath);

            // Build the signature base string to be signed with the Consumer Secret
            string baseString = String.Format("{0}&{1}&{2}", httpMethod, encodedUri, encodedParams);

            //return generateCmac(secret, baseString);
            return generateHMAC(secret, baseString);
        }

        /// <summary>
        /// Normalizes all oauth signable parameters and url query parameters according to OAuth 1.0.
        /// </summary>
        /// <param name="httpMethod">The upper-cased HTTP method.</param>
        /// <param name="url">The request URL.</param>
        /// <param name="oauthParams">The associative set of signable oauth parameters.</param>
        /// <param name="requestBody">A stream containing the serialized message body.</param>
        /// <returns>A string containing normalized and encoded OAuth parameters.</returns>
        private static string normalizeParams(
          string httpMethod,
          Uri url,
          IEnumerable<KeyValuePair<string, string>> oauthParams,
          Stream requestBody
        )
        {
            IEnumerable<KeyValuePair<string, string>> kvpParams = oauthParams;

            // Place any Query String parameters into a key value pair using equals ("=") to mark
            // the key/value relationship and join each paramter with an ampersand ("&")
            if (!String.IsNullOrWhiteSpace(url.Query))
            {
                IEnumerable<KeyValuePair<string, string>> queryParams =
                  from p in url.Query.Substring(1).Split('&').AsEnumerable()
                  let key = Uri.EscapeDataString(p.Substring(0, p.IndexOf("=")))
                  let value = Uri.EscapeDataString(p.Substring(p.IndexOf("=") + 1))
                  select new KeyValuePair<string, string>(key, value);

                kvpParams = kvpParams.Union(queryParams);
            }

            // Include the body parameter if dealing with a POST or PUT request
            if (httpMethod == "POST" || httpMethod == "PUT")
            {
                MemoryStream ms = new MemoryStream();
                requestBody.CopyTo(ms);
                byte[] bodyBytes = ms.ToArray();

                string body = Convert.ToBase64String(bodyBytes, Base64FormattingOptions.None);
                body = Uri.EscapeDataString(body);

                kvpParams = kvpParams.Union(new[]
            {
              new KeyValuePair<string, string>("body", Uri.EscapeDataString(body))
            });
            }

            // Sort the parameters in lexicographical order, 1st by Key then by Value; separate with ("=")
            IEnumerable<string> sortedParams =
              from p in kvpParams
              orderby p.Key ascending, p.Value ascending
              select p.Key + "=" + p.Value;

            // Add the ampersand delimiter and then URL-encode the equals ("%3D") and ampersand ("%26")
            string stringParams = String.Join("&", sortedParams);
            string encodedParams = Uri.EscapeDataString(stringParams);

            return encodedParams;
        }



        private static string generateHMAC(string _key, string _msg)
        {
            string message;
            string key;
            key = _key;
            message = _msg;
            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
            byte[] keyByte = encoding.GetBytes(key);


            HMACSHA1 hmacsha1 = new HMACSHA1(keyByte);

            byte[] messageBytes = encoding.GetBytes(message);


            byte[] hashmessage = hmacsha1.ComputeHash(messageBytes);
            return ByteToString(hashmessage);
        }
        public static string ByteToString(byte[] buff)
        {
            string sbinary = "";

            for (int i = 0; i < buff.Length; i++)
            {
                sbinary += buff[i].ToString("X2"); // hex format
            }
            return (sbinary);

        }

        #endregion // Helper Functions

    }
}

1 个答案:

答案 0 :(得分:1)

这背后有很多原因,但首先请检查网址是否必须使用OAuth1(非OAuth2)进行签名,并且必须具有其他参数的有效值。错误报告可能会因为很多原因而抛出相同的错误,但请确保您的设置正确并确保您的应用程序在新的Chrome应用程序市场上发布。请务必在此处提交Google Apps Marketplace清单审核申请表:

https://docs.google.com/forms/d/14QOb8PbSLKDgwIp8Zv-luoAAVurPXUqtzL0Hgikp3rk/viewform

毕竟完成并获得谷歌批准(您将收到一封电子邮件)您的应用程序然后使用oAuth 1.0签名请求调用UpgradeableApp API,以下是一个示例,您可以看到如何执行此操作。

http://www.codeproject.com/Tips/359144/Legged-OAuth-Authentication-in-NET-Csharp

希望有所帮助