Fedex API not returning shipping rates C# - c#

I am trying to fetch shipping rates for fedex using below API and I am using C#
https://developer.fedex.com/api/en-sg/catalog/rate/v1/docs.html
But I am getting this error, below is my full code and error.
First of all I am calling OAuth API and generating token, which I am getting successfully then I am calling API to fetch rates but still not working. So any idea on this.
Error :
{StatusCode: 403, ReasonPhrase: 'Forbidden', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers:
{
Server: Layer7-API-Gateway
Date: Wed, 18 Jan 2023 11:09:22 GMT
Connection: close
Server-Timing: cdn-cache; desc=MISS
Server-Timing: edge; dur=615
Server-Timing: origin; dur=67
Content-Encoding: gzip
Content-Type: application/json;charset=UTF-8
Content-Length: 182
}}
Full code :
var client = new HttpClient();
string clientid = _configuration["FedEx:ClientId"];
string clientsecret = _configuration["FedEx:SecretKey"];
var url = "https://apis-sandbox.fedex.com/oauth/token";
var parametersAuth = new Dictionary<string, string>();
parametersAuth.Add("grant_type", "client_credentials");
parametersAuth.Add("client_id", clientid);
parametersAuth.Add("client_secret", clientsecret);
var reqAuth = new HttpRequestMessage(HttpMethod.Post, url) { Content = new FormUrlEncodedContent(parametersAuth) };
var resAuth = await client.SendAsync(reqAuth);
var authDetailsJson = await resAuth.Content.ReadAsStringAsync(); // here I am getting toekn successfully.
if (resAuth.StatusCode == System.Net.HttpStatusCode.OK)
{
var authDetails = JsonConvert.DeserializeObject<dynamic>(authDetailsJson);
JObject objRateContent = JObject.FromObject(new
{
AccountNumber = JObject.FromObject(new
{
Value = "My account number I am placing here"
}),
RequestedShipment = JObject.FromObject(new
{
Shipper = JObject.FromObject(new
{
Address = JObject.FromObject(new
{
City = "Anchorage",
StateOrProvinceCode = "AK",
PostalCode = "99504",
CountryCode = "US"
})
}),
Recipient = JObject.FromObject(new
{
Address = JObject.FromObject(new
{
City = "Kenai",
StateOrProvinceCode = "AK",
PostalCode = "99611",
CountryCode = "US"
})
}),
PickupType = "CONTACT_FEDEX_TO_SCHEDULE",
RequestedPackageLineItem = JObject.FromObject(new
{
Weight = JObject.FromObject(new
{
Units = "KG",
Value = 25
})
})
})
});
var input = JsonConvert.SerializeObject(objRateContent);
var urlquote = "https://apis-sandbox.fedex.com/rate/v1/rates/quotes";
var request = new HttpRequestMessage(HttpMethod.Post, urlquote);
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
request.Headers.Add("X-locale", "en_US");
request.Headers.Add("Authorization", "Bearer " + authDetails.access_token);
request.Content = new StringContent(input, Encoding.UTF8, "application/json");
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var response = await client.SendAsync(request);
var content = await response.Content.ReadAsStringAsync();

Related

C# REST Api always return 401 status code when i am calling API by HttpClient

I am working with Nasdaq Fund Network Data Service first time. i am calling their one of the API where passing user id,pwd and access key but always getting 401 status code. i am not able to figure out what is wrong in my http call. please some one have a look at the code and tell me where i made the mistake for which i am getting 401 status code instead of right response.
here is my sample code where i could not share actual credentials and access key.
giving the code
string url = "sample url";
Uri u = new Uri(url);
string username = "test1";
string password = "test2";
string accessKey = "myaccesskey";
var payload = new Dictionary<string, string>
{
{"username", username},
{"password", password},
{ "accessKey", accessKey}
};
string strPayload = JsonConvert.SerializeObject(payload);
//HttpContent c = new StringContent(strPayload, Encoding.UTF8, "application/json");
HttpContent c = new StringContent(strPayload, Encoding.UTF8, "application/x-www-form-urlencoded");
var response = string.Empty;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11;
using (var client = new HttpClient())
{
HttpRequestMessage request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = u,
Content = c
};
var result = client.SendAsync(request).Result;
if (result.IsSuccessStatusCode)
{
response = result.StatusCode.ToString();
}
}
This Error i am getting
{StatusCode: 401, ReasonPhrase: 'Check Username/Password or Access
Key', Version: 1.1, Content: System.Net.Http.StreamContent, Headers: {
Pragma: no-cache X-Frame-Options: SAMEORIGIN Cache-Control:
no-cache Date: Wed, 10 Aug 2022 11:55:36 GMT Content-Length: 0
Expires: -1 }}
Try the following in order to extract the JWT token you receive as a response.
var url = "https://nfn.nasdaq.com/servicecall/tempsession";
var formDataDictionary = new Dictionary<string, string>
{
{ "username", "test1"},
{ "password", "test2"},
{ "accessKey", "myaccesskey"}
};
var formData = new FormUrlEncodedContent(formDataDictionary);
using (var client = new HttpClient())
{
var response = await client.PostAsync(url, formData);
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadAsStringAsync();
var responseBody = JObject.Parse(result);
var accessToken = responseBody["data']"].Value<string>();
}

RestSharp: Error "expected type: JSONObject, found: Null"

I am using RestSharp library for my REST APIs, and I am getting 400 BadRequest "expected type: JSONObject, found: Null" for GET request. With Postman it is working fine.
{
"Result": {
"RequestId": "495f45c0-d9e9-11eb-9936-02a74f481686",
"OverallStatus": "FAILURE",
"ErrorDetails": [
{
"ErrorLineItem": {
"ErrorCode": "400",
"ErrorMessage": "Bad Request",
"ErrorDescription": "expected type: JSONObject, found: Null"
}
}
]
}
}
Below is my code:
var request = new GetAlertProfileDistributionChannelRequest
{
AccountCustomerNumber = "*****201",
DistributionChannelSubscriptions = new AlertProfileDistributionChannelSubscriptions
{
AlertProfileId = Guid.Parse("7adaaa2c-5b2d-424c-8dc8-4e9a01908729")
}
};
var client = new RestClient("https://******/v1/profile/channels")
{
Timeout = -1
};
var apiRequest = new RestRequest(Method.GET) { RequestFormat = DataFormat.Json };
apiRequest.AddHeader("client_id", "********4cedc");
apiRequest.AddHeader("client_secret", "*******d526c");
apiRequest.AddHeader("Authorization", $"Bearer eyJhbGciOiJSUzI*******");
apiRequest.AddHeader("Content-Type", "application/json");
apiRequest.AddParameter("application/json", JsonConvert.SerializeObject(request), ParameterType.RequestBody);
var apiResponse = client.ExecuteAsync(apiRequest).Result;
Console.WriteLine(apiResponse.Content);
With Postman it is working fine:
Am I missing something here?
I resolved my issue with System.Net.Http.WinHttpHandler package that does support the functionality - simply installed and used when constructing my HttpClient instances.
var request = new GetAlertProfileDistributionChannelRequest
{
AccountCustomerNumber = "***0201",
DistributionChannelSubscriptions = new AlertProfileDistributionChannelSubscriptions
{
AlertProfileId = Guid.Parse("7adaaa2c-5b2d-424c-8dc8-4e9a01908729")
}
};
var handler = new WinHttpHandler();
var client = new HttpClient(handler);
client.DefaultRequestHeaders.Add("client_id", "**********5487");
client.DefaultRequestHeaders.Add("client_secret", "*******c99");
client.DefaultRequestHeaders.Add("Authorization", "Bearer eyJhbGciOiJSU");
var apirequest = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri("https://*********profile/channels"),
Content = new StringContent(JsonConvert.SerializeObject(request), Encoding.UTF8, "application/json"),
};
var response = client.SendAsync(apirequest).Result;
response.EnsureSuccessStatusCode();
var result = response.Content.ReadAsStringAsync().Result;

MS Graph API returns 400 Bad request

I am using HttpClient to call Microsoft Graph and create a new Team. I am using the Beta version.
string TeamsName = objTeam.TeamsName.ToString();
string TeamsDescription = objTeam.TeamsDescription.ToString();
var objJson = new CreateTeamsJson
{
templateodatabind = "https://graph.microsoft.com/beta/teamsTemplates(\'educationClass\')",
displayName = TeamsName,
description = TeamsDescription
};
var json = JsonConvert.SerializeObject(objJson, jsonSettings);
var modifiedjson = json.Replace("templateodatabind", "template#odata.bind");
StringContent postContent = new StringContent(modifiedjson, UnicodeEncoding.UTF8, "application/json");
if (!string.IsNullOrEmpty(TeamsName))
{
TokenHelper tokenHelper = new TokenHelper();
TokenResponse tokenResponse = tokenHelper.GetTokenAsync().Result;
using(HttpClient httpClient = new HttpClient())
{
var request = new HttpRequestMessage(HttpMethod.Post, "https://graph.microsoft.com/beta/teams");
request.Headers.Authorization = new AuthenticationHeaderValue("bearer", tokenResponse.access_token);
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
request.Content = postContent;
var response = httpClient.SendAsync(request).Result;
var createdTeamDetails = response.Headers.Location;
if (response.IsSuccessStatusCode)
{
responseMessage = string.Format("Successfully created team - details: '{0}'", createdTeamDetails);
}
else
{
responseMessage = "ERROR: Failed to create Team.";
}
}
}
else
{
log.Info("Please provide Teams Name");
responseMessage = "Please provide Teams Name";
IsError = true;
}
When I run the code I am getting a 400 - Bad Rrequest at the following line:
var response = httpClient.SendAsync(request).Result;
I tried the same endpoint and same JSON body request in Graph Explorer and I could create teams successfully. Can anybody help me?

HttpClient with csrf_token response unauthorized error

so able to do this manually using postman. Two steps involved , first do a Get with UserID/password. From the response get the csrf token attach the same in Another post method. No Authentication required in second call but just token with JSON payload returns the 200 response code.
Now tried these steps in C# and getting UnAuthorized error. Not sure if am attaching the token correct. below is the code.
var awdToken = await getAWDToken();
if (awdToken != null)
{
awdAddUser = await AddAWDUser(awdToken, userDetails);
}
private async Task<string> getAWDToken()
{
using (var client = new HttpClient())
{
string targetUri = string.Empty;
string userId = string.Empty;
string pass = string.Empty;
Dictionary<string, string> _awdConfigs;
_userSecurityWrok.CleintConfiguration.ClientAppConfigs.TryGetValue(string.Concat("AWD", "1"), out _awdConfigs);
if (_awdConfigs != null)
{
_awdConfigs.TryGetValue("AWDShortNameURL", out targetUri);
_awdConfigs.TryGetValue("UserName", out userId);
_awdConfigs.TryGetValue("Password", out pass);
}
client.BaseAddress = new Uri(targetUri);
var byteArray = new UTF8Encoding().GetBytes(userId + ":" + pass);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
client.DefaultRequestHeaders.ExpectContinue = false;
var response = await client.GetAsync(targetUri).ConfigureAwait(false);
IEnumerable<string> _tokens = response.Headers.GetValues("csrf_token");
var token = _tokens.FirstOrDefault();
var responseInfo = await response.Content.ReadAsStringAsync();
return token;
}
}
private async Task<UpdateResult> AddAWDUser(string awdToken, UserDetail userDetails)
{
UpdateResult userAddresult = new UpdateResult() { Success = false, Errors = new List<string>(), Messages = new List<string>() };
ClientDetails clientData = await _clientWork.GetClientDetails(userDetails.ClientId);
var awdPayLoad = await prepareAWDPayload(userDetails);
using (var handler = new HttpClientHandler { UseCookies = false })
using (var client = new HttpClient(handler))
{
string targetUri = string.Empty;
Dictionary<string, string> _awdConfigs;
_userSecurityWrok.CleintConfiguration.ClientAppConfigs.TryGetValue(string.Concat("AWD", "1"), out _awdConfigs);
if (_awdConfigs != null)
{
_awdConfigs.TryGetValue("AWDShortNameURL", out targetUri);
}
client.BaseAddress = new Uri(targetUri);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("csrf_token", awdToken);
client.DefaultRequestHeaders.Add("Cookie", "csrf_token=" + awdToken);
client.DefaultRequestHeaders.ExpectContinue = false;
var content = new StringContent(awdPayLoad, Encoding.UTF8, "application/json");
var response = await client.PostAsync(targetUri, content).ConfigureAwait(false);
var responseInfo = await response.Content.ReadAsStringAsync();
if (response.StatusCode == HttpStatusCode.OK)
{
userAddresult.Success = true;
}
else
{
userAddresult.Success = false;
userAddresult.Errors = new List<string> { "AWD returned error as " + response.StatusCode.ToString() };
}
}
return userAddresult;
}
Need to get this working... any idea?
attaching postman dump
POST /devapp/awdServer/awd/services/v1/users/ HTTP/1.1
Host: awdwaldn.nonprod.awdprocess.net:8443
csrf_token: L1HmyGPvEC4GvrOqBioL0Q..
Content-Type: application/json
User-Agent: PostmanRuntime/7.20.1
Accept: */*
Cache-Control: no-cache
Postman-Token: 594c3d97-de46-4fc3-9c2d-1b5f74278e60,8be8e538-267f-4544-b33a-211b2d479b3b
Host: ***** //removed host details
Accept-Encoding: gzip, deflate
Content-Length: 325
Cookie: BIGipServerawdwaldn-nonprod-web-8443-dev-web=454308362.16671.0000; JSESSIONID=8hl6G3gImEf4S71c8CFIzfMd.JVM1
Connection: keep-alive
cache-control: no-cache
{
"userId": "DST1234",
"alias": "DST1234",
"password": "TextAW1#",
"firstName": "chi",
"lastName": "chan",
"workSelect": "1",
"group": "WORK GROUP",
"countryCode": 1,
"earlyTime": "00:00:01",
"lateTime": "23:59:59",
"queue": "N",
"status": "A",
"workSelect": 1
}
I found it. its the cookies. We need to read the cookies from first response and attach it to second one. Issue resolved. thanks for your help.

Forbidden access when calling twitter api geo/search.json

I'm new in using twitter API, I've successfully called:
https://api.twitter.com/1.1/statuses/user_timeline.json
api.twitter.com/1.1/followers/list.json
but when I call:
https://api.twitter.com/1.1/geo/search.json?query=Pakistan
I get Forbidden access.
Following is my request:
Method: GET, RequestUri: 'https://api.twitter.com/1.1/geo/search.json?query=Pakistan', Version: 1.1, Content: , Headers:
{
Authorization: Bearer xxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyzzzzzzzzzzzzzzzzzzzzzzzzz%aaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbb
}
And the response that I get is:
StatusCode: 403, ReasonPhrase: 'Forbidden', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
strict-transport-security: max-age=631138519
x-connection-hash: 3a7f405036803861a700cef30f7b1e7f
x-response-time: 107
Date: Fri, 05 May 2017 03:18:15 GMT
Set-Cookie: guest_id=v1%3A149395429589966721; Domain=.twitter.com; Path=/; Expires=Sun, 05-May-2019 03:18:15 UTC
Server: tsa_o
Content-Length: 91
Content-Type: application/json; charset=utf-8
}
If you're interested in looking at my C# code that I'm using, here you go:
public async Task<IEnumerable<string>> GetTweetsByLatLong(double latitude, double longitude, int count, string accessToken = null)
{
if (accessToken == null)
{
accessToken = await GetAccessToken();
}
var requestUserTimeline = new HttpRequestMessage(HttpMethod.Get, string.Format("https://api.twitter.com/1.1/geo/search.json?query=Pakistan"));
requestUserTimeline.Headers.Add("Authorization", "Bearer " + accessToken);
var httpClient = new HttpClient();
HttpResponseMessage responseUserTimeLine = await httpClient.SendAsync(requestUserTimeline);
if (responseUserTimeLine.IsSuccessStatusCode)
{
var serializer = new JavaScriptSerializer();
dynamic json = ((serializer.Deserialize<object>(await responseUserTimeLine.Content.ReadAsStringAsync())) as Dictionary<string, object>).Values.ElementAt(0);
//new System.Collections.Generic.Mscorlib_DictionaryValueCollectionDebugView<string, object>((json as Dictionary<string, object>).Values).Items[0]
var enumerableTwitts = (json as IEnumerable<dynamic>);
if (enumerableTwitts == null)
{
return null;
}
return enumerableTwitts.Select(t => (string)(t["name"].ToString()));
}
else
{
return new string[] { responseUserTimeLine.ToString() };
}
}
public async Task<string> GetAccessToken()
{
var httpClient = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://api.twitter.com/oauth2/token ");
var customerInfo = Convert.ToBase64String(new UTF8Encoding().GetBytes(OAuthConsumerKey + ":" + OAuthConsumerSecret));
request.Headers.Add("Authorization", "Basic " + customerInfo);
request.Content = new StringContent("grant_type=client_credentials", Encoding.UTF8, "application/x-www-form-urlencoded");
HttpResponseMessage response = await httpClient.SendAsync(request);
string json = await response.Content.ReadAsStringAsync();
var serializer = new JavaScriptSerializer();
dynamic item = serializer.Deserialize<object>(json);
return item["access_token"];
}
I believe it is because you are using Application-only authentication by providing a Bearer token.
See "Requires Authentication" in both
https://dev.twitter.com/rest/reference/get/geo/search
and
https://dev.twitter.com/rest/reference/get/statuses/user_timeline
And read https://dev.twitter.com/oauth

Categories