我有一个Python
代码段来连接有效的API。
我想要做的是使用C#复制相同的代码片段但没有运气..
我得到了异常The remote server returned an error: (401) Unauthorized.
- 所以下一步找出代码之间的差异就是使用fiddler,我看到的第一个不同的东西是:
CONNECT api.stg.xxx.org:443 HTTP/1.1
使用C#时,CONNECT api.stg.XXX.org:443 HTTP/1.0
。所以我尝试设置协议:req.ProtocolVersion = HttpVersion.Version10;
其中req是HttpWebRequest
但是当我用fiddler看时 - HTTP标头仍然是:
CONNECT api.stg.printopt.org:443 HTTP/1.1
我错过了什么吗?
(401) Unauthorized.
可以相关吗?
#!/usr/bin/python
__author__ = 'xxx'
import requests, json, hmac, hashlib, datetime, base64, string, random
def id_generator(size=6, chars=string.ascii_uppercase + string.digits):
return ''.join(random.choice(chars) for _ in range(size))
def create_headers(method, path, timestamp):
string_to_sign = method + ' ' + path + ' ' + timestamp
#print(string_to_sign)
signature = hmac.new(secret, string_to_sign, hashlib.sha1).hexdigest()
xxx_auth = token + ':' + signature
return {'content-type': 'application/json',
'x-xxx-authorization': xxx_auth,
'x-xxx-date': timestamp}
def xxx_request(method, path, data):
timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
print(timestamp)
url = endpoint + path
headers = create_headers(method, path, timestamp)
result = requests.post(url, data, headers=headers)
return result.content
def validate_order(order):
print ("Validating Order")
return xxx_request("POST", '/api/order/validate', order)
def submit_order(order):
print ("Submitting Order")
return xxx_request("POST", '/api/order', order)
#access credentials
token = '12345'
secret = '54321'
endpoint = "https://api.stg.url.org/workflow"
#Here are the variables required for a single item order
#this is not a full set of fields available
destination = 'dest'
orderId = id_generator()
itemId = id_generator()
postbackAddress = "http://postback.xxx.com"
sku = "Business Cards"
quantity = 1
fetchPath = "https://Server/Path/business_cards.pdf"
componentCode = "Content"
shipTo = {
"name": "John Doe",
"address1": "5th Avenue",
"town": "New York",
"postcode": "12345",
"state": "New York",
"isoCountry": "US",
"email": "johnd@acme.com",
"phone": "01234567890"
}
carrier = {
"code": "customer",
"service": "pickup"
}
#nothing to change below here
#create an item - this goes into the order below
item = {
"sourceItemId": itemId,
"sku": sku,
"quantity": quantity,
"components": [{
"code": componentCode,
"path": fetchPath,
"fetch": "true"
}]
}
#create a shipment - this goes into the order below
shipment = {
"shipTo": shipTo,
"carrier": carrier
}
#put together the complete order
order = {
"destination": {
"name": destination
},
"orderData": {
"sourceOrderId": orderId,
"postbackAddress": postbackAddress,
"items": [ item ],
"shipments": [ shipment ]
}
}
#validate the order
print (validate_order(json.dumps(order)))
#finally, submit the order
#print (submit_order(json.dumps(order)))
The remote server returned an error: (401) Unauthorized.
using Newtonsoft.Json;
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Cache;
using System.Security.Cryptography;
using System.Text;
namespace urlIntegration_Demo
{
public class Program
{
// access credentials
static string token = "12345";
static string secret = "54321";
static string endpoint = "https://api.stg.url.org/workflow";
static void Main(string[] args)
{
url_request("POST", "/api/order/validate", "");
}
private static string id_generator()
{
int size = 6;
var random = new Random((int)DateTime.Now.Ticks);
string input = "abcdefghijklmnopqrstuvwxyz0123456789";
var chars = Enumerable.Range(0, size)
.Select(x => input[random.Next(0, input.Length)]);
return new string(chars.ToArray());
}
// http://stackoverflow.com/questions/11790599/python-hmac-and-c-sharp-hmac
public static string ToHexString(byte[] array)
{
StringBuilder hex = new StringBuilder(array.Length * 2);
foreach (byte b in array)
{
hex.AppendFormat("{0:x2}", b);
}
return hex.ToString();
}
public static String HashMe(string string_to_sign)
{
ASCIIEncoding encoder = new ASCIIEncoding();
Byte[] code = encoder.GetBytes(secret);
HMACSHA1 hmSha1 = new HMACSHA1(code);
Byte[] hashMe = encoder.GetBytes(string_to_sign);
Byte[] hmBytes = hmSha1.ComputeHash(hashMe);
return ToHexString(hmBytes);
}
#region exampleJson
static string exampleJson = " {\"orderData\": {\"shipments\": [{\"shipTo\": {\"town\": \"New York\", \"isoCountry\": \"US\", \"state\": \"New York\", \"name\": \"John Doe\", \"phone\": \"01234567890\", \"address1\": \"5th Avenue\", \"email\": \"johnd@acme.com\", \"postcode\": \"12345\"}, \"carrier\": {\"code\": \"customer\", \"service\": \"pickup\"}}], \"items\": [{\"sku\": \"Business Cards\", \"sourceItemId\": \"KIDJ7J\", \"components\": [{\"path\": \"https://Server/Path/business_cards.pdf\",\"code\": \"Content\", \"fetch\": \"true\"}], \"quantity\": 1}], \"postbackAddress\": \"http://postback.url.com\", \"sourceOrderId\": \"P27XWG\"}, \"destination\": {\"name\": \"dest\"}}";
#endregion
//prepare the request
private static string url_request(string method, string path, string data)
{
// creating the headers
var timestamp = DateTime.UtcNow.ToString("yyyy-MM-ddThh:mm:ss.sssZ");
var string_to_sign = method + ' ' + path + ' ' + timestamp;
string signature = HashMe(string_to_sign);
string url_auth = token + ':' + signature;
// building the headers
string x_url_authorization = "'x-url-authorization':" + url_auth;
string x_url_date = "'x-url-date':" + timestamp;
string url = endpoint + path;
string result = GetResponse(x_url_authorization, x_url_date, url);
return result;
}
// get the API response
private static string GetResponse(string x_url_authorization, string x_url_date, string url)
{
var t = string.Empty;
var Obj_response = string.Empty;
byte[] requestData = Encoding.UTF8.GetBytes(exampleJson);
HttpWebRequest req = WebRequest.Create(new Uri(url)) as HttpWebRequest;
req.ProtocolVersion = HttpVersion.Version10;
req.Method = "POST";
req.ContentType = "application/json";
req.Accept = "application/json";
req.Headers.Add("x-url-authorization",x_url_authorization);
req.Headers.Add("x-url-date",x_url_date);
req.ContentLength = requestData.Length;
using (Stream post = req.GetRequestStream())
{
post.Write(requestData, 0, requestData.Length);
using (HttpWebResponse resp = req.GetResponse() as HttpWebResponse)
{
if (resp.StatusCode == HttpStatusCode.OK)
{
var ms = new StreamReader(resp.GetResponseStream(), UTF8Encoding.UTF8);
t = ms.ReadToEnd();
Obj_response = JsonConvert.DeserializeObject<string>(t);
}
return Obj_response;
}
}
}
}
}
答案 0 :(得分:0)
问题出在标题中,我也用标题的名称填充了自定义标题,因此它被写了两次。