Ok so I'm having a bit of trouble getting these JSON requests through to the Ebay API.
Here is the json request:
string jsonInventoryRequest = "{" +
"\"requests\": [";
int commaCount = 1;
foreach (var ep in productsToProcess)
{
jsonInventoryRequest += "{\"offers\": [{" +
"\"availableQuantity\":" + ep.EbayProductStockQuantity + "," +
"\"offerId\":\"" + ep.EbayID.ToString() + "\"," +
"\"price\": {" +
"\"currency\": \"AUD\"," +
"\"value\":\"" + ep.EbayProductPrice.ToString() + "\"" +
"}" +
"}],";
jsonInventoryRequest += "\"shipToLocationAvailability\": " + "{" +
"\"quantity\":" + ep.EbayProductStockQuantity +
"},";
jsonInventoryRequest += "\"sku\": " + ep.EbayProductSKU.ToString() + "}";
if (commaCount < productsToProcess.Count())
jsonInventoryRequest += ",";
commaCount++;
sendEbayApiRequest = true;
}
jsonInventoryRequest +=
"]" +
"}";
And the Debug.WriteLine() output of the above JSON request is :
json string = {"requests": [{"offers": [{"availableQuantity":0,"offerId":"098772298312","price": {"currency": "AUD","value":"148.39"}}],"shipToLocationAvailability": {"quantity":0},"sku": 135779},{"offers": [{"availableQuantity":1,"offerId":"044211823133","price": {"currency": "AUD","value":"148.39"}}],"shipToLocationAvailability": {"quantity":1},"sku": 133607}]}
Here is the code in C# to send the request:
var ebayAppIdSetting = _settingService.GetSettingByKey(
"ebaysetting.appid", "");
var ebayCertIdSetting = _settingService.GetSettingByKey(
"ebaysetting.certid", "");
var ebayRuNameSetting = _settingService.GetSettingByKey(
"ebaysetting.appid", "");
var stringToEncode = ebayAppIdSetting + ":" + ebayCertIdSetting;
HttpClient client = new HttpClient();
byte[] bytes = Encoding.UTF8.GetBytes(stringToEncode);
var base64string = "Basic " + System.Convert.ToBase64String(bytes);
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Authorization", base64string);
var stringContent = "?grant_type=client_credentials&" + "redirect_uri=" + ebayRuNameSetting + "&scope=https://api.sandbox.ebay.com/oauth/api_scope";
var requestBody = new StringContent(stringContent.ToString(), Encoding.UTF8, "application/json");
requestBody.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
var response = client.PostAsync("https://api.sandbox.ebay.com/identity/v1/oauth2/token", requestBody);
The output I get when I do Debug.WriteLine("response.Content = " + response.Result); is:
response.Content = StatusCode: 401, ReasonPhrase: 'Unauthorized',
Version: 1.1, Content: System.Net.Http.StreamContent, Headers: {
RlogId:
t6ldssk%28ciudbq%60anng%7Fu2h%3F%3Cwk%7Difvqn*14%3F0513%29pqtfwpu%29pdhcaj%7E%29fgg%7E%606%28dlh-1613f3af633-0xbd
X-EBAY-C-REQUEST-ID: ri=HNOZE3cmCr94,rci=6kMHBw5dW0vMDp8A
X-EBAY-C-VERSION: 1.0.0 X-EBAY-REQUEST-ID:
1613f3af62e.a096c6b.25e7e.ffa2b377!/identity/v1/oauth2/!10.9.108.107!r1esbngcos[]!token.unknown_grant!10.9.107.168!r1oauth-envadvcdhidzs5k[]
Connection: keep-alive Date: Mon, 29 Jan 2018 00:04:44 GMT
Set-Cookie: ebay=%5Esbf%3D%23%5E;Domain=.ebay.com;Path=/
WWW-Authenticate: Basic Content-Length: 77 Content-Type:
application/json }
Can anyone see where I'm going wrong. Cheers
Ok so the authentication was failing because I was sending wrong authentication token. Needed to get oauth token from application tokens.
So instead of base64 encoding token like this:
var base64string = "Basic " + System.Convert.ToBase64String(bytes);
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Authorization", base64string);
I needed to do the following:
url = "https://api.sandbox.ebay.com/sell/inventory/v1/bulk_update_price_quantity";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
//request.ContentType = "application/json; charset=utf-8";
request.Headers.Add("Authorization", "Bearer **OAUTH TOKEN GOES HERE WITHOUT ASTERIKS**");
// Send the request
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
streamWriter.Write(jsonInventoryRequest);
streamWriter.Flush();
streamWriter.Close();
}
// Get the response
HttpWebResponse response = (HttpWebResponse) request.GetResponse();
if (response != null)
{
using (var streamReader = new StreamReader(response.GetResponseStream()))
{
// Parse the JSON response
var result = streamReader.ReadToEnd();
}
}
Related
I need to send a POST request with usage of HttpClient, what i have right now:
[Route("RegisterTransaction")]
[HttpPost]
public async Task<ActionResult<string>> RegisterTransaction()
{
var httpClient = this._httpClientFactory.CreateClient();
try
{
string jsonData = "{\"sessionId\":\"1\"," +
"\"merchantId\":00000," +
"\"amount\":2137," +
"\"currency\":\"PLN\"," +
"\"crc\":\"xxxxxxxx\"}";
byte[] byteArray = Encoding.UTF8.GetBytes(jsonData);
SHA384 shaM = new SHA384Managed();
var hashResult = shaM.ComputeHash(byteArray);
string stringHashResult = BitConverter.ToString(hashResult).Replace("-", String.Empty).ToLower();
using (var client = new HttpClient())
{
// Set the base address and headers for the request
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
// Set the Basic Authentication header
var authValue = Convert.ToBase64String(Encoding.ASCII.GetBytes($"{merchantId}:{clientSecret}"));
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", authValue);
var urlReturn = System.Web.HttpUtility.UrlEncode("http://sample.com/");
var payload =
"{" +
"\"merchantId\":" + $"{merchantId}" + "," +
"\"posId\":" + $"{merchantId}" + "," +
"\"sessionId\":" + "\"1\"" + "," +
"\"amount\":" + "2137" + "," +
"\"currency\":" + "\"PLN\"" + "," +
"\"description\":" + "\"test_from_c#\"" + "," +
"\"email\":" + "\"sample#gmail.com\"" + "," +
"\"country\":" + "\"PL\"" + "," +
"\"language\":" + "\"pl\"" + "," +
"\"urlReturn\":" + $"\"{urlReturn}\"" + "," +
"\"timeLimit\":" + "15" + "," +
"\"waitForResult\":" + "true" + "," +
"\"shipping\":" + "0" + "," +
"\"sign\":" + $"\"{stringHashResult}\"" +
"}";
var content = new StringContent(payload, Encoding.UTF8, "application/json");
// Send the POST request and get the response
var response = await client.PostAsync(uriPath, content);
response.EnsureSuccessStatusCode();
var responseString = await response.Content.ReadAsStringAsync();
}
return Ok();
}
catch (HttpRequestException ex)
{
return BadRequest(ex.Message);
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
Problem is that, this code generates response 400:
{StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers:{ Access-Control-Allow-Origin: * Strict-Transport-Security: max-age=16000000; includeSubDomains; preload; Cache-Control: max-age=0, no-cache, no-store Pragma: no-cache Date: Sun, 18 Dec 2022 19:52:14 GMT Connection: close Set-Cookie: PHPSESSID=20417919ff332939962473ac49ab1f1e; path=/; secure; HttpOnly Set-Cookie: akaalb_Sandbox=~op=sandbox:sandbox-dc1|~rv=60~m=sandbox-dc1:0|~os=352131486e59fe329be9d171af3005ed~id=903a75e16940cf8c12e4c2e79ee82d78; path=/; HttpOnly; Secure; SameSite=None DC: DC1 Content-Type: application/json Content-Length: 40 Expires: Sun, 18 Dec 2022 19:52:14 GMT}, Trailing Headers:{}}
with a little to no information usefull to me, while this exact same request sended from Postman is resulting in response 200.
My question is: Why is that?
Why this same payload with these same headers generating different responses? I've checked json payload and it is 100% correct, also generated hashes and username and password in header. What am I missing?
I try to bring the pdf file into a standard software, wrote the code, an exception is issued because of wrong format with json although json string corresponds exactly to the specified json of api call of standard software. can you please take a look if I wrote something wrong here or if I forgot something?
I covered some information with a star
Many Thanks
IRestResponse response3;
client = new RestClient("http://***.***.***.*");
client.Authenticator = new HttpBasicAuthenticator("********", "*********");
client.Timeout = -1;
request = new RestRequest("/*****/api/******/*****/***", Method.POST);
request.AddHeader("content-type", "multipart/form-data");
request.AlwaysMultipartFormData = true;
request.AddParameter("Object", "{" +
"\"cabinet\":\"Posteingang\"," +
"\"name\":\"Posteingang\"," +
"\"objectTypeId\":\"2\"," +
"\"fields\":{" +
"\"Datum\":{\"value\":\"" + DateTime.Now.ToString("dd.MM.yyyy") + "\"}" +
"}" +
"}");
request.AddFile("file","C:/Users/*********/Documents/*********/Org.pdf","Org.pdf");
MultipartFormDataContent multipartForm = new MultipartFormDataContent();
byte[] file_bytes = File.ReadAllBytes("C:/Users/********/Documents/********/Org.pdf");
multipartForm.Add(new ByteArrayContent(file_bytes, 0, file_bytes.Length), "profile_pic", "hello1.jpg");
multipartForm.Add(new StringContent("Object"), "{" +
"\"cabinet\":\"Posteingang\"," +
"\"name\":\"Dokument\"," +
"\"objectTypeId\":\"******\"," +
"\"fields\":{" +
"\"Datum\":{\"MAIL_SUBMIT_TIME\":{\"value\":\"" + DateTime.Now.ToString("dd.MM.yyyy") + "\"},\"Typ\":" +
"{\"feld4\":{\"value\": \"Brief\"}},\"Absender\": {\"Mail_FROM\":{\"value\": \"*********\"}}}}}");
response3 = client.Execute(request);
Console.WriteLine(response3.Content);
}
}
}
i am trying to fetch an access token by calling an API with an auth code and keeping getting a 400 error.
I have read many a web sites and can't see what is wrong with this. thanks. I have left in commented bits as this is other ways I have tried. Appreciate any quick advice
HttpWebRequest request = WebRequest.Create("https://identity.xero.com/connect/token") as HttpWebRequest;
request.Headers.Add("Authorization", "Basic " + b64_id_secret);
//string data = "{ grant_type : refresh_token, refresh_token : " + l_auth_code+ "}";
//string data = "{ 'grant_type' : 'authorization_code', 'code' : '" + l_auth_code + "', 'redirect_uri' : '" + C_XERO_REDIRECT_URL + "'}";
request.ContentType = "application/json";
request.Method = "POST";
//request.ContentType = "application/json";
//request.ContentLength = postBytes.Length;
//request.Accept = "application/json";
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
string json = "{\"grant_type\":\"authorization_code\"," +
"\"code\":\"" + l_auth_code + "\","+
"\"redirect_uri\":\"" + C_XERO_REDIRECT_URL + "\"}";
streamWriter.Write(json);
}
// crashes here
var httpResponse = (HttpWebResponse)request.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}
I am trying to post Tin Can Statements to a Scorm Cloud LRS via c# HttpWebRequest in JSON format. However I always get error 400. The authentication is correct so what is wrong with the JSON? I have tried encoding as UTF8 also and still no dice
Here is the code and credentials needed:
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create("https://cloud.scorm.com/ScormEngineInterface/TCAPI/RCFZ5D8GXU/sandbox/");
httpWebRequest.ContentType = "application/json; charset=UTF-8";
httpWebRequest.Method = "POST";
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
String autorization= "Basic " + Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes("RCFZ5D8GXU222" + ":" + "YQA3VfX1NiuYkKXEEzkKu723NwejpwNkB6x0Vhg3"));
httpWebRequest.Headers.Add("Authorization", autorization);
httpWebRequest.Headers.Add("X-Experience-API-Version", "1.0.1");
string jsonText = "{"+
" \"actor\": {"+
" \"mbox\": \"mailto:Steeno#gmail.com\","+
" \"name\": \"Austin Glatt\","+
" \"objectType\": \"Agent\""+
"},"+
"\"verb\": {"+
" \"id\": \"http://adlnet.gov/expapi/verbs/attempted\","+
" \"display\": {"+
" \"en-US\": \"attempted\""+
" }"+
"},"+
"\"object\": {"+
" \"id\": \"http://www.example.com/tincan/activities/cMjKwAGI\","+
" \"objectType\": \"Activity\","+
" \"definition\": {"+
" \"name\": {"+
" \"en-US\": \"Part Removal\""+
" },"+
" \"description\": {"+
" \"en-US\": \"On Engine 155\""+
" }"+
" }"+
"}"+
"}";
byte [] jsonData = System.Text.Encoding.UTF8.GetBytes(jsonText);
Debug.Log(System.Text.Encoding.UTF8.GetString(jsonData));
httpWebRequest.ContentLength = jsonData.Length;
using (var streamWriter = httpWebRequest.GetRequestStream())
{
streamWriter.Write(jsonData,0,jsonData.Length);
streamWriter.Flush();
streamWriter.Close();
}
try
{
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
Debug.Log("POST result"+result);
}
}
catch(WebException ex)
{
if (ex.Response != null)
{
Debug.Log(ex.Message);
foreach(DictionaryEntry d in ex.Data)
Debug.Log(d.ToString());
string errorDetail = string.Empty;
using (StreamReader streamReader = new StreamReader(ex.Response.GetResponseStream(), true))
{
errorDetail = streamReader.ReadToEnd();
Debug.Log(errorDetail);
}
}
}
I think you are missing the "statements" on the URL, your request should be going to:
https://cloud.scorm.com/ScormEngineInterface/TCAPI/RCFZ5D8GXU/sandbox/statements
Original answer in case anyone cares:
It appears you are posting a 0.95 or 1.0.x statement, but you don't seem to be setting an X-Experience-API-Version header, so the LRS is probably interpreting it as a 0.9 statement which would be invalid.
I'd highly recommend using a library to build the requests along with the content of the request. We have one available here:
http://rusticisoftware.github.io/TinCan.NET/
I am trying to use the ImageShack API to upload images. To use it, I am supposed to POST the image using multipart/form-data. I did it like ...
var postData = "";
var req = HttpWebRequest.Create("http://www.imageshack.us/upload_api.php");
req.Method = "POST";
req.ContentType = "multipart/form-data";
postData += "key=my_key_here&";
postData += "type=base64&";
// get base64 data from image
byte[] bytes = File.ReadAllBytes(#"D:\tmp\WpfApplication1\WpfApplication1\Images\Icon128.gif");
string encoded = Convert.ToBase64String(bytes);
postData += "fileupload=" + encoded;
byte[] reqData = Encoding.UTF8.GetBytes(postData);
using (Stream dataStream = req.GetRequestStream())
{
dataStream.Write(reqData, 0, reqData.Length);
}
var res = (HttpWebResponse)req.GetResponse();
var resStream = res.GetResponseStream();
var reader = new StreamReader(resStream);
string resString = reader.ReadToEnd();
txt1.Text = resString;
but ImageShack is complaining that
<links>
<error id="parameter_missing">Sorry, but we've detected that unexpected data is received. Required parameter 'fileupload' is missing or your post is not multipart/form-data</error>
</links>
FileUpload is present and I am using multipart/form-data whats wrong?
UPDATE:
New Code http://pastebin.com/TN6e0CD8
Post data http://pastebin.com/fYE9fsxs
UPDATE 2
i looked at the other question Multipart forms from C# client. modified my code with boundary, removed the expect 100 header still i cant get it working ...
ServicePointManager.Expect100Continue = false;
var boundary = "-----------------------------28520690214962";
var newLine = Environment.NewLine;
var propFormat = boundary + newLine +
"Content-Disposition: form-data; name=\"{0}\"" + newLine + newLine +
"{1}" + newLine + newLine;
var fileHeaderFormat = boundary + newLine +
"Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"" + newLine;
var req = (HttpWebRequest)HttpWebRequest.Create("http://jm/php/upload.php");
req.Method = WebRequestMethods.Http.Post;
req.ContentType = "multipart/form-data; boundary=" + boundary;
using (var reqStream = req.GetRequestStream()) {
var reqWriter = new StreamWriter(reqStream);
var tmp = string.Format(propFormat, "str1", "hello world");
reqWriter.Write(tmp);
tmp = string.Format(propFormat, "str2", "hello world 2");
reqWriter.Write(tmp);
reqWriter.Write(boundary + "--");
reqWriter.Flush();
}
var res = req.GetResponse();
using (var resStream = res.GetResponseStream()) {
var reader = new StreamReader(resStream);
txt1.Text = reader.ReadToEnd();
}
I finally got it with the following code ...
var boundary = "------------------------" + DateTime.Now.Ticks;
var newLine = Environment.NewLine;
var propFormat = "--" + boundary + newLine +
"Content-Disposition: form-data; name=\"{0}\"" + newLine + newLine +
"{1}" + newLine;
var fileHeaderFormat = "--" + boundary + newLine +
"Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"" + newLine;
var req = (HttpWebRequest)HttpWebRequest.Create("http://jm/php/upload.php");
req.Method = WebRequestMethods.Http.Post;
req.ContentType = "multipart/form-data; boundary=" + boundary;
using (var reqStream = req.GetRequestStream()) {
var reqWriter = new StreamWriter(reqStream);
var tmp = string.Format(propFormat, "str1", "hello world");
reqWriter.Write(tmp);
tmp = string.Format(propFormat, "str2", "hello world 2");
reqWriter.Write(tmp);
reqWriter.Write("--" + boundary + "--");
reqWriter.Flush();
}
var res = req.GetResponse();
using (var resStream = res.GetResponseStream()) {
var reader = new StreamReader(resStream);
txt1.Text = reader.ReadToEnd();
}
Notice boundaries have to begin with -- {boundary declared in ContentType} and ending boundary must begin & end with -- . in my case, I originally used
var propFormat = boundary + newLine +
"Content-Disposition: form-data; name=\"{0}\"" + newLine + newLine +
"{1}" + newLine;
replace it with
var propFormat = "--" + boundary + newLine +
"Content-Disposition: form-data; name=\"{0}\"" + newLine + newLine +
"{1}" + newLine;
and everything works
I believe that you are not building the request body correctly.
First, you need to include part boundary (random text) in content type header. For example,
Content-Type: multipart/form-data;
boundary=----WebKitFormBoundarySkAQdHysJKel8YBM
Now format of request body will be something like
------WebKitFormBoundarySkAQdHysJKel8YBM
Content-Disposition: form-data;name="key"
KeyValueGoesHere
------WebKitFormBoundarySkAQdHysJKel8YBM
Content-Disposition: form-data;name="param2"
ValueHere
------WebKitFormBoundarySkAQdHysJKel8YBM
Content-Disposition: form-data;name="fileUpload"; filename="y1.jpg"
Content-Type: image/jpeg
[image data goes here]
I will suggest you to use tool such as Fiddler to understand how these requests are built.
This is nothing like multipart/form-data
There's no boundaries between fields (needed even with one field).
Why are you base-64 encoding?
There's no indication of the content-type of the image.
Take a look at RFC 2388 for the actual format spec. It can also be useful to look at a Fiddler grab of a file upload from a web-page.