Google Analytics Api 400 Bad Request - c#

I want to import data from Google Analytics.
var gas = new AnalyticsService(auth);
var r = gas.Data.Ga.Get("ga:6332XXXX", "2013-02-01", "2013-02-11", "ga:visits");
r.Dimensions = "ga:date";
r.Sort = "ga:visits";
r.StartIndex = 1;
var data = r.Fetch();
I get 400 bad request error in Fetch method. What is the wrong of my code?
My full code like following:
var scope = AnalyticsService.Scopes.AnalyticsReadonly.ToString();
var clientId = "--------.apps.googleusercontent.com";
var keyFile = #"C:\-----------------privatekey.p12";
var keyPassword = "notasecret";
var desc = GoogleAuthenticationServer.Description;
var key = new X509Certificate2(keyFile, keyPassword, X509KeyStorageFlags.Exportable);
var client = new AssertionFlowClient(desc, key)
{
ServiceAccountId = clientId,
Scope = scope
};
var auth = new OAuth2Authenticator<AssertionFlowClient>(client, AssertionFlowClient.GetState);
var gas = new AnalyticsService(auth);
var r = gas.Data.Ga.Get("ga:6332XXXX", "2013-02-01", "2013-02-11", "ga:visits");
r.Dimensions = "ga:date";
r.Sort = "ga:visits";
r.StartIndex = 1;
var data = r.Fetch();
Thaks for your interest.

A couple of ideas:
your clientId should be your SERVICE ACCOUNT EMAIL (not id)
your scope should be "https://www.googleapis.com/auth/analytics.readonly"
If this doesn't work, check #Martyn's answer

Related

Unable to update graph application based subscription with C#

I am trying to update the subscription expiry for my graph token. This is an application based subscription.
This is what I have tried:
var tokenExpiry = DateTime.UtcNow.AddMinutes(4230).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.0Z");
Lookup lp = new Lookup();
string access_token = "{MYACCESSTOKEN}";
_CreateRequestBody requestBody = new _CreateRequestBody
{
expirationDateTime = tokenExpiry
};
RestClient rc = new RestClient();
rc.EndPoint = "https://graph.microsoft.com/v1.0/subscriptions/" + subscriptionId;
rc.AccessToken = access_token;
rc.Method = HttpVerbs.PATCH;
rc.PostData = JsonConvert.SerializeObject(requestBody);
Error message is Invalid: expirationDateTime and its value must be included in the payload.

Algotrading: MEXC Authentication issue C#

I'm building a MEXC connector and I use their official docs here: https://mxcdevelop.github.io/APIDoc/open.api.v2.en.html#request-format
I have an issue with the authentication method they provided. I have an authentication function which I took from their example code in the docs (which is here). I use RestSharp to connect to the REST API. However, I get authentication errors when I try to post a spot trade order. Other methods work fine which still have authentication. Here is my Place Order method:
public async Task<PlaceOrder> GetPlaceOrderAsync(string symbol, string price, string quantity, string trade_type, string order_type)
{
PlaceOrder result = new PlaceOrder();
var Params = new Dictionary<string, string>
{
{"order_type", order_type },
{"price" , price },
{"quantity", quantity },
{"symbol" , symbol },
{"trade_type", trade_type },
};
var serializedParams = JsonConvert.SerializeObject(Params);
var paramString = getRequestParamString(Params);
var encodedString = urlEncode(paramString);
var Timestamp = DateTime.UtcNow.ToUnixTimeMilliseconds().ToString();
var signature = sign(Timestamp, paramString);
var cleanedSignature = signature.Replace("-", "");
var restClient = new RestClient();
var restRequest = new RestRequest("https://www.mexc.com/open/api/v2/order/place?" +
"api_key=" + this.ApiKey +
"&req_time=" + Timestamp +
"&sign=" + cleanedSignature,
Method.POST);
restRequest.AddHeader("ApiKey", this.ApiKey);
restRequest.AddHeader("Signature", cleanedSignature.ToLowerInvariant());
restRequest.AddHeader("Request-Time", Timestamp);
restRequest.AddHeader("content-type", "application/json");
restRequest.AddBody(serializedParams);
restRequest.RequestFormat = DataFormat.Json;
var restResponse = await restClient.ExecuteAsync(restRequest);
result = JsonConvert.DeserializeObject<PlaceOrder>(restResponse.Content);
return result;
What I get in return as a response is this:
"{"msg":"authorize failed","code":401}"
Which indicates that there is something wrong with the authentication but I have used the same authentication method in other private methods which require authentication. For comparison here is a User Balance checking method, note that balance method does not require any parameters so I'm sending an empty dictionary:
public async Task<Balance> GetBalanceAsync()
{
var Params = new Dictionary<string, string>
{
};
var paramString = getRequestParamString(Params);
var encodedString = urlEncode(paramString);
var Timestamp = DateTime.UtcNow.ToUnixTimeMilliseconds().ToString();
var signature = sign(Timestamp, encodedString);
var cleanedSignature = signature.Replace("-", "");
Balance result = new Balance();
var restClient = new RestClient();
var restRequest = new RestRequest("https://www.mexc.com/open/api/v2/account/info", Method.GET);
restRequest.AddHeader("ApiKey", this.ApiKey);
restRequest.AddHeader("Signature", cleanedSignature.ToLowerInvariant());
restRequest.AddHeader("Request-Time", Timestamp);
var restResponse = await restClient.ExecuteAsync(restRequest);
result = JsonConvert.DeserializeObject<Balance>(restResponse.Content);
return result;
}
If anyone could point out something that I can't see I would really appreciate it. MEXC integration is not very widespread on the net so I'm struggling to find other examples.

The system cannot find the file specified using X509Certificate2 to connect Google OAuth2.0 in an Azure Server

I'm using this code to connect to Google OAuth2.0 and I'm using the C# libraries.
using (var tImpersonationContext = new ImpersonationContext(ConfigurationManager.AppSettings["ImpersonationDomain"], ConfigurationManager.AppSettings["ImpersonationUser"], ConfigurationManager.AppSettings["ImpersonationPassword"]))
{
string[] tScopes = new string[] { AnalyticsService.Scope.Analytics };
var tKeyFilePath = Path.Combine(System.IO.Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]), String.Format("GoogleCertificates\\{0}", this.OAuthKeyName));
var tServiceAccountEmail = this.OAuthServiceAccountEmail;
//loading the Key file
var tCertificate = new X509Certificate2(tKeyFilePath, this.OAuthKeyPassword, X509KeyStorageFlags.Exportable);
var tCredential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(tServiceAccountEmail)
{
Scopes = tScopes
}.FromCertificate(tCertificate));
if (tCredential.RequestAccessTokenAsync(CancellationToken.None).Result)
{
this.SessionToken = tCredential.Token.AccessToken;
}
}
In my dev enviroment everything works just perfect but when I move the app to my Azure Server I got this error:
The system cannot find the file specified.
When I try to execute this line:
var tCertificate = new X509Certificate2(tKeyFilePath, this.OAuthKeyPassword, X509KeyStorageFlags.Exportable);
I'm sure that the path is correct, in fact if I copy and paste the path in the File Explorer the wizard to import the certificate starts.
I'm sure that the impersonation is working because the line is excecuted.
I have tried to change it to:
var tCertificate = new X509Certificate2(tKeyFilePath, this.OAuthKeyPassword, X509KeyStorageFlags.MachineKeySet);
Or this:
var tCertificate = new X509Certificate2(tKeyFilePath, this.OAuthKeyPassword, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.UserKeySet | X509KeyStorageFlags.UserProtected | X509KeyStorageFlags.DefaultKeySet);
And nothing is working, in fact everything I have tried from other questions of this web site are not working.
If it help is a Windows App that I pretend to use in a task scheduled, to get data from Google Analytics.
Does someone have any idea why is not working in the Azure Server??
Thanks in advance.
UPDATE
I have tried to install the certificate and I have change the code to this:
var tCertificate = new X509Certificate2(tKeyFilePath, this.OAuthKeyPassword, X509KeyStorageFlags.MachineKeySet);
But now I get this error:
Key not valid for use in specified state.
I have change all the code an the aproach and now is working.
First you have to instal your certificate in the MMC manager inside trusted root certificates authorities under certificates and it have to be set as a local machine.
And then you just have to use this code:
X509Store tCertStore = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
tCertStore.Open(OpenFlags.ReadOnly);
X509Certificate2Collection tCertCollection = tCertStore.Certificates.Find(X509FindType.FindByThumbprint, this.OAuthKeyFingerprint, false);
// Get the first cert with the thumbprint
if (tCertCollection.Count > 0)
{
// header
var tHeader = new { typ = "JWT", alg = "RS256" };
// claimset
var tTimes = GetExpiryAndIssueDate();
var tClaimset = new
{
iss = this.OAuthServiceAccountEmail,
scope = "https://www.googleapis.com/auth/analytics",
aud = "https://www.googleapis.com/oauth2/v3/token",
iat = tTimes[0],
exp = tTimes[1],
};
JavaScriptSerializer ser = new JavaScriptSerializer();
// encoded header
var tHeaderSerialized = ser.Serialize(tHeader);
var tHeaderBytes = Encoding.UTF8.GetBytes(tHeaderSerialized);
var tHeaderEncoded = Convert.ToBase64String(tHeaderBytes);
// encoded claimset
var tClaimsetSerialized = ser.Serialize(tClaimset);
var tClaimsetBytes = Encoding.UTF8.GetBytes(tClaimsetSerialized);
var tClaimsetEncoded = Convert.ToBase64String(tClaimsetBytes);
// input
var tInput = tHeaderEncoded + "." + tClaimsetEncoded;
var tInputBytes = Encoding.UTF8.GetBytes(tInput);
X509Certificate2 tCertificate = tCertCollection[0];
// signiture
var tRSA = tCertificate.PrivateKey as RSACryptoServiceProvider;
var tCspParam = new CspParameters
{
KeyContainerName = tRSA.CspKeyContainerInfo.KeyContainerName,
KeyNumber = tRSA.CspKeyContainerInfo.KeyNumber == KeyNumber.Exchange ? 1 : 2,
Flags = CspProviderFlags.UseMachineKeyStore
};
var tAesCsp = new RSACryptoServiceProvider(1024, tCspParam) { PersistKeyInCsp = true };
var tSignatureBytes = tAesCsp.SignData(tInputBytes, "SHA256");
var tSignatureEncoded = Convert.ToBase64String(tSignatureBytes);
// jwt
var tJWT = tHeaderEncoded + "." + tClaimsetEncoded + "." + tSignatureEncoded;
HttpClient tClient = new HttpClient();
Dictionary<string, string> tPost = new Dictionary<string, string>
{
{"assertion", tJWT},
{"grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer"}
};
FormUrlEncodedContent tContent = new FormUrlEncodedContent(tPost);
var tURI = "https://www.googleapis.com/oauth2/v3/token";
HttpResponseMessage tResult = tClient.PostAsync(tURI, tContent).Result;
TokenResponse tTokenObject = JsonConvert.DeserializeObject<TokenResponse>(tResult.Content.ReadAsStringAsync().Result);
this.SessionToken = tTokenObject.access_token;
}
tCertStore.Close();
I hope this help someone.
Happy coding.

ASP.NET MVC with MongoDB

Now I'm using C# MVC to implement an API, and the API data is from remote MongoDB. I found when I was testing my API, it had MongoDB connection timeout error appeared sometimes. Does anyone know how to solve this problem?
This is the connection code
var settings = new MongoClientSettings
{
Credentials = new[] { MongoCredential.CreateMongoCRCredential("database", "user", "pw") },
Server = new MongoServerAddress("XXX.XXX.XXX", XXXXX),
ConnectTimeout = TimeSpan.FromSeconds(1800),
MaxConnectionIdleTime = TimeSpan.FromSeconds(1800),
};
//Get a Reference to the Client Object
var mongoClient = new MongoClient(settings);
var mongoServer = mongoClient.GetServer();
var database = mongoServer.GetDatabase("MongoDB");
Now I changed my code as follow, but I still encounter the same problem
var settings = new MongoClientSettings
{
Credentials = new[] { MongoCredential.CreateMongoCRCredential("database", "user", "pw") },
Server = new MongoServerAddress("XXX.XXX.XXX.XXX", XXXXX),
ConnectTimeout = TimeSpan.FromSeconds(1800),
MaxConnectionIdleTime = TimeSpan.FromSeconds(1800)
};
var mongoClient = new MongoClient(settings);
var database = mongoClient.GetDatabase(ConfigurationManager.AppSettings["mongoDBdatabase"]);
return database;
and get the data by the following code:
var database = Mongo.TestConnectDB();
var collection = database.GetCollection<BsonDocument>("User");
var builder = Builders<BsonDocument>.Filter;
var filter = builder.Eq("_id", ObjectId.Parse(id));
var cursor = await collection.FindAsync(filter);
var friendList = new List<MongoModels.User.Circle.Friend>();
while (await cursor.MoveNextAsync())
{
var user = cursor.Current;
friendList=BsonSerializer.Deserialize<MongoModels.User>(user.First()).circle.friend;
}

How to post to user's wall from application's name?

I tried to post to users wall using application access token but it still posts from users name. Is it possible to post from application's name?
var fbc = new FacebookWebClient();
var wc = new WebClient();
var tokenStr = wc.DownloadString(string.Format("https://graph.facebook.com/oauth/access_token?client_id={0}&client_secret={1}&grant_type=client_credentials",
FacebookApplication.Current.AppId, FacebookApplication.Current.AppSecret));
fbc.AccessToken = tokenStr.Replace("access_token=", string.Empty);
dynamic parameters = new ExpandoObject();
parameters.message = "testMessage";
//parameters.link = pageLink;
parameters.name = "testCaption";
dynamic result = fbc.Post(string.Format("{0}/feed", userID), parameters);
var fbPost = new FacebookClient ( accessToken );
dynamic result = fbPost.Post ( "me/feed", new { message = "Welcome to C# SDK and me" } );

Categories

Resources