I haven't been able to figure out how to properly upload a label onto eBay using the /post-order/v2/return/{returnId}/file/upload call. I keep getting "The remote server returned an error: (400) Bad Request.".
I believe it may have to do with the image encoding, but I am not entirely certain. I was already able to approve the return with POST /return/{returnId}/decide but the next step in uploading is the problem. I have the image data saved as a base 64 string in a database. I know the data is good, because in other calls I am able to transform that base 64 string into an image in my application. So the data from the image isn't in question. The thing is on http://developer.ebay.com/Devzone/post-order/post-order_v2_return-returnId_file_upload__post.html#samplesellerlabel it states that the image data should be "base64-encoded binary representation of the file".
So is it possible that the data I received when grabbing the image with Convert.ToBase64String(imageBytes) is not what I actually need? There are little to no examples on how to do this particular call in C# and I've tried so many things. I've checked the JSON syntax and it looks to be correct. (I've removed a large portion of the string as it is too large.)
{"fileName":"5074119065_shippingLabel.jpeg","data":"R0lGODlhCAewBIEAAAAAAP///wAAAAAAACH/C05...zR2On54kkB4nfJYrLFRAAOw==","filePurpose":"LABEL_RELATED"}
I'm fairly convinced that the image data is somehow not formatted correctly, but I'm just not sure. If anyone has any experience with this call I'd appreciate your help. Below is my code and the error comes up on the last line. The headers and the JSON code has worked without any issues on other eBay calls which is also a reason I suspect my problem may have to do with the formatting of the image data.
string url = "https://api.ebay.com/post-order/v2/return/" + returnId + "/file/upload";
var cancelOrderRequest = (HttpWebRequest)WebRequest.Create(url);
cancelOrderRequest.Headers.Add("Authorization", "TOKEN " + authToken);
cancelOrderRequest.ContentType = "application/json";
cancelOrderRequest.Accept = "application/json";
cancelOrderRequest.Headers.Add("X-EBAY-C-MARKETPLACE-ID", "EBAY_US");
cancelOrderRequest.Method = "POST";
string fileName = returnId + "_shippingLabel.jpeg";
using (var streamWriter = new StreamWriter(cancelOrderRequest.GetRequestStream()))
{
string json = "{\"fileName\":\"" + fileName + "\",\"data\":\"" + labelData + "\",\"filePurpose\":\"LABEL_RELATED" + "\"}";
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
}
var response = (HttpWebResponse)cancelOrderRequest.GetResponse();
Hmm. The eBay documentation appears to be inconsistent. In the top part of the documentation page you linked for the Upload Return File method call, it seems to indicate that the data part of the JSON should be an array of strings, not just a single string.
Payload model
The following lists all fields that could be included in the request.
{ /* UploadFileRequest */
"data": [
string
/* More string nodes here */
],
"fileName": string,
"filePurpose": token
}
But in the JSON sample they show on the same page, the data is clearly a single string like you have it in your code. (Notice the square brackets are missing.)
URL format. See also the non-wrapped version of this URL.
POST https://api.ebay.com/post-order/v2/return/5000124931/file/upload
{
"fileName" : "jasmine.jpeg",
"data" : "SGVyZSBpcyB5b3VyIHJld...YWNraW5nIG51bWJlciBpcyAxMjM0NTY3ODk4NzY1",
"filePurpose" : "ITEM_RELATED"
}
I would try changing it to an array to match the documented payload. I'm guessing the sample is probably wrong here.
Also, I would highly recommend using a JSON serializer like Json.Net rather than hand-rolling your own JSON, as it is very easy to get the formatting wrong, which will just end up giving you more "400 Bad Request" headaches. Instead, try making the JSON by using an anonymous object and then serializing it, like this:
var payload = new
{
fileName = returnId + "_shippingLabel.jpeg",
data = new List<string> { labelData },
filePurpose = "LABEL_RELATED"
};
string json = JsonConvert.SerializeObject(payload);
Related
Good morning,
I am using ASP.NET HTTP API as Actions on Google fullfilment. I have an error message when I try to send tokens to Actions on Google project. Regarding to another question I read I made sure to have clear int value (not decimal) and it doesn't work.
My JSON which I send to Actions on Google:
{"token_type":"Bearer","access_token":"edeaa27e-12b7-43a1-bc7c-e6bbf9af71c3","refresh_token":"4344383b-cf07-4d12-a5c2-44b6481f5f48","expires_in":86400}
Error message:
{
insertId: "1o7lj2bmu"
jsonPayload: {
#type: "type.googleapis.com/google.identity.accountlinking.type.AccountLinkingError"
errorReason: "Can't parse the response. The response needs to be JSON format."
response: {
body: ""{\"token_type\":\"Bearer\",\"access_token\":\"edeaa27e-12b7-43a1-bc7c-e6bbf9af71c3\",\"refresh_token\":\"4344383b-cf07-4d12-a5c2-44b6481f5f48\",\"expires_in\":86400}""
status: 200
}
step: "AUTH_CODE_EXCHANGE"
}
logName: "projects/smartlightproject-f47f4/logs/accountlinking-pa.googleapis.com%2Ferror"
receiveTimestamp: "2022-07-12T12:32:40.739532642Z"
resource: {2}
severity: "ERROR"
timestamp: "2022-07-12T12:32:40.539Z"
}
What's wrong with that JSON? Or maybe I should do it in some other way?
I will be very very grateful if you could help me with that.
Here's my code after some improvements:
var result_acceess_token = "edeaa27e-12b7-43a1-bc7c-e6bbf9af71c3";
var result_refresh_token = "4344383b-cf07-4d12-a5c2-44b6481f5f48";
var expires_expires_in = 86400;
var resultObj = new
{
token_type = "Bearer",
access_token = result_acceess_token,
refresh_token = result_refresh_token,
expires_in = expires_expires_in
};
return Ok(resultObj);
Earlier I tried to serialize JSON with JsonConvert and return it as JsonResult or raw string value.
It looks like the response you're sending back is the JSON as a quoted string. That is - there is a quote at the beginning and end of the JSON. While this is a valid JSON string (it is, after all, a quoted string), it sounds like it is looking for a JSON object.
Verify the body of the response and make sure it does not contain the opening and closing quotes.
While using something like this
"
Dictionary<string, string> form = new Dictionary<string, string>
{
{_metajson, JsonConvert.SerializeObject(metaJson)}
};
HttpResponseMessage response = await httpClient.PostAsync(url, new FormUrlEncodedContent(form));
However on the php side of things with $_Request I get the string and all the quotes are turned into " so the json looks like
{"name":"myname"}
Is there a better way to send json to a php backend?
On the PHP end of things I am simply assigning the json which has now lost the quotes and has weird marks with
$json = $_REQUEST["test"];
The json I am sending is in memory, its not saved to a file anywhere. It is very small like shown above and is needed for the purposes of the application I am writing.
Use php://input
php://input is a read-only stream that allows you to read raw data from the request body.
Example:
$json_string = file_get_contents('php://input');
//Converting It to PHP object:
$data = json_decode($json_string );
I was just working with the same problem and here is my solution, it works for me
$data = $_POST['json'] ;
$json = json_decode($data, true);
echo json_encode($json);
afterwards, you can take the $json variable an do whatever you want to do with it
I ended up changing the approach which worked very well
I simply base64 encoded the json to avoid http changing special characters to odd string formats like " to " and what not.
C# side - using this string in the dictionary form
string encodedJson = Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(metaJson)));
PHP side
$encoded_input = $_REQUEST["metajson"];
$base64_decoded_input = base64_decode($encoded_input, true);
if (!$base64_decoded_input)
{
// error out
}
$meta_json = json_encode(json_decode($base64_decoded_input));
since i'm new to the flutter.io-app-framework and c#-http-sever (request and response), i'm struggling with an error for about two weeks or so.
I'm completly new to JSON.
My problem is an invalid JSON header. To be precise, my Android Studio is saying something like "error: HttpException: Invalid response status code, uri = http://127.0.0.1:2508/user/1".
The error is only occurring when using the app for a http request. My firefox and chrome are doing fine. The result is shown as it should.
In my dart/flutter app, i'm just sending a http get request which does look like the following:
Future<String> getData() async {
var response = await http.get(
Uri.encodeFull("http://127.0.0.1:2508/user/1"),
headers: {"Accept": "text/json"});
this.setState(() {
user = json.decode(response.body);
print(user[0]);
});
return "Success!";
}
My c# server code looks like this:
private void HandleClient(TcpClient client)
{
StreamReader reader = new StreamReader(client.GetStream());
StreamWriter writer = new StreamWriter(client.GetStream());
String request = reader.ReadLine();
if (!String.IsNullOrEmpty(request))
{
Log.WriteLine("\nRequest: \n" + request);
string[] tokens = request.Split(' ');
Log.WriteLine("~~~~~ Tokens ~~~~~");
foreach (String token in tokens)
{
Log.WriteLine("~ " + token);
}
Log.WriteLine("~~~~~~~~~~~~~~~~~~\n");
String[] cmds = tokens[1].Split('/');
String cmd = cmds[1].ToUpper();
String json = "";
switch (cmd)
{
case "USER":
if ((cmds.Length >= 3) && (cmds[2] != ""))
{
json += Tools.toJSON(Data.GetBenutzer(Convert.ToInt16(cmds[2])));
}
break;
default:
break;
}
writer.WriteLine(VERSION + " \n200 OK\nServer: " + NAME + "\nContent-Type: text/json\nAccess-Control-Allow-Origin: *\n");
writer.WriteLine(json);
Log.WriteLine("~~~~~~ Json ~~~~~~\n" +
json + "\n" +
"~~~~~~~~~~~~~~~~~~\n");
writer.Flush();
writer.Close();
writer.Dispose();
}
}
Is anything essential missing in the JSON response?
Maybe you have another inspiring idea that can help me.
First off, I'd highly recommend using a http server package that handles the low level stuff like writing headers for you! Someone has gone to the effort of doing this stuff, verifying that it meets the HTTP RFC, testing it, and then giving it away for free!
If this is for an assignment or to learn http, or you have some other good reason, fair enough. But otherwise, there's almost no point in writing something like this from scratch where you could introduce bugs that are hard to figure out. Not only could you introduce http errors, but you'll have to make sure you do threading properly or you could run into problems when you get more traffic. And you'll save a lot of time because someone else has already figured out the hard stuff, so you can concentrate on making whatever it is you actually want to make.
But for your problem - it appears that the http part of the response isn't formatted quite right because flutter isn't recognizing the 200 response code you're trying to send (and therefore isn't reading it).
It's hard to tell without you actually posting what the http response looks like in full, but I think it's to do with an extra line feed.
You have writer.WriteLine(VERSION + " \n200 OK\nServer: "... but I think it should be writer.WriteLine(VERSION + " 200 OK\nServer: " (assuming version is something like HTTP/1.1).
Also you should be aware that the HTTP protocol actually wants \r\n for line feeds, although all modern servers/clients should be able to support just '\n' as well. But it's always better to follow the protocol specification.
This is wrecking my brain for a while now. The code works fine when I post a smaller XML string. As soon as I add more XML nodes and post, I get the infamous '404 Error'
I'm posting XML data as a string to a Generic Handler in C#.
string strXML = "Large XML Content Here";
WebClient client = new WebClient();
string xmlResult = "";
try
{
xmlResult = client.DownloadString(_workContext.AccountingWebServiceLink
+ "?action=updateprimary&xml="
+ System.Web.HttpUtility.UrlEncode(strXML));
}
catch(Exception e)
{
System.IO.File.AppendAllText(Server.MapPath("~/addressXMLReturnError.txt"),
"Error: " + e.Message + " returnValue = " + xmlResult);
}
I think it might have something to do with the server not accepting large strings?
Finally got it working using suggestions from comments above.
So posting the XML data is the best route for me.
Using code from this SO post > HTTP post XML data in C#
To receive the data on the other side, check out this link > https://code.msdn.microsoft.com/Enviar-datos-por-el-metodo-2e580ace
First of all what I want to do is legal (since they let you download the pdf).
I just wanted to make a faster and automatic method of downloading the pdf.
For example: http://www.lasirena.es/article/&path=10_17&ID=782
It has an embedded flash pdf and when I download that page source code, the link to the pdf:
http://issuu.com/lasirena/docs/af_fulleto_setembre_andorra_sense_c?e=3360093/9079351
Doesn't show up, the only thing that I have on the source code is this: 3360093/9079351
I tried to find a way to build the pdf link from it, but I can't find the name "af_fulleto_setembre_andorra_sense_c" anywhere...
I've made plenty of automatic downloads like this, but it's the first time that I can't build or get the pdf link and I can't seem to find a way, is it even possible?
I tried to try and find jpg's links but without success either. Either way (jpg or pdf) is fine...
PS: the Document ID doesn't show on the downloaded source code either.
Thank you.
I thought a workaround for this, some might not consider this a solution but in my case works fine because it depends on the ISSUU publisher account.
The Solution itself is making a Request to ISSUU API connected with the publisher account I'm looking for.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://api.issuu.com/query?action=issuu.documents.list" +
"&apiKey=Inser Your API Key" +
"&format=json" +
"&documentUsername=User of the account you want to make a request" +
"&pageSize=100&resultOrder=asc" +
"&responseParams=name,documentId,pageCount" +
"&username=Insert your ISSUU username" +
"&token=Insert Your Token here");
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.Accept = "application/json";
try
{
using (WebResponse response = request.GetResponse())
{
var responseValue = string.Empty;
// grab the response
using (var responseStream = response.GetResponseStream())
{
using (var reader = new StreamReader(responseStream))
{
responseValue = reader.ReadToEnd();
}
}
if (responseValue != "")
{
List<string> lista_linkss = new List<string>();
JObject ApiRequest = JObject.Parse(responseValue);
//// get JSON result objects into a list
IList<JToken> results = ApiRequest["rsp"]["_content"]["result"]["_content"].Children()["document"].ToList();
for (int i = 0; i < results.Count(); i++)
{
Folheto folheto = new Folheto();
folheto.name = results[i]["name"].ToString();
folheto.documentId = results[i]["documentId"].ToString();
folheto.pageCount = Int32.Parse(results[i]["pageCount"].ToString());
string _date = Newtonsoft.Json.JsonConvert.SerializeObject(results[i]["uploadTimestamp"], Formatting.None, new IsoDateTimeConverter() { DateTimeFormat = "yyyy-MM-dd hh:mm:ss" }).Replace(#"""", string.Empty);
folheto.uploadTimestamp = Convert.ToDateTime(_date);
if (!lista_nomes_Sirena.Contains(folheto.name))
{
list.Add(folheto);
}
}
}
}
}
catch (WebException ex)
{
// Handle error
}
You have to pay attention to the Parameter "pageSize" the maximum permitted by the API is 100, this means the maximum number of results you get is 100, since the account I'm following has around 240 pdf's, I used this request once with the Parameter "resultOrder = asc" and another time with the value "resultOrder=desc".
This allowed me to get the first 100 pdfs and the latest 100 pdfs inserted.
Since I didn't need a history but just the pdf's they will be sending out from now, it didn't make a difference.
Finalizing my code I'm sending all the document's ID's to a sql database I made, and when I start the program, I make a check to see if the ID was already downloaded, if not it downloads the pdf, if yes it doesn't.
Hope someone can find this work around useful